@firestone-hs/simulate-bgs-battle 1.1.641 → 1.1.643
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/cards/impl/minion/wrathscale-rogue.js +1 -1
- package/dist/cards/impl/minion/wrathscale-rogue.js.map +1 -1
- package/dist/simulation/attack.js +3 -2
- package/dist/simulation/attack.js.map +1 -1
- package/dist/simulation/secrets.js +3 -0
- package/dist/simulation/secrets.js.map +1 -1
- package/dist/simulation/stats.d.ts +1 -1
- package/dist/simulation/stats.js +4 -2
- package/dist/simulation/stats.js.map +1 -1
- package/package.json +1 -1
|
@@ -12,7 +12,7 @@ exports.WrathscaleRogue = {
|
|
|
12
12
|
input.healthAmount > 0) {
|
|
13
13
|
const mult = minion.cardId === "BG33_920_G" ? 2 : 1;
|
|
14
14
|
for (let i = 0; i < mult; i++) {
|
|
15
|
-
(0, stats_1.modifyStats)(input.target, minion, input.healthAmount, 0, input.board, input.hero, input.gameState, false);
|
|
15
|
+
(0, stats_1.modifyStats)(input.target, minion, input.healthAmount, 0, input.board, input.hero, input.gameState, false, true, false);
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrathscale-rogue.js","sourceRoot":"","sources":["../../../../src/cards/impl/minion/wrathscale-rogue.ts"],"names":[],"mappings":";;;AAAA,iEAAoD;AAGpD,qDAA6E;AAC7E,0CAAiD;AAGpC,QAAA,eAAe,GAAuB;IAClD,OAAO,EAAE,0BAAsE;IAC/E,cAAc,EAAE,CAAC,MAAmB,EAAE,KAA0B,EAAE,EAAE;QACnE,IACC,KAAK,CAAC,MAAM,KAAK,MAAM;YACvB,IAAA,uBAAe,EAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,EAAE,qBAAI,CAAC,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC;YACzG,KAAK,CAAC,YAAY,GAAG,CAAC,EACrB;YACD,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,iBAAuC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1E,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE;gBAG9B,IAAA,mBAAW,EACV,KAAK,CAAC,MAAM,EACZ,MAAM,EACN,KAAK,CAAC,YAAY,EAClB,CAAC,EACD,KAAK,CAAC,KAAK,EACX,KAAK,CAAC,IAAI,EACV,KAAK,CAAC,SAAS,EACf,KAAK,CACL,CAAC;aACF;SACD;IACF,CAAC;CACD,CAAC","sourcesContent":["import { Race } from '@firestone-hs/reference-data';\r\nimport { BoardEntity } from '../../../board-entity';\r\nimport { CardIds } from '../../../services/card-ids';\r\nimport { modifyStats, OnStatsChangedInput } from '../../../simulation/stats';\r\nimport { hasCorrectTribe } from '../../../utils';\r\nimport { OnStatsChangedCard } from '../../card.interface';\r\n\r\nexport const WrathscaleRogue: OnStatsChangedCard = {\r\n\tcardIds: [CardIds.WrathscaleRogue_BG33_920, CardIds.WrathscaleRogue_BG33_920_G],\r\n\tonStatsChanged: (minion: BoardEntity, input: OnStatsChangedInput) => {\r\n\t\tif (\r\n\t\t\tinput.target !== minion &&\r\n\t\t\thasCorrectTribe(input.target, input.hero, Race.NAGA, input.gameState.anomalies, input.gameState.allCards) &&\r\n\t\t\tinput.healthAmount > 0\r\n\t\t) {\r\n\t\t\tconst mult = minion.cardId === CardIds.WrathscaleRogue_BG33_920_G ? 2 : 1;\r\n\t\t\tfor (let i = 0; i < mult; i++) {\r\n\t\t\t\t// Patch 33.6.2 made it so Wrathscale Rogue does not trigger Sinestra / Whelp Smuggler / Titanic Guardian\r\n\t\t\t\t// For now we simply mark is as not triggering stat gain effects, and will refine this later\r\n\t\t\t\tmodifyStats(\r\n\t\t\t\t\tinput.target,\r\n\t\t\t\t\tminion,\r\n\t\t\t\t\tinput.healthAmount,\r\n\t\t\t\t\t0,\r\n\t\t\t\t\tinput.board,\r\n\t\t\t\t\tinput.hero,\r\n\t\t\t\t\tinput.gameState,\r\n\t\t\t\t\tfalse,\r\n\t\t\t\t);\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n};\r\n"]}
|
|
1
|
+
{"version":3,"file":"wrathscale-rogue.js","sourceRoot":"","sources":["../../../../src/cards/impl/minion/wrathscale-rogue.ts"],"names":[],"mappings":";;;AAAA,iEAAoD;AAGpD,qDAA6E;AAC7E,0CAAiD;AAGpC,QAAA,eAAe,GAAuB;IAClD,OAAO,EAAE,0BAAsE;IAC/E,cAAc,EAAE,CAAC,MAAmB,EAAE,KAA0B,EAAE,EAAE;QACnE,IACC,KAAK,CAAC,MAAM,KAAK,MAAM;YACvB,IAAA,uBAAe,EAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,EAAE,qBAAI,CAAC,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC;YACzG,KAAK,CAAC,YAAY,GAAG,CAAC,EACrB;YACD,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,iBAAuC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1E,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE;gBAG9B,IAAA,mBAAW,EACV,KAAK,CAAC,MAAM,EACZ,MAAM,EACN,KAAK,CAAC,YAAY,EAClB,CAAC,EACD,KAAK,CAAC,KAAK,EACX,KAAK,CAAC,IAAI,EACV,KAAK,CAAC,SAAS,EACf,KAAK,EACL,IAAI,EACJ,KAAK,CACL,CAAC;aACF;SACD;IACF,CAAC;CACD,CAAC","sourcesContent":["import { Race } from '@firestone-hs/reference-data';\r\nimport { BoardEntity } from '../../../board-entity';\r\nimport { CardIds } from '../../../services/card-ids';\r\nimport { modifyStats, OnStatsChangedInput } from '../../../simulation/stats';\r\nimport { hasCorrectTribe } from '../../../utils';\r\nimport { OnStatsChangedCard } from '../../card.interface';\r\n\r\nexport const WrathscaleRogue: OnStatsChangedCard = {\r\n\tcardIds: [CardIds.WrathscaleRogue_BG33_920, CardIds.WrathscaleRogue_BG33_920_G],\r\n\tonStatsChanged: (minion: BoardEntity, input: OnStatsChangedInput) => {\r\n\t\tif (\r\n\t\t\tinput.target !== minion &&\r\n\t\t\thasCorrectTribe(input.target, input.hero, Race.NAGA, input.gameState.anomalies, input.gameState.allCards) &&\r\n\t\t\tinput.healthAmount > 0\r\n\t\t) {\r\n\t\t\tconst mult = minion.cardId === CardIds.WrathscaleRogue_BG33_920_G ? 2 : 1;\r\n\t\t\tfor (let i = 0; i < mult; i++) {\r\n\t\t\t\t// Patch 33.6.2 made it so Wrathscale Rogue does not trigger Sinestra / Whelp Smuggler / Titanic Guardian\r\n\t\t\t\t// For now we simply mark is as not triggering stat gain effects, and will refine this later\r\n\t\t\t\tmodifyStats(\r\n\t\t\t\t\tinput.target,\r\n\t\t\t\t\tminion,\r\n\t\t\t\t\tinput.healthAmount,\r\n\t\t\t\t\t0,\r\n\t\t\t\t\tinput.board,\r\n\t\t\t\t\tinput.hero,\r\n\t\t\t\t\tinput.gameState,\r\n\t\t\t\t\tfalse,\r\n\t\t\t\t\ttrue,\r\n\t\t\t\t\tfalse,\r\n\t\t\t\t);\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n};\r\n"]}
|
|
@@ -34,6 +34,9 @@ const simulateAttack = (attackingBoard, attackingBoardHero, defendingBoard, defe
|
|
|
34
34
|
if (!isAttackingImmediately) {
|
|
35
35
|
attackingEntitiesToTheLeft.forEach((entity) => (entity.hasAttacked = 2));
|
|
36
36
|
}
|
|
37
|
+
else {
|
|
38
|
+
attackingEntity.attackImmediately = false;
|
|
39
|
+
}
|
|
37
40
|
const numberOfAttacks = attackingEntity.windfury ? 2 : 1;
|
|
38
41
|
for (let i = 0; i < numberOfAttacks; i++) {
|
|
39
42
|
if (attackingBoard.length === 0 || defendingBoard.length === 0) {
|
|
@@ -144,7 +147,6 @@ const performAttack = (attackingEntity, defendingEntity, attackingBoard, attacki
|
|
|
144
147
|
return { damageDoneByAttacker, damageDoneByDefender };
|
|
145
148
|
};
|
|
146
149
|
const getAttackingEntity = (attackingBoard, allCards) => {
|
|
147
|
-
var _a;
|
|
148
150
|
let validAttackers = attackingBoard.filter((entity) => (0, entity_utils_1.canAttack)(entity));
|
|
149
151
|
if (validAttackers.length === 0) {
|
|
150
152
|
return null;
|
|
@@ -159,7 +161,6 @@ const getAttackingEntity = (attackingBoard, allCards) => {
|
|
|
159
161
|
validAttackers = validAttackers.filter((entity) => !entity.hasAttacked);
|
|
160
162
|
}
|
|
161
163
|
const attacker = validAttackers[0];
|
|
162
|
-
const attackerName = (_a = allCards.getCard(attacker.cardId)) === null || _a === void 0 ? void 0 : _a.name;
|
|
163
164
|
return attacker;
|
|
164
165
|
};
|
|
165
166
|
const findNearestEnemies = (attackingBoard, entity, entityIndexFromRight, defendingBoard, numberOfTargets, allCards) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attack.js","sourceRoot":"","sources":["../../src/simulation/attack.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-use-before-define */\r\nimport { AllCardsService } from '@firestone-hs/reference-data';\r\nimport { BgsPlayerEntity } from '../bgs-player-entity';\r\nimport { BoardEntity } from '../board-entity';\r\nimport { hasOnAfterDeath, hasOnDeath } from '../cards/card.interface';\r\nimport { cardMappings } from '../cards/impl/_card-mappings';\r\nimport { debugState } from '../debug-state';\r\nimport { updateDivineShield } from '../keywords/divine-shield';\r\nimport { updateVenomous } from '../keywords/venomous';\r\nimport { CardIds } from '../services/card-ids';\r\nimport { groupByFunction, pickRandom } from '../services/utils';\r\nimport { addImpliedMechanics, isFish } from '../utils';\r\nimport { applyAfterAttackEffects, applyAfterAttackTrinkets } from './after-attack';\r\nimport { onEntityDamaged } from './damage-effects';\r\nimport { rememberDeathrattles } from './deathrattle-effects';\r\nimport { orchestrateMinionDeathEffects } from './deathrattle-orchestration';\r\nimport { spawnEntities } from './deathrattle-spawns';\r\nimport { FullGameState } from './internal-game-state';\r\nimport { makeMinionsDie } from './minion-death';\r\nimport { onMinionKill } from './minion-kill';\r\nimport { applyOnAttackEffects } from './on-attack';\r\nimport { applyOnBeingAttackedBuffs } from './on-being-attacked';\r\nimport { performEntitySpawns } from './spawns';\r\nimport { applyAfterStatsUpdate } from './stats';\r\nimport { handleSummonsWhenSpace } from './summon-when-space';\r\nimport { canAttack } from './utils/entity-utils';\r\n\r\n// Only use it to simulate actual attack. To simulate damage, or something similar, use bumpInto\r\nexport const simulateAttack = (\r\n\tattackingBoard: BoardEntity[],\r\n\tattackingBoardHero: BgsPlayerEntity,\r\n\tdefendingBoard: BoardEntity[],\r\n\tdefendingBoardHero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n): BoardEntity => {\r\n\t// console.debug(\r\n\t// \t'\\nsimulating attack',\r\n\t// \tstringifySimple(attackingBoard, gameState.allCards),\r\n\t// \t'\\n',\r\n\t// \tstringifySimple(defendingBoard, gameState.allCards),\r\n\t// );\r\n\tif (attackingBoard.length === 0 || defendingBoard.length === 0) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst attackingEntity = getAttackingEntity(attackingBoard, gameState.allCards);\r\n\tif (attackingEntity) {\r\n\t\tgameState.sharedState.currentAttackerEntityId = attackingEntity.entityId;\r\n\t\t// Get the left entities now, otherwise things might break if the attacker dies and/or other\r\n\t\t// entities pop\r\n\t\tconst attackingEntityIndex = attackingBoard.indexOf(attackingEntity);\r\n\t\tconst attackingEntitiesToTheLeft = attackingBoard.slice(0, attackingEntityIndex);\r\n\t\tconst isAttackingImmediately = attackingEntity.attackImmediately;\r\n\t\t// In case of Broodmother spawn, it spawns where the dead minion was, and has no influence on the\r\n\t\t// attack order\r\n\t\t// Situation this is trying to resolve by putting this right at the top of the loop:\r\n\t\t// - One scallywag attacks into another one, both die\r\n\t\t// - The first one attacks. To its left is a Harmless Bonehead with 1 HP. The scallywag attacks, and both scallys die\r\n\t\t// - The *other* sky pirate attacks first, and kills the bonehead. Two minions are spawned\r\n\t\t// - The first sy pirate attacks\r\n\t\t// - The initial loop is resolved. If this is at the end, the Harmless Bonehead is already dead, and not flagged\r\n\t\t// While having this right away, we immediately flag all minions to the left\r\n\t\tif (!isAttackingImmediately) {\r\n\t\t\t// Make sure they won't be able to attack until everyone has attacked\r\n\t\t\t// See http://replays.firestoneapp.com/?reviewId=a1b3066d-e806-44c1-ab4b-7ef9dbf9b5b9&turn=5&action=4\r\n\t\t\tattackingEntitiesToTheLeft.forEach((entity) => (entity.hasAttacked = 2));\r\n\t\t}\r\n\r\n\t\tconst numberOfAttacks = attackingEntity.windfury ? 2 : 1;\r\n\t\tfor (let i = 0; i < numberOfAttacks; i++) {\r\n\t\t\t// We refresh the entity in case of windfury\r\n\t\t\tif (attackingBoard.length === 0 || defendingBoard.length === 0) {\r\n\t\t\t\t// We still want to flag the entity as having attacked, so that it doesn't attack again\r\n\t\t\t\t// after teammate switch in Duos\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t// Check that didn't die\r\n\t\t\tif (attackingBoard.find((entity) => entity.entityId === attackingEntity.entityId)) {\r\n\t\t\t\tconst defendingEntity: BoardEntity = getDefendingEntity(defendingBoard, attackingEntity);\r\n\t\t\t\t// Can happen with a single defender that has stealth\r\n\t\t\t\tif (defendingEntity) {\r\n\t\t\t\t\tdoFullAttack(\r\n\t\t\t\t\t\tattackingEntity,\r\n\t\t\t\t\t\tattackingBoard,\r\n\t\t\t\t\t\tattackingBoardHero,\r\n\t\t\t\t\t\tdefendingEntity,\r\n\t\t\t\t\t\tdefendingBoard,\r\n\t\t\t\t\t\tdefendingBoardHero,\r\n\t\t\t\t\t\tgameState,\r\n\t\t\t\t\t);\r\n\t\t\t\t} else {\r\n\t\t\t\t\t// Solves the edge case of Sky Pirate vs a stealth board\r\n\t\t\t\t\tattackingEntity.attackImmediately = false;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tgameState.sharedState.currentAttackerEntityId = null;\r\n\t\tattackingEntity.hasAttacked = 1;\r\n\t}\r\n\treturn attackingEntity;\r\n};\r\n\r\nexport const doFullAttack = (\r\n\tattackingEntity: BoardEntity,\r\n\tattackingBoard: BoardEntity[],\r\n\tattackingBoardHero: BgsPlayerEntity,\r\n\tdefendingEntity: BoardEntity,\r\n\tdefendingBoard: BoardEntity[],\r\n\tdefendingBoardHero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n) => {\r\n\tconst isAttackingImmediately = attackingEntity.attackImmediately;\r\n\tgameState.spectator.registerAttack(\r\n\t\tattackingEntity,\r\n\t\tdefendingEntity,\r\n\t\tattackingBoard,\r\n\t\tdefendingBoard,\r\n\t\tattackingBoardHero,\r\n\t\tdefendingBoardHero,\r\n\t);\r\n\t// http://replays.firestoneapp.com/?reviewId=50576a9f-2e6a-4600-87ba-6e737ca9853e&turn=21&action=4\r\n\t// Looks like onBeingAttacked effects apply before onAttack effects\r\n\tapplyOnBeingAttackedBuffs(\r\n\t\tattackingEntity,\r\n\t\tattackingBoard,\r\n\t\tattackingBoardHero,\r\n\t\tdefendingEntity,\r\n\t\tdefendingBoard,\r\n\t\tdefendingBoardHero,\r\n\t\tgameState,\r\n\t);\r\n\tconst { damageDoneByAttacker: damageDoneByAttacker1, damageDoneByDefender: damageDoneByDefender1 } =\r\n\t\tapplyOnAttackEffects(\r\n\t\t\tattackingEntity,\r\n\t\t\tattackingBoard,\r\n\t\t\tattackingBoardHero,\r\n\t\t\tdefendingEntity,\r\n\t\t\tdefendingBoard,\r\n\t\t\tdefendingBoardHero,\r\n\t\t\tgameState,\r\n\t\t);\r\n\tconst { damageDoneByAttacker: damageDoneByAttacker2, damageDoneByDefender: damageDoneByDefender2 } = performAttack(\r\n\t\tattackingEntity,\r\n\t\tdefendingEntity,\r\n\t\tattackingBoard,\r\n\t\tattackingBoardHero,\r\n\t\tdefendingBoard,\r\n\t\tdefendingBoardHero,\r\n\t\tgameState,\r\n\t);\r\n\tconst damageDoneByAttacker = damageDoneByAttacker1 + damageDoneByAttacker2;\r\n\tconst damageDoneByDefender = damageDoneByDefender1 + damageDoneByDefender2;\r\n\r\n\t// Process this after the minions die and deathrattles are triggered/spawned\r\n\t// https://replays.firestoneapp.com/?reviewId=dd4e9dbe-abca-434a-ab94-04777cbedefe&turn=29&action=3\r\n\t// BUT: the attacking entity's afterAttack (like Macaw) needs to be processed\r\n\t// To recap:\r\n\t// - Jar o'Gems procs after the deathrattles have spawned\r\n\t// - When Monstrous Macaw procs a deathrattle, it is still on board, thus limiting the spawn room\r\n\t// So not sure what the exact timings are. It could be:\r\n\t// 1. Trigger minion's after attack\r\n\t// 2. Make minions die\r\n\t// 3. Process trinkets after attack\r\n\t// I have asked on Discord - for now I will consider a \"minion after attack\" phase and a \"trinket after attack\" phase.\r\n\t// I'm not sure about the secrets / trinkets, they will need to be adapted\r\n\tapplyAfterAttackEffects(\r\n\t\tattackingEntity,\r\n\t\tattackingBoard,\r\n\t\tattackingBoardHero,\r\n\t\tdefendingEntity,\r\n\t\tdefendingBoard,\r\n\t\tdefendingBoardHero,\r\n\t\tdamageDoneByAttacker,\r\n\t\tdamageDoneByDefender,\r\n\t\tgameState,\r\n\t);\r\n\r\n\tprocessMinionDeath(\r\n\t\tattackingBoard,\r\n\t\tattackingBoardHero,\r\n\t\tdefendingBoard,\r\n\t\tdefendingBoardHero,\r\n\t\tgameState,\r\n\t\tisAttackingImmediately,\r\n\t);\r\n\r\n\tapplyAfterAttackTrinkets(\r\n\t\tattackingEntity,\r\n\t\tattackingBoard,\r\n\t\tattackingBoardHero,\r\n\t\tdefendingEntity,\r\n\t\tdefendingBoard,\r\n\t\tdefendingBoardHero,\r\n\t\tdamageDoneByAttacker,\r\n\t\tdamageDoneByDefender,\r\n\t\tgameState,\r\n\t);\r\n\tapplyAfterStatsUpdate(gameState);\r\n\tattackingEntity.immuneWhenAttackCharges = Math.max(0, (attackingEntity.immuneWhenAttackCharges ?? 0) - 1);\r\n\t// if (\r\n\t// \tdefendingEntity.health > 0 &&\r\n\t// \t!defendingEntity.definitelyDead\r\n\t// \t&& (defendingEntity.cardId === CardIds.YoHoOgre_BGS_060 ||\r\n\t// \t\tdefendingEntity.cardId === CardIds.YoHoOgre_TB_BaconUps_150)\r\n\t// ) {\r\n\t// \tdefendingEntity.attackImmediately = true;\r\n\t// \tif (defendingEntity.attackImmediately) {\r\n\t// \t\tsimulateAttack(defendingBoard, defendingBoardHero, attackingBoard, attackingBoardHero, gameState);\r\n\t// \t}\r\n\t// }\r\n};\r\n\r\nconst performAttack = (\r\n\tattackingEntity: BoardEntity,\r\n\tdefendingEntity: BoardEntity,\r\n\tattackingBoard: BoardEntity[],\r\n\tattackingBoardHero: BgsPlayerEntity,\r\n\tdefendingBoard: BoardEntity[],\r\n\tdefendingBoardHero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n): { damageDoneByAttacker: number; damageDoneByDefender: number } => {\r\n\tlet damageDoneByAttacker = 0;\r\n\tlet damageDoneByDefender = 0;\r\n\r\n\t// if (hasCorrectTribe(attackingEntity, attackingBoardHero, Race.DRAGON, gameState.anomalies, gameState.allCards)) {\r\n\t// \tconst prestors = attackingBoard\r\n\t// \t\t.filter((e) => e.entityId !== attackingEntity.entityId)\r\n\t// \t\t.filter(\r\n\t// \t\t\t(e) =>\r\n\t// \t\t\t\te.cardId === CardIds.PrestorsPyrospawn_BG21_012 ||\r\n\t// \t\t\t\te.cardId === CardIds.PrestorsPyrospawn_BG21_012_G,\r\n\t// \t\t);\r\n\t// \tprestors.forEach((prestor) => {\r\n\t// \t\tgameState.spectator.registerPowerTarget(\r\n\t// \t\t\tprestor,\r\n\t// \t\t\tdefendingEntity,\r\n\t// \t\t\tdefendingBoard,\r\n\t// \t\t\tattackingBoardHero,\r\n\t// \t\t\tdefendingBoardHero,\r\n\t// \t\t);\r\n\t// \t\tdamageDoneByAttacker += dealDamageToMinion(\r\n\t// \t\t\tdefendingEntity,\r\n\t// \t\t\tdefendingBoard,\r\n\t// \t\t\tdefendingBoardHero,\r\n\t// \t\t\tprestor,\r\n\t// \t\t\tprestor.cardId === CardIds.PrestorsPyrospawn_BG21_012_G ? 6 : 3,\r\n\t// \t\t\tattackingBoard,\r\n\t// \t\t\tattackingBoardHero,\r\n\t// \t\t\tgameState,\r\n\t// \t\t);\r\n\t// \t});\r\n\t// }\r\n\t// if (\r\n\t// \tattackingEntity.cardId === CardIds.Atramedes_BG23_362 ||\r\n\t// \tattackingEntity.cardId === CardIds.Atramedes_BG23_362_G\r\n\t// ) {\r\n\t// \tconst targets = [defendingEntity, ...getNeighbours(defendingBoard, defendingEntity)];\r\n\t// \tconst multiplier = attackingEntity.cardId === CardIds.Atramedes_BG23_362_G ? 2 : 1;\r\n\r\n\t// \tfor (let i = 0; i < multiplier; i++) {\r\n\t// \t\ttargets.forEach((target) => {\r\n\t// \t\t\tgameState.spectator.registerPowerTarget(\r\n\t// \t\t\t\tattackingEntity,\r\n\t// \t\t\t\ttarget,\r\n\t// \t\t\t\tdefendingBoard,\r\n\t// \t\t\t\tattackingBoardHero,\r\n\t// \t\t\t\tdefendingBoardHero,\r\n\t// \t\t\t);\r\n\t// \t\t\tdamageDoneByAttacker += dealDamageToMinion(\r\n\t// \t\t\t\ttarget,\r\n\t// \t\t\t\tdefendingBoard,\r\n\t// \t\t\t\tdefendingBoardHero,\r\n\t// \t\t\t\tattackingEntity,\r\n\t// \t\t\t\t3,\r\n\t// \t\t\t\tattackingBoard,\r\n\t// \t\t\t\tattackingBoardHero,\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// } else\r\n\tif ([CardIds.BabyKrush_BG22_001, CardIds.BabyKrush_BG22_001_G].includes(attackingEntity.cardId as CardIds)) {\r\n\t\tconst spawns = spawnEntities(\r\n\t\t\tattackingEntity.cardId === CardIds.BabyKrush_BG22_001_G\r\n\t\t\t\t? CardIds.BabyKrush_BG22_001_G\r\n\t\t\t\t: CardIds.BabyKrush_DevilsaurToken,\r\n\t\t\t1,\r\n\t\t\tattackingBoard,\r\n\t\t\tattackingBoardHero,\r\n\t\t\tdefendingBoard,\r\n\t\t\tdefendingBoardHero,\r\n\t\t\tgameState,\r\n\t\t\ttrue,\r\n\t\t\ttrue,\r\n\t\t);\r\n\t\tif (spawns.length > 0) {\r\n\t\t\tconst sourceIndex = attackingBoard.indexOf(attackingEntity);\r\n\t\t\tconst actualSpawns = performEntitySpawns(\r\n\t\t\t\tspawns,\r\n\t\t\t\tattackingBoard,\r\n\t\t\t\tattackingBoardHero,\r\n\t\t\t\tattackingEntity,\r\n\t\t\t\tsourceIndex,\r\n\t\t\t\tdefendingBoard,\r\n\t\t\t\tdefendingBoardHero,\r\n\t\t\t\tgameState,\r\n\t\t\t);\r\n\t\t\tfor (const actualSpawn of actualSpawns) {\r\n\t\t\t\tif (defendingEntity.health > 0 && !defendingEntity.definitelyDead) {\r\n\t\t\t\t\tperformAttack(\r\n\t\t\t\t\t\tactualSpawn,\r\n\t\t\t\t\t\tdefendingEntity,\r\n\t\t\t\t\t\tattackingBoard,\r\n\t\t\t\t\t\tattackingBoardHero,\r\n\t\t\t\t\t\tdefendingBoard,\r\n\t\t\t\t\t\tdefendingBoardHero,\r\n\t\t\t\t\t\tgameState,\r\n\t\t\t\t\t);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// For Prestor\r\n\tconst defenderAliveBeforeAttack = defendingEntity.health > 0 && !defendingEntity.definitelyDead;\r\n\t// Because of Bristleback Knight, which changes its divine shield status during bumpEntities\r\n\tconst attackerHadDivineShield = attackingEntity.divineShield;\r\n\tconst defenderHadDivineShield = defendingEntity.divineShield;\r\n\t// For cleave\r\n\t// We do that now so that we don't include entities that spawn on entity damaged\r\n\tconst defenderNeighbours: readonly BoardEntity[] = getNeighbours(defendingBoard, defendingEntity);\r\n\tif (defenderAliveBeforeAttack) {\r\n\t\tif (!attackingEntity.immuneWhenAttackCharges) {\r\n\t\t\t// TODO: this bumpEntities approach doesn't work well, as it leads to code duplication\r\n\t\t\tdamageDoneByDefender += bumpEntities(\r\n\t\t\t\tattackingEntity,\r\n\t\t\t\tdefendingEntity,\r\n\t\t\t\tattackingBoard,\r\n\t\t\t\tattackingBoardHero,\r\n\t\t\t\tdefendingBoard,\r\n\t\t\t\tdefendingBoardHero,\r\n\t\t\t\tgameState,\r\n\t\t\t);\r\n\t\t}\r\n\t\tdamageDoneByAttacker += bumpEntities(\r\n\t\t\tdefendingEntity,\r\n\t\t\tattackingEntity,\r\n\t\t\tdefendingBoard,\r\n\t\t\tdefendingBoardHero,\r\n\t\t\tattackingBoard,\r\n\t\t\tattackingBoardHero,\r\n\t\t\tgameState,\r\n\t\t);\r\n\t\tif (defendingEntity.attack > 0 && attackerHadDivineShield && !attackingEntity.immuneWhenAttackCharges) {\r\n\t\t\tupdateDivineShield(\r\n\t\t\t\tattackingEntity,\r\n\t\t\t\tattackingBoard,\r\n\t\t\t\tattackingBoardHero,\r\n\t\t\t\tdefendingBoardHero,\r\n\t\t\t\tfalse,\r\n\t\t\t\tgameState,\r\n\t\t\t);\r\n\t\t}\r\n\t\tif (attackingEntity.attack > 0 && defenderHadDivineShield) {\r\n\t\t\tupdateDivineShield(\r\n\t\t\t\tdefendingEntity,\r\n\t\t\t\tdefendingBoard,\r\n\t\t\t\tdefendingBoardHero,\r\n\t\t\t\tattackingBoardHero,\r\n\t\t\t\tfalse,\r\n\t\t\t\tgameState,\r\n\t\t\t);\r\n\t\t}\r\n\t\t// Do it after the damage has been done, so that entities that update on DS lose / gain (CyborgDrake) don't\r\n\t\t// cause wrong results to happen\r\n\t\t// This whole logic is a MEEEEESSSSSSSSSSSSSSS\r\n\t\tif (damageDoneByDefender > 0) {\r\n\t\t\tonEntityDamaged(\r\n\t\t\t\tattackingEntity,\r\n\t\t\t\tattackingBoard,\r\n\t\t\t\tattackingBoardHero,\r\n\t\t\t\tdefendingBoard,\r\n\t\t\t\tdefendingBoardHero,\r\n\t\t\t\tdefendingEntity,\r\n\t\t\t\tdamageDoneByDefender,\r\n\t\t\t\tgameState,\r\n\t\t\t);\r\n\t\t}\r\n\t\tif (damageDoneByAttacker > 0) {\r\n\t\t\tonEntityDamaged(\r\n\t\t\t\tdefendingEntity,\r\n\t\t\t\tdefendingBoard,\r\n\t\t\t\tdefendingBoardHero,\r\n\t\t\t\tattackingBoard,\r\n\t\t\t\tattackingBoardHero,\r\n\t\t\t\tattackingEntity,\r\n\t\t\t\tdamageDoneByAttacker,\r\n\t\t\t\tgameState,\r\n\t\t\t);\r\n\t\t}\r\n\r\n\t\tif (defendingEntity.health <= 0 || defendingEntity.definitelyDead) {\r\n\t\t\tconst { dmgDoneByAttacker, dmgDoneByDefender } = onMinionKill(\r\n\t\t\t\tattackingEntity,\r\n\t\t\t\ttrue,\r\n\t\t\t\tdefendingEntity,\r\n\t\t\t\tattackingBoard,\r\n\t\t\t\tattackingBoardHero,\r\n\t\t\t\tdefendingBoard,\r\n\t\t\t\tdefendingBoardHero,\r\n\t\t\t\tdefenderNeighbours,\r\n\t\t\t\tgameState,\r\n\t\t\t);\r\n\t\t\tdamageDoneByAttacker += dmgDoneByAttacker;\r\n\t\t\tdamageDoneByDefender += dmgDoneByDefender;\r\n\t\t}\r\n\t\tif (attackingEntity.health <= 0 || attackingEntity.definitelyDead) {\r\n\t\t\tconst { dmgDoneByAttacker, dmgDoneByDefender } = onMinionKill(\r\n\t\t\t\tdefendingEntity,\r\n\t\t\t\tfalse,\r\n\t\t\t\tattackingEntity,\r\n\t\t\t\tdefendingBoard,\r\n\t\t\t\tdefendingBoardHero,\r\n\t\t\t\tattackingBoard,\r\n\t\t\t\tattackingBoardHero,\r\n\t\t\t\tdefenderNeighbours,\r\n\t\t\t\tgameState,\r\n\t\t\t);\r\n\t\t\tdamageDoneByAttacker += dmgDoneByAttacker;\r\n\t\t\tdamageDoneByDefender += dmgDoneByDefender;\r\n\t\t}\r\n\t}\r\n\t// Cleave\r\n\tif (attackingEntity.cleave) {\r\n\t\tfor (const neighbour of defenderNeighbours) {\r\n\t\t\tconst thisAttackDamage = bumpEntities(\r\n\t\t\t\tneighbour,\r\n\t\t\t\tattackingEntity,\r\n\t\t\t\tdefendingBoard,\r\n\t\t\t\tdefendingBoardHero,\r\n\t\t\t\tattackingBoard,\r\n\t\t\t\tattackingBoardHero,\r\n\t\t\t\tgameState,\r\n\t\t\t);\r\n\t\t\tdamageDoneByAttacker += thisAttackDamage;\r\n\t\t\t// Do it after the damage has been done, so that entities that update on DS lose / gain (CyborgDrake) don't\r\n\t\t\t// cause wrong results to happen\r\n\t\t\tif (attackingEntity.attack > 0 && neighbour.divineShield) {\r\n\t\t\t\tupdateDivineShield(neighbour, defendingBoard, defendingBoardHero, attackingBoardHero, false, gameState);\r\n\t\t\t}\r\n\t\t\tif (thisAttackDamage > 0) {\r\n\t\t\t\tonEntityDamaged(\r\n\t\t\t\t\tneighbour,\r\n\t\t\t\t\tdefendingBoard,\r\n\t\t\t\t\tdefendingBoardHero,\r\n\t\t\t\t\tattackingBoard,\r\n\t\t\t\t\tattackingBoardHero,\r\n\t\t\t\t\tattackingEntity,\r\n\t\t\t\t\tthisAttackDamage,\r\n\t\t\t\t\tgameState,\r\n\t\t\t\t);\r\n\t\t\t}\r\n\t\t\tif (neighbour.health <= 0 || neighbour.definitelyDead) {\r\n\t\t\t\tconst { dmgDoneByAttacker, dmgDoneByDefender } = onMinionKill(\r\n\t\t\t\t\tattackingEntity,\r\n\t\t\t\t\ttrue,\r\n\t\t\t\t\tneighbour,\r\n\t\t\t\t\tattackingBoard,\r\n\t\t\t\t\tattackingBoardHero,\r\n\t\t\t\t\tdefendingBoard,\r\n\t\t\t\t\tdefendingBoardHero,\r\n\t\t\t\t\tdefenderNeighbours,\r\n\t\t\t\t\tgameState,\r\n\t\t\t\t);\r\n\t\t\t\tdamageDoneByAttacker += dmgDoneByAttacker;\r\n\t\t\t\tdamageDoneByDefender += dmgDoneByDefender;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tattackingEntity.attackImmediately = false;\r\n\tif (attackingEntity.enchantments.some((e) => e.cardId === CardIds.VolatileVenom_VolatileEnchantment)) {\r\n\t\tattackingEntity.definitelyDead = true;\r\n\t}\r\n\treturn { damageDoneByAttacker, damageDoneByDefender };\r\n};\r\n\r\n// TODO: Could it be possible to store the index of the entity that last attacked? Probably not, because minion\r\n// spawns would mess this up? Could we update the indexes as each entity spawns / dies?\r\nconst getAttackingEntity = (attackingBoard: BoardEntity[], allCards: AllCardsService): BoardEntity => {\r\n\tlet validAttackers = attackingBoard.filter((entity) => canAttack(entity));\r\n\tif (validAttackers.length === 0) {\r\n\t\treturn null;\r\n\t}\r\n\r\n\tif (validAttackers.some((entity) => entity.attackImmediately)) {\r\n\t\tvalidAttackers = validAttackers.filter((entity) => entity.attackImmediately);\r\n\t} else if (validAttackers.every((e) => e.hasAttacked)) {\r\n\t\tattackingBoard.forEach((e) => (e.hasAttacked = 0));\r\n\t} else {\r\n\t\tvalidAttackers = validAttackers.filter((entity) => !entity.hasAttacked);\r\n\t}\r\n\tconst attacker = validAttackers[0];\r\n\tconst attackerName = allCards.getCard(attacker.cardId)?.name;\r\n\treturn attacker;\r\n};\r\n\r\nexport const findNearestEnemies = (\r\n\tattackingBoard: BoardEntity[],\r\n\tentity: BoardEntity,\r\n\tentityIndexFromRight: number,\r\n\tdefendingBoard: BoardEntity[],\r\n\tnumberOfTargets: number,\r\n\tallCards: AllCardsService,\r\n): BoardEntity[] => {\r\n\tconst result = [];\r\n\tif (defendingBoard.length > 0) {\r\n\t\t// console.debug('defending board', numberOfTargets, stringifySimple(defendingBoard, allCards));\r\n\t\tconst attackerIndex = attackingBoard.length - entityIndexFromRight - 1;\r\n\t\tconst targetIndex = attackerIndex - (attackingBoard.length - defendingBoard.length) / 2;\r\n\t\t// console.debug('indexes', attackerIndex, entityIndexFromRight, targetIndex, attackingBoard.length);\r\n\r\n\t\tfor (let i = 0; i < numberOfTargets; i++) {\r\n\t\t\tconst possibleTargets = defendingBoard\r\n\t\t\t\t.filter((e) => !e.definitelyDead && e.health > 0)\r\n\t\t\t\t.filter((e) => !result.includes(e));\r\n\t\t\t// console.debug('possibleTargets', stringifySimple(possibleTargets, allCards));\r\n\t\t\tif (!possibleTargets.length) {\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tconst targetGroups = groupByFunction((e: BoardEntity) => Math.abs(defendingBoard.indexOf(e) - targetIndex))(\r\n\t\t\t\tpossibleTargets,\r\n\t\t\t);\r\n\t\t\tconst distances = Object.keys(targetGroups)\r\n\t\t\t\t.map((k) => +k)\r\n\t\t\t\t.sort();\r\n\t\t\tconst nearestDistance = distances[0];\r\n\t\t\tif (nearestDistance != null) {\r\n\t\t\t\t// console.debug(\r\n\t\t\t\t// \t'targetGroups[nearestDistance]',\r\n\t\t\t\t// \tnearestDistance,\r\n\t\t\t\t// \tstringifySimple(targetGroups[nearestDistance], allCards),\r\n\t\t\t\t// );\r\n\t\t\t\tconst target = pickRandom(targetGroups[nearestDistance]);\r\n\t\t\t\tresult.push(target);\r\n\t\t\t}\r\n\t\t\t// console.debug('\\n');\r\n\t\t}\r\n\t}\r\n\treturn result.filter((e) => !!e);\r\n};\r\n\r\nexport const getNeighbours = (\r\n\tboard: BoardEntity[],\r\n\tentity: BoardEntity,\r\n\tdeadEntityIndexFromRight?: number,\r\n): readonly BoardEntity[] => {\r\n\tconst neighbours = [];\r\n\t// When triggering DR with Hawkstrider, the entity is still on the board\r\n\tif (deadEntityIndexFromRight != null && !board.includes(entity)) {\r\n\t\tconst leftNeighbourIndex = board.length - 1 - deadEntityIndexFromRight;\r\n\t\tconst leftNeighbour = board[leftNeighbourIndex];\r\n\t\tif (leftNeighbour) {\r\n\t\t\tneighbours.push(leftNeighbour);\r\n\t\t}\r\n\r\n\t\t// If the deadEntityIndexFromRight === 0 (right-most minion), no neighbour will be found\r\n\t\tconst rightNeighbourIndex = board.length - 1 - (deadEntityIndexFromRight - 1);\r\n\t\tconst rightNeighbour = board[rightNeighbourIndex];\r\n\t\tif (rightNeighbour) {\r\n\t\t\tneighbours.push(rightNeighbour);\r\n\t\t}\r\n\t} else {\r\n\t\tconst index = board.map((e) => e.entityId).indexOf(entity.entityId);\r\n\t\tif (index - 1 >= 0) {\r\n\t\t\tneighbours.push(board[index - 1]);\r\n\t\t}\r\n\t\t// neighbours.push(entity);\r\n\t\tif (index + 1 < board.length) {\r\n\t\t\tneighbours.push(board[index + 1]);\r\n\t\t}\r\n\t}\r\n\treturn neighbours;\r\n};\r\n\r\nexport const getLeftNeighbour = (\r\n\tboard: BoardEntity[],\r\n\tentity: BoardEntity,\r\n\tdeadEntityIndexFromRight?: number,\r\n): BoardEntity => {\r\n\t// When triggering DR with Hawkstrider, the entity is still on the board\r\n\tif (deadEntityIndexFromRight != null && !board.includes(entity)) {\r\n\t\tconst leftNeighbourIndex = board.length - 1 - deadEntityIndexFromRight;\r\n\t\tconst leftNeighbour = board[leftNeighbourIndex];\r\n\t\tif (leftNeighbour) {\r\n\t\t\treturn leftNeighbour;\r\n\t\t}\r\n\t} else {\r\n\t\tconst index = board.map((e) => e.entityId).indexOf(entity.entityId);\r\n\t\tif (index - 1 >= 0) {\r\n\t\t\treturn board[index - 1];\r\n\t\t}\r\n\t}\r\n\treturn null;\r\n};\r\n\r\nexport const dealDamageToRandomEnemy = (\r\n\tboardToBeDamaged: BoardEntity[],\r\n\tboardToBeDamagedHero: BgsPlayerEntity,\r\n\tdamageSource: BoardEntity,\r\n\tdamage: number,\r\n\tboardWithAttackOrigin: BoardEntity[],\r\n\tboardWithAttackOriginHero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n): void => {\r\n\tif (boardToBeDamaged.length === 0) {\r\n\t\treturn;\r\n\t}\r\n\tconst validTargets = boardToBeDamaged.filter((e) => e.health > 0 && !e.definitelyDead);\r\n\tconst defendingEntity: BoardEntity = pickRandom(validTargets);\r\n\tif (defendingEntity) {\r\n\t\tgameState.spectator.registerPowerTarget(\r\n\t\t\tdamageSource,\r\n\t\t\tdefendingEntity,\r\n\t\t\tboardToBeDamaged,\r\n\t\t\tboardToBeDamagedHero,\r\n\t\t\tboardWithAttackOriginHero,\r\n\t\t);\r\n\t\tdealDamageToMinion(\r\n\t\t\tdefendingEntity,\r\n\t\t\tboardToBeDamaged,\r\n\t\t\tboardToBeDamagedHero,\r\n\t\t\tdamageSource,\r\n\t\t\tdamage,\r\n\t\t\tboardWithAttackOrigin,\r\n\t\t\tboardWithAttackOriginHero,\r\n\t\t\tgameState,\r\n\t\t);\r\n\t}\r\n};\r\n\r\nexport const dealDamageToMinion = (\r\n\ttarget: BoardEntity,\r\n\tboard: BoardEntity[],\r\n\thero: BgsPlayerEntity,\r\n\tdamageSource: BoardEntity | BgsPlayerEntity,\r\n\tdamage: number,\r\n\totherBoard: BoardEntity[],\r\n\totherHero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n): number => {\r\n\t// console.log('dealing damage to', damage, stringifySimpleCard(defendingEntity, allCards));\r\n\tif (!target) {\r\n\t\treturn 0;\r\n\t}\r\n\r\n\tconst isDeadBeforeDamage = target.definitelyDead || target.health <= 0;\r\n\tconst spawns = [];\r\n\t// Why do we use a fakeAttacker? Is that for the \"attacking\" prop?\r\n\t// That prop is only used for Overkill, and even in that case it looks like it would work\r\n\t// without it\r\n\tconst fakeAttacker = {\r\n\t\t...(damageSource || {}),\r\n\t\tentityId: -1,\r\n\t\tattack: damage,\r\n\t\t// attacking: true,\r\n\t} as BoardEntity;\r\n\tconst actualDamageDone = bumpEntities(target, fakeAttacker, board, hero, otherBoard, otherHero, gameState);\r\n\r\n\t// Do it after the damage has been done, so that entities that update on DS lose / gain (CyborgDrake) don't\r\n\t// cause wrong results to happen\r\n\t// TODO: why isn't it done in bumpEntities?\r\n\t// Because of how \"bump\" works: we do it first for the attacker, then the defender, and we only want to update\r\n\t// the divine shield once both bumps are done\r\n\t// The problem is with the Frenzy: bumpEntities can trigger the frenzy, and which can act on the divine shield\r\n\tif (fakeAttacker.attack > 0 && target.divineShield) {\r\n\t\tupdateDivineShield(target, board, hero, otherHero, false, gameState);\r\n\t}\r\n\r\n\tif (actualDamageDone > 0) {\r\n\t\t// TODO: handle entities that have been spawned here to adjust the dead entity index from parent stack\r\n\t\tconst newSpawns = onEntityDamaged(\r\n\t\t\ttarget,\r\n\t\t\tboard,\r\n\t\t\thero,\r\n\t\t\totherBoard,\r\n\t\t\totherHero,\r\n\t\t\tdamageSource,\r\n\t\t\tactualDamageDone,\r\n\t\t\tgameState,\r\n\t\t);\r\n\t}\r\n\tif (!isDeadBeforeDamage && actualDamageDone > 0 && 'attack' in damageSource && 'health' in damageSource) {\r\n\t\ttarget.lastAffectedByEntity = damageSource as BoardEntity;\r\n\r\n\t\tif (target.health <= 0 || target.definitelyDead) {\r\n\t\t\tonMinionKill(damageSource as BoardEntity, false, target, otherBoard, otherHero, board, hero, [], gameState);\r\n\t\t}\r\n\t}\r\n\tconst defendingEntityIndex = board.map((entity) => entity.entityId).indexOf(target.entityId);\r\n\tboard[defendingEntityIndex] = target;\r\n\treturn actualDamageDone;\r\n};\r\n\r\nexport const getDefendingEntity = (\r\n\tdefendingBoard: BoardEntity[],\r\n\tattackingEntity: BoardEntity,\r\n\tignoreTaunts = false,\r\n): BoardEntity => {\r\n\tif (debugState.active) {\r\n\t\tfor (const forcedFaceOff of debugState.forcedFaceOff) {\r\n\t\t\tif (debugState.isCorrectEntity(forcedFaceOff.attacker, attackingEntity)) {\r\n\t\t\t\t// if (attackingEntity.entityId === forcedFaceOff.attacker.entityId) {\r\n\t\t\t\tconst def = defendingBoard.find((e) => debugState.isCorrectEntity(forcedFaceOff.defender, e));\r\n\t\t\t\tif (!!def) {\r\n\t\t\t\t\t// Remove the face-off\r\n\t\t\t\t\tdebugState.forcedFaceOff = debugState.forcedFaceOff.filter((f) => f != forcedFaceOff);\r\n\t\t\t\t\treturn def;\r\n\t\t\t\t}\r\n\t\t\t\t// }\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tlet possibleDefenders: readonly BoardEntity[];\r\n\tif (\r\n\t\tattackingEntity.cardId === CardIds.ZappSlywick_BGS_022 ||\r\n\t\tattackingEntity.cardId === CardIds.ZappSlywick_TB_BaconUps_091 ||\r\n\t\tattackingEntity.cardId === CardIds.MercilessMammoth_BG33_845 ||\r\n\t\tattackingEntity.cardId === CardIds.MercilessMammoth_BG33_845_G\r\n\t) {\r\n\t\tconst minAttack = Math.min(...defendingBoard.map((entity) => entity.attack));\r\n\t\tpossibleDefenders = defendingBoard.filter((entity) => entity.attack === minAttack);\r\n\t} else if (\r\n\t\tattackingEntity.cardId === CardIds.WorgenVigilante_BG26_921 ||\r\n\t\tattackingEntity.cardId === CardIds.WorgenVigilante_BG26_921_G\r\n\t) {\r\n\t\tpossibleDefenders = defendingBoard\r\n\t\t\t.filter(\r\n\t\t\t\t(entity) =>\r\n\t\t\t\t\tentity.health <= attackingEntity.attack || attackingEntity.venomous || attackingEntity.poisonous,\r\n\t\t\t)\r\n\t\t\t.filter((e) => !e.divineShield);\r\n\t\tif (!possibleDefenders.length) {\r\n\t\t\tpossibleDefenders = defendingBoard;\r\n\t\t}\r\n\t} else {\r\n\t\tpossibleDefenders = defendingBoard.filter((e) => !e.stealth);\r\n\t\tif (!ignoreTaunts) {\r\n\t\t\tconst taunts = possibleDefenders.filter((entity) => entity.taunt);\r\n\t\t\tpossibleDefenders = taunts.length > 0 ? taunts : possibleDefenders;\r\n\t\t}\r\n\t}\r\n\r\n\tconst chosenDefender = pickRandom(possibleDefenders);\r\n\t// if (chosenDefender?.taunt) {\r\n\t// \tconst elistras = defendingBoard.filter(\r\n\t// \t\t(entity) =>\r\n\t// \t\t\tentity.cardId === CardIds.ElistraTheImmortal_BGS_205 ||\r\n\t// \t\t\tentity.cardId === CardIds.ElistraTheImmortal_TB_BaconUps_306,\r\n\t// \t);\r\n\t// \tif (elistras.length > 0) {\r\n\t// \t\tchosenDefender = elistras[Math.floor(Math.random() * elistras.length)];\r\n\t// \t}\r\n\t// }\r\n\treturn chosenDefender;\r\n};\r\n\r\nexport const bumpEntities = (\r\n\tentity: BoardEntity,\r\n\tbumpInto: BoardEntity,\r\n\tentityBoard: BoardEntity[],\r\n\tentityBoardHero: BgsPlayerEntity,\r\n\totherBoard: BoardEntity[],\r\n\totherHero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n\tapplyVenomous = true,\r\n): number => {\r\n\t// No attack has no impact\r\n\tconst debug = bumpInto.cardId === 'BG26_888';\r\n\tif (bumpInto.attack === 0) {\r\n\t\treturn 0;\r\n\t}\r\n\r\n\t// Matador effect has priority\r\n\tif (\r\n\t\tentity.abiityChargesLeft > 0 &&\r\n\t\t(entity.cardId === CardIds.MadMatador_BG28_404 || entity.cardId === CardIds.MadMatador_BG28_404_G)\r\n\t) {\r\n\t\tentity.abiityChargesLeft--;\r\n\t\tconst newTarget = pickRandom(otherBoard);\r\n\t\tif (newTarget) {\r\n\t\t\tgameState.spectator.registerPowerTarget(entity, newTarget, otherBoard, entityBoardHero, otherHero);\r\n\t\t\t// TODO: here the MadMatador is the source of the damage, not the initial attacker\r\n\t\t\t// Not sure exactly what the impact would be, as there is no counter\r\n\t\t\tconst newSource = {\r\n\t\t\t\t...entity,\r\n\t\t\t\tattack: bumpInto.attack,\r\n\t\t\t\t// attacking: true,\r\n\t\t\t} as BoardEntity;\r\n\t\t\tconst defenderHadDivineShield = newTarget.divineShield;\r\n\t\t\tconst damageDone = bumpEntities(\r\n\t\t\t\tnewTarget,\r\n\t\t\t\tnewSource,\r\n\t\t\t\totherBoard,\r\n\t\t\t\totherHero,\r\n\t\t\t\tentityBoard,\r\n\t\t\t\tentityBoardHero,\r\n\t\t\t\tgameState,\r\n\t\t\t\tfalse,\r\n\t\t\t);\r\n\t\t\tif (newSource.attack > 0 && defenderHadDivineShield) {\r\n\t\t\t\tupdateDivineShield(newTarget, otherBoard, otherHero, entityBoardHero, false, gameState);\r\n\t\t\t}\r\n\t\t\tif (damageDone > 0) {\r\n\t\t\t\tonEntityDamaged(\r\n\t\t\t\t\tnewTarget,\r\n\t\t\t\t\totherBoard,\r\n\t\t\t\t\totherHero,\r\n\t\t\t\t\tentityBoard,\r\n\t\t\t\t\tentityBoardHero,\r\n\t\t\t\t\tnewSource,\r\n\t\t\t\t\tdamageDone,\r\n\t\t\t\t\tgameState,\r\n\t\t\t\t);\r\n\t\t\t}\r\n\t\t\treturn damageDone;\r\n\t\t}\r\n\t}\r\n\r\n\tif (entity.divineShield) {\r\n\t\tgameState.spectator.registerDamageDealt(bumpInto, entity, 0, entityBoard);\r\n\t\treturn 0;\r\n\t}\r\n\r\n\tconst damageDealt = (entity.damageMultiplier || 1) * bumpInto.attack;\r\n\tentity.health = entity.health - damageDealt;\r\n\t// FIXME: This will likely be incorrect in terms of timings, e.g. if the entity ends up\r\n\t// surviving following a buff like Spawn.\r\n\tgameState.spectator.registerDamageDealt(bumpInto, entity, damageDealt, entityBoard);\r\n\r\n\t// if (entity.cardId === CardIds.Bubblette_BG_TID_713 && bumpInto.attack === 1) {\r\n\t// \tentity.definitelyDead = true;\r\n\t// } else if (entity.cardId === CardIds.Bubblette_BG_TID_713_G && bumpInto.attack === 2) {\r\n\t// \tentity.definitelyDead = true;\r\n\t// }\r\n\t// Do it last, so that other effects are still processed\r\n\tif (bumpInto.poisonous) {\r\n\t\t// So that further buffs don't revive it\r\n\t\t// And we don't just set the health to avoid applying overkill effects\r\n\t\tentity.definitelyDead = true;\r\n\t}\r\n\tif (bumpInto.venomous && applyVenomous) {\r\n\t\t// So that further buffs don't revive it\r\n\t\t// And we don't just set the health to avoid applying overkill effects\r\n\t\tentity.definitelyDead = true;\r\n\t\tupdateVenomous(bumpInto, false, otherBoard, otherHero, entityBoardHero, gameState);\r\n\t}\r\n\t// Ideally we should do the Reckoning stuff here. However, at this point we only have half the damage\r\n\t// information, so it is possible that the entity deals more than 3 (which should trigger Reckoning)\r\n\t// but dies during the exchange (and Reckoning doesn't trigger then)\r\n\r\n\tentity.lastAffectedByEntity = bumpInto;\r\n\t// if (entity.frenzyChargesLeft > 0 && entity.health > 0 && !entity.definitelyDead) {\r\n\t// \tapplyFrenzy(entity, entityBoard, entityBoardHero, gameState);\r\n\t// \tentity.frenzyChargesLeft--;\r\n\t// }\r\n\r\n\t// We spawn them here, because it says \"whenever\", and so happens right away\r\n\t// FIXME: there could be a bug here, if a Cleave attacks several IGB at the same time. The current\r\n\t// implementation could spawn minions above the max board size. Fringe case though, so leaving it\r\n\t// like this for now\r\n\t// const entitySpawns = getWheneverEntitySpawns(\r\n\t// \tentity,\r\n\t// \tentityBoard,\r\n\t// \tentityBoardHero,\r\n\t// \totherBoard,\r\n\t// \totherHero,\r\n\t// \tgameState.allCards,\r\n\t// \tgameState.cardsData,\r\n\t// \tgameState.sharedState,\r\n\t// \tgameState.spectator,\r\n\t// );\r\n\t// if (!!entitySpawns?.length) {\r\n\t// \t// Spawn to the right\r\n\t// \tconst index = entityBoard.map((e) => e.entityId).indexOf(entity.entityId) + 1;\r\n\t// \taddMinionsToBoard(entityBoard, entityBoardHero, otherHero, index, entitySpawns, gameState);\r\n\t// \tgameState.spectator.registerMinionsSpawn(entity, entityBoard, entitySpawns);\r\n\t// }\r\n\treturn bumpInto.attack;\r\n};\r\n\r\n// const getWheneverEntitySpawns = (\r\n// \tentity: BoardEntity,\r\n// \tentityBoard: BoardEntity[],\r\n// \tentityBoardHero: BgsPlayerEntity,\r\n// \totherBoard: BoardEntity[],\r\n// \totherHero: BgsPlayerEntity,\r\n// \tallCards: AllCardsService,\r\n// \tcardsData: CardsData,\r\n// \tsharedState: SharedState,\r\n// \tspectator: Spectator,\r\n// ): readonly BoardEntity[] => {\r\n// \tif (entityBoard.length === 7) {\r\n// \t\treturn null;\r\n// \t}\r\n\r\n// \tif (entity.cardId === CardIds.ImpGangBoss_BRM_006) {\r\n// \t\treturn spawnEntities(\r\n// \t\t\tCardIds.ImpGangBoss_ImpToken_BRM_006t,\r\n// \t\t\t1,\r\n// \t\t\tentityBoard,\r\n// \t\t\tentityBoardHero,\r\n// \t\t\totherBoard,\r\n// \t\t\totherHero,\r\n// \t\t\tallCards,\r\n// \t\t\tcardsData,\r\n// \t\t\tsharedState,\r\n// \t\t\tspectator,\r\n// \t\t\tentity.friendly,\r\n// \t\t\ttrue,\r\n// \t\t);\r\n// \t} else if (entity.cardId === CardIds.ImpGangBoss_TB_BaconUps_030) {\r\n// \t\treturn spawnEntities(\r\n// \t\t\tCardIds.ImpGangBoss_ImpToken_TB_BaconUps_030t,\r\n// \t\t\t1,\r\n// \t\t\tentityBoard,\r\n// \t\t\tentityBoardHero,\r\n// \t\t\totherBoard,\r\n// \t\t\totherHero,\r\n// \t\t\tallCards,\r\n// \t\t\tcardsData,\r\n// \t\t\tsharedState,\r\n// \t\t\tspectator,\r\n// \t\t\tentity.friendly,\r\n// \t\t\ttrue,\r\n// \t\t);\r\n// \t} else if (entity.cardId === CardIds.ImpMama_BGS_044) {\r\n// \t\treturn spawnEntities(\r\n// \t\t\tcardsData.impMamaSpawns[Math.floor(Math.random() * cardsData.impMamaSpawns.length)],\r\n// \t\t\t1,\r\n// \t\t\tentityBoard,\r\n// \t\t\tentityBoardHero,\r\n// \t\t\totherBoard,\r\n// \t\t\totherHero,\r\n// \t\t\tallCards,\r\n// \t\t\tcardsData,\r\n// \t\t\tsharedState,\r\n// \t\t\tspectator,\r\n// \t\t\tentity.friendly,\r\n// \t\t\ttrue,\r\n// \t\t).map((entity) => ({ ...entity, taunt: true }));\r\n// \t} else if (entity.cardId === CardIds.ImpMama_TB_BaconUps_116) {\r\n// \t\treturn spawnEntities(\r\n// \t\t\tcardsData.impMamaSpawns[Math.floor(Math.random() * cardsData.impMamaSpawns.length)],\r\n// \t\t\t2,\r\n// \t\t\tentityBoard,\r\n// \t\t\tentityBoardHero,\r\n// \t\t\totherBoard,\r\n// \t\t\totherHero,\r\n// \t\t\tallCards,\r\n// \t\t\tcardsData,\r\n// \t\t\tsharedState,\r\n// \t\t\tspectator,\r\n// \t\t\tentity.friendly,\r\n// \t\t\ttrue,\r\n// \t\t).map((entity) => ({ ...entity, taunt: true }));\r\n// \t} else if (entity.cardId === CardIds.SecurityRover_BOT_218) {\r\n// \t\treturn spawnEntities(\r\n// \t\t\tCardIds.SecurityRover_GuardBotToken_BOT_218t,\r\n// \t\t\t1,\r\n// \t\t\tentityBoard,\r\n// \t\t\tentityBoardHero,\r\n// \t\t\totherBoard,\r\n// \t\t\totherHero,\r\n// \t\t\tallCards,\r\n// \t\t\tcardsData,\r\n// \t\t\tsharedState,\r\n// \t\t\tspectator,\r\n// \t\t\tentity.friendly,\r\n// \t\t\ttrue,\r\n// \t\t);\r\n// \t} else if (entity.cardId === CardIds.SecurityRover_TB_BaconUps_041) {\r\n// \t\treturn spawnEntities(\r\n// \t\t\tCardIds.SecurityRover_GuardBotToken_TB_BaconUps_041t,\r\n// \t\t\t1,\r\n// \t\t\tentityBoard,\r\n// \t\t\tentityBoardHero,\r\n// \t\t\totherBoard,\r\n// \t\t\totherHero,\r\n// \t\t\tallCards,\r\n// \t\t\tcardsData,\r\n// \t\t\tsharedState,\r\n// \t\t\tspectator,\r\n// \t\t\tentity.friendly,\r\n// \t\t\ttrue,\r\n// \t\t);\r\n// \t}\r\n// \treturn null;\r\n// };\r\n\r\nexport const processMinionDeath = (\r\n\tboard1: BoardEntity[],\r\n\tboard1Hero: BgsPlayerEntity,\r\n\tboard2: BoardEntity[],\r\n\tboard2Hero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n\t// When we're in an \"attack immediately\" phase, we wait until we're out of the phase to summon minions\r\n\tskipSummonWhenSpace = false,\r\n): void => {\r\n\t// const debug = board1.some((e) => e.health <= 0) || board2.some((e) => e.health <= 0);\r\n\t// debug && console.debug('\\nprocessing minions death');\r\n\t// debug && console.debug(stringifySimple(board1, gameState.allCards));\r\n\t// debug && console.debug(stringifySimple(board2, gameState.allCards));\r\n\tconst [deadMinionIndexesFromLeft1, deadMinionIndexesFromRights1, deadEntities1] = makeMinionsDie(\r\n\t\tboard1,\r\n\t\tboard1Hero,\r\n\t\tboard2,\r\n\t\tboard2Hero,\r\n\t\tgameState,\r\n\t);\r\n\tconst [deadMinionIndexesFromLeft2, deadMinionIndexesFromRights2, deadEntities2] = makeMinionsDie(\r\n\t\tboard2,\r\n\t\tboard2Hero,\r\n\t\tboard1,\r\n\t\tboard1Hero,\r\n\t\tgameState,\r\n\t);\r\n\t// debug && console.debug('after processing minions death');\r\n\t// debug && console.debug(stringifySimple(board1, gameState.allCards));\r\n\t// debug && console.debug(stringifySimple(board2, gameState.allCards));\r\n\t// debug && console.debug(deadMinionIndexesFromRights1);\r\n\t// debug && console.debug(deadMinionIndexesFromRights2);\r\n\t// console.debug('dead entities', stringifySimple(deadEntities1, allCards), stringifySimple(deadEntities2, allCards));\r\n\t// No death to process, we can return\r\n\tif (deadEntities1.length === 0 && deadEntities2.length === 0) {\r\n\t\treturn;\r\n\t\t// return [board1, board2];\r\n\t}\r\n\r\n\t// Remember them right away, so that subsequent deaths do not break the order\r\n\t// TODO: move this to the deathrattle-orchestration?\r\n\t// If the fish dies (from Scallywag for instance), it doesn't remember the deathrattle\r\n\t// console.debug(\r\n\t// \t'\\n\\ndeadEntities',\r\n\t// \tstringifySimple(deadEntities1, gameState.allCards),\r\n\t// \tstringifySimple(deadEntities2, gameState.allCards),\r\n\t// );\r\n\tboard1\r\n\t\t.filter((entity) => isFish(entity))\r\n\t\t.forEach((entity) =>\r\n\t\t\trememberDeathrattles(entity, deadEntities1, gameState.cardsData, gameState.allCards, gameState.sharedState),\r\n\t\t);\r\n\tboard2\r\n\t\t.filter((entity) => isFish(entity))\r\n\t\t.forEach((entity) =>\r\n\t\t\trememberDeathrattles(entity, deadEntities2, gameState.cardsData, gameState.allCards, gameState.sharedState),\r\n\t\t);\r\n\r\n\tgameState.spectator.registerDeadEntities(\r\n\t\tdeadMinionIndexesFromRights1,\r\n\t\tdeadEntities1,\r\n\t\tboard1,\r\n\t\tdeadMinionIndexesFromRights2,\r\n\t\tdeadEntities2,\r\n\t\tboard2,\r\n\t);\r\n\tgameState.sharedState.deaths.push(\r\n\t\t...deadEntities1.map((e, index) =>\r\n\t\t\taddImpliedMechanics(\r\n\t\t\t\t{\r\n\t\t\t\t\t...e,\r\n\t\t\t\t\thealth: e.maxHealth,\r\n\t\t\t\t\tdefinitelyDead: false,\r\n\t\t\t\t\tindexFromLeftAtTimeOfDeath: deadMinionIndexesFromLeft1[index],\r\n\t\t\t\t},\r\n\t\t\t\tgameState.cardsData,\r\n\t\t\t),\r\n\t\t),\r\n\t);\r\n\tgameState.sharedState.deaths.push(\r\n\t\t...deadEntities2.map((e, index) =>\r\n\t\t\taddImpliedMechanics(\r\n\t\t\t\t{\r\n\t\t\t\t\t...e,\r\n\t\t\t\t\thealth: e.maxHealth,\r\n\t\t\t\t\tdefinitelyDead: false,\r\n\t\t\t\t\tindexFromLeftAtTimeOfDeath: deadMinionIndexesFromLeft2[index],\r\n\t\t\t\t},\r\n\t\t\t\tgameState.cardsData,\r\n\t\t\t),\r\n\t\t),\r\n\t);\r\n\r\n\tfor (const deadEntity of deadEntities1) {\r\n\t\tconst onDeathImpl = cardMappings[deadEntity.cardId];\r\n\t\tif (hasOnDeath(onDeathImpl)) {\r\n\t\t\tonDeathImpl.onDeath(deadEntity, {\r\n\t\t\t\thero: board1Hero,\r\n\t\t\t\tboard: board1,\r\n\t\t\t\tgameState: gameState,\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\tfor (const deadEntity of deadEntities2) {\r\n\t\tconst onDeathImpl = cardMappings[deadEntity.cardId];\r\n\t\tif (hasOnDeath(onDeathImpl)) {\r\n\t\t\tonDeathImpl.onDeath(deadEntity, {\r\n\t\t\t\thero: board2Hero,\r\n\t\t\t\tboard: board2,\r\n\t\t\t\tgameState: gameState,\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\r\n\tboard1Hero.globalInfo.EternalKnightsDeadThisGame =\r\n\t\tboard1Hero.globalInfo.EternalKnightsDeadThisGame +\r\n\t\tdeadEntities1.filter(\r\n\t\t\t(e) => e.cardId === CardIds.EternalKnight_BG25_008 || e.cardId === CardIds.EternalKnight_BG25_008_G,\r\n\t\t).length;\r\n\tboard2Hero.globalInfo.EternalKnightsDeadThisGame =\r\n\t\tboard2Hero.globalInfo.EternalKnightsDeadThisGame +\r\n\t\tdeadEntities2.filter(\r\n\t\t\t(e) => e.cardId === CardIds.EternalKnight_BG25_008 || e.cardId === CardIds.EternalKnight_BG25_008_G,\r\n\t\t).length;\r\n\r\n\torchestrateMinionDeathEffects({\r\n\t\tgameState: gameState,\r\n\t\tplayerDeadEntities: board1Hero.friendly ? deadEntities1 : deadEntities2,\r\n\t\tplayerDeadEntityIndexesFromRight: board1Hero.friendly\r\n\t\t\t? deadMinionIndexesFromRights1\r\n\t\t\t: deadMinionIndexesFromRights2,\r\n\t\topponentDeadEntities: board1Hero.friendly ? deadEntities2 : deadEntities1,\r\n\t\topponentDeadEntityIndexesFromRight: board1Hero.friendly\r\n\t\t\t? deadMinionIndexesFromRights2\r\n\t\t\t: deadMinionIndexesFromRights1,\r\n\t});\r\n\r\n\t// Make sure we only return when there are no more deaths to process\r\n\t// Make sure to do this right before the end of the process\r\n\t// FIXME: this will propagate the killer between rounds, which is incorrect. For instance,\r\n\t// if a dragon kills a Ghoul, then the Ghoul's deathrattle kills a Kaboom, the killer should\r\n\t// now be the ghoul. Then if the Kaboom kills someone, the killer should again change. You could\r\n\t// also have multiple killers, which is not taken into account here.\r\n\t// The current assumption is that it's a suffienctly fringe case to not matter too much\r\n\tprocessMinionDeath(board1, board1Hero, board2, board2Hero, gameState);\r\n\r\n\t// Not sure about the timing here, but I have bothered Mitchell quite a lot already recently :)\r\n\tif (!skipSummonWhenSpace) {\r\n\t\thandleSummonsWhenSpace(board1, board1Hero, board2, board2Hero, gameState);\r\n\t}\r\n\r\n\t// Apply \"after minion death\" effects\r\n\thandleAfterMinionsDeaths(board1, deadEntities1, board1Hero, board2, deadEntities2, board2Hero, gameState);\r\n};\r\n\r\nconst handleAfterMinionsDeaths = (\r\n\tboard1: BoardEntity[],\r\n\tdeadEntities1: BoardEntity[],\r\n\theroEntity1: BgsPlayerEntity,\r\n\tboard2: BoardEntity[],\r\n\tdeadEntities2: BoardEntity[],\r\n\theroEntity2: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n) => {\r\n\tconst random = Math.random() > 0.5;\r\n\thandleAfterMinionsDeathsForBoard(\r\n\t\trandom ? board1 : board2,\r\n\t\trandom ? deadEntities1 : deadEntities2,\r\n\t\trandom ? heroEntity1 : heroEntity2,\r\n\t\trandom ? board2 : board1,\r\n\t\trandom ? deadEntities2 : deadEntities1,\r\n\t\trandom ? heroEntity2 : heroEntity1,\r\n\t\tgameState,\r\n\t);\r\n\thandleAfterMinionsDeathsForBoard(\r\n\t\t!random ? board1 : board2,\r\n\t\t!random ? deadEntities1 : deadEntities2,\r\n\t\t!random ? heroEntity1 : heroEntity2,\r\n\t\t!random ? board2 : board1,\r\n\t\t!random ? deadEntities2 : deadEntities1,\r\n\t\t!random ? heroEntity2 : heroEntity1,\r\n\t\tgameState,\r\n\t);\r\n};\r\n\r\nconst handleAfterMinionsDeathsForBoard = (\r\n\tfriendlyBoard: BoardEntity[],\r\n\tfriendlyDeadEntities: BoardEntity[],\r\n\tfriendlyHeroEntity: BgsPlayerEntity,\r\n\totherBoard: BoardEntity[],\r\n\totherDeadEntities: BoardEntity[],\r\n\totherHeroEntity: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n) => {\r\n\tconst candidateEntities = [];\r\n\r\n\tfor (const trinket of friendlyHeroEntity.trinkets ?? []) {\r\n\t\tconst onAfterDeathImpl = cardMappings[trinket.cardId];\r\n\t\tif (hasOnAfterDeath(onAfterDeathImpl)) {\r\n\t\t\tonAfterDeathImpl.onAfterDeath(trinket, {\r\n\t\t\t\thero: friendlyHeroEntity,\r\n\t\t\t\tboard: friendlyBoard,\r\n\t\t\t\totherHero: otherHeroEntity,\r\n\t\t\t\totherBoard: otherBoard,\r\n\t\t\t\tdeadEntities: friendlyDeadEntities,\r\n\t\t\t\tgameState: gameState,\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\tfor (const entity of friendlyBoard) {\r\n\t\tconst onAfterDeathImpl = cardMappings[entity.cardId];\r\n\t\tif (hasOnAfterDeath(onAfterDeathImpl)) {\r\n\t\t\tonAfterDeathImpl.onAfterDeath(entity, {\r\n\t\t\t\thero: friendlyHeroEntity,\r\n\t\t\t\tboard: friendlyBoard,\r\n\t\t\t\totherHero: otherHeroEntity,\r\n\t\t\t\totherBoard: otherBoard,\r\n\t\t\t\tdeadEntities: friendlyDeadEntities,\r\n\t\t\t\tgameState: gameState,\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\r\n\tconst secretTriggered = null;\r\n\t// if (\r\n\t// \t(secretTriggered = friendlyHeroEntity.secrets?.find(\r\n\t// \t\t(secret) => !secret.triggered && secret?.cardId === CardIds.MagicBlackSoulstone,\r\n\t// \t)) != null\r\n\t// ) {\r\n\t// \tif (friendlyBoard.length === 0) {\r\n\t// \t\tsecretTriggered.triggered = true;\r\n\t// \t\tfor (let i = 0; i < 2; i++) {\r\n\t// \t\t\tconst toSummon = pickRandom(gameState.cardsData.demonSpawns);\r\n\t// \t\t\tcandidateEntities.push(\r\n\t// \t\t\t\t...spawnEntities(\r\n\t// \t\t\t\t\ttoSummon,\r\n\t// \t\t\t\t\t1,\r\n\t// \t\t\t\t\tfriendlyBoard,\r\n\t// \t\t\t\t\tfriendlyHeroEntity,\r\n\t// \t\t\t\t\totherBoard,\r\n\t// \t\t\t\t\totherHeroEntity,\r\n\t// \t\t\t\t\tgameState,\r\n\t// \t\t\t\t\tfriendlyHeroEntity.friendly,\r\n\t// \t\t\t\t\tfalse,\r\n\t// \t\t\t\t),\r\n\t// \t\t\t);\r\n\t// \t\t}\r\n\t// \t}\r\n\t// }\r\n\tperformEntitySpawns(\r\n\t\tcandidateEntities,\r\n\t\tfriendlyBoard,\r\n\t\tfriendlyHeroEntity,\r\n\t\tsecretTriggered,\r\n\t\t0,\r\n\t\totherBoard,\r\n\t\totherHeroEntity,\r\n\t\tgameState,\r\n\t);\r\n};\r\n\r\nexport interface OnDeathInput {\r\n\treadonly hero: BgsPlayerEntity;\r\n\treadonly board: BoardEntity[];\r\n\treadonly gameState: FullGameState;\r\n}\r\nexport interface OnAfterDeathInput {\r\n\treadonly hero: BgsPlayerEntity;\r\n\treadonly board: BoardEntity[];\r\n\treadonly otherHero: BgsPlayerEntity;\r\n\treadonly otherBoard: BoardEntity[];\r\n\treadonly deadEntities: BoardEntity[];\r\n\treadonly gameState: FullGameState;\r\n}\r\nexport interface OnMinionKilledInput {\r\n\treadonly killer: BoardEntity;\r\n\treadonly killerIsAttacking: boolean;\r\n\treadonly minionKilled: BoardEntity;\r\n\treadonly attackingHero: BgsPlayerEntity;\r\n\treadonly attackingBoard: BoardEntity[];\r\n\treadonly defendingHero: BgsPlayerEntity;\r\n\treadonly defendingBoard: BoardEntity[];\r\n\treadonly defenderNeighbours: readonly BoardEntity[];\r\n\treadonly gameState: FullGameState;\r\n\treadonly playerIsFriendly: boolean;\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"attack.js","sourceRoot":"","sources":["../../src/simulation/attack.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-use-before-define */\r\nimport { AllCardsService } from '@firestone-hs/reference-data';\r\nimport { BgsPlayerEntity } from '../bgs-player-entity';\r\nimport { BoardEntity } from '../board-entity';\r\nimport { hasOnAfterDeath, hasOnDeath } from '../cards/card.interface';\r\nimport { cardMappings } from '../cards/impl/_card-mappings';\r\nimport { debugState } from '../debug-state';\r\nimport { updateDivineShield } from '../keywords/divine-shield';\r\nimport { updateVenomous } from '../keywords/venomous';\r\nimport { CardIds } from '../services/card-ids';\r\nimport { groupByFunction, pickRandom } from '../services/utils';\r\nimport { addImpliedMechanics, isFish } from '../utils';\r\nimport { applyAfterAttackEffects, applyAfterAttackTrinkets } from './after-attack';\r\nimport { onEntityDamaged } from './damage-effects';\r\nimport { rememberDeathrattles } from './deathrattle-effects';\r\nimport { orchestrateMinionDeathEffects } from './deathrattle-orchestration';\r\nimport { spawnEntities } from './deathrattle-spawns';\r\nimport { FullGameState } from './internal-game-state';\r\nimport { makeMinionsDie } from './minion-death';\r\nimport { onMinionKill } from './minion-kill';\r\nimport { applyOnAttackEffects } from './on-attack';\r\nimport { applyOnBeingAttackedBuffs } from './on-being-attacked';\r\nimport { performEntitySpawns } from './spawns';\r\nimport { applyAfterStatsUpdate } from './stats';\r\nimport { handleSummonsWhenSpace } from './summon-when-space';\r\nimport { canAttack } from './utils/entity-utils';\r\n\r\n// Only use it to simulate actual attack. To simulate damage, or something similar, use bumpInto\r\nexport const simulateAttack = (\r\n\tattackingBoard: BoardEntity[],\r\n\tattackingBoardHero: BgsPlayerEntity,\r\n\tdefendingBoard: BoardEntity[],\r\n\tdefendingBoardHero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n): BoardEntity => {\r\n\t// console.debug(\r\n\t// \t'\\nsimulating attack',\r\n\t// \tstringifySimple(attackingBoard, gameState.allCards),\r\n\t// \t'\\n',\r\n\t// \tstringifySimple(defendingBoard, gameState.allCards),\r\n\t// );\r\n\tif (attackingBoard.length === 0 || defendingBoard.length === 0) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst attackingEntity = getAttackingEntity(attackingBoard, gameState.allCards);\r\n\tif (attackingEntity) {\r\n\t\tgameState.sharedState.currentAttackerEntityId = attackingEntity.entityId;\r\n\t\t// Get the left entities now, otherwise things might break if the attacker dies and/or other\r\n\t\t// entities pop\r\n\t\tconst attackingEntityIndex = attackingBoard.indexOf(attackingEntity);\r\n\t\tconst attackingEntitiesToTheLeft = attackingBoard.slice(0, attackingEntityIndex);\r\n\t\tconst isAttackingImmediately = attackingEntity.attackImmediately;\r\n\t\t// In case of Broodmother spawn, it spawns where the dead minion was, and has no influence on the\r\n\t\t// attack order\r\n\t\t// Situation this is trying to resolve by putting this right at the top of the loop:\r\n\t\t// - One scallywag attacks into another one, both die\r\n\t\t// - The first one attacks. To its left is a Harmless Bonehead with 1 HP. The scallywag attacks, and both scallys die\r\n\t\t// - The *other* sky pirate attacks first, and kills the bonehead. Two minions are spawned\r\n\t\t// - The first sy pirate attacks\r\n\t\t// - The initial loop is resolved. If this is at the end, the Harmless Bonehead is already dead, and not flagged\r\n\t\t// While having this right away, we immediately flag all minions to the left\r\n\t\tif (!isAttackingImmediately) {\r\n\t\t\t// Make sure they won't be able to attack until everyone has attacked\r\n\t\t\t// See http://replays.firestoneapp.com/?reviewId=a1b3066d-e806-44c1-ab4b-7ef9dbf9b5b9&turn=5&action=4\r\n\t\t\tattackingEntitiesToTheLeft.forEach((entity) => (entity.hasAttacked = 2));\r\n\t\t} else {\r\n\t\t\t// Change it right away so that new spawns don't trigger the \"attack immediately\" again\r\n\t\t\tattackingEntity.attackImmediately = false;\r\n\t\t}\r\n\r\n\t\tconst numberOfAttacks = attackingEntity.windfury ? 2 : 1;\r\n\t\tfor (let i = 0; i < numberOfAttacks; i++) {\r\n\t\t\t// We refresh the entity in case of windfury\r\n\t\t\tif (attackingBoard.length === 0 || defendingBoard.length === 0) {\r\n\t\t\t\t// We still want to flag the entity as having attacked, so that it doesn't attack again\r\n\t\t\t\t// after teammate switch in Duos\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t// Check that didn't die\r\n\t\t\tif (attackingBoard.find((entity) => entity.entityId === attackingEntity.entityId)) {\r\n\t\t\t\tconst defendingEntity: BoardEntity = getDefendingEntity(defendingBoard, attackingEntity);\r\n\t\t\t\t// Can happen with a single defender that has stealth\r\n\t\t\t\tif (defendingEntity) {\r\n\t\t\t\t\tdoFullAttack(\r\n\t\t\t\t\t\tattackingEntity,\r\n\t\t\t\t\t\tattackingBoard,\r\n\t\t\t\t\t\tattackingBoardHero,\r\n\t\t\t\t\t\tdefendingEntity,\r\n\t\t\t\t\t\tdefendingBoard,\r\n\t\t\t\t\t\tdefendingBoardHero,\r\n\t\t\t\t\t\tgameState,\r\n\t\t\t\t\t);\r\n\t\t\t\t} else {\r\n\t\t\t\t\t// Solves the edge case of Sky Pirate vs a stealth board\r\n\t\t\t\t\tattackingEntity.attackImmediately = false;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tgameState.sharedState.currentAttackerEntityId = null;\r\n\t\tattackingEntity.hasAttacked = 1;\r\n\t}\r\n\treturn attackingEntity;\r\n};\r\n\r\nexport const doFullAttack = (\r\n\tattackingEntity: BoardEntity,\r\n\tattackingBoard: BoardEntity[],\r\n\tattackingBoardHero: BgsPlayerEntity,\r\n\tdefendingEntity: BoardEntity,\r\n\tdefendingBoard: BoardEntity[],\r\n\tdefendingBoardHero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n) => {\r\n\tconst isAttackingImmediately = attackingEntity.attackImmediately;\r\n\tgameState.spectator.registerAttack(\r\n\t\tattackingEntity,\r\n\t\tdefendingEntity,\r\n\t\tattackingBoard,\r\n\t\tdefendingBoard,\r\n\t\tattackingBoardHero,\r\n\t\tdefendingBoardHero,\r\n\t);\r\n\t// http://replays.firestoneapp.com/?reviewId=50576a9f-2e6a-4600-87ba-6e737ca9853e&turn=21&action=4\r\n\t// Looks like onBeingAttacked effects apply before onAttack effects\r\n\tapplyOnBeingAttackedBuffs(\r\n\t\tattackingEntity,\r\n\t\tattackingBoard,\r\n\t\tattackingBoardHero,\r\n\t\tdefendingEntity,\r\n\t\tdefendingBoard,\r\n\t\tdefendingBoardHero,\r\n\t\tgameState,\r\n\t);\r\n\tconst { damageDoneByAttacker: damageDoneByAttacker1, damageDoneByDefender: damageDoneByDefender1 } =\r\n\t\tapplyOnAttackEffects(\r\n\t\t\tattackingEntity,\r\n\t\t\tattackingBoard,\r\n\t\t\tattackingBoardHero,\r\n\t\t\tdefendingEntity,\r\n\t\t\tdefendingBoard,\r\n\t\t\tdefendingBoardHero,\r\n\t\t\tgameState,\r\n\t\t);\r\n\tconst { damageDoneByAttacker: damageDoneByAttacker2, damageDoneByDefender: damageDoneByDefender2 } = performAttack(\r\n\t\tattackingEntity,\r\n\t\tdefendingEntity,\r\n\t\tattackingBoard,\r\n\t\tattackingBoardHero,\r\n\t\tdefendingBoard,\r\n\t\tdefendingBoardHero,\r\n\t\tgameState,\r\n\t);\r\n\tconst damageDoneByAttacker = damageDoneByAttacker1 + damageDoneByAttacker2;\r\n\tconst damageDoneByDefender = damageDoneByDefender1 + damageDoneByDefender2;\r\n\r\n\t// Process this after the minions die and deathrattles are triggered/spawned\r\n\t// https://replays.firestoneapp.com/?reviewId=dd4e9dbe-abca-434a-ab94-04777cbedefe&turn=29&action=3\r\n\t// BUT: the attacking entity's afterAttack (like Macaw) needs to be processed\r\n\t// To recap:\r\n\t// - Jar o'Gems procs after the deathrattles have spawned\r\n\t// - When Monstrous Macaw procs a deathrattle, it is still on board, thus limiting the spawn room\r\n\t// So not sure what the exact timings are. It could be:\r\n\t// 1. Trigger minion's after attack\r\n\t// 2. Make minions die\r\n\t// 3. Process trinkets after attack\r\n\t// I have asked on Discord - for now I will consider a \"minion after attack\" phase and a \"trinket after attack\" phase.\r\n\t// I'm not sure about the secrets / trinkets, they will need to be adapted\r\n\tapplyAfterAttackEffects(\r\n\t\tattackingEntity,\r\n\t\tattackingBoard,\r\n\t\tattackingBoardHero,\r\n\t\tdefendingEntity,\r\n\t\tdefendingBoard,\r\n\t\tdefendingBoardHero,\r\n\t\tdamageDoneByAttacker,\r\n\t\tdamageDoneByDefender,\r\n\t\tgameState,\r\n\t);\r\n\r\n\tprocessMinionDeath(\r\n\t\tattackingBoard,\r\n\t\tattackingBoardHero,\r\n\t\tdefendingBoard,\r\n\t\tdefendingBoardHero,\r\n\t\tgameState,\r\n\t\tisAttackingImmediately,\r\n\t);\r\n\r\n\tapplyAfterAttackTrinkets(\r\n\t\tattackingEntity,\r\n\t\tattackingBoard,\r\n\t\tattackingBoardHero,\r\n\t\tdefendingEntity,\r\n\t\tdefendingBoard,\r\n\t\tdefendingBoardHero,\r\n\t\tdamageDoneByAttacker,\r\n\t\tdamageDoneByDefender,\r\n\t\tgameState,\r\n\t);\r\n\tapplyAfterStatsUpdate(gameState);\r\n\tattackingEntity.immuneWhenAttackCharges = Math.max(0, (attackingEntity.immuneWhenAttackCharges ?? 0) - 1);\r\n\t// if (\r\n\t// \tdefendingEntity.health > 0 &&\r\n\t// \t!defendingEntity.definitelyDead\r\n\t// \t&& (defendingEntity.cardId === CardIds.YoHoOgre_BGS_060 ||\r\n\t// \t\tdefendingEntity.cardId === CardIds.YoHoOgre_TB_BaconUps_150)\r\n\t// ) {\r\n\t// \tdefendingEntity.attackImmediately = true;\r\n\t// \tif (defendingEntity.attackImmediately) {\r\n\t// \t\tsimulateAttack(defendingBoard, defendingBoardHero, attackingBoard, attackingBoardHero, gameState);\r\n\t// \t}\r\n\t// }\r\n};\r\n\r\nconst performAttack = (\r\n\tattackingEntity: BoardEntity,\r\n\tdefendingEntity: BoardEntity,\r\n\tattackingBoard: BoardEntity[],\r\n\tattackingBoardHero: BgsPlayerEntity,\r\n\tdefendingBoard: BoardEntity[],\r\n\tdefendingBoardHero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n): { damageDoneByAttacker: number; damageDoneByDefender: number } => {\r\n\tlet damageDoneByAttacker = 0;\r\n\tlet damageDoneByDefender = 0;\r\n\r\n\t// if (hasCorrectTribe(attackingEntity, attackingBoardHero, Race.DRAGON, gameState.anomalies, gameState.allCards)) {\r\n\t// \tconst prestors = attackingBoard\r\n\t// \t\t.filter((e) => e.entityId !== attackingEntity.entityId)\r\n\t// \t\t.filter(\r\n\t// \t\t\t(e) =>\r\n\t// \t\t\t\te.cardId === CardIds.PrestorsPyrospawn_BG21_012 ||\r\n\t// \t\t\t\te.cardId === CardIds.PrestorsPyrospawn_BG21_012_G,\r\n\t// \t\t);\r\n\t// \tprestors.forEach((prestor) => {\r\n\t// \t\tgameState.spectator.registerPowerTarget(\r\n\t// \t\t\tprestor,\r\n\t// \t\t\tdefendingEntity,\r\n\t// \t\t\tdefendingBoard,\r\n\t// \t\t\tattackingBoardHero,\r\n\t// \t\t\tdefendingBoardHero,\r\n\t// \t\t);\r\n\t// \t\tdamageDoneByAttacker += dealDamageToMinion(\r\n\t// \t\t\tdefendingEntity,\r\n\t// \t\t\tdefendingBoard,\r\n\t// \t\t\tdefendingBoardHero,\r\n\t// \t\t\tprestor,\r\n\t// \t\t\tprestor.cardId === CardIds.PrestorsPyrospawn_BG21_012_G ? 6 : 3,\r\n\t// \t\t\tattackingBoard,\r\n\t// \t\t\tattackingBoardHero,\r\n\t// \t\t\tgameState,\r\n\t// \t\t);\r\n\t// \t});\r\n\t// }\r\n\t// if (\r\n\t// \tattackingEntity.cardId === CardIds.Atramedes_BG23_362 ||\r\n\t// \tattackingEntity.cardId === CardIds.Atramedes_BG23_362_G\r\n\t// ) {\r\n\t// \tconst targets = [defendingEntity, ...getNeighbours(defendingBoard, defendingEntity)];\r\n\t// \tconst multiplier = attackingEntity.cardId === CardIds.Atramedes_BG23_362_G ? 2 : 1;\r\n\r\n\t// \tfor (let i = 0; i < multiplier; i++) {\r\n\t// \t\ttargets.forEach((target) => {\r\n\t// \t\t\tgameState.spectator.registerPowerTarget(\r\n\t// \t\t\t\tattackingEntity,\r\n\t// \t\t\t\ttarget,\r\n\t// \t\t\t\tdefendingBoard,\r\n\t// \t\t\t\tattackingBoardHero,\r\n\t// \t\t\t\tdefendingBoardHero,\r\n\t// \t\t\t);\r\n\t// \t\t\tdamageDoneByAttacker += dealDamageToMinion(\r\n\t// \t\t\t\ttarget,\r\n\t// \t\t\t\tdefendingBoard,\r\n\t// \t\t\t\tdefendingBoardHero,\r\n\t// \t\t\t\tattackingEntity,\r\n\t// \t\t\t\t3,\r\n\t// \t\t\t\tattackingBoard,\r\n\t// \t\t\t\tattackingBoardHero,\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// } else\r\n\tif ([CardIds.BabyKrush_BG22_001, CardIds.BabyKrush_BG22_001_G].includes(attackingEntity.cardId as CardIds)) {\r\n\t\tconst spawns = spawnEntities(\r\n\t\t\tattackingEntity.cardId === CardIds.BabyKrush_BG22_001_G\r\n\t\t\t\t? CardIds.BabyKrush_BG22_001_G\r\n\t\t\t\t: CardIds.BabyKrush_DevilsaurToken,\r\n\t\t\t1,\r\n\t\t\tattackingBoard,\r\n\t\t\tattackingBoardHero,\r\n\t\t\tdefendingBoard,\r\n\t\t\tdefendingBoardHero,\r\n\t\t\tgameState,\r\n\t\t\ttrue,\r\n\t\t\ttrue,\r\n\t\t);\r\n\t\tif (spawns.length > 0) {\r\n\t\t\tconst sourceIndex = attackingBoard.indexOf(attackingEntity);\r\n\t\t\tconst actualSpawns = performEntitySpawns(\r\n\t\t\t\tspawns,\r\n\t\t\t\tattackingBoard,\r\n\t\t\t\tattackingBoardHero,\r\n\t\t\t\tattackingEntity,\r\n\t\t\t\tsourceIndex,\r\n\t\t\t\tdefendingBoard,\r\n\t\t\t\tdefendingBoardHero,\r\n\t\t\t\tgameState,\r\n\t\t\t);\r\n\t\t\tfor (const actualSpawn of actualSpawns) {\r\n\t\t\t\tif (defendingEntity.health > 0 && !defendingEntity.definitelyDead) {\r\n\t\t\t\t\tperformAttack(\r\n\t\t\t\t\t\tactualSpawn,\r\n\t\t\t\t\t\tdefendingEntity,\r\n\t\t\t\t\t\tattackingBoard,\r\n\t\t\t\t\t\tattackingBoardHero,\r\n\t\t\t\t\t\tdefendingBoard,\r\n\t\t\t\t\t\tdefendingBoardHero,\r\n\t\t\t\t\t\tgameState,\r\n\t\t\t\t\t);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// For Prestor\r\n\tconst defenderAliveBeforeAttack = defendingEntity.health > 0 && !defendingEntity.definitelyDead;\r\n\t// Because of Bristleback Knight, which changes its divine shield status during bumpEntities\r\n\tconst attackerHadDivineShield = attackingEntity.divineShield;\r\n\tconst defenderHadDivineShield = defendingEntity.divineShield;\r\n\t// For cleave\r\n\t// We do that now so that we don't include entities that spawn on entity damaged\r\n\tconst defenderNeighbours: readonly BoardEntity[] = getNeighbours(defendingBoard, defendingEntity);\r\n\tif (defenderAliveBeforeAttack) {\r\n\t\tif (!attackingEntity.immuneWhenAttackCharges) {\r\n\t\t\t// TODO: this bumpEntities approach doesn't work well, as it leads to code duplication\r\n\t\t\tdamageDoneByDefender += bumpEntities(\r\n\t\t\t\tattackingEntity,\r\n\t\t\t\tdefendingEntity,\r\n\t\t\t\tattackingBoard,\r\n\t\t\t\tattackingBoardHero,\r\n\t\t\t\tdefendingBoard,\r\n\t\t\t\tdefendingBoardHero,\r\n\t\t\t\tgameState,\r\n\t\t\t);\r\n\t\t}\r\n\t\tdamageDoneByAttacker += bumpEntities(\r\n\t\t\tdefendingEntity,\r\n\t\t\tattackingEntity,\r\n\t\t\tdefendingBoard,\r\n\t\t\tdefendingBoardHero,\r\n\t\t\tattackingBoard,\r\n\t\t\tattackingBoardHero,\r\n\t\t\tgameState,\r\n\t\t);\r\n\t\tif (defendingEntity.attack > 0 && attackerHadDivineShield && !attackingEntity.immuneWhenAttackCharges) {\r\n\t\t\tupdateDivineShield(\r\n\t\t\t\tattackingEntity,\r\n\t\t\t\tattackingBoard,\r\n\t\t\t\tattackingBoardHero,\r\n\t\t\t\tdefendingBoardHero,\r\n\t\t\t\tfalse,\r\n\t\t\t\tgameState,\r\n\t\t\t);\r\n\t\t}\r\n\t\tif (attackingEntity.attack > 0 && defenderHadDivineShield) {\r\n\t\t\tupdateDivineShield(\r\n\t\t\t\tdefendingEntity,\r\n\t\t\t\tdefendingBoard,\r\n\t\t\t\tdefendingBoardHero,\r\n\t\t\t\tattackingBoardHero,\r\n\t\t\t\tfalse,\r\n\t\t\t\tgameState,\r\n\t\t\t);\r\n\t\t}\r\n\t\t// Do it after the damage has been done, so that entities that update on DS lose / gain (CyborgDrake) don't\r\n\t\t// cause wrong results to happen\r\n\t\t// This whole logic is a MEEEEESSSSSSSSSSSSSSS\r\n\t\tif (damageDoneByDefender > 0) {\r\n\t\t\tonEntityDamaged(\r\n\t\t\t\tattackingEntity,\r\n\t\t\t\tattackingBoard,\r\n\t\t\t\tattackingBoardHero,\r\n\t\t\t\tdefendingBoard,\r\n\t\t\t\tdefendingBoardHero,\r\n\t\t\t\tdefendingEntity,\r\n\t\t\t\tdamageDoneByDefender,\r\n\t\t\t\tgameState,\r\n\t\t\t);\r\n\t\t}\r\n\t\tif (damageDoneByAttacker > 0) {\r\n\t\t\tonEntityDamaged(\r\n\t\t\t\tdefendingEntity,\r\n\t\t\t\tdefendingBoard,\r\n\t\t\t\tdefendingBoardHero,\r\n\t\t\t\tattackingBoard,\r\n\t\t\t\tattackingBoardHero,\r\n\t\t\t\tattackingEntity,\r\n\t\t\t\tdamageDoneByAttacker,\r\n\t\t\t\tgameState,\r\n\t\t\t);\r\n\t\t}\r\n\r\n\t\tif (defendingEntity.health <= 0 || defendingEntity.definitelyDead) {\r\n\t\t\tconst { dmgDoneByAttacker, dmgDoneByDefender } = onMinionKill(\r\n\t\t\t\tattackingEntity,\r\n\t\t\t\ttrue,\r\n\t\t\t\tdefendingEntity,\r\n\t\t\t\tattackingBoard,\r\n\t\t\t\tattackingBoardHero,\r\n\t\t\t\tdefendingBoard,\r\n\t\t\t\tdefendingBoardHero,\r\n\t\t\t\tdefenderNeighbours,\r\n\t\t\t\tgameState,\r\n\t\t\t);\r\n\t\t\tdamageDoneByAttacker += dmgDoneByAttacker;\r\n\t\t\tdamageDoneByDefender += dmgDoneByDefender;\r\n\t\t}\r\n\t\tif (attackingEntity.health <= 0 || attackingEntity.definitelyDead) {\r\n\t\t\tconst { dmgDoneByAttacker, dmgDoneByDefender } = onMinionKill(\r\n\t\t\t\tdefendingEntity,\r\n\t\t\t\tfalse,\r\n\t\t\t\tattackingEntity,\r\n\t\t\t\tdefendingBoard,\r\n\t\t\t\tdefendingBoardHero,\r\n\t\t\t\tattackingBoard,\r\n\t\t\t\tattackingBoardHero,\r\n\t\t\t\tdefenderNeighbours,\r\n\t\t\t\tgameState,\r\n\t\t\t);\r\n\t\t\tdamageDoneByAttacker += dmgDoneByAttacker;\r\n\t\t\tdamageDoneByDefender += dmgDoneByDefender;\r\n\t\t}\r\n\t}\r\n\t// Cleave\r\n\tif (attackingEntity.cleave) {\r\n\t\tfor (const neighbour of defenderNeighbours) {\r\n\t\t\tconst thisAttackDamage = bumpEntities(\r\n\t\t\t\tneighbour,\r\n\t\t\t\tattackingEntity,\r\n\t\t\t\tdefendingBoard,\r\n\t\t\t\tdefendingBoardHero,\r\n\t\t\t\tattackingBoard,\r\n\t\t\t\tattackingBoardHero,\r\n\t\t\t\tgameState,\r\n\t\t\t);\r\n\t\t\tdamageDoneByAttacker += thisAttackDamage;\r\n\t\t\t// Do it after the damage has been done, so that entities that update on DS lose / gain (CyborgDrake) don't\r\n\t\t\t// cause wrong results to happen\r\n\t\t\tif (attackingEntity.attack > 0 && neighbour.divineShield) {\r\n\t\t\t\tupdateDivineShield(neighbour, defendingBoard, defendingBoardHero, attackingBoardHero, false, gameState);\r\n\t\t\t}\r\n\t\t\tif (thisAttackDamage > 0) {\r\n\t\t\t\tonEntityDamaged(\r\n\t\t\t\t\tneighbour,\r\n\t\t\t\t\tdefendingBoard,\r\n\t\t\t\t\tdefendingBoardHero,\r\n\t\t\t\t\tattackingBoard,\r\n\t\t\t\t\tattackingBoardHero,\r\n\t\t\t\t\tattackingEntity,\r\n\t\t\t\t\tthisAttackDamage,\r\n\t\t\t\t\tgameState,\r\n\t\t\t\t);\r\n\t\t\t}\r\n\t\t\tif (neighbour.health <= 0 || neighbour.definitelyDead) {\r\n\t\t\t\tconst { dmgDoneByAttacker, dmgDoneByDefender } = onMinionKill(\r\n\t\t\t\t\tattackingEntity,\r\n\t\t\t\t\ttrue,\r\n\t\t\t\t\tneighbour,\r\n\t\t\t\t\tattackingBoard,\r\n\t\t\t\t\tattackingBoardHero,\r\n\t\t\t\t\tdefendingBoard,\r\n\t\t\t\t\tdefendingBoardHero,\r\n\t\t\t\t\tdefenderNeighbours,\r\n\t\t\t\t\tgameState,\r\n\t\t\t\t);\r\n\t\t\t\tdamageDoneByAttacker += dmgDoneByAttacker;\r\n\t\t\t\tdamageDoneByDefender += dmgDoneByDefender;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tattackingEntity.attackImmediately = false;\r\n\tif (attackingEntity.enchantments.some((e) => e.cardId === CardIds.VolatileVenom_VolatileEnchantment)) {\r\n\t\tattackingEntity.definitelyDead = true;\r\n\t}\r\n\treturn { damageDoneByAttacker, damageDoneByDefender };\r\n};\r\n\r\n// TODO: Could it be possible to store the index of the entity that last attacked? Probably not, because minion\r\n// spawns would mess this up? Could we update the indexes as each entity spawns / dies?\r\nconst getAttackingEntity = (attackingBoard: BoardEntity[], allCards: AllCardsService): BoardEntity => {\r\n\tlet validAttackers = attackingBoard.filter((entity) => canAttack(entity));\r\n\tif (validAttackers.length === 0) {\r\n\t\treturn null;\r\n\t}\r\n\r\n\tif (validAttackers.some((entity) => entity.attackImmediately)) {\r\n\t\tvalidAttackers = validAttackers.filter((entity) => entity.attackImmediately);\r\n\t} else if (validAttackers.every((e) => e.hasAttacked)) {\r\n\t\tattackingBoard.forEach((e) => (e.hasAttacked = 0));\r\n\t} else {\r\n\t\tvalidAttackers = validAttackers.filter((entity) => !entity.hasAttacked);\r\n\t}\r\n\tconst attacker = validAttackers[0];\r\n\t// const debug = attacker.cardId === CardIds.Onyxia_OnyxianWhelpToken;\r\n\t// const attackerName = allCards.getCard(attacker.cardId)?.name;\r\n\treturn attacker;\r\n};\r\n\r\nexport const findNearestEnemies = (\r\n\tattackingBoard: BoardEntity[],\r\n\tentity: BoardEntity,\r\n\tentityIndexFromRight: number,\r\n\tdefendingBoard: BoardEntity[],\r\n\tnumberOfTargets: number,\r\n\tallCards: AllCardsService,\r\n): BoardEntity[] => {\r\n\tconst result = [];\r\n\tif (defendingBoard.length > 0) {\r\n\t\t// console.debug('defending board', numberOfTargets, stringifySimple(defendingBoard, allCards));\r\n\t\tconst attackerIndex = attackingBoard.length - entityIndexFromRight - 1;\r\n\t\tconst targetIndex = attackerIndex - (attackingBoard.length - defendingBoard.length) / 2;\r\n\t\t// console.debug('indexes', attackerIndex, entityIndexFromRight, targetIndex, attackingBoard.length);\r\n\r\n\t\tfor (let i = 0; i < numberOfTargets; i++) {\r\n\t\t\tconst possibleTargets = defendingBoard\r\n\t\t\t\t.filter((e) => !e.definitelyDead && e.health > 0)\r\n\t\t\t\t.filter((e) => !result.includes(e));\r\n\t\t\t// console.debug('possibleTargets', stringifySimple(possibleTargets, allCards));\r\n\t\t\tif (!possibleTargets.length) {\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tconst targetGroups = groupByFunction((e: BoardEntity) => Math.abs(defendingBoard.indexOf(e) - targetIndex))(\r\n\t\t\t\tpossibleTargets,\r\n\t\t\t);\r\n\t\t\tconst distances = Object.keys(targetGroups)\r\n\t\t\t\t.map((k) => +k)\r\n\t\t\t\t.sort();\r\n\t\t\tconst nearestDistance = distances[0];\r\n\t\t\tif (nearestDistance != null) {\r\n\t\t\t\t// console.debug(\r\n\t\t\t\t// \t'targetGroups[nearestDistance]',\r\n\t\t\t\t// \tnearestDistance,\r\n\t\t\t\t// \tstringifySimple(targetGroups[nearestDistance], allCards),\r\n\t\t\t\t// );\r\n\t\t\t\tconst target = pickRandom(targetGroups[nearestDistance]);\r\n\t\t\t\tresult.push(target);\r\n\t\t\t}\r\n\t\t\t// console.debug('\\n');\r\n\t\t}\r\n\t}\r\n\treturn result.filter((e) => !!e);\r\n};\r\n\r\nexport const getNeighbours = (\r\n\tboard: BoardEntity[],\r\n\tentity: BoardEntity,\r\n\tdeadEntityIndexFromRight?: number,\r\n): readonly BoardEntity[] => {\r\n\tconst neighbours = [];\r\n\t// When triggering DR with Hawkstrider, the entity is still on the board\r\n\tif (deadEntityIndexFromRight != null && !board.includes(entity)) {\r\n\t\tconst leftNeighbourIndex = board.length - 1 - deadEntityIndexFromRight;\r\n\t\tconst leftNeighbour = board[leftNeighbourIndex];\r\n\t\tif (leftNeighbour) {\r\n\t\t\tneighbours.push(leftNeighbour);\r\n\t\t}\r\n\r\n\t\t// If the deadEntityIndexFromRight === 0 (right-most minion), no neighbour will be found\r\n\t\tconst rightNeighbourIndex = board.length - 1 - (deadEntityIndexFromRight - 1);\r\n\t\tconst rightNeighbour = board[rightNeighbourIndex];\r\n\t\tif (rightNeighbour) {\r\n\t\t\tneighbours.push(rightNeighbour);\r\n\t\t}\r\n\t} else {\r\n\t\tconst index = board.map((e) => e.entityId).indexOf(entity.entityId);\r\n\t\tif (index - 1 >= 0) {\r\n\t\t\tneighbours.push(board[index - 1]);\r\n\t\t}\r\n\t\t// neighbours.push(entity);\r\n\t\tif (index + 1 < board.length) {\r\n\t\t\tneighbours.push(board[index + 1]);\r\n\t\t}\r\n\t}\r\n\treturn neighbours;\r\n};\r\n\r\nexport const getLeftNeighbour = (\r\n\tboard: BoardEntity[],\r\n\tentity: BoardEntity,\r\n\tdeadEntityIndexFromRight?: number,\r\n): BoardEntity => {\r\n\t// When triggering DR with Hawkstrider, the entity is still on the board\r\n\tif (deadEntityIndexFromRight != null && !board.includes(entity)) {\r\n\t\tconst leftNeighbourIndex = board.length - 1 - deadEntityIndexFromRight;\r\n\t\tconst leftNeighbour = board[leftNeighbourIndex];\r\n\t\tif (leftNeighbour) {\r\n\t\t\treturn leftNeighbour;\r\n\t\t}\r\n\t} else {\r\n\t\tconst index = board.map((e) => e.entityId).indexOf(entity.entityId);\r\n\t\tif (index - 1 >= 0) {\r\n\t\t\treturn board[index - 1];\r\n\t\t}\r\n\t}\r\n\treturn null;\r\n};\r\n\r\nexport const dealDamageToRandomEnemy = (\r\n\tboardToBeDamaged: BoardEntity[],\r\n\tboardToBeDamagedHero: BgsPlayerEntity,\r\n\tdamageSource: BoardEntity,\r\n\tdamage: number,\r\n\tboardWithAttackOrigin: BoardEntity[],\r\n\tboardWithAttackOriginHero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n): void => {\r\n\tif (boardToBeDamaged.length === 0) {\r\n\t\treturn;\r\n\t}\r\n\tconst validTargets = boardToBeDamaged.filter((e) => e.health > 0 && !e.definitelyDead);\r\n\tconst defendingEntity: BoardEntity = pickRandom(validTargets);\r\n\tif (defendingEntity) {\r\n\t\tgameState.spectator.registerPowerTarget(\r\n\t\t\tdamageSource,\r\n\t\t\tdefendingEntity,\r\n\t\t\tboardToBeDamaged,\r\n\t\t\tboardToBeDamagedHero,\r\n\t\t\tboardWithAttackOriginHero,\r\n\t\t);\r\n\t\tdealDamageToMinion(\r\n\t\t\tdefendingEntity,\r\n\t\t\tboardToBeDamaged,\r\n\t\t\tboardToBeDamagedHero,\r\n\t\t\tdamageSource,\r\n\t\t\tdamage,\r\n\t\t\tboardWithAttackOrigin,\r\n\t\t\tboardWithAttackOriginHero,\r\n\t\t\tgameState,\r\n\t\t);\r\n\t}\r\n};\r\n\r\nexport const dealDamageToMinion = (\r\n\ttarget: BoardEntity,\r\n\tboard: BoardEntity[],\r\n\thero: BgsPlayerEntity,\r\n\tdamageSource: BoardEntity | BgsPlayerEntity,\r\n\tdamage: number,\r\n\totherBoard: BoardEntity[],\r\n\totherHero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n): number => {\r\n\t// console.log('dealing damage to', damage, stringifySimpleCard(defendingEntity, allCards));\r\n\tif (!target) {\r\n\t\treturn 0;\r\n\t}\r\n\r\n\tconst isDeadBeforeDamage = target.definitelyDead || target.health <= 0;\r\n\tconst spawns = [];\r\n\t// Why do we use a fakeAttacker? Is that for the \"attacking\" prop?\r\n\t// That prop is only used for Overkill, and even in that case it looks like it would work\r\n\t// without it\r\n\tconst fakeAttacker = {\r\n\t\t...(damageSource || {}),\r\n\t\tentityId: -1,\r\n\t\tattack: damage,\r\n\t\t// attacking: true,\r\n\t} as BoardEntity;\r\n\tconst actualDamageDone = bumpEntities(target, fakeAttacker, board, hero, otherBoard, otherHero, gameState);\r\n\r\n\t// Do it after the damage has been done, so that entities that update on DS lose / gain (CyborgDrake) don't\r\n\t// cause wrong results to happen\r\n\t// TODO: why isn't it done in bumpEntities?\r\n\t// Because of how \"bump\" works: we do it first for the attacker, then the defender, and we only want to update\r\n\t// the divine shield once both bumps are done\r\n\t// The problem is with the Frenzy: bumpEntities can trigger the frenzy, and which can act on the divine shield\r\n\tif (fakeAttacker.attack > 0 && target.divineShield) {\r\n\t\tupdateDivineShield(target, board, hero, otherHero, false, gameState);\r\n\t}\r\n\r\n\tif (actualDamageDone > 0) {\r\n\t\t// TODO: handle entities that have been spawned here to adjust the dead entity index from parent stack\r\n\t\tconst newSpawns = onEntityDamaged(\r\n\t\t\ttarget,\r\n\t\t\tboard,\r\n\t\t\thero,\r\n\t\t\totherBoard,\r\n\t\t\totherHero,\r\n\t\t\tdamageSource,\r\n\t\t\tactualDamageDone,\r\n\t\t\tgameState,\r\n\t\t);\r\n\t}\r\n\tif (!isDeadBeforeDamage && actualDamageDone > 0 && 'attack' in damageSource && 'health' in damageSource) {\r\n\t\ttarget.lastAffectedByEntity = damageSource as BoardEntity;\r\n\r\n\t\tif (target.health <= 0 || target.definitelyDead) {\r\n\t\t\tonMinionKill(damageSource as BoardEntity, false, target, otherBoard, otherHero, board, hero, [], gameState);\r\n\t\t}\r\n\t}\r\n\tconst defendingEntityIndex = board.map((entity) => entity.entityId).indexOf(target.entityId);\r\n\tboard[defendingEntityIndex] = target;\r\n\treturn actualDamageDone;\r\n};\r\n\r\nexport const getDefendingEntity = (\r\n\tdefendingBoard: BoardEntity[],\r\n\tattackingEntity: BoardEntity,\r\n\tignoreTaunts = false,\r\n): BoardEntity => {\r\n\tif (debugState.active) {\r\n\t\tfor (const forcedFaceOff of debugState.forcedFaceOff) {\r\n\t\t\tif (debugState.isCorrectEntity(forcedFaceOff.attacker, attackingEntity)) {\r\n\t\t\t\t// if (attackingEntity.entityId === forcedFaceOff.attacker.entityId) {\r\n\t\t\t\tconst def = defendingBoard.find((e) => debugState.isCorrectEntity(forcedFaceOff.defender, e));\r\n\t\t\t\tif (!!def) {\r\n\t\t\t\t\t// Remove the face-off\r\n\t\t\t\t\tdebugState.forcedFaceOff = debugState.forcedFaceOff.filter((f) => f != forcedFaceOff);\r\n\t\t\t\t\treturn def;\r\n\t\t\t\t}\r\n\t\t\t\t// }\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tlet possibleDefenders: readonly BoardEntity[];\r\n\tif (\r\n\t\tattackingEntity.cardId === CardIds.ZappSlywick_BGS_022 ||\r\n\t\tattackingEntity.cardId === CardIds.ZappSlywick_TB_BaconUps_091 ||\r\n\t\tattackingEntity.cardId === CardIds.MercilessMammoth_BG33_845 ||\r\n\t\tattackingEntity.cardId === CardIds.MercilessMammoth_BG33_845_G\r\n\t) {\r\n\t\tconst minAttack = Math.min(...defendingBoard.map((entity) => entity.attack));\r\n\t\tpossibleDefenders = defendingBoard.filter((entity) => entity.attack === minAttack);\r\n\t} else if (\r\n\t\tattackingEntity.cardId === CardIds.WorgenVigilante_BG26_921 ||\r\n\t\tattackingEntity.cardId === CardIds.WorgenVigilante_BG26_921_G\r\n\t) {\r\n\t\tpossibleDefenders = defendingBoard\r\n\t\t\t.filter(\r\n\t\t\t\t(entity) =>\r\n\t\t\t\t\tentity.health <= attackingEntity.attack || attackingEntity.venomous || attackingEntity.poisonous,\r\n\t\t\t)\r\n\t\t\t.filter((e) => !e.divineShield);\r\n\t\tif (!possibleDefenders.length) {\r\n\t\t\tpossibleDefenders = defendingBoard;\r\n\t\t}\r\n\t} else {\r\n\t\tpossibleDefenders = defendingBoard.filter((e) => !e.stealth);\r\n\t\tif (!ignoreTaunts) {\r\n\t\t\tconst taunts = possibleDefenders.filter((entity) => entity.taunt);\r\n\t\t\tpossibleDefenders = taunts.length > 0 ? taunts : possibleDefenders;\r\n\t\t}\r\n\t}\r\n\r\n\tconst chosenDefender = pickRandom(possibleDefenders);\r\n\t// if (chosenDefender?.taunt) {\r\n\t// \tconst elistras = defendingBoard.filter(\r\n\t// \t\t(entity) =>\r\n\t// \t\t\tentity.cardId === CardIds.ElistraTheImmortal_BGS_205 ||\r\n\t// \t\t\tentity.cardId === CardIds.ElistraTheImmortal_TB_BaconUps_306,\r\n\t// \t);\r\n\t// \tif (elistras.length > 0) {\r\n\t// \t\tchosenDefender = elistras[Math.floor(Math.random() * elistras.length)];\r\n\t// \t}\r\n\t// }\r\n\treturn chosenDefender;\r\n};\r\n\r\nexport const bumpEntities = (\r\n\tentity: BoardEntity,\r\n\tbumpInto: BoardEntity,\r\n\tentityBoard: BoardEntity[],\r\n\tentityBoardHero: BgsPlayerEntity,\r\n\totherBoard: BoardEntity[],\r\n\totherHero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n\tapplyVenomous = true,\r\n): number => {\r\n\t// No attack has no impact\r\n\tconst debug = bumpInto.cardId === 'BG26_888';\r\n\tif (bumpInto.attack === 0) {\r\n\t\treturn 0;\r\n\t}\r\n\r\n\t// Matador effect has priority\r\n\tif (\r\n\t\tentity.abiityChargesLeft > 0 &&\r\n\t\t(entity.cardId === CardIds.MadMatador_BG28_404 || entity.cardId === CardIds.MadMatador_BG28_404_G)\r\n\t) {\r\n\t\tentity.abiityChargesLeft--;\r\n\t\tconst newTarget = pickRandom(otherBoard);\r\n\t\tif (newTarget) {\r\n\t\t\tgameState.spectator.registerPowerTarget(entity, newTarget, otherBoard, entityBoardHero, otherHero);\r\n\t\t\t// TODO: here the MadMatador is the source of the damage, not the initial attacker\r\n\t\t\t// Not sure exactly what the impact would be, as there is no counter\r\n\t\t\tconst newSource = {\r\n\t\t\t\t...entity,\r\n\t\t\t\tattack: bumpInto.attack,\r\n\t\t\t\t// attacking: true,\r\n\t\t\t} as BoardEntity;\r\n\t\t\tconst defenderHadDivineShield = newTarget.divineShield;\r\n\t\t\tconst damageDone = bumpEntities(\r\n\t\t\t\tnewTarget,\r\n\t\t\t\tnewSource,\r\n\t\t\t\totherBoard,\r\n\t\t\t\totherHero,\r\n\t\t\t\tentityBoard,\r\n\t\t\t\tentityBoardHero,\r\n\t\t\t\tgameState,\r\n\t\t\t\tfalse,\r\n\t\t\t);\r\n\t\t\tif (newSource.attack > 0 && defenderHadDivineShield) {\r\n\t\t\t\tupdateDivineShield(newTarget, otherBoard, otherHero, entityBoardHero, false, gameState);\r\n\t\t\t}\r\n\t\t\tif (damageDone > 0) {\r\n\t\t\t\tonEntityDamaged(\r\n\t\t\t\t\tnewTarget,\r\n\t\t\t\t\totherBoard,\r\n\t\t\t\t\totherHero,\r\n\t\t\t\t\tentityBoard,\r\n\t\t\t\t\tentityBoardHero,\r\n\t\t\t\t\tnewSource,\r\n\t\t\t\t\tdamageDone,\r\n\t\t\t\t\tgameState,\r\n\t\t\t\t);\r\n\t\t\t}\r\n\t\t\treturn damageDone;\r\n\t\t}\r\n\t}\r\n\r\n\tif (entity.divineShield) {\r\n\t\tgameState.spectator.registerDamageDealt(bumpInto, entity, 0, entityBoard);\r\n\t\treturn 0;\r\n\t}\r\n\r\n\tconst damageDealt = (entity.damageMultiplier || 1) * bumpInto.attack;\r\n\tentity.health = entity.health - damageDealt;\r\n\t// FIXME: This will likely be incorrect in terms of timings, e.g. if the entity ends up\r\n\t// surviving following a buff like Spawn.\r\n\tgameState.spectator.registerDamageDealt(bumpInto, entity, damageDealt, entityBoard);\r\n\r\n\t// if (entity.cardId === CardIds.Bubblette_BG_TID_713 && bumpInto.attack === 1) {\r\n\t// \tentity.definitelyDead = true;\r\n\t// } else if (entity.cardId === CardIds.Bubblette_BG_TID_713_G && bumpInto.attack === 2) {\r\n\t// \tentity.definitelyDead = true;\r\n\t// }\r\n\t// Do it last, so that other effects are still processed\r\n\tif (bumpInto.poisonous) {\r\n\t\t// So that further buffs don't revive it\r\n\t\t// And we don't just set the health to avoid applying overkill effects\r\n\t\tentity.definitelyDead = true;\r\n\t}\r\n\tif (bumpInto.venomous && applyVenomous) {\r\n\t\t// So that further buffs don't revive it\r\n\t\t// And we don't just set the health to avoid applying overkill effects\r\n\t\tentity.definitelyDead = true;\r\n\t\tupdateVenomous(bumpInto, false, otherBoard, otherHero, entityBoardHero, gameState);\r\n\t}\r\n\t// Ideally we should do the Reckoning stuff here. However, at this point we only have half the damage\r\n\t// information, so it is possible that the entity deals more than 3 (which should trigger Reckoning)\r\n\t// but dies during the exchange (and Reckoning doesn't trigger then)\r\n\r\n\tentity.lastAffectedByEntity = bumpInto;\r\n\t// if (entity.frenzyChargesLeft > 0 && entity.health > 0 && !entity.definitelyDead) {\r\n\t// \tapplyFrenzy(entity, entityBoard, entityBoardHero, gameState);\r\n\t// \tentity.frenzyChargesLeft--;\r\n\t// }\r\n\r\n\t// We spawn them here, because it says \"whenever\", and so happens right away\r\n\t// FIXME: there could be a bug here, if a Cleave attacks several IGB at the same time. The current\r\n\t// implementation could spawn minions above the max board size. Fringe case though, so leaving it\r\n\t// like this for now\r\n\t// const entitySpawns = getWheneverEntitySpawns(\r\n\t// \tentity,\r\n\t// \tentityBoard,\r\n\t// \tentityBoardHero,\r\n\t// \totherBoard,\r\n\t// \totherHero,\r\n\t// \tgameState.allCards,\r\n\t// \tgameState.cardsData,\r\n\t// \tgameState.sharedState,\r\n\t// \tgameState.spectator,\r\n\t// );\r\n\t// if (!!entitySpawns?.length) {\r\n\t// \t// Spawn to the right\r\n\t// \tconst index = entityBoard.map((e) => e.entityId).indexOf(entity.entityId) + 1;\r\n\t// \taddMinionsToBoard(entityBoard, entityBoardHero, otherHero, index, entitySpawns, gameState);\r\n\t// \tgameState.spectator.registerMinionsSpawn(entity, entityBoard, entitySpawns);\r\n\t// }\r\n\treturn bumpInto.attack;\r\n};\r\n\r\n// const getWheneverEntitySpawns = (\r\n// \tentity: BoardEntity,\r\n// \tentityBoard: BoardEntity[],\r\n// \tentityBoardHero: BgsPlayerEntity,\r\n// \totherBoard: BoardEntity[],\r\n// \totherHero: BgsPlayerEntity,\r\n// \tallCards: AllCardsService,\r\n// \tcardsData: CardsData,\r\n// \tsharedState: SharedState,\r\n// \tspectator: Spectator,\r\n// ): readonly BoardEntity[] => {\r\n// \tif (entityBoard.length === 7) {\r\n// \t\treturn null;\r\n// \t}\r\n\r\n// \tif (entity.cardId === CardIds.ImpGangBoss_BRM_006) {\r\n// \t\treturn spawnEntities(\r\n// \t\t\tCardIds.ImpGangBoss_ImpToken_BRM_006t,\r\n// \t\t\t1,\r\n// \t\t\tentityBoard,\r\n// \t\t\tentityBoardHero,\r\n// \t\t\totherBoard,\r\n// \t\t\totherHero,\r\n// \t\t\tallCards,\r\n// \t\t\tcardsData,\r\n// \t\t\tsharedState,\r\n// \t\t\tspectator,\r\n// \t\t\tentity.friendly,\r\n// \t\t\ttrue,\r\n// \t\t);\r\n// \t} else if (entity.cardId === CardIds.ImpGangBoss_TB_BaconUps_030) {\r\n// \t\treturn spawnEntities(\r\n// \t\t\tCardIds.ImpGangBoss_ImpToken_TB_BaconUps_030t,\r\n// \t\t\t1,\r\n// \t\t\tentityBoard,\r\n// \t\t\tentityBoardHero,\r\n// \t\t\totherBoard,\r\n// \t\t\totherHero,\r\n// \t\t\tallCards,\r\n// \t\t\tcardsData,\r\n// \t\t\tsharedState,\r\n// \t\t\tspectator,\r\n// \t\t\tentity.friendly,\r\n// \t\t\ttrue,\r\n// \t\t);\r\n// \t} else if (entity.cardId === CardIds.ImpMama_BGS_044) {\r\n// \t\treturn spawnEntities(\r\n// \t\t\tcardsData.impMamaSpawns[Math.floor(Math.random() * cardsData.impMamaSpawns.length)],\r\n// \t\t\t1,\r\n// \t\t\tentityBoard,\r\n// \t\t\tentityBoardHero,\r\n// \t\t\totherBoard,\r\n// \t\t\totherHero,\r\n// \t\t\tallCards,\r\n// \t\t\tcardsData,\r\n// \t\t\tsharedState,\r\n// \t\t\tspectator,\r\n// \t\t\tentity.friendly,\r\n// \t\t\ttrue,\r\n// \t\t).map((entity) => ({ ...entity, taunt: true }));\r\n// \t} else if (entity.cardId === CardIds.ImpMama_TB_BaconUps_116) {\r\n// \t\treturn spawnEntities(\r\n// \t\t\tcardsData.impMamaSpawns[Math.floor(Math.random() * cardsData.impMamaSpawns.length)],\r\n// \t\t\t2,\r\n// \t\t\tentityBoard,\r\n// \t\t\tentityBoardHero,\r\n// \t\t\totherBoard,\r\n// \t\t\totherHero,\r\n// \t\t\tallCards,\r\n// \t\t\tcardsData,\r\n// \t\t\tsharedState,\r\n// \t\t\tspectator,\r\n// \t\t\tentity.friendly,\r\n// \t\t\ttrue,\r\n// \t\t).map((entity) => ({ ...entity, taunt: true }));\r\n// \t} else if (entity.cardId === CardIds.SecurityRover_BOT_218) {\r\n// \t\treturn spawnEntities(\r\n// \t\t\tCardIds.SecurityRover_GuardBotToken_BOT_218t,\r\n// \t\t\t1,\r\n// \t\t\tentityBoard,\r\n// \t\t\tentityBoardHero,\r\n// \t\t\totherBoard,\r\n// \t\t\totherHero,\r\n// \t\t\tallCards,\r\n// \t\t\tcardsData,\r\n// \t\t\tsharedState,\r\n// \t\t\tspectator,\r\n// \t\t\tentity.friendly,\r\n// \t\t\ttrue,\r\n// \t\t);\r\n// \t} else if (entity.cardId === CardIds.SecurityRover_TB_BaconUps_041) {\r\n// \t\treturn spawnEntities(\r\n// \t\t\tCardIds.SecurityRover_GuardBotToken_TB_BaconUps_041t,\r\n// \t\t\t1,\r\n// \t\t\tentityBoard,\r\n// \t\t\tentityBoardHero,\r\n// \t\t\totherBoard,\r\n// \t\t\totherHero,\r\n// \t\t\tallCards,\r\n// \t\t\tcardsData,\r\n// \t\t\tsharedState,\r\n// \t\t\tspectator,\r\n// \t\t\tentity.friendly,\r\n// \t\t\ttrue,\r\n// \t\t);\r\n// \t}\r\n// \treturn null;\r\n// };\r\n\r\nexport const processMinionDeath = (\r\n\tboard1: BoardEntity[],\r\n\tboard1Hero: BgsPlayerEntity,\r\n\tboard2: BoardEntity[],\r\n\tboard2Hero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n\t// When we're in an \"attack immediately\" phase, we wait until we're out of the phase to summon minions\r\n\tskipSummonWhenSpace = false,\r\n): void => {\r\n\t// const debug = board1.some((e) => e.health <= 0) || board2.some((e) => e.health <= 0);\r\n\t// debug && console.debug('\\nprocessing minions death');\r\n\t// debug && console.debug(stringifySimple(board1, gameState.allCards));\r\n\t// debug && console.debug(stringifySimple(board2, gameState.allCards));\r\n\tconst [deadMinionIndexesFromLeft1, deadMinionIndexesFromRights1, deadEntities1] = makeMinionsDie(\r\n\t\tboard1,\r\n\t\tboard1Hero,\r\n\t\tboard2,\r\n\t\tboard2Hero,\r\n\t\tgameState,\r\n\t);\r\n\tconst [deadMinionIndexesFromLeft2, deadMinionIndexesFromRights2, deadEntities2] = makeMinionsDie(\r\n\t\tboard2,\r\n\t\tboard2Hero,\r\n\t\tboard1,\r\n\t\tboard1Hero,\r\n\t\tgameState,\r\n\t);\r\n\t// debug && console.debug('after processing minions death');\r\n\t// debug && console.debug(stringifySimple(board1, gameState.allCards));\r\n\t// debug && console.debug(stringifySimple(board2, gameState.allCards));\r\n\t// debug && console.debug(deadMinionIndexesFromRights1);\r\n\t// debug && console.debug(deadMinionIndexesFromRights2);\r\n\t// console.debug('dead entities', stringifySimple(deadEntities1, allCards), stringifySimple(deadEntities2, allCards));\r\n\t// No death to process, we can return\r\n\tif (deadEntities1.length === 0 && deadEntities2.length === 0) {\r\n\t\treturn;\r\n\t\t// return [board1, board2];\r\n\t}\r\n\r\n\t// Remember them right away, so that subsequent deaths do not break the order\r\n\t// TODO: move this to the deathrattle-orchestration?\r\n\t// If the fish dies (from Scallywag for instance), it doesn't remember the deathrattle\r\n\t// console.debug(\r\n\t// \t'\\n\\ndeadEntities',\r\n\t// \tstringifySimple(deadEntities1, gameState.allCards),\r\n\t// \tstringifySimple(deadEntities2, gameState.allCards),\r\n\t// );\r\n\tboard1\r\n\t\t.filter((entity) => isFish(entity))\r\n\t\t.forEach((entity) =>\r\n\t\t\trememberDeathrattles(entity, deadEntities1, gameState.cardsData, gameState.allCards, gameState.sharedState),\r\n\t\t);\r\n\tboard2\r\n\t\t.filter((entity) => isFish(entity))\r\n\t\t.forEach((entity) =>\r\n\t\t\trememberDeathrattles(entity, deadEntities2, gameState.cardsData, gameState.allCards, gameState.sharedState),\r\n\t\t);\r\n\r\n\tgameState.spectator.registerDeadEntities(\r\n\t\tdeadMinionIndexesFromRights1,\r\n\t\tdeadEntities1,\r\n\t\tboard1,\r\n\t\tdeadMinionIndexesFromRights2,\r\n\t\tdeadEntities2,\r\n\t\tboard2,\r\n\t);\r\n\tgameState.sharedState.deaths.push(\r\n\t\t...deadEntities1.map((e, index) =>\r\n\t\t\taddImpliedMechanics(\r\n\t\t\t\t{\r\n\t\t\t\t\t...e,\r\n\t\t\t\t\thealth: e.maxHealth,\r\n\t\t\t\t\tdefinitelyDead: false,\r\n\t\t\t\t\tindexFromLeftAtTimeOfDeath: deadMinionIndexesFromLeft1[index],\r\n\t\t\t\t},\r\n\t\t\t\tgameState.cardsData,\r\n\t\t\t),\r\n\t\t),\r\n\t);\r\n\tgameState.sharedState.deaths.push(\r\n\t\t...deadEntities2.map((e, index) =>\r\n\t\t\taddImpliedMechanics(\r\n\t\t\t\t{\r\n\t\t\t\t\t...e,\r\n\t\t\t\t\thealth: e.maxHealth,\r\n\t\t\t\t\tdefinitelyDead: false,\r\n\t\t\t\t\tindexFromLeftAtTimeOfDeath: deadMinionIndexesFromLeft2[index],\r\n\t\t\t\t},\r\n\t\t\t\tgameState.cardsData,\r\n\t\t\t),\r\n\t\t),\r\n\t);\r\n\r\n\tfor (const deadEntity of deadEntities1) {\r\n\t\tconst onDeathImpl = cardMappings[deadEntity.cardId];\r\n\t\tif (hasOnDeath(onDeathImpl)) {\r\n\t\t\tonDeathImpl.onDeath(deadEntity, {\r\n\t\t\t\thero: board1Hero,\r\n\t\t\t\tboard: board1,\r\n\t\t\t\tgameState: gameState,\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\tfor (const deadEntity of deadEntities2) {\r\n\t\tconst onDeathImpl = cardMappings[deadEntity.cardId];\r\n\t\tif (hasOnDeath(onDeathImpl)) {\r\n\t\t\tonDeathImpl.onDeath(deadEntity, {\r\n\t\t\t\thero: board2Hero,\r\n\t\t\t\tboard: board2,\r\n\t\t\t\tgameState: gameState,\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\r\n\tboard1Hero.globalInfo.EternalKnightsDeadThisGame =\r\n\t\tboard1Hero.globalInfo.EternalKnightsDeadThisGame +\r\n\t\tdeadEntities1.filter(\r\n\t\t\t(e) => e.cardId === CardIds.EternalKnight_BG25_008 || e.cardId === CardIds.EternalKnight_BG25_008_G,\r\n\t\t).length;\r\n\tboard2Hero.globalInfo.EternalKnightsDeadThisGame =\r\n\t\tboard2Hero.globalInfo.EternalKnightsDeadThisGame +\r\n\t\tdeadEntities2.filter(\r\n\t\t\t(e) => e.cardId === CardIds.EternalKnight_BG25_008 || e.cardId === CardIds.EternalKnight_BG25_008_G,\r\n\t\t).length;\r\n\r\n\torchestrateMinionDeathEffects({\r\n\t\tgameState: gameState,\r\n\t\tplayerDeadEntities: board1Hero.friendly ? deadEntities1 : deadEntities2,\r\n\t\tplayerDeadEntityIndexesFromRight: board1Hero.friendly\r\n\t\t\t? deadMinionIndexesFromRights1\r\n\t\t\t: deadMinionIndexesFromRights2,\r\n\t\topponentDeadEntities: board1Hero.friendly ? deadEntities2 : deadEntities1,\r\n\t\topponentDeadEntityIndexesFromRight: board1Hero.friendly\r\n\t\t\t? deadMinionIndexesFromRights2\r\n\t\t\t: deadMinionIndexesFromRights1,\r\n\t});\r\n\r\n\t// Make sure we only return when there are no more deaths to process\r\n\t// Make sure to do this right before the end of the process\r\n\t// FIXME: this will propagate the killer between rounds, which is incorrect. For instance,\r\n\t// if a dragon kills a Ghoul, then the Ghoul's deathrattle kills a Kaboom, the killer should\r\n\t// now be the ghoul. Then if the Kaboom kills someone, the killer should again change. You could\r\n\t// also have multiple killers, which is not taken into account here.\r\n\t// The current assumption is that it's a suffienctly fringe case to not matter too much\r\n\tprocessMinionDeath(board1, board1Hero, board2, board2Hero, gameState);\r\n\r\n\t// Not sure about the timing here, but I have bothered Mitchell quite a lot already recently :)\r\n\tif (!skipSummonWhenSpace) {\r\n\t\thandleSummonsWhenSpace(board1, board1Hero, board2, board2Hero, gameState);\r\n\t}\r\n\r\n\t// Apply \"after minion death\" effects\r\n\thandleAfterMinionsDeaths(board1, deadEntities1, board1Hero, board2, deadEntities2, board2Hero, gameState);\r\n};\r\n\r\nconst handleAfterMinionsDeaths = (\r\n\tboard1: BoardEntity[],\r\n\tdeadEntities1: BoardEntity[],\r\n\theroEntity1: BgsPlayerEntity,\r\n\tboard2: BoardEntity[],\r\n\tdeadEntities2: BoardEntity[],\r\n\theroEntity2: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n) => {\r\n\tconst random = Math.random() > 0.5;\r\n\thandleAfterMinionsDeathsForBoard(\r\n\t\trandom ? board1 : board2,\r\n\t\trandom ? deadEntities1 : deadEntities2,\r\n\t\trandom ? heroEntity1 : heroEntity2,\r\n\t\trandom ? board2 : board1,\r\n\t\trandom ? deadEntities2 : deadEntities1,\r\n\t\trandom ? heroEntity2 : heroEntity1,\r\n\t\tgameState,\r\n\t);\r\n\thandleAfterMinionsDeathsForBoard(\r\n\t\t!random ? board1 : board2,\r\n\t\t!random ? deadEntities1 : deadEntities2,\r\n\t\t!random ? heroEntity1 : heroEntity2,\r\n\t\t!random ? board2 : board1,\r\n\t\t!random ? deadEntities2 : deadEntities1,\r\n\t\t!random ? heroEntity2 : heroEntity1,\r\n\t\tgameState,\r\n\t);\r\n};\r\n\r\nconst handleAfterMinionsDeathsForBoard = (\r\n\tfriendlyBoard: BoardEntity[],\r\n\tfriendlyDeadEntities: BoardEntity[],\r\n\tfriendlyHeroEntity: BgsPlayerEntity,\r\n\totherBoard: BoardEntity[],\r\n\totherDeadEntities: BoardEntity[],\r\n\totherHeroEntity: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n) => {\r\n\tconst candidateEntities = [];\r\n\r\n\tfor (const trinket of friendlyHeroEntity.trinkets ?? []) {\r\n\t\tconst onAfterDeathImpl = cardMappings[trinket.cardId];\r\n\t\tif (hasOnAfterDeath(onAfterDeathImpl)) {\r\n\t\t\tonAfterDeathImpl.onAfterDeath(trinket, {\r\n\t\t\t\thero: friendlyHeroEntity,\r\n\t\t\t\tboard: friendlyBoard,\r\n\t\t\t\totherHero: otherHeroEntity,\r\n\t\t\t\totherBoard: otherBoard,\r\n\t\t\t\tdeadEntities: friendlyDeadEntities,\r\n\t\t\t\tgameState: gameState,\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\tfor (const entity of friendlyBoard) {\r\n\t\tconst onAfterDeathImpl = cardMappings[entity.cardId];\r\n\t\tif (hasOnAfterDeath(onAfterDeathImpl)) {\r\n\t\t\tonAfterDeathImpl.onAfterDeath(entity, {\r\n\t\t\t\thero: friendlyHeroEntity,\r\n\t\t\t\tboard: friendlyBoard,\r\n\t\t\t\totherHero: otherHeroEntity,\r\n\t\t\t\totherBoard: otherBoard,\r\n\t\t\t\tdeadEntities: friendlyDeadEntities,\r\n\t\t\t\tgameState: gameState,\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\r\n\tconst secretTriggered = null;\r\n\t// if (\r\n\t// \t(secretTriggered = friendlyHeroEntity.secrets?.find(\r\n\t// \t\t(secret) => !secret.triggered && secret?.cardId === CardIds.MagicBlackSoulstone,\r\n\t// \t)) != null\r\n\t// ) {\r\n\t// \tif (friendlyBoard.length === 0) {\r\n\t// \t\tsecretTriggered.triggered = true;\r\n\t// \t\tfor (let i = 0; i < 2; i++) {\r\n\t// \t\t\tconst toSummon = pickRandom(gameState.cardsData.demonSpawns);\r\n\t// \t\t\tcandidateEntities.push(\r\n\t// \t\t\t\t...spawnEntities(\r\n\t// \t\t\t\t\ttoSummon,\r\n\t// \t\t\t\t\t1,\r\n\t// \t\t\t\t\tfriendlyBoard,\r\n\t// \t\t\t\t\tfriendlyHeroEntity,\r\n\t// \t\t\t\t\totherBoard,\r\n\t// \t\t\t\t\totherHeroEntity,\r\n\t// \t\t\t\t\tgameState,\r\n\t// \t\t\t\t\tfriendlyHeroEntity.friendly,\r\n\t// \t\t\t\t\tfalse,\r\n\t// \t\t\t\t),\r\n\t// \t\t\t);\r\n\t// \t\t}\r\n\t// \t}\r\n\t// }\r\n\tperformEntitySpawns(\r\n\t\tcandidateEntities,\r\n\t\tfriendlyBoard,\r\n\t\tfriendlyHeroEntity,\r\n\t\tsecretTriggered,\r\n\t\t0,\r\n\t\totherBoard,\r\n\t\totherHeroEntity,\r\n\t\tgameState,\r\n\t);\r\n};\r\n\r\nexport interface OnDeathInput {\r\n\treadonly hero: BgsPlayerEntity;\r\n\treadonly board: BoardEntity[];\r\n\treadonly gameState: FullGameState;\r\n}\r\nexport interface OnAfterDeathInput {\r\n\treadonly hero: BgsPlayerEntity;\r\n\treadonly board: BoardEntity[];\r\n\treadonly otherHero: BgsPlayerEntity;\r\n\treadonly otherBoard: BoardEntity[];\r\n\treadonly deadEntities: BoardEntity[];\r\n\treadonly gameState: FullGameState;\r\n}\r\nexport interface OnMinionKilledInput {\r\n\treadonly killer: BoardEntity;\r\n\treadonly killerIsAttacking: boolean;\r\n\treadonly minionKilled: BoardEntity;\r\n\treadonly attackingHero: BgsPlayerEntity;\r\n\treadonly attackingBoard: BoardEntity[];\r\n\treadonly defendingHero: BgsPlayerEntity;\r\n\treadonly defendingBoard: BoardEntity[];\r\n\treadonly defenderNeighbours: readonly BoardEntity[];\r\n\treadonly gameState: FullGameState;\r\n\treadonly playerIsFriendly: boolean;\r\n}\r\n"]}
|
|
@@ -20,6 +20,9 @@ const handlePackTactics = (defendingEntity, defendingBoard, defendingPlayerEntit
|
|
|
20
20
|
const candidateEntities = (0, deathrattle_spawns_1.spawnEntities)(defendingEntity.cardId, 1, defendingBoard, defendingPlayerEntity, attackerBoard, attackerHero, gameState, defendingEntity.friendly, false, false, true, { ...defendingEntity });
|
|
21
21
|
const indexFromRight = defendingBoard.length - (defendingBoard.indexOf(defendingEntity) + 1);
|
|
22
22
|
const spawned = (0, spawns_1.performEntitySpawns)(candidateEntities, defendingBoard, defendingPlayerEntity, defendingEntity, indexFromRight, attackerBoard, attackerHero, gameState);
|
|
23
|
+
spawned.forEach((e) => {
|
|
24
|
+
e.hasAttacked = defendingEntity.hasAttacked;
|
|
25
|
+
});
|
|
23
26
|
if (secretCardId === "TB_Bacon_Secrets_15") {
|
|
24
27
|
spawned.forEach((e) => (0, stats_1.setEntityStats)(e, 3, 3, defendingBoard, defendingPlayerEntity, gameState));
|
|
25
28
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secrets.js","sourceRoot":"","sources":["../../src/simulation/secrets.ts"],"names":[],"mappings":";;;AAGA,6DAAqD;AAErD,qCAA+C;AAC/C,mCAAyC;AAElC,MAAM,oBAAoB,GAAG,CACnC,eAA4B,EAC5B,cAA6B,EAC7B,qBAAsC,EACtC,aAA4B,EAC5B,YAA6B,EAC7B,SAAwB,EACjB,EAAE;IACT,MAAM,IAAI,GAAgB;QACzB,GAAG,eAAe;QAClB,MAAM,EAAE,CAAC;QACT,MAAM,EAAE,CAAC;QACT,SAAS,EAAE,CAAC;KACZ,CAAC;IACF,MAAM,iBAAiB,GAAG,IAAA,kCAAa,EACtC,eAAe,CAAC,MAAM,EACtB,CAAC,EACD,cAAc,EACd,qBAAqB,EACrB,aAAa,EACb,YAAY,EACZ,SAAS,EACT,eAAe,CAAC,QAAQ,EACxB,KAAK,EACL,KAAK,EACL,IAAI,EACJ,IAAI,CACJ,CAAC;IACF,MAAM,cAAc,GAAG,cAAc,CAAC,MAAM,GAAG,CAAC,cAAc,CAAC,OAAO,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7F,IAAA,4BAAmB,EAClB,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,eAAe,EACf,cAAc,EACd,aAAa,EACb,YAAY,EACZ,SAAS,CACT,CAAC;AACH,CAAC,CAAC;AAvCW,QAAA,oBAAoB,wBAuC/B;AAEK,MAAM,iBAAiB,GAAG,CAChC,eAA4B,EAC5B,cAA6B,EAC7B,qBAAsC,EACtC,aAA4B,EAC5B,YAA6B,EAC7B,SAAwB,EACxB,YAAoB,EACb,EAAE;IACT,MAAM,iBAAiB,GAAG,IAAA,kCAAa,EACtC,eAAe,CAAC,MAAM,EACtB,CAAC,EACD,cAAc,EACd,qBAAqB,EACrB,aAAa,EACb,YAAY,EACZ,SAAS,EACT,eAAe,CAAC,QAAQ,EACxB,KAAK,EACL,KAAK,EACL,IAAI,EACJ,EAAE,GAAG,eAAe,EAAE,CACtB,CAAC;IACF,MAAM,cAAc,GAAG,cAAc,CAAC,MAAM,GAAG,CAAC,cAAc,CAAC,OAAO,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7F,MAAM,OAAO,GAAG,IAAA,4BAAmB,EAClC,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,eAAe,EACf,cAAc,EACd,aAAa,EACb,YAAY,EACZ,SAAS,CACT,CAAC;IACF,IAAI,YAAY,0BAA4C,EAAE;QAC7D,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAA,sBAAc,EAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,cAAc,EAAE,qBAAqB,EAAE,SAAS,CAAC,CAAC,CAAC;KAClG;AACF,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"secrets.js","sourceRoot":"","sources":["../../src/simulation/secrets.ts"],"names":[],"mappings":";;;AAGA,6DAAqD;AAErD,qCAA+C;AAC/C,mCAAyC;AAElC,MAAM,oBAAoB,GAAG,CACnC,eAA4B,EAC5B,cAA6B,EAC7B,qBAAsC,EACtC,aAA4B,EAC5B,YAA6B,EAC7B,SAAwB,EACjB,EAAE;IACT,MAAM,IAAI,GAAgB;QACzB,GAAG,eAAe;QAClB,MAAM,EAAE,CAAC;QACT,MAAM,EAAE,CAAC;QACT,SAAS,EAAE,CAAC;KACZ,CAAC;IACF,MAAM,iBAAiB,GAAG,IAAA,kCAAa,EACtC,eAAe,CAAC,MAAM,EACtB,CAAC,EACD,cAAc,EACd,qBAAqB,EACrB,aAAa,EACb,YAAY,EACZ,SAAS,EACT,eAAe,CAAC,QAAQ,EACxB,KAAK,EACL,KAAK,EACL,IAAI,EACJ,IAAI,CACJ,CAAC;IACF,MAAM,cAAc,GAAG,cAAc,CAAC,MAAM,GAAG,CAAC,cAAc,CAAC,OAAO,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7F,IAAA,4BAAmB,EAClB,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,eAAe,EACf,cAAc,EACd,aAAa,EACb,YAAY,EACZ,SAAS,CACT,CAAC;AACH,CAAC,CAAC;AAvCW,QAAA,oBAAoB,wBAuC/B;AAEK,MAAM,iBAAiB,GAAG,CAChC,eAA4B,EAC5B,cAA6B,EAC7B,qBAAsC,EACtC,aAA4B,EAC5B,YAA6B,EAC7B,SAAwB,EACxB,YAAoB,EACb,EAAE;IACT,MAAM,iBAAiB,GAAG,IAAA,kCAAa,EACtC,eAAe,CAAC,MAAM,EACtB,CAAC,EACD,cAAc,EACd,qBAAqB,EACrB,aAAa,EACb,YAAY,EACZ,SAAS,EACT,eAAe,CAAC,QAAQ,EACxB,KAAK,EACL,KAAK,EACL,IAAI,EACJ,EAAE,GAAG,eAAe,EAAE,CACtB,CAAC;IACF,MAAM,cAAc,GAAG,cAAc,CAAC,MAAM,GAAG,CAAC,cAAc,CAAC,OAAO,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7F,MAAM,OAAO,GAAG,IAAA,4BAAmB,EAClC,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,eAAe,EACf,cAAc,EACd,aAAa,EACb,YAAY,EACZ,SAAS,CACT,CAAC;IACF,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;QAGrB,CAAC,CAAC,WAAW,GAAG,eAAe,CAAC,WAAW,CAAC;IAC7C,CAAC,CAAC,CAAC;IACH,IAAI,YAAY,0BAA4C,EAAE;QAC7D,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAA,sBAAc,EAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,cAAc,EAAE,qBAAqB,EAAE,SAAS,CAAC,CAAC,CAAC;KAClG;AACF,CAAC,CAAC;AA1CW,QAAA,iBAAiB,qBA0C5B;AAEK,MAAM,eAAe,GAAG,CAC9B,eAA4B,EAC5B,cAA6B,EAC7B,qBAAsC,EACtC,aAA4B,EAC5B,YAA6B,EAC7B,SAAwB,EACjB,EAAE;IACT,MAAM,iBAAiB,GAA2B,IAAA,kCAAa,cAE9D,CAAC,EACD,cAAc,EACd,qBAAqB,EACrB,aAAa,EACb,YAAY,EACZ,SAAS,EACT,eAAe,CAAC,QAAQ,EACxB,KAAK,CACL,CAAC;IACF,IAAA,4BAAmB,EAClB,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,eAAe,EACf,CAAC,EACD,aAAa,EACb,YAAY,EACZ,SAAS,CACT,CAAC;AACH,CAAC,CAAC;AA7BW,QAAA,eAAe,mBA6B1B;AAEK,MAAM,qBAAqB,GAAG,CACpC,eAA4B,EAC5B,cAA6B,EAC7B,qBAAsC,EACtC,aAA4B,EAC5B,YAA6B,EAC7B,SAAwB,EACvB,EAAE;IACH,MAAM,iBAAiB,GAA2B,IAAA,kCAAa,gBAE9D,CAAC,EACD,cAAc,EACd,qBAAqB,EACrB,aAAa,EACb,YAAY,EACZ,SAAS,EACT,eAAe,CAAC,QAAQ,EACxB,KAAK,CACL,CAAC;IACF,MAAM,MAAM,GAAG,IAAA,4BAAmB,EACjC,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,eAAe,EACf,CAAC,EACD,aAAa,EACb,YAAY,EACZ,SAAS,CACT,CAAC;IACF,OAAO,MAAM,CAAC;AACf,CAAC,CAAC;AA9BW,QAAA,qBAAqB,yBA8BhC","sourcesContent":["import { BgsPlayerEntity } from '../bgs-player-entity';\r\nimport { BoardEntity } from '../board-entity';\r\nimport { CardIds } from '../services/card-ids';\r\nimport { spawnEntities } from './deathrattle-spawns';\r\nimport { FullGameState } from './internal-game-state';\r\nimport { performEntitySpawns } from './spawns';\r\nimport { setEntityStats } from './stats';\r\n\r\nexport const handleSplittingImage = (\r\n\tdefendingEntity: BoardEntity,\r\n\tdefendingBoard: BoardEntity[],\r\n\tdefendingPlayerEntity: BgsPlayerEntity,\r\n\tattackerBoard: BoardEntity[],\r\n\tattackerHero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n): void => {\r\n\tconst copy: BoardEntity = {\r\n\t\t...defendingEntity,\r\n\t\tattack: 3,\r\n\t\thealth: 3,\r\n\t\tmaxHealth: 3,\r\n\t};\r\n\tconst candidateEntities = spawnEntities(\r\n\t\tdefendingEntity.cardId,\r\n\t\t1,\r\n\t\tdefendingBoard,\r\n\t\tdefendingPlayerEntity,\r\n\t\tattackerBoard,\r\n\t\tattackerHero,\r\n\t\tgameState,\r\n\t\tdefendingEntity.friendly,\r\n\t\tfalse,\r\n\t\tfalse,\r\n\t\ttrue,\r\n\t\tcopy,\r\n\t);\r\n\tconst indexFromRight = defendingBoard.length - (defendingBoard.indexOf(defendingEntity) + 1);\r\n\tperformEntitySpawns(\r\n\t\tcandidateEntities,\r\n\t\tdefendingBoard,\r\n\t\tdefendingPlayerEntity,\r\n\t\tdefendingEntity,\r\n\t\tindexFromRight,\r\n\t\tattackerBoard,\r\n\t\tattackerHero,\r\n\t\tgameState,\r\n\t);\r\n};\r\n\r\nexport const handlePackTactics = (\r\n\tdefendingEntity: BoardEntity,\r\n\tdefendingBoard: BoardEntity[],\r\n\tdefendingPlayerEntity: BgsPlayerEntity,\r\n\tattackerBoard: BoardEntity[],\r\n\tattackerHero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n\tsecretCardId: string,\r\n): void => {\r\n\tconst candidateEntities = spawnEntities(\r\n\t\tdefendingEntity.cardId,\r\n\t\t1,\r\n\t\tdefendingBoard,\r\n\t\tdefendingPlayerEntity,\r\n\t\tattackerBoard,\r\n\t\tattackerHero,\r\n\t\tgameState,\r\n\t\tdefendingEntity.friendly,\r\n\t\tfalse,\r\n\t\tfalse,\r\n\t\ttrue,\r\n\t\t{ ...defendingEntity },\r\n\t);\r\n\tconst indexFromRight = defendingBoard.length - (defendingBoard.indexOf(defendingEntity) + 1);\r\n\tconst spawned = performEntitySpawns(\r\n\t\tcandidateEntities,\r\n\t\tdefendingBoard,\r\n\t\tdefendingPlayerEntity,\r\n\t\tdefendingEntity,\r\n\t\tindexFromRight,\r\n\t\tattackerBoard,\r\n\t\tattackerHero,\r\n\t\tgameState,\r\n\t);\r\n\tspawned.forEach((e) => {\r\n\t\t// Might be a HS bug\r\n\t\t// 33.6.2 https://replays.firestoneapp.com/?reviewId=06e89a29-8f63-4c55-bdac-d908ed6e5857&turn=9&action=1\r\n\t\te.hasAttacked = defendingEntity.hasAttacked;\r\n\t});\r\n\tif (secretCardId === CardIds.PackTactics_TB_Bacon_Secrets_15) {\r\n\t\tspawned.forEach((e) => setEntityStats(e, 3, 3, defendingBoard, defendingPlayerEntity, gameState));\r\n\t}\r\n};\r\n\r\nexport const handleSnakeTrap = (\r\n\tdefendingEntity: BoardEntity,\r\n\tdefendingBoard: BoardEntity[],\r\n\tdefendingPlayerEntity: BgsPlayerEntity,\r\n\tattackerBoard: BoardEntity[],\r\n\tattackerHero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n): void => {\r\n\tconst candidateEntities: readonly BoardEntity[] = spawnEntities(\r\n\t\tCardIds.SnakeTrap_SnakeLegacyToken,\r\n\t\t3,\r\n\t\tdefendingBoard,\r\n\t\tdefendingPlayerEntity,\r\n\t\tattackerBoard,\r\n\t\tattackerHero,\r\n\t\tgameState,\r\n\t\tdefendingEntity.friendly,\r\n\t\tfalse,\r\n\t);\r\n\tperformEntitySpawns(\r\n\t\tcandidateEntities,\r\n\t\tdefendingBoard,\r\n\t\tdefendingPlayerEntity,\r\n\t\tdefendingEntity,\r\n\t\t0,\r\n\t\tattackerBoard,\r\n\t\tattackerHero,\r\n\t\tgameState,\r\n\t);\r\n};\r\n\r\nexport const handleVenomstrikeTrap = (\r\n\tdefendingEntity: BoardEntity,\r\n\tdefendingBoard: BoardEntity[],\r\n\tdefendingPlayerEntity: BgsPlayerEntity,\r\n\tattackerBoard: BoardEntity[],\r\n\tattackerHero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n) => {\r\n\tconst candidateEntities: readonly BoardEntity[] = spawnEntities(\r\n\t\tCardIds.EmperorCobraLegacy_BG_EX1_170,\r\n\t\t1,\r\n\t\tdefendingBoard,\r\n\t\tdefendingPlayerEntity,\r\n\t\tattackerBoard,\r\n\t\tattackerHero,\r\n\t\tgameState,\r\n\t\tdefendingEntity.friendly,\r\n\t\tfalse,\r\n\t);\r\n\tconst spawns = performEntitySpawns(\r\n\t\tcandidateEntities,\r\n\t\tdefendingBoard,\r\n\t\tdefendingPlayerEntity,\r\n\t\tdefendingEntity,\r\n\t\t0,\r\n\t\tattackerBoard,\r\n\t\tattackerHero,\r\n\t\tgameState,\r\n\t);\r\n\treturn spawns;\r\n};\r\n"]}
|
|
@@ -3,7 +3,7 @@ import { BoardEntity } from '../board-entity';
|
|
|
3
3
|
import { BoardSecret } from '../board-secret';
|
|
4
4
|
import { FullGameState } from './internal-game-state';
|
|
5
5
|
export declare const setEntityStats: (entity: BoardEntity, attack: number | null, health: number | null, board: BoardEntity[], boardHero: BgsPlayerEntity, gameState: FullGameState) => void;
|
|
6
|
-
export declare const modifyStats: (entity: BoardEntity, source: BoardEntity | BoardSecret | BoardTrinket | BgsPlayerEntity | BgsHeroPower, attackAmount: number, healthAmount: number, friendlyBoard: BoardEntity[], friendlyBoardHero: BgsPlayerEntity, gameState: FullGameState, registerSpectator?: boolean, isEnchantment?: boolean) => void;
|
|
6
|
+
export declare const modifyStats: (entity: BoardEntity, source: BoardEntity | BoardSecret | BoardTrinket | BgsPlayerEntity | BgsHeroPower, attackAmount: number, healthAmount: number, friendlyBoard: BoardEntity[], friendlyBoardHero: BgsPlayerEntity, gameState: FullGameState, registerSpectator?: boolean, isEnchantment?: boolean, countsAsStatsGain?: boolean) => void;
|
|
7
7
|
export declare const applyAfterStatsUpdate: (gameState: FullGameState) => void;
|
|
8
8
|
export interface OnStatsChangedInput {
|
|
9
9
|
target: BoardEntity;
|
package/dist/simulation/stats.js
CHANGED
|
@@ -21,7 +21,7 @@ const setEntityStats = (entity, attack, health, board, boardHero, gameState) =>
|
|
|
21
21
|
(0, add_minion_to_board_1.applyAurasToSelf)(entity, board, boardHero, gameState);
|
|
22
22
|
};
|
|
23
23
|
exports.setEntityStats = setEntityStats;
|
|
24
|
-
const modifyStats = (entity, source, attackAmount, healthAmount, friendlyBoard, friendlyBoardHero, gameState, registerSpectator = true, isEnchantment = true) => {
|
|
24
|
+
const modifyStats = (entity, source, attackAmount, healthAmount, friendlyBoard, friendlyBoardHero, gameState, registerSpectator = true, isEnchantment = true, countsAsStatsGain = true) => {
|
|
25
25
|
const debug = attackAmount === 10;
|
|
26
26
|
if (attackAmount === 0 && healthAmount === 0) {
|
|
27
27
|
return;
|
|
@@ -104,7 +104,9 @@ const modifyStats = (entity, source, attackAmount, healthAmount, friendlyBoard,
|
|
|
104
104
|
(0, exports.modifyStats)(mishmash, mishmash, (mishmash.cardId === "TB_BaconShop_HERO_33_Buddy_G" ? 2 : 1) * realAttackAmount, (mishmash.cardId === "TB_BaconShop_HERO_33_Buddy_G" ? 2 : 1) * realHealthAmount, friendlyBoard, friendlyBoardHero, gameState);
|
|
105
105
|
});
|
|
106
106
|
}
|
|
107
|
-
|
|
107
|
+
if (countsAsStatsGain) {
|
|
108
|
+
onStatsUpdate(entity, realAttackAmount, realHealthAmount, friendlyBoard, friendlyBoardHero, otherBoardHero, gameState);
|
|
109
|
+
}
|
|
108
110
|
};
|
|
109
111
|
exports.modifyStats = modifyStats;
|
|
110
112
|
const onStatsUpdate = (entity, realAttackAmount, realHealthAmount, friendlyBoard, friendlyHero, otherHero, gameState) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stats.js","sourceRoot":"","sources":["../../src/simulation/stats.ts"],"names":[],"mappings":"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","sourcesContent":["import { Race } from '@firestone-hs/reference-data';\r\nimport { BgsHeroPower, BgsPlayerEntity, BoardTrinket } from '../bgs-player-entity';\r\nimport { BoardEntity } from '../board-entity';\r\nimport { BoardSecret } from '../board-secret';\r\nimport { hasOnStatsChanged } from '../cards/card.interface';\r\nimport { cardMappings } from '../cards/impl/_card-mappings';\r\nimport { CardIds } from '../services/card-ids';\r\nimport { hasCorrectTribe } from '../utils';\r\nimport { applyAurasToSelf, removeAurasFromSelf } from './add-minion-to-board';\r\nimport { getNeighbours } from './attack';\r\nimport { FullGameState, PlayerState } from './internal-game-state';\r\nimport { onQuestProgressUpdated } from './quest';\r\n\r\nexport const setEntityStats = (\r\n\tentity: BoardEntity,\r\n\tattack: number | null,\r\n\thealth: number | null,\r\n\tboard: BoardEntity[],\r\n\tboardHero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n): void => {\r\n\tremoveAurasFromSelf(entity, board, boardHero, gameState);\r\n\tif (attack !== null) {\r\n\t\tentity.attack = attack;\r\n\t\tentity.maxAttack = attack;\r\n\t}\r\n\tif (health !== null) {\r\n\t\tentity.health = health;\r\n\t\tentity.maxHealth = health;\r\n\t}\r\n\tapplyAurasToSelf(entity, board, boardHero, gameState);\r\n};\r\n\r\nexport const modifyStats = (\r\n\tentity: BoardEntity,\r\n\tsource: BoardEntity | BoardSecret | BoardTrinket | BgsPlayerEntity | BgsHeroPower,\r\n\tattackAmount: number,\r\n\thealthAmount: number,\r\n\tfriendlyBoard: BoardEntity[],\r\n\tfriendlyBoardHero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n\tregisterSpectator = true,\r\n\t// All stat modifications become enchantments, excepted the ones coming from gilding a minion\r\n\tisEnchantment = true,\r\n): void => {\r\n\tconst debug = attackAmount === 10;\r\n\tif (attackAmount === 0 && healthAmount === 0) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (entity.cardId === CardIds.LocPrince_BG29_889 || entity.cardId === CardIds.LocPrince_BG29_889_G) {\r\n\t\tconst buff = entity.cardId === CardIds.LocPrince_BG29_889_G ? 2 : 1;\r\n\t\tattackAmount += 2 * buff;\r\n\t\thealthAmount += 1 * buff;\r\n\t}\r\n\r\n\tif (\r\n\t\tentity?.entityId !== source?.entityId &&\r\n\t\thasCorrectTribe(\r\n\t\t\tsource as BoardEntity,\r\n\t\t\tfriendlyBoardHero,\r\n\t\t\tRace.ELEMENTAL,\r\n\t\t\tgameState.anomalies,\r\n\t\t\tgameState.allCards,\r\n\t\t) &&\r\n\t\t// Safeguard\r\n\t\tattackAmount >= 0 &&\r\n\t\thealthAmount >= 0\r\n\t) {\r\n\t\tattackAmount += friendlyBoardHero.globalInfo.ElementalAttackBuff;\r\n\t\thealthAmount += friendlyBoardHero.globalInfo.ElementalHealthBuff;\r\n\t}\r\n\r\n\t// The only spell for now that grants stats is the Fleeting Vigor secret, and the stats it grants\r\n\t// are in scriptDataNum1 and 2\r\n\t// if (\r\n\t// \tentity?.entityId !== source?.entityId &&\r\n\t// \tgameState.allCards.getCard(source?.cardId).type?.toUpperCase() === CardType[CardType.BATTLEGROUND_SPELL] &&\r\n\t// \t// Safeguard\r\n\t// \tattackAmount >= 0 &&\r\n\t// \thealthAmount >= 0\r\n\t// ) {\r\n\t// \tattackAmount += friendlyBoardHero.globalInfo.TavernSpellAttackBuff;\r\n\t// \thealthAmount += friendlyBoardHero.globalInfo.TavernSpellHealthBuff;\r\n\t// }\r\n\r\n\tconst otherBoardHero: BgsPlayerEntity =\r\n\t\tgameState.gameState.player.player === friendlyBoardHero\r\n\t\t\t? gameState.gameState.opponent.player\r\n\t\t\t: gameState.gameState.player.player;\r\n\r\n\tconst neighbours = getNeighbours(friendlyBoard, entity);\r\n\tconst poetMultipliers =\r\n\t\tisEnchantment &&\r\n\t\thasCorrectTribe(entity, friendlyBoardHero, Race.DRAGON, gameState.anomalies, gameState.allCards)\r\n\t\t\t? neighbours.filter((e) => e.cardId === CardIds.PersistentPoet_BG29_813_G).length * 2 || 1\r\n\t\t\t: 1;\r\n\tconst tarecgosaMultiplier = isEnchantment && entity.cardId === CardIds.Tarecgosa_BG21_015_G ? 2 : 1;\r\n\r\n\tconst realAttackAmount = attackAmount * poetMultipliers * tarecgosaMultiplier;\r\n\tconst realHealthAmount = healthAmount * poetMultipliers * tarecgosaMultiplier;\r\n\r\n\tentity.attack = Math.max(0, entity.attack + realAttackAmount);\r\n\tentity.previousAttack = entity.attack;\r\n\tentity.pendingAttackBuffs = entity.pendingAttackBuffs || [];\r\n\tentity.pendingAttackBuffs.push(realAttackAmount);\r\n\tentity.health += realHealthAmount;\r\n\r\n\tif (realAttackAmount > 0) {\r\n\t\tentity.maxAttack += realAttackAmount;\r\n\r\n\t\tif (hasCorrectTribe(entity, friendlyBoardHero, Race.DRAGON, gameState.anomalies, gameState.allCards)) {\r\n\t\t\tif (entity.cardId !== CardIds.Stormbringer_BG26_966 && entity.cardId !== CardIds.Stormbringer_BG26_966_G) {\r\n\t\t\t\tconst stormbringers = friendlyBoard.filter(\r\n\t\t\t\t\t(e) => e.cardId === CardIds.Stormbringer_BG26_966 || e.cardId === CardIds.Stormbringer_BG26_966_G,\r\n\t\t\t\t);\r\n\t\t\t\tstormbringers.forEach((stormbringer) => {\r\n\t\t\t\t\tconst multiplier = stormbringer.cardId === CardIds.Stormbringer_BG26_966_G ? 2 : 1;\r\n\t\t\t\t\tstormbringer.attack += multiplier * realAttackAmount;\r\n\t\t\t\t\tgameState.spectator.registerPowerTarget(\r\n\t\t\t\t\t\tstormbringer,\r\n\t\t\t\t\t\tstormbringer,\r\n\t\t\t\t\t\tfriendlyBoard,\r\n\t\t\t\t\t\tfriendlyBoardHero,\r\n\t\t\t\t\t\totherBoardHero,\r\n\t\t\t\t\t);\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Sinestra\r\n\t\tfriendlyBoard\r\n\t\t\t.filter(\r\n\t\t\t\t(e) =>\r\n\t\t\t\t\te.cardId === CardIds.LadySinestra_TB_BaconShop_HERO_52_Buddy ||\r\n\t\t\t\t\te.cardId === CardIds.LadySinestra_TB_BaconShop_HERO_52_Buddy_G,\r\n\t\t\t)\r\n\t\t\t.forEach((sinestra) => {\r\n\t\t\t\tconst buff = sinestra.cardId === CardIds.LadySinestra_TB_BaconShop_HERO_52_Buddy_G ? 2 : 1;\r\n\t\t\t\tentity.health += buff;\r\n\t\t\t\tgameState.spectator.registerPowerTarget(\r\n\t\t\t\t\tsinestra,\r\n\t\t\t\t\tentity,\r\n\t\t\t\t\tfriendlyBoard,\r\n\t\t\t\t\tfriendlyBoardHero,\r\n\t\t\t\t\totherBoardHero,\r\n\t\t\t\t);\r\n\t\t\t});\r\n\t}\r\n\r\n\tif (realHealthAmount > 0) {\r\n\t\tentity.maxHealth += realHealthAmount;\r\n\t\tconst titanicGuardians = friendlyBoard\r\n\t\t\t.filter((e) => e.entityId !== entity.entityId)\r\n\t\t\t.filter(\r\n\t\t\t\t(e) =>\r\n\t\t\t\t\te.cardId === CardIds.TitanicGuardian_TB_BaconShop_HERO_39_Buddy ||\r\n\t\t\t\t\te.cardId === CardIds.TitanicGuardian_TB_BaconShop_HERO_39_Buddy_G,\r\n\t\t\t);\r\n\t\ttitanicGuardians.forEach((guardian) => {\r\n\t\t\tconst buff =\r\n\t\t\t\t(guardian.cardId === CardIds.TitanicGuardian_TB_BaconShop_HERO_39_Buddy_G ? 2 : 1) * realHealthAmount;\r\n\t\t\tif (buff > 0) {\r\n\t\t\t\tguardian.health += buff;\r\n\t\t\t\tguardian.maxHealth += buff;\r\n\t\t\t}\r\n\t\t});\r\n\t}\r\n\r\n\tif (registerSpectator && !!source) {\r\n\t\tgameState.spectator.registerPowerTarget(source, entity, friendlyBoard, friendlyBoardHero, otherBoardHero);\r\n\t}\r\n\r\n\tif (\r\n\t\tentity.cardId === CardIds.Menagerist_AmalgamToken ||\r\n\t\tentity.cardId === CardIds.Amalgam ||\r\n\t\tentity.cardId === CardIds.Cuddlgam_TB_BaconShop_HP_033t_SKIN_A ||\r\n\t\tentity.cardId === CardIds.Cuddlgam_TB_BaconShop_HP_033t_SKIN_A_G ||\r\n\t\tentity.cardId === CardIds.AbominableAmalgam_TB_BaconShop_HP_033t_SKIN_D ||\r\n\t\tentity.cardId === CardIds.AbominableAmalgam_TB_BaconShop_HP_033t_SKIN_D_G\r\n\t) {\r\n\t\tconst mishmashes = friendlyBoard.filter(\r\n\t\t\t(e) =>\r\n\t\t\t\te.cardId === CardIds.Mishmash_TB_BaconShop_HERO_33_Buddy ||\r\n\t\t\t\te.cardId === CardIds.Mishmash_TB_BaconShop_HERO_33_Buddy_G,\r\n\t\t);\r\n\t\tmishmashes.forEach((mishmash) => {\r\n\t\t\tmodifyStats(\r\n\t\t\t\tmishmash,\r\n\t\t\t\tmishmash,\r\n\t\t\t\t(mishmash.cardId === CardIds.Mishmash_TB_BaconShop_HERO_33_Buddy_G ? 2 : 1) * realAttackAmount,\r\n\t\t\t\t(mishmash.cardId === CardIds.Mishmash_TB_BaconShop_HERO_33_Buddy_G ? 2 : 1) * realHealthAmount,\r\n\t\t\t\tfriendlyBoard,\r\n\t\t\t\tfriendlyBoardHero,\r\n\t\t\t\tgameState,\r\n\t\t\t);\r\n\t\t});\r\n\t}\r\n\r\n\tonStatsUpdate(\r\n\t\tentity,\r\n\t\trealAttackAmount,\r\n\t\trealHealthAmount,\r\n\t\tfriendlyBoard,\r\n\t\tfriendlyBoardHero,\r\n\t\totherBoardHero,\r\n\t\tgameState,\r\n\t);\r\n};\r\n\r\nconst onStatsUpdate = (\r\n\tentity: BoardEntity,\r\n\trealAttackAmount: number,\r\n\trealHealthAmount: number,\r\n\tfriendlyBoard: BoardEntity[],\r\n\tfriendlyHero: BgsPlayerEntity,\r\n\totherHero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n): void => {\r\n\tonStatUpdateMinions(entity, realAttackAmount, realHealthAmount, friendlyBoard, friendlyHero, otherHero, gameState);\r\n\tonStatUpdateQuests(entity, friendlyBoard, friendlyHero, gameState);\r\n};\r\n\r\nexport const applyAfterStatsUpdate = (gameState: FullGameState) => {\r\n\tfor (const entity of gameState.gameState.player.board) {\r\n\t\tapplyAfterStatsUpdateForEntity(entity, gameState.gameState.player, gameState.gameState.opponent, gameState);\r\n\t}\r\n\tfor (const entity of gameState.gameState.opponent.board) {\r\n\t\tapplyAfterStatsUpdateForEntity(entity, gameState.gameState.opponent, gameState.gameState.player, gameState);\r\n\t}\r\n};\r\n\r\nconst applyAfterStatsUpdateForEntity = (\r\n\tentity: BoardEntity,\r\n\tplayerState: PlayerState,\r\n\topponentState: PlayerState,\r\n\tgameState: FullGameState,\r\n): void => {\r\n\tentity.pendingAttackBuffs = [];\r\n};\r\n\r\nconst onStatUpdateQuests = (\r\n\tentity: BoardEntity,\r\n\tboard: BoardEntity[],\r\n\thero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n): void => {\r\n\tconst quests = hero.questEntities ?? [];\r\n\tif (!quests.length) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tfor (const quest of quests) {\r\n\t\tswitch (quest.CardId) {\r\n\t\t\tcase CardIds.FindTheMurderWeapon:\r\n\t\t\t\tonQuestProgressUpdated(hero, quest, board, gameState);\r\n\t\t\t\tbreak;\r\n\t\t\tcase CardIds.PressureTheAuthorities:\r\n\t\t\t\tconst totalAttack = board.map((e) => e.attack).reduce((a, b) => a + b, 0);\r\n\t\t\t\tif (totalAttack >= 35) {\r\n\t\t\t\t\tonQuestProgressUpdated(hero, quest, board, gameState);\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n};\r\n\r\nconst onStatUpdateMinions = (\r\n\tentity: BoardEntity,\r\n\tattackAmount: number,\r\n\thealthAmount: number,\r\n\tfriendlyBoard: BoardEntity[],\r\n\tfriendlyBoardHero: BgsPlayerEntity,\r\n\totherHero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n): void => {\r\n\tif (attackAmount > 0 || healthAmount > 0) {\r\n\t\tfor (const boardEntity of friendlyBoard) {\r\n\t\t\tconst onStatsChangedImpl = cardMappings[boardEntity.cardId];\r\n\t\t\tif (hasOnStatsChanged(onStatsChangedImpl)) {\r\n\t\t\t\tonStatsChangedImpl.onStatsChanged(boardEntity, {\r\n\t\t\t\t\ttarget: entity,\r\n\t\t\t\t\tattackAmount: attackAmount,\r\n\t\t\t\t\thealthAmount: healthAmount,\r\n\t\t\t\t\tboard: friendlyBoard,\r\n\t\t\t\t\thero: friendlyBoardHero,\r\n\t\t\t\t\totherHero: otherHero,\r\n\t\t\t\t\tgameState: gameState,\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (hasCorrectTribe(entity, friendlyBoardHero, Race.ELEMENTAL, gameState.anomalies, gameState.allCards)) {\r\n\t\tconst masterOfRealities = friendlyBoard.filter(\r\n\t\t\t(e) => e.cardId === CardIds.MasterOfRealities_BG21_036 || e.cardId === CardIds.MasterOfRealities_BG21_036_G,\r\n\t\t);\r\n\t\tmasterOfRealities.forEach((master) => {\r\n\t\t\tconst baseBuff = 2;\r\n\t\t\tconst mult = master.cardId === CardIds.MasterOfRealities_BG21_036_G ? 2 : 1;\r\n\t\t\tmodifyStats(master, master, baseBuff * mult, baseBuff * mult, friendlyBoard, friendlyBoardHero, gameState);\r\n\t\t});\r\n\t}\r\n\tconst tentaclesOfCthun = friendlyBoard\r\n\t\t.filter((e) => e.entityId !== entity.entityId)\r\n\t\t.filter(\r\n\t\t\t(e) =>\r\n\t\t\t\te.cardId === CardIds.TentacleOfCthun_TB_BaconShop_HERO_29_Buddy ||\r\n\t\t\t\te.cardId === CardIds.TentacleOfCthun_TB_BaconShop_HERO_29_Buddy_G,\r\n\t\t);\r\n\ttentaclesOfCthun.forEach((tentacle) => {\r\n\t\ttentacle.attack += tentacle.cardId === CardIds.TentacleOfCthun_TB_BaconShop_HERO_29_Buddy_G ? 2 : 1;\r\n\t\ttentacle.health += tentacle.cardId === CardIds.TentacleOfCthun_TB_BaconShop_HERO_29_Buddy_G ? 2 : 1;\r\n\t});\r\n};\r\n\r\nexport interface OnStatsChangedInput {\r\n\ttarget: BoardEntity;\r\n\tattackAmount: number;\r\n\thealthAmount: number;\r\n\tboard: BoardEntity[];\r\n\thero: BgsPlayerEntity;\r\n\totherHero: BgsPlayerEntity;\r\n\tgameState: FullGameState;\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"stats.js","sourceRoot":"","sources":["../../src/simulation/stats.ts"],"names":[],"mappings":"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","sourcesContent":["import { Race } from '@firestone-hs/reference-data';\r\nimport { BgsHeroPower, BgsPlayerEntity, BoardTrinket } from '../bgs-player-entity';\r\nimport { BoardEntity } from '../board-entity';\r\nimport { BoardSecret } from '../board-secret';\r\nimport { hasOnStatsChanged } from '../cards/card.interface';\r\nimport { cardMappings } from '../cards/impl/_card-mappings';\r\nimport { CardIds } from '../services/card-ids';\r\nimport { hasCorrectTribe } from '../utils';\r\nimport { applyAurasToSelf, removeAurasFromSelf } from './add-minion-to-board';\r\nimport { getNeighbours } from './attack';\r\nimport { FullGameState, PlayerState } from './internal-game-state';\r\nimport { onQuestProgressUpdated } from './quest';\r\n\r\nexport const setEntityStats = (\r\n\tentity: BoardEntity,\r\n\tattack: number | null,\r\n\thealth: number | null,\r\n\tboard: BoardEntity[],\r\n\tboardHero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n): void => {\r\n\tremoveAurasFromSelf(entity, board, boardHero, gameState);\r\n\tif (attack !== null) {\r\n\t\tentity.attack = attack;\r\n\t\tentity.maxAttack = attack;\r\n\t}\r\n\tif (health !== null) {\r\n\t\tentity.health = health;\r\n\t\tentity.maxHealth = health;\r\n\t}\r\n\tapplyAurasToSelf(entity, board, boardHero, gameState);\r\n};\r\n\r\nexport const modifyStats = (\r\n\tentity: BoardEntity,\r\n\tsource: BoardEntity | BoardSecret | BoardTrinket | BgsPlayerEntity | BgsHeroPower,\r\n\tattackAmount: number,\r\n\thealthAmount: number,\r\n\tfriendlyBoard: BoardEntity[],\r\n\tfriendlyBoardHero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n\tregisterSpectator = true,\r\n\t// All stat modifications become enchantments, excepted the ones coming from gilding a minion\r\n\tisEnchantment = true,\r\n\tcountsAsStatsGain = true,\r\n): void => {\r\n\tconst debug = attackAmount === 10;\r\n\tif (attackAmount === 0 && healthAmount === 0) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (entity.cardId === CardIds.LocPrince_BG29_889 || entity.cardId === CardIds.LocPrince_BG29_889_G) {\r\n\t\tconst buff = entity.cardId === CardIds.LocPrince_BG29_889_G ? 2 : 1;\r\n\t\tattackAmount += 2 * buff;\r\n\t\thealthAmount += 1 * buff;\r\n\t}\r\n\r\n\tif (\r\n\t\tentity?.entityId !== source?.entityId &&\r\n\t\thasCorrectTribe(\r\n\t\t\tsource as BoardEntity,\r\n\t\t\tfriendlyBoardHero,\r\n\t\t\tRace.ELEMENTAL,\r\n\t\t\tgameState.anomalies,\r\n\t\t\tgameState.allCards,\r\n\t\t) &&\r\n\t\t// Safeguard\r\n\t\tattackAmount >= 0 &&\r\n\t\thealthAmount >= 0\r\n\t) {\r\n\t\tattackAmount += friendlyBoardHero.globalInfo.ElementalAttackBuff;\r\n\t\thealthAmount += friendlyBoardHero.globalInfo.ElementalHealthBuff;\r\n\t}\r\n\r\n\t// The only spell for now that grants stats is the Fleeting Vigor secret, and the stats it grants\r\n\t// are in scriptDataNum1 and 2\r\n\t// if (\r\n\t// \tentity?.entityId !== source?.entityId &&\r\n\t// \tgameState.allCards.getCard(source?.cardId).type?.toUpperCase() === CardType[CardType.BATTLEGROUND_SPELL] &&\r\n\t// \t// Safeguard\r\n\t// \tattackAmount >= 0 &&\r\n\t// \thealthAmount >= 0\r\n\t// ) {\r\n\t// \tattackAmount += friendlyBoardHero.globalInfo.TavernSpellAttackBuff;\r\n\t// \thealthAmount += friendlyBoardHero.globalInfo.TavernSpellHealthBuff;\r\n\t// }\r\n\r\n\tconst otherBoardHero: BgsPlayerEntity =\r\n\t\tgameState.gameState.player.player === friendlyBoardHero\r\n\t\t\t? gameState.gameState.opponent.player\r\n\t\t\t: gameState.gameState.player.player;\r\n\r\n\tconst neighbours = getNeighbours(friendlyBoard, entity);\r\n\tconst poetMultipliers =\r\n\t\tisEnchantment &&\r\n\t\thasCorrectTribe(entity, friendlyBoardHero, Race.DRAGON, gameState.anomalies, gameState.allCards)\r\n\t\t\t? neighbours.filter((e) => e.cardId === CardIds.PersistentPoet_BG29_813_G).length * 2 || 1\r\n\t\t\t: 1;\r\n\tconst tarecgosaMultiplier = isEnchantment && entity.cardId === CardIds.Tarecgosa_BG21_015_G ? 2 : 1;\r\n\r\n\tconst realAttackAmount = attackAmount * poetMultipliers * tarecgosaMultiplier;\r\n\tconst realHealthAmount = healthAmount * poetMultipliers * tarecgosaMultiplier;\r\n\r\n\tentity.attack = Math.max(0, entity.attack + realAttackAmount);\r\n\tentity.previousAttack = entity.attack;\r\n\tentity.pendingAttackBuffs = entity.pendingAttackBuffs || [];\r\n\tentity.pendingAttackBuffs.push(realAttackAmount);\r\n\tentity.health += realHealthAmount;\r\n\r\n\tif (realAttackAmount > 0) {\r\n\t\tentity.maxAttack += realAttackAmount;\r\n\r\n\t\tif (hasCorrectTribe(entity, friendlyBoardHero, Race.DRAGON, gameState.anomalies, gameState.allCards)) {\r\n\t\t\tif (entity.cardId !== CardIds.Stormbringer_BG26_966 && entity.cardId !== CardIds.Stormbringer_BG26_966_G) {\r\n\t\t\t\tconst stormbringers = friendlyBoard.filter(\r\n\t\t\t\t\t(e) => e.cardId === CardIds.Stormbringer_BG26_966 || e.cardId === CardIds.Stormbringer_BG26_966_G,\r\n\t\t\t\t);\r\n\t\t\t\tstormbringers.forEach((stormbringer) => {\r\n\t\t\t\t\tconst multiplier = stormbringer.cardId === CardIds.Stormbringer_BG26_966_G ? 2 : 1;\r\n\t\t\t\t\tstormbringer.attack += multiplier * realAttackAmount;\r\n\t\t\t\t\tgameState.spectator.registerPowerTarget(\r\n\t\t\t\t\t\tstormbringer,\r\n\t\t\t\t\t\tstormbringer,\r\n\t\t\t\t\t\tfriendlyBoard,\r\n\t\t\t\t\t\tfriendlyBoardHero,\r\n\t\t\t\t\t\totherBoardHero,\r\n\t\t\t\t\t);\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Sinestra\r\n\t\tfriendlyBoard\r\n\t\t\t.filter(\r\n\t\t\t\t(e) =>\r\n\t\t\t\t\te.cardId === CardIds.LadySinestra_TB_BaconShop_HERO_52_Buddy ||\r\n\t\t\t\t\te.cardId === CardIds.LadySinestra_TB_BaconShop_HERO_52_Buddy_G,\r\n\t\t\t)\r\n\t\t\t.forEach((sinestra) => {\r\n\t\t\t\tconst buff = sinestra.cardId === CardIds.LadySinestra_TB_BaconShop_HERO_52_Buddy_G ? 2 : 1;\r\n\t\t\t\tentity.health += buff;\r\n\t\t\t\tgameState.spectator.registerPowerTarget(\r\n\t\t\t\t\tsinestra,\r\n\t\t\t\t\tentity,\r\n\t\t\t\t\tfriendlyBoard,\r\n\t\t\t\t\tfriendlyBoardHero,\r\n\t\t\t\t\totherBoardHero,\r\n\t\t\t\t);\r\n\t\t\t});\r\n\t}\r\n\r\n\tif (realHealthAmount > 0) {\r\n\t\tentity.maxHealth += realHealthAmount;\r\n\t\tconst titanicGuardians = friendlyBoard\r\n\t\t\t.filter((e) => e.entityId !== entity.entityId)\r\n\t\t\t.filter(\r\n\t\t\t\t(e) =>\r\n\t\t\t\t\te.cardId === CardIds.TitanicGuardian_TB_BaconShop_HERO_39_Buddy ||\r\n\t\t\t\t\te.cardId === CardIds.TitanicGuardian_TB_BaconShop_HERO_39_Buddy_G,\r\n\t\t\t);\r\n\t\ttitanicGuardians.forEach((guardian) => {\r\n\t\t\tconst buff =\r\n\t\t\t\t(guardian.cardId === CardIds.TitanicGuardian_TB_BaconShop_HERO_39_Buddy_G ? 2 : 1) * realHealthAmount;\r\n\t\t\tif (buff > 0) {\r\n\t\t\t\tguardian.health += buff;\r\n\t\t\t\tguardian.maxHealth += buff;\r\n\t\t\t}\r\n\t\t});\r\n\t}\r\n\r\n\tif (registerSpectator && !!source) {\r\n\t\tgameState.spectator.registerPowerTarget(source, entity, friendlyBoard, friendlyBoardHero, otherBoardHero);\r\n\t}\r\n\r\n\tif (\r\n\t\tentity.cardId === CardIds.Menagerist_AmalgamToken ||\r\n\t\tentity.cardId === CardIds.Amalgam ||\r\n\t\tentity.cardId === CardIds.Cuddlgam_TB_BaconShop_HP_033t_SKIN_A ||\r\n\t\tentity.cardId === CardIds.Cuddlgam_TB_BaconShop_HP_033t_SKIN_A_G ||\r\n\t\tentity.cardId === CardIds.AbominableAmalgam_TB_BaconShop_HP_033t_SKIN_D ||\r\n\t\tentity.cardId === CardIds.AbominableAmalgam_TB_BaconShop_HP_033t_SKIN_D_G\r\n\t) {\r\n\t\tconst mishmashes = friendlyBoard.filter(\r\n\t\t\t(e) =>\r\n\t\t\t\te.cardId === CardIds.Mishmash_TB_BaconShop_HERO_33_Buddy ||\r\n\t\t\t\te.cardId === CardIds.Mishmash_TB_BaconShop_HERO_33_Buddy_G,\r\n\t\t);\r\n\t\tmishmashes.forEach((mishmash) => {\r\n\t\t\tmodifyStats(\r\n\t\t\t\tmishmash,\r\n\t\t\t\tmishmash,\r\n\t\t\t\t(mishmash.cardId === CardIds.Mishmash_TB_BaconShop_HERO_33_Buddy_G ? 2 : 1) * realAttackAmount,\r\n\t\t\t\t(mishmash.cardId === CardIds.Mishmash_TB_BaconShop_HERO_33_Buddy_G ? 2 : 1) * realHealthAmount,\r\n\t\t\t\tfriendlyBoard,\r\n\t\t\t\tfriendlyBoardHero,\r\n\t\t\t\tgameState,\r\n\t\t\t);\r\n\t\t});\r\n\t}\r\n\r\n\tif (countsAsStatsGain) {\r\n\t\tonStatsUpdate(\r\n\t\t\tentity,\r\n\t\t\trealAttackAmount,\r\n\t\t\trealHealthAmount,\r\n\t\t\tfriendlyBoard,\r\n\t\t\tfriendlyBoardHero,\r\n\t\t\totherBoardHero,\r\n\t\t\tgameState,\r\n\t\t);\r\n\t}\r\n};\r\n\r\nconst onStatsUpdate = (\r\n\tentity: BoardEntity,\r\n\trealAttackAmount: number,\r\n\trealHealthAmount: number,\r\n\tfriendlyBoard: BoardEntity[],\r\n\tfriendlyHero: BgsPlayerEntity,\r\n\totherHero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n): void => {\r\n\tonStatUpdateMinions(entity, realAttackAmount, realHealthAmount, friendlyBoard, friendlyHero, otherHero, gameState);\r\n\tonStatUpdateQuests(entity, friendlyBoard, friendlyHero, gameState);\r\n};\r\n\r\nexport const applyAfterStatsUpdate = (gameState: FullGameState) => {\r\n\tfor (const entity of gameState.gameState.player.board) {\r\n\t\tapplyAfterStatsUpdateForEntity(entity, gameState.gameState.player, gameState.gameState.opponent, gameState);\r\n\t}\r\n\tfor (const entity of gameState.gameState.opponent.board) {\r\n\t\tapplyAfterStatsUpdateForEntity(entity, gameState.gameState.opponent, gameState.gameState.player, gameState);\r\n\t}\r\n};\r\n\r\nconst applyAfterStatsUpdateForEntity = (\r\n\tentity: BoardEntity,\r\n\tplayerState: PlayerState,\r\n\topponentState: PlayerState,\r\n\tgameState: FullGameState,\r\n): void => {\r\n\tentity.pendingAttackBuffs = [];\r\n};\r\n\r\nconst onStatUpdateQuests = (\r\n\tentity: BoardEntity,\r\n\tboard: BoardEntity[],\r\n\thero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n): void => {\r\n\tconst quests = hero.questEntities ?? [];\r\n\tif (!quests.length) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tfor (const quest of quests) {\r\n\t\tswitch (quest.CardId) {\r\n\t\t\tcase CardIds.FindTheMurderWeapon:\r\n\t\t\t\tonQuestProgressUpdated(hero, quest, board, gameState);\r\n\t\t\t\tbreak;\r\n\t\t\tcase CardIds.PressureTheAuthorities:\r\n\t\t\t\tconst totalAttack = board.map((e) => e.attack).reduce((a, b) => a + b, 0);\r\n\t\t\t\tif (totalAttack >= 35) {\r\n\t\t\t\t\tonQuestProgressUpdated(hero, quest, board, gameState);\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n};\r\n\r\nconst onStatUpdateMinions = (\r\n\tentity: BoardEntity,\r\n\tattackAmount: number,\r\n\thealthAmount: number,\r\n\tfriendlyBoard: BoardEntity[],\r\n\tfriendlyBoardHero: BgsPlayerEntity,\r\n\totherHero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n): void => {\r\n\tif (attackAmount > 0 || healthAmount > 0) {\r\n\t\tfor (const boardEntity of friendlyBoard) {\r\n\t\t\tconst onStatsChangedImpl = cardMappings[boardEntity.cardId];\r\n\t\t\tif (hasOnStatsChanged(onStatsChangedImpl)) {\r\n\t\t\t\tonStatsChangedImpl.onStatsChanged(boardEntity, {\r\n\t\t\t\t\ttarget: entity,\r\n\t\t\t\t\tattackAmount: attackAmount,\r\n\t\t\t\t\thealthAmount: healthAmount,\r\n\t\t\t\t\tboard: friendlyBoard,\r\n\t\t\t\t\thero: friendlyBoardHero,\r\n\t\t\t\t\totherHero: otherHero,\r\n\t\t\t\t\tgameState: gameState,\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (hasCorrectTribe(entity, friendlyBoardHero, Race.ELEMENTAL, gameState.anomalies, gameState.allCards)) {\r\n\t\tconst masterOfRealities = friendlyBoard.filter(\r\n\t\t\t(e) => e.cardId === CardIds.MasterOfRealities_BG21_036 || e.cardId === CardIds.MasterOfRealities_BG21_036_G,\r\n\t\t);\r\n\t\tmasterOfRealities.forEach((master) => {\r\n\t\t\tconst baseBuff = 2;\r\n\t\t\tconst mult = master.cardId === CardIds.MasterOfRealities_BG21_036_G ? 2 : 1;\r\n\t\t\tmodifyStats(master, master, baseBuff * mult, baseBuff * mult, friendlyBoard, friendlyBoardHero, gameState);\r\n\t\t});\r\n\t}\r\n\tconst tentaclesOfCthun = friendlyBoard\r\n\t\t.filter((e) => e.entityId !== entity.entityId)\r\n\t\t.filter(\r\n\t\t\t(e) =>\r\n\t\t\t\te.cardId === CardIds.TentacleOfCthun_TB_BaconShop_HERO_29_Buddy ||\r\n\t\t\t\te.cardId === CardIds.TentacleOfCthun_TB_BaconShop_HERO_29_Buddy_G,\r\n\t\t);\r\n\ttentaclesOfCthun.forEach((tentacle) => {\r\n\t\ttentacle.attack += tentacle.cardId === CardIds.TentacleOfCthun_TB_BaconShop_HERO_29_Buddy_G ? 2 : 1;\r\n\t\ttentacle.health += tentacle.cardId === CardIds.TentacleOfCthun_TB_BaconShop_HERO_29_Buddy_G ? 2 : 1;\r\n\t});\r\n};\r\n\r\nexport interface OnStatsChangedInput {\r\n\ttarget: BoardEntity;\r\n\tattackAmount: number;\r\n\thealthAmount: number;\r\n\tboard: BoardEntity[];\r\n\thero: BgsPlayerEntity;\r\n\totherHero: BgsPlayerEntity;\r\n\tgameState: FullGameState;\r\n}\r\n"]}
|