@firestone-hs/simulate-bgs-battle 1.1.765 → 1.1.767

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/dist/board-entity.d.ts +1 -0
  2. package/dist/board-entity.js.map +1 -1
  3. package/dist/cards/card.interface.d.ts +7 -3
  4. package/dist/cards/card.interface.js +4 -2
  5. package/dist/cards/card.interface.js.map +1 -1
  6. package/dist/cards/impl/_card-mappings.js +6 -0
  7. package/dist/cards/impl/_card-mappings.js.map +1 -1
  8. package/dist/cards/impl/bg-spell/boon-of-beetles.js +3 -2
  9. package/dist/cards/impl/bg-spell/boon-of-beetles.js.map +1 -1
  10. package/dist/cards/impl/enchantments/booming.d.ts +2 -0
  11. package/dist/cards/impl/enchantments/booming.js +44 -0
  12. package/dist/cards/impl/enchantments/booming.js.map +1 -0
  13. package/dist/cards/impl/enchantments/golemancy.js +1 -1
  14. package/dist/cards/impl/enchantments/golemancy.js.map +1 -1
  15. package/dist/cards/impl/enchantments/set-sail.d.ts +2 -0
  16. package/dist/cards/impl/enchantments/set-sail.js +39 -0
  17. package/dist/cards/impl/enchantments/set-sail.js.map +1 -0
  18. package/dist/cards/impl/enchantments/spell-siphon.js +5 -7
  19. package/dist/cards/impl/enchantments/spell-siphon.js.map +1 -1
  20. package/dist/cards/impl/hero-power/mechgyver.d.ts +2 -0
  21. package/dist/cards/impl/hero-power/mechgyver.js +27 -0
  22. package/dist/cards/impl/hero-power/mechgyver.js.map +1 -0
  23. package/dist/cards/impl/minion/cthun.js.map +1 -1
  24. package/dist/cards/impl/minion/diremuck-forager.js +4 -1
  25. package/dist/cards/impl/minion/diremuck-forager.js.map +1 -1
  26. package/dist/cards/impl/minion/expert-aviator.js +3 -1
  27. package/dist/cards/impl/minion/expert-aviator.js.map +1 -1
  28. package/dist/cards/impl/minion/faceless-converter.d.ts +2 -2
  29. package/dist/cards/impl/minion/faceless-converter.js +38 -5
  30. package/dist/cards/impl/minion/faceless-converter.js.map +1 -1
  31. package/dist/cards/impl/minion/hopebringer.js +10 -6
  32. package/dist/cards/impl/minion/hopebringer.js.map +1 -1
  33. package/dist/cards/impl/minion/jailbird-juggernaut.js +7 -14
  34. package/dist/cards/impl/minion/jailbird-juggernaut.js.map +1 -1
  35. package/dist/cards/impl/minion/sinrunner-blanchy.d.ts +1 -1
  36. package/dist/cards/impl/minion/sinrunner-blanchy.js +3 -1
  37. package/dist/cards/impl/minion/sinrunner-blanchy.js.map +1 -1
  38. package/dist/cards/impl/minion/wildfire-elemental.js +1 -1
  39. package/dist/cards/impl/minion/wildfire-elemental.js.map +1 -1
  40. package/dist/cards/impl/minion/yshaarj.js +6 -4
  41. package/dist/cards/impl/minion/yshaarj.js.map +1 -1
  42. package/dist/cards/impl/trinket/artisanal-urn.js +3 -2
  43. package/dist/cards/impl/trinket/artisanal-urn.js.map +1 -1
  44. package/dist/cards/impl/trinket/blood-golem-sticker.d.ts +2 -2
  45. package/dist/cards/impl/trinket/blood-golem-sticker.js +2 -2
  46. package/dist/cards/impl/trinket/blood-golem-sticker.js.map +1 -1
  47. package/dist/cards/impl/trinket/miniature-ship.js +21 -1
  48. package/dist/cards/impl/trinket/miniature-ship.js.map +1 -1
  49. package/dist/cards/impl/trinket/soul-fermenter.js +4 -1
  50. package/dist/cards/impl/trinket/soul-fermenter.js.map +1 -1
  51. package/dist/input-clone.js +8 -2
  52. package/dist/input-clone.js.map +1 -1
  53. package/dist/mechanics/tavern-spell-repeat.js +4 -4
  54. package/dist/mechanics/tavern-spell-repeat.js.map +1 -1
  55. package/dist/simulation/add-minion-to-board.js +5 -2
  56. package/dist/simulation/add-minion-to-board.js.map +1 -1
  57. package/dist/simulation/attack.js +8 -1
  58. package/dist/simulation/attack.js.map +1 -1
  59. package/dist/simulation/auras.js +8 -5
  60. package/dist/simulation/auras.js.map +1 -1
  61. package/dist/simulation/death-effects.js +21 -4
  62. package/dist/simulation/death-effects.js.map +1 -1
  63. package/dist/simulation/deathrattle-effects.js +8 -1
  64. package/dist/simulation/deathrattle-effects.js.map +1 -1
  65. package/dist/simulation/deathrattle-orchestration.js +2 -6
  66. package/dist/simulation/deathrattle-orchestration.js.map +1 -1
  67. package/dist/simulation/deathrattle-spawns.d.ts +3 -1
  68. package/dist/simulation/deathrattle-spawns.js +32 -2
  69. package/dist/simulation/deathrattle-spawns.js.map +1 -1
  70. package/dist/simulation/deity.d.ts +6 -1
  71. package/dist/simulation/deity.js +23 -13
  72. package/dist/simulation/deity.js.map +1 -1
  73. package/dist/simulation/reborn.d.ts +10 -0
  74. package/dist/simulation/reborn.js +75 -8
  75. package/dist/simulation/reborn.js.map +1 -1
  76. package/dist/simulation/shared-state.d.ts +1 -0
  77. package/dist/simulation/shared-state.js +1 -0
  78. package/dist/simulation/shared-state.js.map +1 -1
  79. package/dist/simulation/start-of-combat/soc-illidan-hero-power.js +5 -2
  80. package/dist/simulation/start-of-combat/soc-illidan-hero-power.js.map +1 -1
  81. package/dist/simulation/start-of-combat/soc-minion.js +1 -1
  82. package/dist/simulation/start-of-combat/soc-minion.js.map +1 -1
  83. package/dist/simulation/start-of-combat/soc-trinket.js +35 -17
  84. package/dist/simulation/start-of-combat/soc-trinket.js.map +1 -1
  85. package/dist/simulation/start-of-combat/start-of-combat.js.map +1 -1
  86. package/dist/simulation/stats.js +8 -6
  87. package/dist/simulation/stats.js.map +1 -1
  88. package/dist/simulation/summon-when-space.js +13 -1
  89. package/dist/simulation/summon-when-space.js.map +1 -1
  90. package/package.json +10 -2
@@ -16,11 +16,13 @@ exports.YShaarj = {
16
16
  const spawned = [];
17
17
  for (const candidate of candidates) {
18
18
  const spawns = (0, deathrattle_spawns_1.spawnEntities)(candidate.cardId, 1, input.boardWithDeadEntity, input.boardWithDeadEntityHero, input.otherBoard, input.otherBoardHero, input.gameState, minion.friendly, false, false, true);
19
+ const attack = (_a = candidate.maxAttack) !== null && _a !== void 0 ? _a : candidate.attack;
20
+ const health = (_b = candidate.maxHealth) !== null && _b !== void 0 ? _b : candidate.health;
19
21
  for (const spawn of spawns) {
20
- spawn.attack = (_a = candidate.maxAttack) !== null && _a !== void 0 ? _a : candidate.attack;
21
- spawn.maxAttack = spawn.attack;
22
- spawn.health = (_b = candidate.maxHealth) !== null && _b !== void 0 ? _b : candidate.health;
23
- spawn.maxHealth = spawn.health;
22
+ spawn.attack = attack;
23
+ spawn.maxAttack = attack;
24
+ spawn.health = health;
25
+ spawn.maxHealth = health;
24
26
  }
25
27
  spawned.push(...spawns);
26
28
  }
@@ -1 +1 @@
1
- {"version":3,"file":"yshaarj.js","sourceRoot":"","sources":["../../../../src/cards/impl/minion/yshaarj.ts"],"names":[],"mappings":";;;AAYA,+EAAuE;AACvE,qDAAsE;AAGzD,QAAA,OAAO,GAAyB;IAC5C,OAAO,EAAE,4BAAwD;IACjE,gBAAgB,EAAE,CAAC,MAAmB,EAAE,KAAgC,EAA0B,EAAE;;QACnG,MAAM,aAAa,GAAG,MAAM,CAAC,cAAc,IAAI,CAAC,MAAM,CAAC,MAAM,kBAAgC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACvG,MAAM,UAAU,GAAG,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,MAAM;aACnD,MAAM,CACN,CAAC,MAAM,EAAE,EAAE,CACV,MAAM,CAAC,QAAQ,KAAK,MAAM,CAAC,QAAQ;YACnC,CAAC,IAAA,mBAAW,EAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC;YACrD,IAAA,oBAAY,EAAC,MAAM,EAAE,KAAK,CAAC,uBAAuB,EAAE,KAAK,CAAC,SAAS,CAAC,CACrE;aACA,KAAK,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;QAC1B,MAAM,OAAO,GAAkB,EAAE,CAAC;QAClC,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE;YACnC,MAAM,MAAM,GAAG,IAAA,kCAAa,EAC3B,SAAS,CAAC,MAAM,EAChB,CAAC,EACD,KAAK,CAAC,mBAAmB,EACzB,KAAK,CAAC,uBAAuB,EAC7B,KAAK,CAAC,UAAU,EAChB,KAAK,CAAC,cAAc,EACpB,KAAK,CAAC,SAAS,EACf,MAAM,CAAC,QAAQ,EACf,KAAK,EACL,KAAK,EACL,IAAI,CACJ,CAAC;YACF,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE;gBAC3B,KAAK,CAAC,MAAM,GAAG,MAAA,SAAS,CAAC,SAAS,mCAAI,SAAS,CAAC,MAAM,CAAC;gBACvD,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC;gBAC/B,KAAK,CAAC,MAAM,GAAG,MAAA,SAAS,CAAC,SAAS,mCAAI,SAAS,CAAC,MAAM,CAAC;gBACvD,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC;aAC/B;YACD,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC;SACxB;QACD,OAAO,OAAO,CAAC;IAChB,CAAC;CACD,CAAC","sourcesContent":["/**\r\n * Y'Shaarj (Tier 3, 1/1)\r\n * Deity. Deathrattle: Summon your first 2 Aberrations that died this combat\r\n * with their maximum stats (except Deities).\r\n *\r\n * Golden Y'Shaarj (Tier 3, 2/2)\r\n * Deity. Deathrattle: Summon your first 4 Aberrations that died this combat\r\n * with their maximum stats (except Deities).\r\n */\r\nimport { BoardEntity } from '../../../board-entity';\r\nimport { CardIds } from '../../../services/card-ids';\r\nimport { DeathrattleTriggeredInput } from '../../../simulation/deathrattle-on-trigger';\r\nimport { spawnEntities } from '../../../simulation/deathrattle-spawns';\r\nimport { isAberration, isDeityCard } from '../../../simulation/deity';\r\nimport { DeathrattleSpawnCard } from '../../card.interface';\r\n\r\nexport const YShaarj: DeathrattleSpawnCard = {\r\n\tcardIds: [CardIds.Yshaarj_BGFYM_011, CardIds.Yshaarj_BGFYM_011_G],\r\n\tdeathrattleSpawn: (minion: BoardEntity, input: DeathrattleTriggeredInput): readonly BoardEntity[] => {\r\n\t\tconst numberToSpawn = minion.scriptDataNum1 || (minion.cardId === CardIds.Yshaarj_BGFYM_011_G ? 4 : 2);\r\n\t\tconst candidates = input.gameState.sharedState.deaths\r\n\t\t\t.filter(\r\n\t\t\t\t(entity) =>\r\n\t\t\t\t\tentity.friendly === minion.friendly &&\r\n\t\t\t\t\t!isDeityCard(entity.cardId, input.gameState.allCards) &&\r\n\t\t\t\t\tisAberration(entity, input.boardWithDeadEntityHero, input.gameState),\r\n\t\t\t)\r\n\t\t\t.slice(0, numberToSpawn);\r\n\t\tconst spawned: BoardEntity[] = [];\r\n\t\tfor (const candidate of candidates) {\r\n\t\t\tconst spawns = spawnEntities(\r\n\t\t\t\tcandidate.cardId,\r\n\t\t\t\t1,\r\n\t\t\t\tinput.boardWithDeadEntity,\r\n\t\t\t\tinput.boardWithDeadEntityHero,\r\n\t\t\t\tinput.otherBoard,\r\n\t\t\t\tinput.otherBoardHero,\r\n\t\t\t\tinput.gameState,\r\n\t\t\t\tminion.friendly,\r\n\t\t\t\tfalse,\r\n\t\t\t\tfalse,\r\n\t\t\t\ttrue,\r\n\t\t\t);\r\n\t\t\tfor (const spawn of spawns) {\r\n\t\t\t\tspawn.attack = candidate.maxAttack ?? candidate.attack;\r\n\t\t\t\tspawn.maxAttack = spawn.attack;\r\n\t\t\t\tspawn.health = candidate.maxHealth ?? candidate.health;\r\n\t\t\t\tspawn.maxHealth = spawn.health;\r\n\t\t\t}\r\n\t\t\tspawned.push(...spawns);\r\n\t\t}\r\n\t\treturn spawned;\r\n\t},\r\n};\r\n"]}
1
+ {"version":3,"file":"yshaarj.js","sourceRoot":"","sources":["../../../../src/cards/impl/minion/yshaarj.ts"],"names":[],"mappings":";;;AAYA,+EAAuE;AACvE,qDAAsE;AAGzD,QAAA,OAAO,GAAyB;IAC5C,OAAO,EAAE,4BAAwD;IACjE,gBAAgB,EAAE,CAAC,MAAmB,EAAE,KAAgC,EAA0B,EAAE;;QACnG,MAAM,aAAa,GAAG,MAAM,CAAC,cAAc,IAAI,CAAC,MAAM,CAAC,MAAM,kBAAgC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACvG,MAAM,UAAU,GAAG,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,MAAM;aACnD,MAAM,CACN,CAAC,MAAM,EAAE,EAAE,CACV,MAAM,CAAC,QAAQ,KAAK,MAAM,CAAC,QAAQ;YACnC,CAAC,IAAA,mBAAW,EAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC;YACrD,IAAA,oBAAY,EAAC,MAAM,EAAE,KAAK,CAAC,uBAAuB,EAAE,KAAK,CAAC,SAAS,CAAC,CACrE;aACA,KAAK,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;QAC1B,MAAM,OAAO,GAAkB,EAAE,CAAC;QAClC,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE;YACnC,MAAM,MAAM,GAAG,IAAA,kCAAa,EAC3B,SAAS,CAAC,MAAM,EAChB,CAAC,EACD,KAAK,CAAC,mBAAmB,EACzB,KAAK,CAAC,uBAAuB,EAC7B,KAAK,CAAC,UAAU,EAChB,KAAK,CAAC,cAAc,EACpB,KAAK,CAAC,SAAS,EACf,MAAM,CAAC,QAAQ,EACf,KAAK,EACL,KAAK,EACL,IAAI,CACJ,CAAC;YACF,MAAM,MAAM,GAAG,MAAA,SAAS,CAAC,SAAS,mCAAI,SAAS,CAAC,MAAM,CAAC;YACvD,MAAM,MAAM,GAAG,MAAA,SAAS,CAAC,SAAS,mCAAI,SAAS,CAAC,MAAM,CAAC;YACvD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE;gBAC3B,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;gBACtB,KAAK,CAAC,SAAS,GAAG,MAAM,CAAC;gBACzB,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;gBACtB,KAAK,CAAC,SAAS,GAAG,MAAM,CAAC;aACzB;YACD,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC;SACxB;QACD,OAAO,OAAO,CAAC;IAChB,CAAC;CACD,CAAC","sourcesContent":["/**\r\n * Y'Shaarj (Tier 3, 1/1)\r\n * Deity. Deathrattle: Summon your first 2 Aberrations that died this combat\r\n * with their maximum stats (except Deities).\r\n *\r\n * Golden Y'Shaarj (Tier 3, 2/2)\r\n * Deity. Deathrattle: Summon your first 4 Aberrations that died this combat\r\n * with their maximum stats (except Deities).\r\n */\r\nimport { BoardEntity } from '../../../board-entity';\r\nimport { CardIds } from '../../../services/card-ids';\r\nimport { DeathrattleTriggeredInput } from '../../../simulation/deathrattle-on-trigger';\r\nimport { spawnEntities } from '../../../simulation/deathrattle-spawns';\r\nimport { isAberration, isDeityCard } from '../../../simulation/deity';\r\nimport { DeathrattleSpawnCard } from '../../card.interface';\r\n\r\nexport const YShaarj: DeathrattleSpawnCard = {\r\n\tcardIds: [CardIds.Yshaarj_BGFYM_011, CardIds.Yshaarj_BGFYM_011_G],\r\n\tdeathrattleSpawn: (minion: BoardEntity, input: DeathrattleTriggeredInput): readonly BoardEntity[] => {\r\n\t\tconst numberToSpawn = minion.scriptDataNum1 || (minion.cardId === CardIds.Yshaarj_BGFYM_011_G ? 4 : 2);\r\n\t\tconst candidates = input.gameState.sharedState.deaths\r\n\t\t\t.filter(\r\n\t\t\t\t(entity) =>\r\n\t\t\t\t\tentity.friendly === minion.friendly &&\r\n\t\t\t\t\t!isDeityCard(entity.cardId, input.gameState.allCards) &&\r\n\t\t\t\t\tisAberration(entity, input.boardWithDeadEntityHero, input.gameState),\r\n\t\t\t)\r\n\t\t\t.slice(0, numberToSpawn);\r\n\t\tconst spawned: BoardEntity[] = [];\r\n\t\tfor (const candidate of candidates) {\r\n\t\t\tconst spawns = spawnEntities(\r\n\t\t\t\tcandidate.cardId,\r\n\t\t\t\t1,\r\n\t\t\t\tinput.boardWithDeadEntity,\r\n\t\t\t\tinput.boardWithDeadEntityHero,\r\n\t\t\t\tinput.otherBoard,\r\n\t\t\t\tinput.otherBoardHero,\r\n\t\t\t\tinput.gameState,\r\n\t\t\t\tminion.friendly,\r\n\t\t\t\tfalse,\r\n\t\t\t\tfalse,\r\n\t\t\t\ttrue,\r\n\t\t\t);\r\n\t\t\tconst attack = candidate.maxAttack ?? candidate.attack;\r\n\t\t\tconst health = candidate.maxHealth ?? candidate.health;\r\n\t\t\tfor (const spawn of spawns) {\r\n\t\t\t\tspawn.attack = attack;\r\n\t\t\t\tspawn.maxAttack = attack;\r\n\t\t\t\tspawn.health = health;\r\n\t\t\t\tspawn.maxHealth = health;\r\n\t\t\t}\r\n\t\t\tspawned.push(...spawns);\r\n\t\t}\r\n\t\treturn spawned;\r\n\t},\r\n};\r\n"]}
@@ -1,12 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ArtisanalUrn = void 0;
4
- const global_info_helpers_1 = require("../../../simulation/global-info-helpers");
5
4
  exports.ArtisanalUrn = {
6
5
  cardIds: ["BG30_MagicItem_989", "BG30_MagicItem_989t"],
7
6
  startOfCombat: (trinket, input) => {
7
+ var _a;
8
8
  const buff = trinket.cardId === "BG30_MagicItem_989" ? 4 : 20;
9
- (0, global_info_helpers_1.increaseUndeadAttackBonus)(input.playerEntity, input.playerBoard, input.playerEntity, buff, input.gameState);
9
+ input.playerEntity.globalInfo.UndeadAttackBonus =
10
+ ((_a = input.playerEntity.globalInfo.UndeadAttackBonus) !== null && _a !== void 0 ? _a : 0) + buff;
10
11
  return { hasTriggered: true, shouldRecomputeCurrentAttacker: false };
11
12
  },
12
13
  };
@@ -1 +1 @@
1
- {"version":3,"file":"artisanal-urn.js","sourceRoot":"","sources":["../../../../src/cards/impl/trinket/artisanal-urn.ts"],"names":[],"mappings":";;;AAEA,iFAAoF;AAIvE,QAAA,YAAY,GAAsB;IAC9C,OAAO,EAAE,6CAAqG;IAC9G,aAAa,EAAE,CAAC,OAAqB,EAAE,KAAe,EAAE,EAAE;QACzD,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,yBAA4C,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACjF,IAAA,+CAAyB,EAAC,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,YAAY,EAAE,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;QAC5G,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,8BAA8B,EAAE,KAAK,EAAE,CAAC;IACtE,CAAC;CACD,CAAC","sourcesContent":["import { BoardTrinket } from '../../../bgs-player-entity';\r\nimport { CardIds } from '../../../services/card-ids';\r\nimport { increaseUndeadAttackBonus } from '../../../simulation/global-info-helpers';\r\nimport { SoCInput } from '../../../simulation/start-of-combat/start-of-combat-input';\r\nimport { StartOfCombatCard } from '../../card.interface';\r\n\r\nexport const ArtisanalUrn: StartOfCombatCard = {\r\n\tcardIds: [CardIds.ArtisanalUrn_BG30_MagicItem_989, CardIds.ArtisanalUrn_ArtisanalUrnToken_BG30_MagicItem_989t],\r\n\tstartOfCombat: (trinket: BoardTrinket, input: SoCInput) => {\r\n\t\tconst buff = trinket.cardId === CardIds.ArtisanalUrn_BG30_MagicItem_989 ? 4 : 20;\r\n\t\tincreaseUndeadAttackBonus(input.playerEntity, input.playerBoard, input.playerEntity, buff, input.gameState);\r\n\t\treturn { hasTriggered: true, shouldRecomputeCurrentAttacker: false };\r\n\t},\r\n};\r\n"]}
1
+ {"version":3,"file":"artisanal-urn.js","sourceRoot":"","sources":["../../../../src/cards/impl/trinket/artisanal-urn.ts"],"names":[],"mappings":";;;AAUa,QAAA,YAAY,GAAsB;IAC9C,OAAO,EAAE,6CAAqG;IAC9G,aAAa,EAAE,CAAC,OAAqB,EAAE,KAAe,EAAE,EAAE;;QACzD,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,yBAA4C,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACjF,KAAK,CAAC,YAAY,CAAC,UAAU,CAAC,iBAAiB;YAC9C,CAAC,MAAA,KAAK,CAAC,YAAY,CAAC,UAAU,CAAC,iBAAiB,mCAAI,CAAC,CAAC,GAAG,IAAI,CAAC;QAC/D,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,8BAA8B,EAAE,KAAK,EAAE,CAAC;IACtE,CAAC;CACD,CAAC","sourcesContent":["import { BoardTrinket } from '../../../bgs-player-entity';\r\nimport { CardIds } from '../../../services/card-ids';\r\nimport { SoCInput } from '../../../simulation/start-of-combat/start-of-combat-input';\r\nimport { StartOfCombatCard } from '../../card.interface';\r\n\r\n/**\r\n * Your Undead have +4 Attack (greater: +20).\r\n * Recruit-board stats already include the aura. Start of combat only raises\r\n * UndeadAttackBonus so minions summoned during combat receive it once.\r\n */\r\nexport const ArtisanalUrn: StartOfCombatCard = {\r\n\tcardIds: [CardIds.ArtisanalUrn_BG30_MagicItem_989, CardIds.ArtisanalUrn_ArtisanalUrnToken_BG30_MagicItem_989t],\r\n\tstartOfCombat: (trinket: BoardTrinket, input: SoCInput) => {\r\n\t\tconst buff = trinket.cardId === CardIds.ArtisanalUrn_BG30_MagicItem_989 ? 4 : 20;\r\n\t\tinput.playerEntity.globalInfo.UndeadAttackBonus =\r\n\t\t\t(input.playerEntity.globalInfo.UndeadAttackBonus ?? 0) + buff;\r\n\t\treturn { hasTriggered: true, shouldRecomputeCurrentAttacker: false };\r\n\t},\r\n};\r\n"]}
@@ -1,2 +1,2 @@
1
- import { DefaultScriptDataNumCard, OnAfterDeathCard } from '../../card.interface';
2
- export declare const BloodGolemSticker: OnAfterDeathCard & DefaultScriptDataNumCard;
1
+ import { BeforeRebornCard, DefaultScriptDataNumCard } from '../../card.interface';
2
+ export declare const BloodGolemSticker: BeforeRebornCard & DefaultScriptDataNumCard;
@@ -8,7 +8,7 @@ const utils_1 = require("../../../utils");
8
8
  exports.BloodGolemSticker = {
9
9
  cardIds: ["BG30_MagicItem_442"],
10
10
  defaultScriptDataNum: (cardId) => 9999,
11
- onAfterDeath: (trinket, input) => {
11
+ beforeReborn: (trinket, input) => {
12
12
  const { hero, gameState, board, otherBoard, otherHero } = input;
13
13
  for (const deadEntity of input.deadEntities) {
14
14
  if (deadEntity.friendly === hero.friendly &&
@@ -30,7 +30,7 @@ exports.BloodGolemSticker = {
30
30
  spawns.forEach((b) => {
31
31
  b.attack = bloodGemAttack;
32
32
  b.health = bloodGemHealth;
33
- b.hasAttacked = deadEntity.hasAttacked;
33
+ b.hasAttacked = 1;
34
34
  });
35
35
  (0, spawns_1.performEntitySpawns)(spawns, board, hero, deadEntity, indexFromRight, otherBoard, otherHero, gameState);
36
36
  }
@@ -1 +1 @@
1
- {"version":3,"file":"blood-golem-sticker.js","sourceRoot":"","sources":["../../../../src/cards/impl/trinket/blood-golem-sticker.ts"],"names":[],"mappings":";;;AAAA,iEAAoD;AAIpD,+EAAuE;AACvE,uDAAiE;AACjE,0CAAiD;AAKpC,QAAA,iBAAiB,GAAgD;IAC7E,OAAO,EAAE,sBAA8C;IACvD,oBAAoB,EAAE,CAAC,MAAc,EAAE,EAAE,CAAC,IAAI;IAC9C,YAAY,EAAE,CAAC,OAAqB,EAAE,KAAwB,EAAE,EAAE;QACjE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC;QAChE,KAAK,MAAM,UAAU,IAAI,KAAK,CAAC,YAAY,EAAE;YAC5C,IACC,UAAU,CAAC,QAAQ,KAAK,IAAI,CAAC,QAAQ;gBACrC,IAAA,uBAAe,EAAC,UAAU,EAAE,IAAI,EAAE,qBAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC,QAAQ,CAAC,EACxF;gBAED,MAAM,cAAc,GAAG,KAAK,CAAC,4BAA4B,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC;gBACtG,IAAI,oBAAoB,GAAG,UAAU,CAAC,YAAY,CAAC,MAAM,CACxD,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,iBAA0C,CACzD,CAAC;gBACF,IAAI,CAAA,oBAAoB,aAApB,oBAAoB,uBAApB,oBAAoB,CAAE,MAAM,MAAK,CAAC,EAAE;oBACvC,oBAAoB,GAAG,UAAU,CAAC,YAAY,CAAC,MAAM,CACpD,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,gBAAyC,CACxD,CAAC;iBACF;gBACD,IAAI,CAAA,oBAAoB,aAApB,oBAAoB,uBAApB,oBAAoB,CAAE,MAAM,IAAG,CAAC,EAAE;oBACrC,MAAM,cAAc,GAAG,oBAAoB;yBACzC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,WAAC,OAAA,MAAA,CAAC,CAAC,iBAAiB,mCAAI,CAAC,CAAA,EAAA,CAAC;yBACpC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;oBAC7B,MAAM,cAAc,GAAG,oBAAoB;yBACzC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,WAAC,OAAA,MAAA,CAAC,CAAC,iBAAiB,mCAAI,CAAC,CAAA,EAAA,CAAC;yBACpC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;oBAC7B,IAAI,cAAc,GAAG,CAAC,IAAI,cAAc,GAAG,CAAC,EAAE;wBAC7C,MAAM,MAAM,GAAG,IAAA,kCAAa,yBAE3B,CAAC,EACD,KAAK,EACL,IAAI,EACJ,UAAU,EACV,SAAS,EACT,SAAS,EACT,UAAU,CAAC,QAAQ,EACnB,KAAK,CACL,CAAC;wBACF,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;4BACpB,CAAC,CAAC,MAAM,GAAG,cAAc,CAAC;4BAC1B,CAAC,CAAC,MAAM,GAAG,cAAc,CAAC;4BAC1B,CAAC,CAAC,WAAW,GAAG,UAAU,CAAC,WAAW,CAAC;wBACxC,CAAC,CAAC,CAAC;wBACH,IAAA,4BAAmB,EAClB,MAAM,EACN,KAAK,EACL,IAAI,EACJ,UAAU,EACV,cAAc,EACd,UAAU,EACV,SAAS,EACT,SAAS,CACT,CAAC;qBACF;iBACD;aACD;SACD;IACF,CAAC;CACD,CAAC","sourcesContent":["import { Race } from '@firestone-hs/reference-data';\r\nimport { BoardTrinket } from '../../../bgs-player-entity';\r\nimport { CardIds } from '../../../services/card-ids';\r\nimport { OnAfterDeathInput } from '../../../simulation/attack';\r\nimport { spawnEntities } from '../../../simulation/deathrattle-spawns';\r\nimport { performEntitySpawns } from '../../../simulation/spawns';\r\nimport { hasCorrectTribe } from '../../../utils';\r\nimport { DefaultScriptDataNumCard, OnAfterDeathCard } from '../../card.interface';\r\n\r\n// 2026-04-17: Deathrattles trigger before the Sticker\r\n// https://replays.firestoneapp.com/?reviewId=99605623-18e1-45ad-a7a1-daf7ef29adcb&turn=23&action=7\r\nexport const BloodGolemSticker: OnAfterDeathCard & DefaultScriptDataNumCard = {\r\n\tcardIds: [CardIds.BloodGolemSticker_BG30_MagicItem_442],\r\n\tdefaultScriptDataNum: (cardId: string) => 9999, // Unlimited, just easier to update\r\n\tonAfterDeath: (trinket: BoardTrinket, input: OnAfterDeathInput) => {\r\n\t\tconst { hero, gameState, board, otherBoard, otherHero } = input;\r\n\t\tfor (const deadEntity of input.deadEntities) {\r\n\t\t\tif (\r\n\t\t\t\tdeadEntity.friendly === hero.friendly &&\r\n\t\t\t\thasCorrectTribe(deadEntity, hero, Race.QUILBOAR, gameState.anomalies, gameState.allCards)\r\n\t\t\t) {\r\n\t\t\t\t// -1 because the minion is already removed from the board\r\n\t\t\t\tconst indexFromRight = input.deadEntitiesIndexesFromRight[input.deadEntities.indexOf(deadEntity)] + 1;\r\n\t\t\t\tlet bloodGemEnchantments = deadEntity.enchantments.filter(\r\n\t\t\t\t\t(e) => e.cardId === CardIds.BloodGem_BloodGemsEnchantment,\r\n\t\t\t\t);\r\n\t\t\t\tif (bloodGemEnchantments?.length === 0) {\r\n\t\t\t\t\tbloodGemEnchantments = deadEntity.enchantments.filter(\r\n\t\t\t\t\t\t(e) => e.cardId === CardIds.BloodGem_BloodGemEnchantment,\r\n\t\t\t\t\t);\r\n\t\t\t\t}\r\n\t\t\t\tif (bloodGemEnchantments?.length > 0) {\r\n\t\t\t\t\tconst bloodGemAttack = bloodGemEnchantments\r\n\t\t\t\t\t\t.map((e) => e.tagScriptDataNum1 ?? 0)\r\n\t\t\t\t\t\t.reduce((a, b) => a + b, 0);\r\n\t\t\t\t\tconst bloodGemHealth = bloodGemEnchantments\r\n\t\t\t\t\t\t.map((e) => e.tagScriptDataNum2 ?? 0)\r\n\t\t\t\t\t\t.reduce((a, b) => a + b, 0);\r\n\t\t\t\t\tif (bloodGemAttack > 0 || bloodGemHealth > 0) {\r\n\t\t\t\t\t\tconst spawns = spawnEntities(\r\n\t\t\t\t\t\t\tCardIds.BloodGolemSticker_BloodGolemToken_BG30_MagicItem_442t,\r\n\t\t\t\t\t\t\t1,\r\n\t\t\t\t\t\t\tboard,\r\n\t\t\t\t\t\t\thero,\r\n\t\t\t\t\t\t\totherBoard,\r\n\t\t\t\t\t\t\totherHero,\r\n\t\t\t\t\t\t\tgameState,\r\n\t\t\t\t\t\t\tdeadEntity.friendly,\r\n\t\t\t\t\t\t\tfalse,\r\n\t\t\t\t\t\t);\r\n\t\t\t\t\t\tspawns.forEach((b) => {\r\n\t\t\t\t\t\t\tb.attack = bloodGemAttack;\r\n\t\t\t\t\t\t\tb.health = bloodGemHealth;\r\n\t\t\t\t\t\t\tb.hasAttacked = deadEntity.hasAttacked;\r\n\t\t\t\t\t\t});\r\n\t\t\t\t\t\tperformEntitySpawns(\r\n\t\t\t\t\t\t\tspawns,\r\n\t\t\t\t\t\t\tboard,\r\n\t\t\t\t\t\t\thero,\r\n\t\t\t\t\t\t\tdeadEntity,\r\n\t\t\t\t\t\t\tindexFromRight,\r\n\t\t\t\t\t\t\totherBoard,\r\n\t\t\t\t\t\t\totherHero,\r\n\t\t\t\t\t\t\tgameState,\r\n\t\t\t\t\t\t);\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"]}
1
+ {"version":3,"file":"blood-golem-sticker.js","sourceRoot":"","sources":["../../../../src/cards/impl/trinket/blood-golem-sticker.ts"],"names":[],"mappings":";;;AAAA,iEAAoD;AAGpD,+EAAuE;AAEvE,uDAAiE;AACjE,0CAAiD;AAQpC,QAAA,iBAAiB,GAAgD;IAC7E,OAAO,EAAE,sBAA8C;IACvD,oBAAoB,EAAE,CAAC,MAAc,EAAE,EAAE,CAAC,IAAI;IAC9C,YAAY,EAAE,CAAC,OAAqB,EAAE,KAAwB,EAAE,EAAE;QACjE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC;QAChE,KAAK,MAAM,UAAU,IAAI,KAAK,CAAC,YAAY,EAAE;YAC5C,IACC,UAAU,CAAC,QAAQ,KAAK,IAAI,CAAC,QAAQ;gBACrC,IAAA,uBAAe,EAAC,UAAU,EAAE,IAAI,EAAE,qBAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC,QAAQ,CAAC,EACxF;gBAED,MAAM,cAAc,GAAG,KAAK,CAAC,4BAA4B,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC;gBACtG,IAAI,oBAAoB,GAAG,UAAU,CAAC,YAAY,CAAC,MAAM,CACxD,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,iBAA0C,CACzD,CAAC;gBACF,IAAI,CAAA,oBAAoB,aAApB,oBAAoB,uBAApB,oBAAoB,CAAE,MAAM,MAAK,CAAC,EAAE;oBACvC,oBAAoB,GAAG,UAAU,CAAC,YAAY,CAAC,MAAM,CACpD,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,gBAAyC,CACxD,CAAC;iBACF;gBACD,IAAI,CAAA,oBAAoB,aAApB,oBAAoB,uBAApB,oBAAoB,CAAE,MAAM,IAAG,CAAC,EAAE;oBACrC,MAAM,cAAc,GAAG,oBAAoB;yBACzC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,WAAC,OAAA,MAAA,CAAC,CAAC,iBAAiB,mCAAI,CAAC,CAAA,EAAA,CAAC;yBACpC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;oBAC7B,MAAM,cAAc,GAAG,oBAAoB;yBACzC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,WAAC,OAAA,MAAA,CAAC,CAAC,iBAAiB,mCAAI,CAAC,CAAA,EAAA,CAAC;yBACpC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;oBAC7B,IAAI,cAAc,GAAG,CAAC,IAAI,cAAc,GAAG,CAAC,EAAE;wBAC7C,MAAM,MAAM,GAAG,IAAA,kCAAa,yBAE3B,CAAC,EACD,KAAK,EACL,IAAI,EACJ,UAAU,EACV,SAAS,EACT,SAAS,EACT,UAAU,CAAC,QAAQ,EACnB,KAAK,CACL,CAAC;wBACF,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;4BACpB,CAAC,CAAC,MAAM,GAAG,cAAc,CAAC;4BAC1B,CAAC,CAAC,MAAM,GAAG,cAAc,CAAC;4BAI1B,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC;wBACnB,CAAC,CAAC,CAAC;wBACH,IAAA,4BAAmB,EAClB,MAAM,EACN,KAAK,EACL,IAAI,EACJ,UAAU,EACV,cAAc,EACd,UAAU,EACV,SAAS,EACT,SAAS,CACT,CAAC;qBACF;iBACD;aACD;SACD;IACF,CAAC;CACD,CAAC","sourcesContent":["import { Race } from '@firestone-hs/reference-data';\r\nimport { BoardTrinket } from '../../../bgs-player-entity';\r\nimport { CardIds } from '../../../services/card-ids';\r\nimport { spawnEntities } from '../../../simulation/deathrattle-spawns';\r\nimport { BeforeRebornInput } from '../../../simulation/reborn';\r\nimport { performEntitySpawns } from '../../../simulation/spawns';\r\nimport { hasCorrectTribe } from '../../../utils';\r\nimport { BeforeRebornCard, DefaultScriptDataNumCard } from '../../card.interface';\r\n\r\n// 2026-04-17: Deathrattles trigger before the Sticker\r\n// https://replays.firestoneapp.com/?reviewId=99605623-18e1-45ad-a7a1-daf7ef29adcb&turn=23&action=7\r\n// The sticker also summons before Reborn. On a full board the golem takes the last\r\n// slot and the reborn copy never enters play.\r\n// https://replays.firestoneapp.com/?debug=true&reviewId=07e140d6-9225-4315-93ad-2e1beaa86707&turn=31&action=0\r\nexport const BloodGolemSticker: BeforeRebornCard & DefaultScriptDataNumCard = {\r\n\tcardIds: [CardIds.BloodGolemSticker_BG30_MagicItem_442],\r\n\tdefaultScriptDataNum: (cardId: string) => 9999, // Unlimited, just easier to update\r\n\tbeforeReborn: (trinket: BoardTrinket, input: BeforeRebornInput) => {\r\n\t\tconst { hero, gameState, board, otherBoard, otherHero } = input;\r\n\t\tfor (const deadEntity of input.deadEntities) {\r\n\t\t\tif (\r\n\t\t\t\tdeadEntity.friendly === hero.friendly &&\r\n\t\t\t\thasCorrectTribe(deadEntity, hero, Race.QUILBOAR, gameState.anomalies, gameState.allCards)\r\n\t\t\t) {\r\n\t\t\t\t// -1 because the minion is already removed from the board\r\n\t\t\t\tconst indexFromRight = input.deadEntitiesIndexesFromRight[input.deadEntities.indexOf(deadEntity)] + 1;\r\n\t\t\t\tlet bloodGemEnchantments = deadEntity.enchantments.filter(\r\n\t\t\t\t\t(e) => e.cardId === CardIds.BloodGem_BloodGemsEnchantment,\r\n\t\t\t\t);\r\n\t\t\t\tif (bloodGemEnchantments?.length === 0) {\r\n\t\t\t\t\tbloodGemEnchantments = deadEntity.enchantments.filter(\r\n\t\t\t\t\t\t(e) => e.cardId === CardIds.BloodGem_BloodGemEnchantment,\r\n\t\t\t\t\t);\r\n\t\t\t\t}\r\n\t\t\t\tif (bloodGemEnchantments?.length > 0) {\r\n\t\t\t\t\tconst bloodGemAttack = bloodGemEnchantments\r\n\t\t\t\t\t\t.map((e) => e.tagScriptDataNum1 ?? 0)\r\n\t\t\t\t\t\t.reduce((a, b) => a + b, 0);\r\n\t\t\t\t\tconst bloodGemHealth = bloodGemEnchantments\r\n\t\t\t\t\t\t.map((e) => e.tagScriptDataNum2 ?? 0)\r\n\t\t\t\t\t\t.reduce((a, b) => a + b, 0);\r\n\t\t\t\t\tif (bloodGemAttack > 0 || bloodGemHealth > 0) {\r\n\t\t\t\t\t\tconst spawns = spawnEntities(\r\n\t\t\t\t\t\t\tCardIds.BloodGolemSticker_BloodGolemToken_BG30_MagicItem_442t,\r\n\t\t\t\t\t\t\t1,\r\n\t\t\t\t\t\t\tboard,\r\n\t\t\t\t\t\t\thero,\r\n\t\t\t\t\t\t\totherBoard,\r\n\t\t\t\t\t\t\totherHero,\r\n\t\t\t\t\t\t\tgameState,\r\n\t\t\t\t\t\t\tdeadEntity.friendly,\r\n\t\t\t\t\t\t\tfalse,\r\n\t\t\t\t\t\t);\r\n\t\t\t\t\t\tspawns.forEach((b) => {\r\n\t\t\t\t\t\t\tb.attack = bloodGemAttack;\r\n\t\t\t\t\t\t\tb.health = bloodGemHealth;\r\n\t\t\t\t\t\t\t// Golems are summoned exhausted, including when the quilboar dies\r\n\t\t\t\t\t\t\t// mid-attack before hasAttacked is flagged on the attacker.\r\n\t\t\t\t\t\t\t// https://replays.firestoneapp.com/?reviewId=23b6fbea-e43a-431f-a5ea-7ed23b017fcf&turn=25&action=0\r\n\t\t\t\t\t\t\tb.hasAttacked = 1;\r\n\t\t\t\t\t\t});\r\n\t\t\t\t\t\tperformEntitySpawns(\r\n\t\t\t\t\t\t\tspawns,\r\n\t\t\t\t\t\t\tboard,\r\n\t\t\t\t\t\t\thero,\r\n\t\t\t\t\t\t\tdeadEntity,\r\n\t\t\t\t\t\t\tindexFromRight,\r\n\t\t\t\t\t\t\totherBoard,\r\n\t\t\t\t\t\t\totherHero,\r\n\t\t\t\t\t\t\tgameState,\r\n\t\t\t\t\t\t);\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"]}
@@ -4,6 +4,25 @@ exports.MiniatureShip = void 0;
4
4
  const reference_data_1 = require("@firestone-hs/reference-data");
5
5
  const stats_1 = require("../../../simulation/stats");
6
6
  const utils_1 = require("../../../utils");
7
+ const SET_SAIL = "BG35_MagicItem_710e";
8
+ const BONUS = 3;
9
+ const rememberSetSail = (entity, trinket, gameState) => {
10
+ var _a, _b, _c;
11
+ entity.enchantments = (_a = entity.enchantments) !== null && _a !== void 0 ? _a : [];
12
+ const existing = entity.enchantments.find((enchantment) => enchantment.cardId === SET_SAIL);
13
+ if (existing) {
14
+ existing.tagScriptDataNum1 = Math.max(0, (_b = existing.tagScriptDataNum1) !== null && _b !== void 0 ? _b : 0) + BONUS;
15
+ existing.tagScriptDataNum2 = Math.max(0, (_c = existing.tagScriptDataNum2) !== null && _c !== void 0 ? _c : 0) + BONUS;
16
+ return;
17
+ }
18
+ entity.enchantments.push({
19
+ cardId: SET_SAIL,
20
+ originEntityId: trinket.entityId,
21
+ timing: gameState.sharedState.currentEntityId++,
22
+ tagScriptDataNum1: BONUS,
23
+ tagScriptDataNum2: BONUS,
24
+ });
25
+ };
7
26
  exports.MiniatureShip = {
8
27
  cardIds: ["BG35_MagicItem_710"],
9
28
  afterTavernSpellCast: (trinket, input) => {
@@ -11,7 +30,8 @@ exports.MiniatureShip = {
11
30
  if (entity.health <= 0 || entity.definitelyDead)
12
31
  continue;
13
32
  if ((0, utils_1.hasCorrectTribe)(entity, input.hero, reference_data_1.Race.PIRATE, input.gameState.anomalies, input.gameState.allCards)) {
14
- (0, stats_1.modifyStats)(entity, trinket, 3, 3, input.board, input.hero, input.gameState);
33
+ (0, stats_1.modifyStats)(entity, trinket, BONUS, BONUS, input.board, input.hero, input.gameState);
34
+ rememberSetSail(entity, trinket, input.gameState);
15
35
  }
16
36
  }
17
37
  },
@@ -1 +1 @@
1
- {"version":3,"file":"miniature-ship.js","sourceRoot":"","sources":["../../../../src/cards/impl/trinket/miniature-ship.ts"],"names":[],"mappings":";;;AAAA,iEAAoD;AAGpD,qDAAwD;AACxD,0CAAiD;AAGpC,QAAA,aAAa,GAA6B;IACtD,OAAO,EAAE,sBAA0C;IACnD,oBAAoB,EAAE,CAAC,OAAqB,EAAE,KAAqB,EAAE,EAAE;QACtE,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,KAAK,EAAE;YACjC,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,MAAM,CAAC,cAAc;gBAAE,SAAS;YAC1D,IAAI,IAAA,uBAAe,EAAC,MAAM,EAAE,KAAK,CAAC,IAAI,EAAE,qBAAI,CAAC,MAAM,EAAE,KAAK,CAAC,SAAS,CAAC,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE;gBAC1G,IAAA,mBAAW,EAAC,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;aAC7E;SACD;IACF,CAAC;CACD,CAAC","sourcesContent":["import { Race } from '@firestone-hs/reference-data';\r\nimport { BoardTrinket } from '../../../bgs-player-entity';\r\nimport { CardIds } from '../../../services/card-ids';\r\nimport { modifyStats } from '../../../simulation/stats';\r\nimport { hasCorrectTribe } from '../../../utils';\r\nimport { AfterTavernSpellCastCard, CastSpellInput } from '../../card.interface';\r\n\r\nexport const MiniatureShip: AfterTavernSpellCastCard = {\r\n\tcardIds: [CardIds.MiniatureShip_BG35_MagicItem_710],\r\n\tafterTavernSpellCast: (trinket: BoardTrinket, input: CastSpellInput) => {\r\n\t\tfor (const entity of input.board) {\r\n\t\t\tif (entity.health <= 0 || entity.definitelyDead) continue;\r\n\t\t\tif (hasCorrectTribe(entity, input.hero, Race.PIRATE, input.gameState.anomalies, input.gameState.allCards)) {\r\n\t\t\t\tmodifyStats(entity, trinket, 3, 3, input.board, input.hero, input.gameState);\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n};\r\n"]}
1
+ {"version":3,"file":"miniature-ship.js","sourceRoot":"","sources":["../../../../src/cards/impl/trinket/miniature-ship.ts"],"names":[],"mappings":";;;AAAA,iEAAoD;AAKpD,qDAAwD;AACxD,0CAAiD;AAGjD,MAAM,QAAQ,wBAA+D,CAAC;AAC9E,MAAM,KAAK,GAAG,CAAC,CAAC;AAOhB,MAAM,eAAe,GAAG,CAAC,MAAmB,EAAE,OAAqB,EAAE,SAAwB,EAAE,EAAE;;IAChG,MAAM,CAAC,YAAY,GAAG,MAAA,MAAM,CAAC,YAAY,mCAAI,EAAE,CAAC;IAChD,MAAM,QAAQ,GAAG,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,WAAW,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC;IAC5F,IAAI,QAAQ,EAAE;QACb,QAAQ,CAAC,iBAAiB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAA,QAAQ,CAAC,iBAAiB,mCAAI,CAAC,CAAC,GAAG,KAAK,CAAC;QAClF,QAAQ,CAAC,iBAAiB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAA,QAAQ,CAAC,iBAAiB,mCAAI,CAAC,CAAC,GAAG,KAAK,CAAC;QAClF,OAAO;KACP;IACD,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC;QACxB,MAAM,EAAE,QAAQ;QAChB,cAAc,EAAE,OAAO,CAAC,QAAQ;QAChC,MAAM,EAAE,SAAS,CAAC,WAAW,CAAC,eAAe,EAAE;QAC/C,iBAAiB,EAAE,KAAK;QACxB,iBAAiB,EAAE,KAAK;KACxB,CAAC,CAAC;AACJ,CAAC,CAAC;AAEW,QAAA,aAAa,GAA6B;IACtD,OAAO,EAAE,sBAA0C;IACnD,oBAAoB,EAAE,CAAC,OAAqB,EAAE,KAAqB,EAAE,EAAE;QACtE,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,KAAK,EAAE;YACjC,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,MAAM,CAAC,cAAc;gBAAE,SAAS;YAC1D,IAAI,IAAA,uBAAe,EAAC,MAAM,EAAE,KAAK,CAAC,IAAI,EAAE,qBAAI,CAAC,MAAM,EAAE,KAAK,CAAC,SAAS,CAAC,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE;gBAC1G,IAAA,mBAAW,EAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;gBACrF,eAAe,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;aAClD;SACD;IACF,CAAC;CACD,CAAC","sourcesContent":["import { Race } from '@firestone-hs/reference-data';\r\nimport { BoardTrinket } from '../../../bgs-player-entity';\r\nimport { BoardEntity } from '../../../board-entity';\r\nimport { CardIds } from '../../../services/card-ids';\r\nimport { FullGameState } from '../../../simulation/internal-game-state';\r\nimport { modifyStats } from '../../../simulation/stats';\r\nimport { hasCorrectTribe } from '../../../utils';\r\nimport { AfterTavernSpellCastCard, CastSpellInput } from '../../card.interface';\r\n\r\nconst SET_SAIL = CardIds.MiniatureShip_SetSailEnchantment_BG35_MagicItem_710e;\r\nconst BONUS = 3;\r\n\r\n/**\r\n * The buff is an aura stored on Set Sail. Stats already include it, and a later\r\n * stat set strips that enchantment and puts it back, so the stored totals have\r\n * to grow with each cast.\r\n */\r\nconst rememberSetSail = (entity: BoardEntity, trinket: BoardTrinket, gameState: FullGameState) => {\r\n\tentity.enchantments = entity.enchantments ?? [];\r\n\tconst existing = entity.enchantments.find((enchantment) => enchantment.cardId === SET_SAIL);\r\n\tif (existing) {\r\n\t\texisting.tagScriptDataNum1 = Math.max(0, existing.tagScriptDataNum1 ?? 0) + BONUS;\r\n\t\texisting.tagScriptDataNum2 = Math.max(0, existing.tagScriptDataNum2 ?? 0) + BONUS;\r\n\t\treturn;\r\n\t}\r\n\tentity.enchantments.push({\r\n\t\tcardId: SET_SAIL,\r\n\t\toriginEntityId: trinket.entityId,\r\n\t\ttiming: gameState.sharedState.currentEntityId++,\r\n\t\ttagScriptDataNum1: BONUS,\r\n\t\ttagScriptDataNum2: BONUS,\r\n\t});\r\n};\r\n\r\nexport const MiniatureShip: AfterTavernSpellCastCard = {\r\n\tcardIds: [CardIds.MiniatureShip_BG35_MagicItem_710],\r\n\tafterTavernSpellCast: (trinket: BoardTrinket, input: CastSpellInput) => {\r\n\t\tfor (const entity of input.board) {\r\n\t\t\tif (entity.health <= 0 || entity.definitelyDead) continue;\r\n\t\t\tif (hasCorrectTribe(entity, input.hero, Race.PIRATE, input.gameState.anomalies, input.gameState.allCards)) {\r\n\t\t\t\tmodifyStats(entity, trinket, BONUS, BONUS, input.board, input.hero, input.gameState);\r\n\t\t\t\trememberSetSail(entity, trinket, input.gameState);\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n};\r\n"]}
@@ -9,6 +9,9 @@ exports.SoulFermenter = {
9
9
  startOfCombatTiming: 'start-of-combat',
10
10
  startOfCombat: (trinket, input) => {
11
11
  const targets = input.playerBoard.slice(0, 3);
12
+ if (!targets.length) {
13
+ return false;
14
+ }
12
15
  trinket.rememberedMinions = [];
13
16
  for (const target of targets) {
14
17
  const copy = (0, utils_1.copyEntity)(target);
@@ -16,7 +19,7 @@ exports.SoulFermenter = {
16
19
  trinket.rememberedMinions.push(copy);
17
20
  target.definitelyDead = true;
18
21
  }
19
- return true;
22
+ return { hasTriggered: true, shouldRecomputeCurrentAttacker: true };
20
23
  },
21
24
  onAfterFriendlyMinionDeath: (trinket, input) => {
22
25
  var _a;
@@ -1 +1 @@
1
- {"version":3,"file":"soul-fermenter.js","sourceRoot":"","sources":["../../../../src/cards/impl/trinket/soul-fermenter.ts"],"names":[],"mappings":";;;AAEA,iFAA8E;AAE9E,+EAA+F;AAE/F,0CAA4C;AAG/B,QAAA,aAAa,GAAuD;IAChF,OAAO,EAAE,sBAA0C;IACnD,mBAAmB,EAAE,iBAAiB;IACtC,aAAa,EAAE,CAAC,OAAqB,EAAE,KAAe,EAAE,EAAE;QACzD,MAAM,OAAO,GAAG,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC9C,OAAO,CAAC,iBAAiB,GAAG,EAAE,CAAC;QAC/B,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE;YAC7B,MAAM,IAAI,GAAG,IAAA,kBAAU,EAAC,MAAM,CAAC,CAAC;YAChC,IAAA,yCAAmB,EAAC,IAAI,EAAE,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;YAClF,OAAO,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACrC,MAAM,CAAC,cAAc,GAAG,IAAI,CAAC;SAC7B;QACD,OAAO,IAAI,CAAC;IACb,CAAC;IACD,0BAA0B,EAAE,CAAC,OAAqB,EAAE,KAAsC,EAAE,EAAE;;QAG7F,IAAI,KAAK,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAA,MAAA,OAAO,CAAC,iBAAiB,0CAAE,MAAM,CAAA,EAAE;YAC5E,OAAO;SACP;QAED,KAAK,MAAM,MAAM,IAAI,OAAO,CAAC,iBAAiB,EAAE;YAC/C,IAAA,0DAAqC,EACpC,MAAM,CAAC,MAAM,EACb,CAAC,EACD;gBACC,mBAAmB,EAAE,KAAK,CAAC,KAAK;gBAChC,uBAAuB,EAAE,KAAK,CAAC,IAAI;gBACnC,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,cAAc,EAAE,KAAK,CAAC,SAAS;gBAC/B,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,UAAU,EAAE,MAAM;aAClB,EACD,OAAO,EACP,CAAC,EACD,MAAM,CACN,CAAC;SACF;QAED,OAAO,CAAC,iBAAiB,GAAG,EAAE,CAAC;IAChC,CAAC;CACD,CAAC","sourcesContent":["import { BoardTrinket } from '../../../bgs-player-entity';\r\nimport { CardIds } from '../../../services/card-ids';\r\nimport { removeAurasFromSelf } from '../../../simulation/add-minion-to-board';\r\nimport { OnAfterFriendlyMinionDeathInput } from '../../../simulation/attack';\r\nimport { simplifiedSpawnEntitiesWithAddToBoard } from '../../../simulation/deathrattle-spawns';\r\nimport { SoCInput } from '../../../simulation/start-of-combat/start-of-combat-input';\r\nimport { copyEntity } from '../../../utils';\r\nimport { OnAfterFriendlyMinionDeathCard, StartOfCombatCard } from '../../card.interface';\r\n\r\nexport const SoulFermenter: StartOfCombatCard & OnAfterFriendlyMinionDeathCard = {\r\n\tcardIds: [CardIds.SoulFermenter_BG35_MagicItem_732],\r\n\tstartOfCombatTiming: 'start-of-combat',\r\n\tstartOfCombat: (trinket: BoardTrinket, input: SoCInput) => {\r\n\t\tconst targets = input.playerBoard.slice(0, 3);\r\n\t\ttrinket.rememberedMinions = [];\r\n\t\tfor (const target of targets) {\r\n\t\t\tconst copy = copyEntity(target);\r\n\t\t\tremoveAurasFromSelf(copy, input.playerBoard, input.playerEntity, input.gameState);\r\n\t\t\ttrinket.rememberedMinions.push(copy);\r\n\t\t\ttarget.definitelyDead = true;\r\n\t\t}\r\n\t\treturn true;\r\n\t},\r\n\tonAfterFriendlyMinionDeath: (trinket: BoardTrinket, input: OnAfterFriendlyMinionDeathInput) => {\r\n\t\t// If there are 2 soul fermenters, they both proc\r\n\t\t// https://replays.firestoneapp.com/?reviewId=ecdfab8d-e20e-4264-be4b-9cbe754118f7&turn=29&action=21\r\n\t\tif (input.boardBeforeProcs.length > 0 || !trinket.rememberedMinions?.length) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tfor (const minion of trinket.rememberedMinions) {\r\n\t\t\tsimplifiedSpawnEntitiesWithAddToBoard(\r\n\t\t\t\tminion.cardId,\r\n\t\t\t\t1,\r\n\t\t\t\t{\r\n\t\t\t\t\tboardWithDeadEntity: input.board,\r\n\t\t\t\t\tboardWithDeadEntityHero: input.hero,\r\n\t\t\t\t\totherBoard: input.otherBoard,\r\n\t\t\t\t\totherBoardHero: input.otherHero,\r\n\t\t\t\t\tgameState: input.gameState,\r\n\t\t\t\t\tdeadEntity: minion,\r\n\t\t\t\t},\r\n\t\t\t\ttrinket,\r\n\t\t\t\t0,\r\n\t\t\t\tminion,\r\n\t\t\t);\r\n\t\t}\r\n\r\n\t\ttrinket.rememberedMinions = [];\r\n\t},\r\n};\r\n"]}
1
+ {"version":3,"file":"soul-fermenter.js","sourceRoot":"","sources":["../../../../src/cards/impl/trinket/soul-fermenter.ts"],"names":[],"mappings":";;;AAEA,iFAA8E;AAE9E,+EAA+F;AAE/F,0CAA4C;AAG/B,QAAA,aAAa,GAAuD;IAChF,OAAO,EAAE,sBAA0C;IACnD,mBAAmB,EAAE,iBAAiB;IACtC,aAAa,EAAE,CAAC,OAAqB,EAAE,KAAe,EAAE,EAAE;QACzD,MAAM,OAAO,GAAG,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC9C,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE;YACpB,OAAO,KAAK,CAAC;SACb;QACD,OAAO,CAAC,iBAAiB,GAAG,EAAE,CAAC;QAC/B,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE;YAC7B,MAAM,IAAI,GAAG,IAAA,kBAAU,EAAC,MAAM,CAAC,CAAC;YAChC,IAAA,yCAAmB,EAAC,IAAI,EAAE,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;YAClF,OAAO,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACrC,MAAM,CAAC,cAAc,GAAG,IAAI,CAAC;SAC7B;QAID,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,8BAA8B,EAAE,IAAI,EAAE,CAAC;IACrE,CAAC;IACD,0BAA0B,EAAE,CAAC,OAAqB,EAAE,KAAsC,EAAE,EAAE;;QAG7F,IAAI,KAAK,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAA,MAAA,OAAO,CAAC,iBAAiB,0CAAE,MAAM,CAAA,EAAE;YAC5E,OAAO;SACP;QAED,KAAK,MAAM,MAAM,IAAI,OAAO,CAAC,iBAAiB,EAAE;YAC/C,IAAA,0DAAqC,EACpC,MAAM,CAAC,MAAM,EACb,CAAC,EACD;gBACC,mBAAmB,EAAE,KAAK,CAAC,KAAK;gBAChC,uBAAuB,EAAE,KAAK,CAAC,IAAI;gBACnC,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,cAAc,EAAE,KAAK,CAAC,SAAS;gBAC/B,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,UAAU,EAAE,MAAM;aAClB,EACD,OAAO,EACP,CAAC,EACD,MAAM,CACN,CAAC;SACF;QAED,OAAO,CAAC,iBAAiB,GAAG,EAAE,CAAC;IAChC,CAAC;CACD,CAAC","sourcesContent":["import { BoardTrinket } from '../../../bgs-player-entity';\r\nimport { CardIds } from '../../../services/card-ids';\r\nimport { removeAurasFromSelf } from '../../../simulation/add-minion-to-board';\r\nimport { OnAfterFriendlyMinionDeathInput } from '../../../simulation/attack';\r\nimport { simplifiedSpawnEntitiesWithAddToBoard } from '../../../simulation/deathrattle-spawns';\r\nimport { SoCInput } from '../../../simulation/start-of-combat/start-of-combat-input';\r\nimport { copyEntity } from '../../../utils';\r\nimport { OnAfterFriendlyMinionDeathCard, StartOfCombatCard } from '../../card.interface';\r\n\r\nexport const SoulFermenter: StartOfCombatCard & OnAfterFriendlyMinionDeathCard = {\r\n\tcardIds: [CardIds.SoulFermenter_BG35_MagicItem_732],\r\n\tstartOfCombatTiming: 'start-of-combat',\r\n\tstartOfCombat: (trinket: BoardTrinket, input: SoCInput) => {\r\n\t\tconst targets = input.playerBoard.slice(0, 3);\r\n\t\tif (!targets.length) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\ttrinket.rememberedMinions = [];\r\n\t\tfor (const target of targets) {\r\n\t\t\tconst copy = copyEntity(target);\r\n\t\t\tremoveAurasFromSelf(copy, input.playerBoard, input.playerEntity, input.gameState);\r\n\t\t\ttrinket.rememberedMinions.push(copy);\r\n\t\t\ttarget.definitelyDead = true;\r\n\t\t}\r\n\t\t// Deaths are processed before the next start-of-combat effect. Who attacks first\r\n\t\t// is the side with more minions after those deaths, not the pre-combat count.\r\n\t\t// https://replays.firestoneapp.com/?debug=true&reviewId=6b009f5f-5903-4831-bb65-b6436d6af817&turn=17&action=0\r\n\t\treturn { hasTriggered: true, shouldRecomputeCurrentAttacker: true };\r\n\t},\r\n\tonAfterFriendlyMinionDeath: (trinket: BoardTrinket, input: OnAfterFriendlyMinionDeathInput) => {\r\n\t\t// If there are 2 soul fermenters, they both proc\r\n\t\t// https://replays.firestoneapp.com/?reviewId=ecdfab8d-e20e-4264-be4b-9cbe754118f7&turn=29&action=21\r\n\t\tif (input.boardBeforeProcs.length > 0 || !trinket.rememberedMinions?.length) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tfor (const minion of trinket.rememberedMinions) {\r\n\t\t\tsimplifiedSpawnEntitiesWithAddToBoard(\r\n\t\t\t\tminion.cardId,\r\n\t\t\t\t1,\r\n\t\t\t\t{\r\n\t\t\t\t\tboardWithDeadEntity: input.board,\r\n\t\t\t\t\tboardWithDeadEntityHero: input.hero,\r\n\t\t\t\t\totherBoard: input.otherBoard,\r\n\t\t\t\t\totherBoardHero: input.otherHero,\r\n\t\t\t\t\tgameState: input.gameState,\r\n\t\t\t\t\tdeadEntity: minion,\r\n\t\t\t\t},\r\n\t\t\t\ttrinket,\r\n\t\t\t\t0,\r\n\t\t\t\tminion,\r\n\t\t\t);\r\n\t\t}\r\n\r\n\t\ttrinket.rememberedMinions = [];\r\n\t},\r\n};\r\n"]}
@@ -49,10 +49,15 @@ const cloneBoard = (board) => {
49
49
  questRewardEntities: (_b = board.player.questRewardEntities) === null || _b === void 0 ? void 0 : _b.map((reward) => ({ ...reward })),
50
50
  questRewards: (_c = board.player.questRewards) === null || _c === void 0 ? void 0 : _c.map((reward) => reward),
51
51
  hand: (_d = board.player.hand) === null || _d === void 0 ? void 0 : _d.map((entity) => cloneEntity(entity)),
52
- secrets: (_e = board.player.secrets) === null || _e === void 0 ? void 0 : _e.map((secret) => ({ ...secret })).sort((a, b) => a.entityId - b.entityId),
52
+ secrets: (_e = board.player.secrets) === null || _e === void 0 ? void 0 : _e.map((secret) => ({ ...secret, tags: secret.tags ? { ...secret.tags } : undefined })).sort((a, b) => a.entityId - b.entityId),
53
53
  trinkets: (_f = board.player.trinkets) === null || _f === void 0 ? void 0 : _f.map((trinket) => ({ ...trinket, tags: { ...trinket.tags } })),
54
54
  globalInfo: { ...board.player.globalInfo },
55
- heroPowers: (_g = board.player.heroPowers) === null || _g === void 0 ? void 0 : _g.map((heroPower) => ({ ...heroPower })),
55
+ heroPowers: (_g = board.player.heroPowers) === null || _g === void 0 ? void 0 : _g.map((heroPower) => ({
56
+ ...heroPower,
57
+ info: heroPower.info && typeof heroPower.info === 'object'
58
+ ? cloneEntity(heroPower.info)
59
+ : heroPower.info,
60
+ })),
56
61
  },
57
62
  board: board.board.map((entity) => cloneEntity(entity)),
58
63
  };
@@ -67,6 +72,7 @@ const cloneEntity = (entity) => {
67
72
  pendingAttackBuffs: [],
68
73
  additionalCards: (_a = entity.additionalCards) === null || _a === void 0 ? void 0 : _a.map((card) => card),
69
74
  rememberedDeathrattles: [],
75
+ tags: entity.tags ? { ...entity.tags } : entity.tags,
70
76
  };
71
77
  return result;
72
78
  };
@@ -1 +1 @@
1
- {"version":3,"file":"input-clone.js","sourceRoot":"","sources":["../src/input-clone.ts"],"names":[],"mappings":"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","sourcesContent":["import { BgsBattleInfo } from './bgs-battle-info';\r\nimport { BgsBoardInfo } from './bgs-board-info';\r\nimport { BoardEntity } from './board-entity';\r\n\r\n// const cloneInput = (input: BgsBattleInfo): BgsBattleInfo => {\r\n// \treturn structuredClone(input);\r\n// };\r\n// const cloneInput2 = (input: string): BgsBattleInfo => {\r\n// \treturn JSON.parse(input);\r\n// };\r\n\r\n/**\r\n * Builds a function that returns a fresh deep copy of the template on every call.\r\n *\r\n * The template is serialized once, and compiled into a function body that rebuilds it as a\r\n * plain object literal. V8 parses that literal a single time, so each subsequent call only\r\n * allocates the objects, which is much faster than re-parsing JSON on every simulation\r\n * iteration (measured ~0.02ms/clone vs ~0.12ms for JSON.parse on a 7v7 board).\r\n */\r\nexport const buildTemplateCloner = (template: BgsBattleInfo): (() => BgsBattleInfo) => {\r\n\tconst str = JSON.stringify(template);\r\n\t// In an object literal (unlike JSON.parse), a \"__proto__\" key would set the prototype\r\n\t// instead of creating an own property. Our input shape never contains that key, but if\r\n\t// it ever does, fall back to the safe path\r\n\tif (!str.includes('\"__proto__\"')) {\r\n\t\ttry {\r\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-implied-eval\r\n\t\t\treturn new Function(`return ${str};`) as () => BgsBattleInfo;\r\n\t\t} catch (e) {\r\n\t\t\t// Code generation from strings can be disallowed (e.g. by a CSP when this runs\r\n\t\t\t// inside the app); JSON.parse is the fallback\r\n\t\t}\r\n\t}\r\n\treturn () => JSON.parse(str);\r\n};\r\n\r\nexport const cloneInput3 = (input: BgsBattleInfo): BgsBattleInfo => {\r\n\tconst result: BgsBattleInfo = {\r\n\t\tgameState: {\r\n\t\t\tcurrentTurn: input.gameState.currentTurn,\r\n\t\t\tnumberOfPlayersAlive: input.gameState.numberOfPlayersAlive,\r\n\t\t\tanomalies: input.gameState.anomalies,\r\n\t\t\tvalidTribes: input.gameState.validTribes,\r\n\t\t},\r\n\t\theroHasDied: input.heroHasDied,\r\n\t\tplayerBoard: cloneBoard(input.playerBoard),\r\n\t\topponentBoard: cloneBoard(input.opponentBoard),\r\n\t\tplayerTeammateBoard: cloneBoard(input.playerTeammateBoard),\r\n\t\topponentTeammateBoard: cloneBoard(input.opponentTeammateBoard),\r\n\t\t// Monte Carlo knobs are read before cloning; only combat-affecting flags must survive.\r\n\t\toptions:\r\n\t\t\tinput.options?.applyDamageCap || input.options?.applyIceBlock\r\n\t\t\t\t? ({\r\n\t\t\t\t\t\t...(input.options?.applyDamageCap ? { applyDamageCap: true } : {}),\r\n\t\t\t\t\t\t...(input.options?.applyIceBlock ? { applyIceBlock: true } : {}),\r\n\t\t\t\t } as BgsBattleInfo['options'])\r\n\t\t\t\t: null,\r\n\t};\r\n\treturn result;\r\n};\r\n\r\nexport const cloneBoard = (board: BgsBoardInfo): BgsBoardInfo => {\r\n\tif (!board) {\r\n\t\treturn null;\r\n\t}\r\n\tconst result: BgsBoardInfo = {\r\n\t\tplayer: {\r\n\t\t\t...board.player,\r\n\t\t\tquestEntities: board.player.questEntities?.map((quest) => ({ ...quest })),\r\n\t\t\tquestRewardEntities: board.player.questRewardEntities?.map((reward) => ({ ...reward })),\r\n\t\t\tquestRewards: board.player.questRewards?.map((reward) => reward),\r\n\t\t\thand: board.player.hand?.map((entity) => cloneEntity(entity)),\r\n\t\t\tsecrets: board.player.secrets?.map((secret) => ({ ...secret })).sort((a, b) => a.entityId - b.entityId),\r\n\t\t\ttrinkets: board.player.trinkets?.map((trinket) => ({ ...trinket, tags: { ...trinket.tags } })),\r\n\t\t\tglobalInfo: { ...board.player.globalInfo },\r\n\t\t\theroPowers: board.player.heroPowers?.map((heroPower) => ({ ...heroPower })),\r\n\t\t},\r\n\t\tboard: board.board.map((entity) => cloneEntity(entity)),\r\n\t};\r\n\treturn result;\r\n};\r\n\r\nconst cloneEntity = (entity: BoardEntity): BoardEntity => {\r\n\tconst result: BoardEntity = {\r\n\t\t...entity,\r\n\t\tenchantments: entity.enchantments.map((enchant) => ({ ...enchant })),\r\n\t\tpendingAttackBuffs: [],\r\n\t\tadditionalCards: entity.additionalCards?.map((card) => card),\r\n\t\trememberedDeathrattles: [],\r\n\t};\r\n\treturn result;\r\n};\r\n"]}
1
+ {"version":3,"file":"input-clone.js","sourceRoot":"","sources":["../src/input-clone.ts"],"names":[],"mappings":"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","sourcesContent":["import { BgsBattleInfo } from './bgs-battle-info';\r\nimport { BgsBoardInfo } from './bgs-board-info';\r\nimport { BoardEntity } from './board-entity';\r\n\r\n// const cloneInput = (input: BgsBattleInfo): BgsBattleInfo => {\r\n// \treturn structuredClone(input);\r\n// };\r\n// const cloneInput2 = (input: string): BgsBattleInfo => {\r\n// \treturn JSON.parse(input);\r\n// };\r\n\r\n/**\r\n * Builds a function that returns a fresh deep copy of the template on every call.\r\n *\r\n * The template is serialized once, and compiled into a function body that rebuilds it as a\r\n * plain object literal. V8 parses that literal a single time, so each subsequent call only\r\n * allocates the objects, which is much faster than re-parsing JSON on every simulation\r\n * iteration (measured ~0.02ms/clone vs ~0.12ms for JSON.parse on a 7v7 board).\r\n */\r\nexport const buildTemplateCloner = (template: BgsBattleInfo): (() => BgsBattleInfo) => {\r\n\tconst str = JSON.stringify(template);\r\n\t// In an object literal (unlike JSON.parse), a \"__proto__\" key would set the prototype\r\n\t// instead of creating an own property. Our input shape never contains that key, but if\r\n\t// it ever does, fall back to the safe path\r\n\tif (!str.includes('\"__proto__\"')) {\r\n\t\ttry {\r\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-implied-eval\r\n\t\t\treturn new Function(`return ${str};`) as () => BgsBattleInfo;\r\n\t\t} catch (e) {\r\n\t\t\t// Code generation from strings can be disallowed (e.g. by a CSP when this runs\r\n\t\t\t// inside the app); JSON.parse is the fallback\r\n\t\t}\r\n\t}\r\n\treturn () => JSON.parse(str);\r\n};\r\n\r\nexport const cloneInput3 = (input: BgsBattleInfo): BgsBattleInfo => {\r\n\tconst result: BgsBattleInfo = {\r\n\t\tgameState: {\r\n\t\t\tcurrentTurn: input.gameState.currentTurn,\r\n\t\t\tnumberOfPlayersAlive: input.gameState.numberOfPlayersAlive,\r\n\t\t\tanomalies: input.gameState.anomalies,\r\n\t\t\tvalidTribes: input.gameState.validTribes,\r\n\t\t},\r\n\t\theroHasDied: input.heroHasDied,\r\n\t\tplayerBoard: cloneBoard(input.playerBoard),\r\n\t\topponentBoard: cloneBoard(input.opponentBoard),\r\n\t\tplayerTeammateBoard: cloneBoard(input.playerTeammateBoard),\r\n\t\topponentTeammateBoard: cloneBoard(input.opponentTeammateBoard),\r\n\t\t// Monte Carlo knobs are read before cloning; only combat-affecting flags must survive.\r\n\t\toptions:\r\n\t\t\tinput.options?.applyDamageCap || input.options?.applyIceBlock\r\n\t\t\t\t? ({\r\n\t\t\t\t\t\t...(input.options?.applyDamageCap ? { applyDamageCap: true } : {}),\r\n\t\t\t\t\t\t...(input.options?.applyIceBlock ? { applyIceBlock: true } : {}),\r\n\t\t\t\t } as BgsBattleInfo['options'])\r\n\t\t\t\t: null,\r\n\t};\r\n\treturn result;\r\n};\r\n\r\nexport const cloneBoard = (board: BgsBoardInfo): BgsBoardInfo => {\r\n\tif (!board) {\r\n\t\treturn null;\r\n\t}\r\n\tconst result: BgsBoardInfo = {\r\n\t\tplayer: {\r\n\t\t\t...board.player,\r\n\t\t\tquestEntities: board.player.questEntities?.map((quest) => ({ ...quest })),\r\n\t\t\tquestRewardEntities: board.player.questRewardEntities?.map((reward) => ({ ...reward })),\r\n\t\t\tquestRewards: board.player.questRewards?.map((reward) => reward),\r\n\t\t\thand: board.player.hand?.map((entity) => cloneEntity(entity)),\r\n\t\t\tsecrets: board.player.secrets\r\n\t\t\t\t?.map((secret) => ({ ...secret, tags: secret.tags ? { ...secret.tags } : undefined }))\r\n\t\t\t\t.sort((a, b) => a.entityId - b.entityId),\r\n\t\t\ttrinkets: board.player.trinkets?.map((trinket) => ({ ...trinket, tags: { ...trinket.tags } })),\r\n\t\t\tglobalInfo: { ...board.player.globalInfo },\r\n\t\t\theroPowers: board.player.heroPowers?.map((heroPower) => ({\r\n\t\t\t\t...heroPower,\r\n\t\t\t\tinfo:\r\n\t\t\t\t\theroPower.info && typeof heroPower.info === 'object'\r\n\t\t\t\t\t\t? cloneEntity(heroPower.info)\r\n\t\t\t\t\t\t: heroPower.info,\r\n\t\t\t})),\r\n\t\t},\r\n\t\tboard: board.board.map((entity) => cloneEntity(entity)),\r\n\t};\r\n\treturn result;\r\n};\r\n\r\nconst cloneEntity = (entity: BoardEntity): BoardEntity => {\r\n\tconst result: BoardEntity = {\r\n\t\t...entity,\r\n\t\tenchantments: entity.enchantments.map((enchant) => ({ ...enchant })),\r\n\t\tpendingAttackBuffs: [],\r\n\t\tadditionalCards: entity.additionalCards?.map((card) => card),\r\n\t\trememberedDeathrattles: [],\r\n\t\ttags: entity.tags ? { ...entity.tags } : entity.tags,\r\n\t};\r\n\treturn result;\r\n};\r\n"]}
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getTavernSpellEffectRepeatCount = void 0;
4
- const reference_data_1 = require("@firestone-hs/reference-data");
4
+ const REPLICA_CATHEDRAL_READY = 4696;
5
5
  const getTavernSpellEffectRepeatCount = (input) => {
6
6
  var _a, _b;
7
7
  if (input.source !== input.hero) {
@@ -26,14 +26,14 @@ const getTavernSpellEffectRepeatCount = (input) => {
26
26
  repeats += proudPrivateerExtra;
27
27
  }
28
28
  const cathedrals = input.hero.trinkets.filter((t) => {
29
- var _a;
29
+ var _a, _b;
30
30
  return t.cardId === "BG30_MagicItem_434" &&
31
- !((_a = t.tags) === null || _a === void 0 ? void 0 : _a[reference_data_1.GameTag.TAG_SCRIPT_DATA_NUM_6]);
31
+ ((_b = (_a = t.tags) === null || _a === void 0 ? void 0 : _a[REPLICA_CATHEDRAL_READY]) !== null && _b !== void 0 ? _b : 0) > 0;
32
32
  });
33
33
  repeats += cathedrals.length;
34
34
  for (const cathedral of cathedrals) {
35
35
  cathedral.tags = (_b = cathedral.tags) !== null && _b !== void 0 ? _b : {};
36
- cathedral.tags[reference_data_1.GameTag.TAG_SCRIPT_DATA_NUM_6] = 1;
36
+ cathedral.tags[REPLICA_CATHEDRAL_READY] = 0;
37
37
  }
38
38
  return repeats;
39
39
  };
@@ -1 +1 @@
1
- {"version":3,"file":"tavern-spell-repeat.js","sourceRoot":"","sources":["../../src/mechanics/tavern-spell-repeat.ts"],"names":[],"mappings":";;;AAAA,iEAAuD;AAQhD,MAAM,+BAA+B,GAAG,CAAC,KAAqB,EAAU,EAAE;;IAChF,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,IAAI,EAAE;QAChC,OAAO,CAAC,CAAC;KACT;IACD,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,MAAM,gBAAgB,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,iBAA0C,CAAC,CAAC;IACrG,MAAM,gBAAgB,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,eAAwC,CAAC,CAAC;IACnG,IACC,CAAC,gBAAgB,IAAI,gBAAgB,CAAC;QACtC,KAAK,CAAC,MAAM;QACZ,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,EAC5D;QACD,OAAO,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KACnC;IACD,MAAM,cAAc,GACnB,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,eAAuC,CAAC,CAAC,MAAM;QACjF,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,iBAAyC,CAAC,CAAC,MAAM,CAAC;IACzF,OAAO,IAAI,cAAc,CAAC;IAE1B,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IACtE,MAAM,aAAa,GAAG,MAAA,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAE,SAAS,0CAAE,QAAQ,CAAC,cAAc,CAAC,CAAC;IAErE,IAAI,aAAa,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,IAAI,EAAE;QACjD,MAAM,mBAAmB,GACxB,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,eAAoC,CAAC,CAAC,MAAM;YAC9E,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,iBAAsC,CAAC,CAAC,MAAM,CAAC;QACtF,OAAO,IAAI,mBAAmB,CAAC;KAC/B;IAED,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAC5C,CAAC,CAAC,EAAE,EAAE;;QACL,OAAA,CAAC,CAAC,MAAM,yBAAgD;YAexD,CAAC,CAAA,MAAA,CAAC,CAAC,IAAI,0CAAG,wBAAO,CAAC,qBAAqB,CAAC,CAAA,CAAA;KAAA,CACzC,CAAC;IACF,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC;IAC7B,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE;QACnC,SAAS,CAAC,IAAI,GAAG,MAAA,SAAS,CAAC,IAAI,mCAAI,EAAE,CAAC;QACtC,SAAS,CAAC,IAAI,CAAC,wBAAO,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC;KAClD;IAED,OAAO,OAAO,CAAC;AAChB,CAAC,CAAC;AAvDW,QAAA,+BAA+B,mCAuD1C","sourcesContent":["import { GameTag } from '@firestone-hs/reference-data';\r\nimport { CastSpellInput } from '../cards/card.interface';\r\nimport { CardIds } from '../services/card-ids';\r\n\r\n/**\r\n * Balinda Stonehearth: extra spell effect resolutions for spells you cast that target a friendly board minion.\r\n * Maelstrom Emergent: each copy adds +1 extra resolution (golden +2) for tavern spells you cast; stacks additively with Balinda.\r\n */\r\nexport const getTavernSpellEffectRepeatCount = (input: CastSpellInput): number => {\r\n\tif (input.source !== input.hero) {\r\n\t\treturn 1;\r\n\t}\r\n\tlet repeats = 1;\r\n\tconst hasGoldenBalinda = input.board.some((e) => e.cardId === CardIds.BalindaStonehearth_BG35_883_G);\r\n\tconst hasNormalBalinda = input.board.some((e) => e.cardId === CardIds.BalindaStonehearth_BG35_883);\r\n\tif (\r\n\t\t(hasGoldenBalinda || hasNormalBalinda) &&\r\n\t\tinput.target &&\r\n\t\tinput.board.some((e) => e.entityId === input.target.entityId)\r\n\t) {\r\n\t\trepeats = hasGoldenBalinda ? 3 : 2;\r\n\t}\r\n\tconst maelstromExtra =\r\n\t\tinput.board.filter((e) => e.cardId === CardIds.MaelstromEmergent_BG34_922).length +\r\n\t\t2 * input.board.filter((e) => e.cardId === CardIds.MaelstromEmergent_BG34_922_G).length;\r\n\trepeats += maelstromExtra;\r\n\r\n\tconst spellCard = input.gameState.allCards.getCard(input.spellCardId);\r\n\tconst isBountySpell = spellCard?.mechanics?.includes('BACON_BOUNTY');\r\n\t// Proud Privateer only affects bounties *you* (the hero) cast — same as Balinda / onTavernSpellCast.\r\n\tif (isBountySpell && input.source === input.hero) {\r\n\t\tconst proudPrivateerExtra =\r\n\t\t\tinput.board.filter((e) => e.cardId === CardIds.ProudPrivateer_BG33_825).length +\r\n\t\t\t2 * input.board.filter((e) => e.cardId === CardIds.ProudPrivateer_BG33_825_G).length;\r\n\t\trepeats += proudPrivateerExtra;\r\n\t}\r\n\r\n\tconst cathedrals = input.hero.trinkets.filter(\r\n\t\t(t) =>\r\n\t\t\tt.cardId === CardIds.ReplicaCathedral_BG30_MagicItem_434 &&\r\n\t\t\t// 2026-04-25:https://replays.firestoneapp.com/?reviewId=f7d1d5ec-b83d-49f5-9669-b063a3debc79&turn=15&action=1\r\n\t\t\t// It triggered during shop, and doesn't re-trigger during combat\r\n\t\t\t/**\r\n\t\t\t * \t{\r\n\t\t\t\t\t\"cardId\": \"BG30_MagicItem_434\",\r\n\t\t\t\t\t\"entityId\": 306,\r\n\t\t\t\t\t\"scriptDataNum1\": 1,\r\n\t\t\t\t\t\"scriptDataNum2\": 0,\r\n\t\t\t\t\t\"scriptDataNum6\": 1\r\n\t\t\t\t},\r\n\t\t\t */\r\n\t\t\t// 2026-07-22: This is not relevant. I had the case where TRIGGER_VISUAL was 1 but it wouln't re-trigger\r\n\t\t\t// (t.tags?.[GameTag.TRIGGER_VISUAL] ?? 0) > 0,\r\n\t\t\t// Next try is SCRIPT_DATA_NUM_6, assuming 1 meaning it can't trigger\r\n\t\t\t!t.tags?.[GameTag.TAG_SCRIPT_DATA_NUM_6],\r\n\t);\r\n\trepeats += cathedrals.length;\r\n\tfor (const cathedral of cathedrals) {\r\n\t\tcathedral.tags = cathedral.tags ?? {};\r\n\t\tcathedral.tags[GameTag.TAG_SCRIPT_DATA_NUM_6] = 1;\r\n\t}\r\n\r\n\treturn repeats;\r\n};\r\n"]}
1
+ {"version":3,"file":"tavern-spell-repeat.js","sourceRoot":"","sources":["../../src/mechanics/tavern-spell-repeat.ts"],"names":[],"mappings":";;;AAKA,MAAM,uBAAuB,GAAG,IAAe,CAAC;AAMzC,MAAM,+BAA+B,GAAG,CAAC,KAAqB,EAAU,EAAE;;IAChF,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,IAAI,EAAE;QAChC,OAAO,CAAC,CAAC;KACT;IACD,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,MAAM,gBAAgB,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,iBAA0C,CAAC,CAAC;IACrG,MAAM,gBAAgB,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,eAAwC,CAAC,CAAC;IACnG,IACC,CAAC,gBAAgB,IAAI,gBAAgB,CAAC;QACtC,KAAK,CAAC,MAAM;QACZ,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,EAC5D;QACD,OAAO,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KACnC;IACD,MAAM,cAAc,GACnB,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,eAAuC,CAAC,CAAC,MAAM;QACjF,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,iBAAyC,CAAC,CAAC,MAAM,CAAC;IACzF,OAAO,IAAI,cAAc,CAAC;IAE1B,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IACtE,MAAM,aAAa,GAAG,MAAA,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAE,SAAS,0CAAE,QAAQ,CAAC,cAAc,CAAC,CAAC;IAErE,IAAI,aAAa,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,IAAI,EAAE;QACjD,MAAM,mBAAmB,GACxB,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,eAAoC,CAAC,CAAC,MAAM;YAC9E,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,iBAAsC,CAAC,CAAC,MAAM,CAAC;QACtF,OAAO,IAAI,mBAAmB,CAAC;KAC/B;IAED,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAC5C,CAAC,CAAC,EAAE,EAAE;;QACL,OAAA,CAAC,CAAC,MAAM,yBAAgD;YAMxD,CAAC,MAAA,MAAA,CAAC,CAAC,IAAI,0CAAG,uBAAuB,CAAC,mCAAI,CAAC,CAAC,GAAG,CAAC,CAAA;KAAA,CAC7C,CAAC;IACF,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC;IAC7B,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE;QACnC,SAAS,CAAC,IAAI,GAAG,MAAA,SAAS,CAAC,IAAI,mCAAI,EAAE,CAAC;QACtC,SAAS,CAAC,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,CAAC;KAC5C;IAED,OAAO,OAAO,CAAC;AAChB,CAAC,CAAC;AA9CW,QAAA,+BAA+B,mCA8C1C","sourcesContent":["import { GameTag } from '@firestone-hs/reference-data';\r\nimport { CastSpellInput } from '../cards/card.interface';\r\nimport { CardIds } from '../services/card-ids';\r\n\r\n// Unnamed client tag. Replica Cathedral sets it to 1 while its extra cast is still available.\r\nconst REPLICA_CATHEDRAL_READY = 4696 as GameTag;\r\n\r\n/**\r\n * Balinda Stonehearth: extra spell effect resolutions for spells you cast that target a friendly board minion.\r\n * Maelstrom Emergent: each copy adds +1 extra resolution (golden +2) for tavern spells you cast; stacks additively with Balinda.\r\n */\r\nexport const getTavernSpellEffectRepeatCount = (input: CastSpellInput): number => {\r\n\tif (input.source !== input.hero) {\r\n\t\treturn 1;\r\n\t}\r\n\tlet repeats = 1;\r\n\tconst hasGoldenBalinda = input.board.some((e) => e.cardId === CardIds.BalindaStonehearth_BG35_883_G);\r\n\tconst hasNormalBalinda = input.board.some((e) => e.cardId === CardIds.BalindaStonehearth_BG35_883);\r\n\tif (\r\n\t\t(hasGoldenBalinda || hasNormalBalinda) &&\r\n\t\tinput.target &&\r\n\t\tinput.board.some((e) => e.entityId === input.target.entityId)\r\n\t) {\r\n\t\trepeats = hasGoldenBalinda ? 3 : 2;\r\n\t}\r\n\tconst maelstromExtra =\r\n\t\tinput.board.filter((e) => e.cardId === CardIds.MaelstromEmergent_BG34_922).length +\r\n\t\t2 * input.board.filter((e) => e.cardId === CardIds.MaelstromEmergent_BG34_922_G).length;\r\n\trepeats += maelstromExtra;\r\n\r\n\tconst spellCard = input.gameState.allCards.getCard(input.spellCardId);\r\n\tconst isBountySpell = spellCard?.mechanics?.includes('BACON_BOUNTY');\r\n\t// Proud Privateer only affects bounties *you* (the hero) cast — same as Balinda / onTavernSpellCast.\r\n\tif (isBountySpell && input.source === input.hero) {\r\n\t\tconst proudPrivateerExtra =\r\n\t\t\tinput.board.filter((e) => e.cardId === CardIds.ProudPrivateer_BG33_825).length +\r\n\t\t\t2 * input.board.filter((e) => e.cardId === CardIds.ProudPrivateer_BG33_825_G).length;\r\n\t\trepeats += proudPrivateerExtra;\r\n\t}\r\n\r\n\tconst cathedrals = input.hero.trinkets.filter(\r\n\t\t(t) =>\r\n\t\t\tt.cardId === CardIds.ReplicaCathedral_BG30_MagicItem_434 &&\r\n\t\t\t// Unnamed tag. 1 while the extra cast is still available this turn; the client clears it\r\n\t\t\t// when the extra cast fires. TAG_SCRIPT_DATA_NUM_6 is the trinket slot (1 = lesser), and\r\n\t\t\t// TRIGGER_VISUAL can stay 1 after the shop already used the extra cast.\r\n\t\t\t// 2026-04-25 spent in shop: https://replays.firestoneapp.com/?reviewId=f7d1d5ec-b83d-49f5-9669-b063a3debc79&turn=15&action=1\r\n\t\t\t// 2026-10-07 still armed in combat (tag 4696 = 1): report 133\r\n\t\t\t(t.tags?.[REPLICA_CATHEDRAL_READY] ?? 0) > 0,\r\n\t);\r\n\trepeats += cathedrals.length;\r\n\tfor (const cathedral of cathedrals) {\r\n\t\tcathedral.tags = cathedral.tags ?? {};\r\n\t\tcathedral.tags[REPLICA_CATHEDRAL_READY] = 0;\r\n\t}\r\n\r\n\treturn repeats;\r\n};\r\n"]}
@@ -413,8 +413,11 @@ const applyAurasToSelf = (spawned, board, boardHero, gameState, applyAttackAuras
413
413
  if ((0, deity_1.isDeityCard)(spawned.cardId, gameState.allCards) && !(0, deity_1.consumeDeityBaseStatsAssignment)(spawned)) {
414
414
  const { attack, health } = (0, deity_1.getDeityAuraSnapshot)(spawned, boardHero);
415
415
  const card = gameState.allCards.getCard(spawned.cardId);
416
- const auraAttack = Math.max(0, attack - ((_k = card === null || card === void 0 ? void 0 : card.attack) !== null && _k !== void 0 ? _k : 0));
417
- const auraHealth = Math.max(0, health - ((_l = card === null || card === void 0 ? void 0 : card.health) !== null && _l !== void 0 ? _l : 0));
416
+ const printedAttack = (_k = card === null || card === void 0 ? void 0 : card.attack) !== null && _k !== void 0 ? _k : 1;
417
+ const printedHealth = (_l = card === null || card === void 0 ? void 0 : card.health) !== null && _l !== void 0 ? _l : 1;
418
+ const body = (0, deity_1.deityBodyStats)(attack, health, printedAttack, printedHealth);
419
+ const auraAttack = Math.max(0, body.attack - printedAttack);
420
+ const auraHealth = Math.max(0, body.health - printedHealth);
418
421
  spawned.tags = (_m = spawned.tags) !== null && _m !== void 0 ? _m : {};
419
422
  spawned.tags[reference_data_1.GameTag.BACON_OLD_GOD_ATTACK] = attack;
420
423
  spawned.tags[reference_data_1.GameTag.BACON_OLD_GOD_HEALTH] = health;