@firestone-hs/simulate-bgs-battle 1.1.711 → 1.1.713

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.
@@ -17,15 +17,17 @@ exports.Battlecruiser = {
17
17
  const aliveEntities = input.opponentBoard.filter((entity) => entity.health > 0 && !entity.definitelyDead);
18
18
  const targetEntityId = (_a = (0, utils_1.getRandomMinionWithHighestHealth)(aliveEntities)) === null || _a === void 0 ? void 0 : _a.entityId;
19
19
  const cannonDamage = Math.max(...yamatoCannons.map((e) => e.tagScriptDataNum1));
20
- const loops = ((_b = minion.tags) === null || _b === void 0 ? void 0 : _b[reference_data_1.GameTag.BACON_YAMATO_CANNON]) === 1 ? 2 : 1;
21
- for (let i = 0; i < loops; i++) {
22
- let target = input.opponentBoard.find((entity) => entity.entityId === targetEntityId);
23
- if (!target || target.health <= 0 || target.definitelyDead) {
24
- target = (0, utils_1.getRandomMinionWithHighestHealth)(input.opponentBoard);
25
- }
26
- if (!!target) {
27
- input.gameState.spectator.registerPowerTarget(minion, target, input.opponentBoard, input.playerEntity, input.opponentEntity);
28
- (0, attack_1.dealDamageToMinion)(target, input.opponentBoard, input.opponentEntity, minion, cannonDamage, input.playerBoard, input.playerEntity, input.gameState);
20
+ for (const yamatoCannon of yamatoCannons) {
21
+ const loops = ((_b = minion.tags) === null || _b === void 0 ? void 0 : _b[reference_data_1.GameTag.BACON_YAMATO_CANNON]) === 1 ? 2 : 1;
22
+ for (let i = 0; i < loops; i++) {
23
+ let target = input.opponentBoard.find((entity) => entity.entityId === targetEntityId);
24
+ if (!target || target.health <= 0 || target.definitelyDead) {
25
+ target = (0, utils_1.getRandomMinionWithHighestHealth)(input.opponentBoard);
26
+ }
27
+ if (!!target) {
28
+ input.gameState.spectator.registerPowerTarget(minion, target, input.opponentBoard, input.playerEntity, input.opponentEntity);
29
+ (0, attack_1.dealDamageToMinion)(target, input.opponentBoard, input.opponentEntity, minion, cannonDamage, input.playerBoard, input.playerEntity, input.gameState);
30
+ }
29
31
  }
30
32
  }
31
33
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"battlecruiser.js","sourceRoot":"","sources":["../../../../src/cards/impl/minion/battlecruiser.ts"],"names":[],"mappings":"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","sourcesContent":["import { GameTag } from '@firestone-hs/reference-data';\r\nimport { BoardEntity } from '../../../board-entity';\r\nimport { CardIds } from '../../../services/card-ids';\r\nimport { dealDamageToMinion } from '../../../simulation/attack';\r\nimport { DeathrattleTriggeredInput } from '../../../simulation/deathrattle-on-trigger';\r\nimport { OnAttackInput } from '../../../simulation/on-attack';\r\nimport { RebornEffectInput } from '../../../simulation/reborn';\r\nimport { SoCInput } from '../../../simulation/start-of-combat/start-of-combat-input';\r\nimport { modifyStats } from '../../../simulation/stats';\r\nimport { getRandomMinionWithHighestHealth } from '../../../utils';\r\nimport { DeathrattleSpawnCard, RallyCard, RebornSelfEffectCard, StartOfCombatCard } from '../../card.interface';\r\n\r\nexport const Battlecruiser: StartOfCombatCard & RebornSelfEffectCard & RallyCard & DeathrattleSpawnCard = {\r\n\tcardIds: [CardIds.LiftOff_BattlecruiserToken_BG31_HERO_801pt, CardIds.Battlecruiser_BG31_HERO_801pt_G],\r\n\tstartOfCombat: (minion: BoardEntity, input: SoCInput) => {\r\n\t\t// Enchantments can appear multiple times???\r\n\t\tconst yamatoCannons = [...minion.enchantments]\r\n\t\t\t// .reverse()\r\n\t\t\t.filter((e) => e.cardId === CardIds.YamatoCannon_YamatoCannonEnchantment_BG31_HERO_801ptce);\r\n\t\tif (!yamatoCannons?.length) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\t// Still not sure how these should be processed\r\n\t\t// In some cases, it feels like it takes the sum of the damage, in other cases it runs them one after the other\r\n\t\t// (but maybe that's just the replay aggregating the values)\r\n\t\t// I'm not sure about the BACON_YAMATO_CANNON tag; it seems like it indicates multiple cannons, but I'm not sure\r\n\t\t// Other issues: looks like that if there are multiple cannon enchantments but no divine shield, everything is applied to the same target\r\n\t\t// So it looks as if the target is selected first, then everything targets it\r\n\t\t// https://replays.firestoneapp.com/?reviewId=e8f38ab0-3380-4275-88d8-0715d69d3f08&turn=21&action=1\r\n\t\t// Even more than that: the target is the same between multiple battlecruisers\r\n\t\t// https://replays.firestoneapp.com/?reviewId=cbfd6fe9-1a58-400a-a593-6b8852df5427&turn=9&action=0\r\n\t\t// However I'm pretty sure I've seen another behavior\r\n\r\n\t\t// Get the highest health opponent minion at the start of the phase\r\n\t\t// Update 2025-05-16: it looks like it now takes the highest health current minion\r\n\t\t// https://replays.firestoneapp.com/?reviewId=c2620528-e0de-4862-9b11-cf055440b2b8&turn=19&action=2\r\n\t\tconst aliveEntities = input.opponentBoard.filter((entity) => entity.health > 0 && !entity.definitelyDead);\r\n\t\tconst targetEntityId = getRandomMinionWithHighestHealth(aliveEntities)?.entityId;\r\n\t\t// const numberOfCannons = yamatoCannons.length;\r\n\t\tconst cannonDamage = Math.max(...yamatoCannons.map((e) => e.tagScriptDataNum1));\r\n\t\t// for (const yamatoCannon of yamatoCannons) {\r\n\t\t// const damage = yamatoCannon.tagScriptDataNum1;\r\n\t\t// Could this simply be tagScriptDataNum2 on the battlecruiser?\r\n\t\t// I don't understand how this relates to the number enchants in the cruiser itself\r\n\t\t// 35.2 now fires a single time?\r\n\t\t// https://replays.firestoneapp.com/?reviewId=96618003-04fa-4e41-9baa-539f0b63fb9f&turn=17&action=2\r\n\t\tconst loops = minion.tags?.[GameTag.BACON_YAMATO_CANNON] === 1 ? 2 : 1;\r\n\t\tfor (let i = 0; i < loops; i++) {\r\n\t\t\tlet target = input.opponentBoard.find((entity) => entity.entityId === targetEntityId);\r\n\t\t\tif (!target || target.health <= 0 || target.definitelyDead) {\r\n\t\t\t\ttarget = getRandomMinionWithHighestHealth(input.opponentBoard);\r\n\t\t\t}\r\n\t\t\tif (!!target) {\r\n\t\t\t\tinput.gameState.spectator.registerPowerTarget(\r\n\t\t\t\t\tminion,\r\n\t\t\t\t\ttarget,\r\n\t\t\t\t\tinput.opponentBoard,\r\n\t\t\t\t\tinput.playerEntity,\r\n\t\t\t\t\tinput.opponentEntity,\r\n\t\t\t\t);\r\n\t\t\t\tdealDamageToMinion(\r\n\t\t\t\t\ttarget,\r\n\t\t\t\t\tinput.opponentBoard,\r\n\t\t\t\t\tinput.opponentEntity,\r\n\t\t\t\t\tminion,\r\n\t\t\t\t\tcannonDamage,\r\n\t\t\t\t\tinput.playerBoard,\r\n\t\t\t\t\tinput.playerEntity,\r\n\t\t\t\t\tinput.gameState,\r\n\t\t\t\t);\r\n\t\t\t}\r\n\t\t}\r\n\t\t// }\r\n\t\t// Since 33.6 we recompute the first attacker\r\n\t\t// https://replays.firestoneapp.com/?reviewId=f7a4a78c-269c-47b5-a0ae-099123290ccd&turn=13&action=0\r\n\t\treturn {\r\n\t\t\thasTriggered: true,\r\n\t\t\tshouldRecomputeCurrentAttacker: true,\r\n\t\t};\r\n\t},\r\n\trebornSelfEffect: (minion: BoardEntity, input: RebornEffectInput) => {\r\n\t\tconst ultraCapacitors = [...input.rebornEntity.enchantments]\r\n\t\t\t// .reverse()\r\n\t\t\t.filter((e) => e.cardId === CardIds.UltraCapacitor_UltraCapacitorEnchantment_BG31_HERO_801ptje);\r\n\t\tif (!ultraCapacitors?.length) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tminion.enchantments = input.rebornEntity.enchantments;\r\n\t\tminion.attack = input.rebornEntity.maxAttack;\r\n\t\tminion.maxAttack = input.rebornEntity.maxAttack;\r\n\t\tminion.health = input.rebornEntity.maxHealth;\r\n\t\tminion.maxHealth = input.rebornEntity.maxHealth;\r\n\t\tminion.divineShield = input.rebornEntity.hadDivineShield;\r\n\t\tminion.taunt = input.rebornEntity.taunt;\r\n\t\tminion.windfury = input.rebornEntity.windfury;\r\n\t\tminion.poisonous = input.rebornEntity.poisonous;\r\n\t},\r\n\trally: (\r\n\t\tminion: BoardEntity,\r\n\t\tinput: OnAttackInput,\r\n\t): {\r\n\t\tdmgDoneByAttacker: number;\r\n\t\tdmgDoneByDefender: number;\r\n\t} => {\r\n\t\tconst advancedBallistics = [...minion.enchantments]\r\n\t\t\t// .reverse()\r\n\t\t\t.filter((e) => e.cardId === CardIds.AdvancedBallistics_AdvancedBallisticsEnchantment_BG31_HERO_801ptde);\r\n\t\tif (!advancedBallistics?.length) {\r\n\t\t\treturn { dmgDoneByAttacker: 0, dmgDoneByDefender: 0 };\r\n\t\t}\r\n\r\n\t\tconst buff = advancedBallistics.map((e) => e.tagScriptDataNum1 ?? 0).reduce((a, b) => a + b, 0);\r\n\t\tconst targets = input.attackingBoard.filter((entity) => entity !== minion);\r\n\t\tfor (const target of targets) {\r\n\t\t\tmodifyStats(target, minion, buff, 0, input.attackingBoard, input.attackingHero, input.gameState);\r\n\t\t}\r\n\t\treturn { dmgDoneByAttacker: 0, dmgDoneByDefender: 0 };\r\n\t},\r\n\tdeathrattleSpawn: (minion: BoardEntity, input: DeathrattleTriggeredInput) => {\r\n\t\tconst caduceusReactors = [...minion.enchantments]\r\n\t\t\t// .reverse()\r\n\t\t\t.filter((e) => e.cardId === CardIds.CaduceusReactor_CaduceusReactorEnchantment_BG31_HERO_801ptee);\r\n\t\tif (!caduceusReactors?.length) {\r\n\t\t\treturn [];\r\n\t\t}\r\n\r\n\t\tconst target = input.boardWithDeadEntity.filter((e) => e.health > 0 && !e.definitelyDead)[0];\r\n\t\tif (!target) {\r\n\t\t\treturn [];\r\n\t\t}\r\n\r\n\t\tconst buff = caduceusReactors.map((e) => e.tagScriptDataNum1 ?? 0).reduce((a, b) => a + b, 0);\r\n\t\tmodifyStats(\r\n\t\t\ttarget,\r\n\t\t\tminion,\r\n\t\t\tbuff,\r\n\t\t\tbuff,\r\n\t\t\tinput.boardWithDeadEntity,\r\n\t\t\tinput.boardWithDeadEntityHero,\r\n\t\t\tinput.gameState,\r\n\t\t);\r\n\t\treturn [];\r\n\t},\r\n};\r\n"]}
1
+ {"version":3,"file":"battlecruiser.js","sourceRoot":"","sources":["../../../../src/cards/impl/minion/battlecruiser.ts"],"names":[],"mappings":"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","sourcesContent":["import { GameTag } from '@firestone-hs/reference-data';\r\nimport { BoardEntity } from '../../../board-entity';\r\nimport { CardIds } from '../../../services/card-ids';\r\nimport { dealDamageToMinion } from '../../../simulation/attack';\r\nimport { DeathrattleTriggeredInput } from '../../../simulation/deathrattle-on-trigger';\r\nimport { OnAttackInput } from '../../../simulation/on-attack';\r\nimport { RebornEffectInput } from '../../../simulation/reborn';\r\nimport { SoCInput } from '../../../simulation/start-of-combat/start-of-combat-input';\r\nimport { modifyStats } from '../../../simulation/stats';\r\nimport { getRandomMinionWithHighestHealth } from '../../../utils';\r\nimport { DeathrattleSpawnCard, RallyCard, RebornSelfEffectCard, StartOfCombatCard } from '../../card.interface';\r\n\r\nexport const Battlecruiser: StartOfCombatCard & RebornSelfEffectCard & RallyCard & DeathrattleSpawnCard = {\r\n\tcardIds: [CardIds.LiftOff_BattlecruiserToken_BG31_HERO_801pt, CardIds.Battlecruiser_BG31_HERO_801pt_G],\r\n\tstartOfCombat: (minion: BoardEntity, input: SoCInput) => {\r\n\t\t// Enchantments can appear multiple times???\r\n\t\tconst yamatoCannons = [...minion.enchantments]\r\n\t\t\t// .reverse()\r\n\t\t\t.filter((e) => e.cardId === CardIds.YamatoCannon_YamatoCannonEnchantment_BG31_HERO_801ptce);\r\n\t\tif (!yamatoCannons?.length) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\t// Still not sure how these should be processed\r\n\t\t// In some cases, it feels like it takes the sum of the damage, in other cases it runs them one after the other\r\n\t\t// (but maybe that's just the replay aggregating the values)\r\n\t\t// I'm not sure about the BACON_YAMATO_CANNON tag; it seems like it indicates multiple cannons, but I'm not sure\r\n\t\t// Other issues: looks like that if there are multiple cannon enchantments but no divine shield, everything is applied to the same target\r\n\t\t// So it looks as if the target is selected first, then everything targets it\r\n\t\t// https://replays.firestoneapp.com/?reviewId=e8f38ab0-3380-4275-88d8-0715d69d3f08&turn=21&action=1\r\n\t\t// Even more than that: the target is the same between multiple battlecruisers\r\n\t\t// https://replays.firestoneapp.com/?reviewId=cbfd6fe9-1a58-400a-a593-6b8852df5427&turn=9&action=0\r\n\t\t// However I'm pretty sure I've seen another behavior\r\n\r\n\t\t// Get the highest health opponent minion at the start of the phase\r\n\t\t// Update 2025-05-16: it looks like it now takes the highest health current minion\r\n\t\t// https://replays.firestoneapp.com/?reviewId=c2620528-e0de-4862-9b11-cf055440b2b8&turn=19&action=2\r\n\t\tconst aliveEntities = input.opponentBoard.filter((entity) => entity.health > 0 && !entity.definitelyDead);\r\n\t\t// 2026-05-13: Should the target be the minion with the highest max health instead?\r\n\t\t// https://replays.firestoneapp.com/?reviewId=0615c5a6-6548-479e-8eec-0667df49f9a7&turn=17&action=3\r\n\t\tconst targetEntityId = getRandomMinionWithHighestHealth(aliveEntities)?.entityId;\r\n\t\t// const numberOfCannons = yamatoCannons.length;\r\n\t\tconst cannonDamage = Math.max(...yamatoCannons.map((e) => e.tagScriptDataNum1));\r\n\t\t// 35.2 now fires a single time?\r\n\t\t// https://replays.firestoneapp.com/?reviewId=96618003-04fa-4e41-9baa-539f0b63fb9f&turn=17&action=2\r\n\t\t// Could this be because the target is already dead after the first firing of the cannon?\r\n\t\t// And so it can't change targets between shots?\r\n\t\t/*\r\n\t\t\t{\r\n\t\t\t\t\"originEntityId\": 5619,\r\n\t\t\t\t\"cardId\": \"BG31_HERO_801ptce\",\r\n\t\t\t\t\"tagScriptDataNum1\": 36,\r\n\t\t\t\t\"tagScriptDataNum2\": -1,\r\n\t\t\t\t\"timing\": 0\r\n\t\t\t},\r\n\t\t\t{\r\n\t\t\t\t\"originEntityId\": 5624,\r\n\t\t\t\t\"cardId\": \"BG31_HERO_801ptce\",\r\n\t\t\t\t\"tagScriptDataNum1\": 18,\r\n\t\t\t\t\"tagScriptDataNum2\": -1,\r\n\t\t\t\t\"timing\": 0\r\n\t\t\t},\r\n\t\t*/\r\n\t\t// 2026-05-12: the cannon still can fire multiple times\r\n\t\t// https://replays.firestoneapp.com/?reviewId=769f2cc9-5242-41c3-9e4b-ce71476d2325&turn=23&action=3\r\n\t\t// Deals 312, while the cannon is at 156\r\n\t\t/*\r\n\t\t\t{\r\n\t\t\t\t\"originEntityId\": 9370,\r\n\t\t\t\t\"cardId\": \"BG31_HERO_801ptce\",\r\n\t\t\t\t\"tagScriptDataNum1\": 51,\r\n\t\t\t\t\"tagScriptDataNum2\": -1,\r\n\t\t\t\t\"timing\": 0\r\n\t\t\t},\r\n\t\t\t{\r\n\t\t\t\t\"originEntityId\": 9376,\r\n\t\t\t\t\"cardId\": \"BG31_HERO_801ptce\",\r\n\t\t\t\t\"tagScriptDataNum1\": 156,\r\n\t\t\t\t\"tagScriptDataNum2\": -1,\r\n\t\t\t\t\"timing\": 0\r\n\t\t\t},\r\n\t\t */\r\n\t\tfor (const yamatoCannon of yamatoCannons) {\r\n\t\t\t// const damage = yamatoCannon.tagScriptDataNum1;\r\n\t\t\t// Could this simply be tagScriptDataNum2 on the battlecruiser?\r\n\t\t\t// I don't understand how this relates to the number enchants in the cruiser itself\r\n\t\t\tconst loops = minion.tags?.[GameTag.BACON_YAMATO_CANNON] === 1 ? 2 : 1;\r\n\t\t\tfor (let i = 0; i < loops; i++) {\r\n\t\t\t\tlet target = input.opponentBoard.find((entity) => entity.entityId === targetEntityId);\r\n\t\t\t\tif (!target || target.health <= 0 || target.definitelyDead) {\r\n\t\t\t\t\ttarget = getRandomMinionWithHighestHealth(input.opponentBoard);\r\n\t\t\t\t}\r\n\t\t\t\tif (!!target) {\r\n\t\t\t\t\tinput.gameState.spectator.registerPowerTarget(\r\n\t\t\t\t\t\tminion,\r\n\t\t\t\t\t\ttarget,\r\n\t\t\t\t\t\tinput.opponentBoard,\r\n\t\t\t\t\t\tinput.playerEntity,\r\n\t\t\t\t\t\tinput.opponentEntity,\r\n\t\t\t\t\t);\r\n\t\t\t\t\tdealDamageToMinion(\r\n\t\t\t\t\t\ttarget,\r\n\t\t\t\t\t\tinput.opponentBoard,\r\n\t\t\t\t\t\tinput.opponentEntity,\r\n\t\t\t\t\t\tminion,\r\n\t\t\t\t\t\tcannonDamage,\r\n\t\t\t\t\t\tinput.playerBoard,\r\n\t\t\t\t\t\tinput.playerEntity,\r\n\t\t\t\t\t\tinput.gameState,\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\t// Since 33.6 we recompute the first attacker\r\n\t\t// https://replays.firestoneapp.com/?reviewId=f7a4a78c-269c-47b5-a0ae-099123290ccd&turn=13&action=0\r\n\t\treturn {\r\n\t\t\thasTriggered: true,\r\n\t\t\tshouldRecomputeCurrentAttacker: true,\r\n\t\t};\r\n\t},\r\n\trebornSelfEffect: (minion: BoardEntity, input: RebornEffectInput) => {\r\n\t\tconst ultraCapacitors = [...input.rebornEntity.enchantments]\r\n\t\t\t// .reverse()\r\n\t\t\t.filter((e) => e.cardId === CardIds.UltraCapacitor_UltraCapacitorEnchantment_BG31_HERO_801ptje);\r\n\t\tif (!ultraCapacitors?.length) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tminion.enchantments = input.rebornEntity.enchantments;\r\n\t\tminion.attack = input.rebornEntity.maxAttack;\r\n\t\tminion.maxAttack = input.rebornEntity.maxAttack;\r\n\t\tminion.health = input.rebornEntity.maxHealth;\r\n\t\tminion.maxHealth = input.rebornEntity.maxHealth;\r\n\t\tminion.divineShield = input.rebornEntity.hadDivineShield;\r\n\t\tminion.taunt = input.rebornEntity.taunt;\r\n\t\tminion.windfury = input.rebornEntity.windfury;\r\n\t\tminion.poisonous = input.rebornEntity.poisonous;\r\n\t},\r\n\trally: (\r\n\t\tminion: BoardEntity,\r\n\t\tinput: OnAttackInput,\r\n\t): {\r\n\t\tdmgDoneByAttacker: number;\r\n\t\tdmgDoneByDefender: number;\r\n\t} => {\r\n\t\tconst advancedBallistics = [...minion.enchantments]\r\n\t\t\t// .reverse()\r\n\t\t\t.filter((e) => e.cardId === CardIds.AdvancedBallistics_AdvancedBallisticsEnchantment_BG31_HERO_801ptde);\r\n\t\tif (!advancedBallistics?.length) {\r\n\t\t\treturn { dmgDoneByAttacker: 0, dmgDoneByDefender: 0 };\r\n\t\t}\r\n\r\n\t\tconst buff = advancedBallistics.map((e) => e.tagScriptDataNum1 ?? 0).reduce((a, b) => a + b, 0);\r\n\t\tconst targets = input.attackingBoard.filter((entity) => entity !== minion);\r\n\t\tfor (const target of targets) {\r\n\t\t\tmodifyStats(target, minion, buff, 0, input.attackingBoard, input.attackingHero, input.gameState);\r\n\t\t}\r\n\t\treturn { dmgDoneByAttacker: 0, dmgDoneByDefender: 0 };\r\n\t},\r\n\tdeathrattleSpawn: (minion: BoardEntity, input: DeathrattleTriggeredInput) => {\r\n\t\tconst caduceusReactors = [...minion.enchantments]\r\n\t\t\t// .reverse()\r\n\t\t\t.filter((e) => e.cardId === CardIds.CaduceusReactor_CaduceusReactorEnchantment_BG31_HERO_801ptee);\r\n\t\tif (!caduceusReactors?.length) {\r\n\t\t\treturn [];\r\n\t\t}\r\n\r\n\t\tconst target = input.boardWithDeadEntity.filter((e) => e.health > 0 && !e.definitelyDead)[0];\r\n\t\tif (!target) {\r\n\t\t\treturn [];\r\n\t\t}\r\n\r\n\t\tconst buff = caduceusReactors.map((e) => e.tagScriptDataNum1 ?? 0).reduce((a, b) => a + b, 0);\r\n\t\tmodifyStats(\r\n\t\t\ttarget,\r\n\t\t\tminion,\r\n\t\t\tbuff,\r\n\t\t\tbuff,\r\n\t\t\tinput.boardWithDeadEntity,\r\n\t\t\tinput.boardWithDeadEntityHero,\r\n\t\t\tinput.gameState,\r\n\t\t);\r\n\t\treturn [];\r\n\t},\r\n};\r\n"]}
@@ -5,7 +5,7 @@ const global_info_helpers_1 = require("../../../simulation/global-info-helpers")
5
5
  exports.ArtisanalUrn = {
6
6
  cardIds: ["BG30_MagicItem_989", "BG30_MagicItem_989t"],
7
7
  startOfCombat: (trinket, input) => {
8
- const buff = trinket.cardId === "BG30_MagicItem_989" ? 4 : 8;
8
+ const buff = trinket.cardId === "BG30_MagicItem_989" ? 4 : 12;
9
9
  (0, global_info_helpers_1.increaseUndeadAttackBonus)(input.playerEntity, input.playerBoard, input.playerEntity, buff, input.gameState);
10
10
  return { hasTriggered: true, shouldRecomputeCurrentAttacker: false };
11
11
  },
@@ -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,CAAC,CAAC;QAChF,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 : 8;\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":";;;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 : 12;\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"]}
@@ -11,9 +11,9 @@ exports.BloodboundEarrings = {
11
11
  var _a;
12
12
  if (input.source !== input.hero)
13
13
  return;
14
- trinket.scriptDataNum1 = ((_a = trinket.scriptDataNum1) !== null && _a !== void 0 ? _a : 5) - 1;
14
+ trinket.scriptDataNum1 = ((_a = trinket.scriptDataNum1) !== null && _a !== void 0 ? _a : 4) - 1;
15
15
  if (trinket.scriptDataNum1 <= 0) {
16
- trinket.scriptDataNum1 = 5;
16
+ trinket.scriptDataNum1 = 4;
17
17
  const isUpgraded = trinket.cardId === "BG32_MagicItem_808t";
18
18
  const gemsPerMinion = isUpgraded ? 2 : 1;
19
19
  for (const entity of input.board) {
@@ -1 +1 @@
1
- {"version":3,"file":"bloodbound-earrings.js","sourceRoot":"","sources":["../../../../src/cards/impl/trinket/bloodbound-earrings.ts"],"names":[],"mappings":";;;AAEA,+DAAiE;AAGpD,QAAA,kBAAkB,GAA6B;IAC3D,OAAO,EAAE;;;KAGR;IACD,oBAAoB,EAAE,CAAC,OAAqB,EAAE,KAAqB,EAAE,EAAE;;QACtE,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,IAAI;YAAE,OAAO;QAExC,OAAO,CAAC,cAAc,GAAG,CAAC,MAAA,OAAO,CAAC,cAAc,mCAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QAC3D,IAAI,OAAO,CAAC,cAAc,IAAI,CAAC,EAAE;YAChC,OAAO,CAAC,cAAc,GAAG,CAAC,CAAC;YAC3B,MAAM,UAAU,GACf,OAAO,CAAC,MAAM,0BAA2E,CAAC;YAC3F,MAAM,aAAa,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACzC,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,KAAK,EAAE;gBACjC,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,MAAM,CAAC,cAAc;oBAAE,SAAS;gBAC1D,IAAA,4BAAe,EACd,OAAO,EACP,MAAM,EACN,aAAa,EACb,KAAK,CAAC,KAAK,EACX,KAAK,CAAC,IAAI,EACV,KAAK,CAAC,UAAU,EAChB,KAAK,CAAC,SAAS,EACf,KAAK,CAAC,SAAS,CACf,CAAC;aACF;SACD;IACF,CAAC;CACD,CAAC","sourcesContent":["import { BoardTrinket } from '../../../bgs-player-entity';\r\nimport { CardIds } from '../../../services/card-ids';\r\nimport { playBloodGemsOn } from '../../../simulation/blood-gems';\r\nimport { AfterTavernSpellCastCard, CastSpellInput } from '../../card.interface';\r\n\r\nexport const BloodboundEarrings: AfterTavernSpellCastCard = {\r\n\tcardIds: [\r\n\t\tCardIds.BloodboundEarrings_BG32_MagicItem_808,\r\n\t\tCardIds.BloodboundEarrings_BloodboundEarringsToken_BG32_MagicItem_808t,\r\n\t],\r\n\tafterTavernSpellCast: (trinket: BoardTrinket, input: CastSpellInput) => {\r\n\t\tif (input.source !== input.hero) return;\r\n\r\n\t\ttrinket.scriptDataNum1 = (trinket.scriptDataNum1 ?? 5) - 1;\r\n\t\tif (trinket.scriptDataNum1 <= 0) {\r\n\t\t\ttrinket.scriptDataNum1 = 5;\r\n\t\t\tconst isUpgraded =\r\n\t\t\t\ttrinket.cardId === CardIds.BloodboundEarrings_BloodboundEarringsToken_BG32_MagicItem_808t;\r\n\t\t\tconst gemsPerMinion = isUpgraded ? 2 : 1;\r\n\t\t\tfor (const entity of input.board) {\r\n\t\t\t\tif (entity.health <= 0 || entity.definitelyDead) continue;\r\n\t\t\t\tplayBloodGemsOn(\r\n\t\t\t\t\ttrinket,\r\n\t\t\t\t\tentity,\r\n\t\t\t\t\tgemsPerMinion,\r\n\t\t\t\t\tinput.board,\r\n\t\t\t\t\tinput.hero,\r\n\t\t\t\t\tinput.otherBoard,\r\n\t\t\t\t\tinput.otherHero,\r\n\t\t\t\t\tinput.gameState,\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":"bloodbound-earrings.js","sourceRoot":"","sources":["../../../../src/cards/impl/trinket/bloodbound-earrings.ts"],"names":[],"mappings":";;;AAEA,+DAAiE;AAGpD,QAAA,kBAAkB,GAA6B;IAC3D,OAAO,EAAE;;;KAGR;IACD,oBAAoB,EAAE,CAAC,OAAqB,EAAE,KAAqB,EAAE,EAAE;;QACtE,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,IAAI;YAAE,OAAO;QAExC,OAAO,CAAC,cAAc,GAAG,CAAC,MAAA,OAAO,CAAC,cAAc,mCAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QAC3D,IAAI,OAAO,CAAC,cAAc,IAAI,CAAC,EAAE;YAChC,OAAO,CAAC,cAAc,GAAG,CAAC,CAAC;YAC3B,MAAM,UAAU,GACf,OAAO,CAAC,MAAM,0BAA2E,CAAC;YAC3F,MAAM,aAAa,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACzC,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,KAAK,EAAE;gBACjC,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,MAAM,CAAC,cAAc;oBAAE,SAAS;gBAC1D,IAAA,4BAAe,EACd,OAAO,EACP,MAAM,EACN,aAAa,EACb,KAAK,CAAC,KAAK,EACX,KAAK,CAAC,IAAI,EACV,KAAK,CAAC,UAAU,EAChB,KAAK,CAAC,SAAS,EACf,KAAK,CAAC,SAAS,CACf,CAAC;aACF;SACD;IACF,CAAC;CACD,CAAC","sourcesContent":["import { BoardTrinket } from '../../../bgs-player-entity';\r\nimport { CardIds } from '../../../services/card-ids';\r\nimport { playBloodGemsOn } from '../../../simulation/blood-gems';\r\nimport { AfterTavernSpellCastCard, CastSpellInput } from '../../card.interface';\r\n\r\nexport const BloodboundEarrings: AfterTavernSpellCastCard = {\r\n\tcardIds: [\r\n\t\tCardIds.BloodboundEarrings_BG32_MagicItem_808,\r\n\t\tCardIds.BloodboundEarrings_BloodboundEarringsToken_BG32_MagicItem_808t,\r\n\t],\r\n\tafterTavernSpellCast: (trinket: BoardTrinket, input: CastSpellInput) => {\r\n\t\tif (input.source !== input.hero) return;\r\n\r\n\t\ttrinket.scriptDataNum1 = (trinket.scriptDataNum1 ?? 4) - 1;\r\n\t\tif (trinket.scriptDataNum1 <= 0) {\r\n\t\t\ttrinket.scriptDataNum1 = 4;\r\n\t\t\tconst isUpgraded =\r\n\t\t\t\ttrinket.cardId === CardIds.BloodboundEarrings_BloodboundEarringsToken_BG32_MagicItem_808t;\r\n\t\t\tconst gemsPerMinion = isUpgraded ? 2 : 1;\r\n\t\t\tfor (const entity of input.board) {\r\n\t\t\t\tif (entity.health <= 0 || entity.definitelyDead) continue;\r\n\t\t\t\tplayBloodGemsOn(\r\n\t\t\t\t\ttrinket,\r\n\t\t\t\t\tentity,\r\n\t\t\t\t\tgemsPerMinion,\r\n\t\t\t\t\tinput.board,\r\n\t\t\t\t\tinput.hero,\r\n\t\t\t\t\tinput.otherBoard,\r\n\t\t\t\t\tinput.otherHero,\r\n\t\t\t\t\tinput.gameState,\r\n\t\t\t\t);\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n};\r\n"]}
@@ -1,15 +1,20 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.BubbleCrown = void 0;
4
+ const reference_data_1 = require("@firestone-hs/reference-data");
4
5
  exports.BubbleCrown = {
5
6
  cardIds: ["BG35_MagicItem_920"],
6
7
  onBeforeTavernSpellCast: (trinket, input) => {
7
- var _a;
8
- trinket.scriptDataNum1 = ((_a = trinket.scriptDataNum1) !== null && _a !== void 0 ? _a : 10) - 1;
8
+ var _a, _b;
9
+ if (((_a = trinket.tags) === null || _a === void 0 ? void 0 : _a[reference_data_1.GameTag.TRIGGER_VISUAL]) === 0) {
10
+ return;
11
+ }
12
+ trinket.scriptDataNum1 = ((_b = trinket.scriptDataNum1) !== null && _b !== void 0 ? _b : 0) - 1;
9
13
  if (trinket.scriptDataNum1 <= 0) {
10
14
  trinket.scriptDataNum1 = 10;
11
- input.hero.globalInfo.TavernSpellAttackBuff += 5;
12
- input.hero.globalInfo.TavernSpellHealthBuff += 5;
15
+ input.hero.globalInfo.TavernSpellAttackBuff += 4;
16
+ input.hero.globalInfo.TavernSpellHealthBuff += 4;
17
+ trinket.tags[reference_data_1.GameTag.TRIGGER_VISUAL] = 0;
13
18
  }
14
19
  },
15
20
  };
@@ -1 +1 @@
1
- {"version":3,"file":"bubble-crown.js","sourceRoot":"","sources":["../../../../src/cards/impl/trinket/bubble-crown.ts"],"names":[],"mappings":";;;AAIa,QAAA,WAAW,GAAgC;IACvD,OAAO,EAAE,sBAAwC;IAGjD,uBAAuB,EAAE,CAAC,OAAqB,EAAE,KAAqB,EAAE,EAAE;;QACzE,OAAO,CAAC,cAAc,GAAG,CAAC,MAAA,OAAO,CAAC,cAAc,mCAAI,EAAE,CAAC,GAAG,CAAC,CAAC;QAC5D,IAAI,OAAO,CAAC,cAAc,IAAI,CAAC,EAAE;YAChC,OAAO,CAAC,cAAc,GAAG,EAAE,CAAC;YAC5B,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,qBAAqB,IAAI,CAAC,CAAC;YACjD,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,qBAAqB,IAAI,CAAC,CAAC;SACjD;IACF,CAAC;CACD,CAAC","sourcesContent":["import { BoardTrinket } from '../../../bgs-player-entity';\r\nimport { CardIds } from '../../../services/card-ids';\r\nimport { CastSpellInput, OnBeforeTavernSpellCastCard } from '../../card.interface';\r\n\r\nexport const BubbleCrown: OnBeforeTavernSpellCastCard = {\r\n\tcardIds: [CardIds.BubbleCrown_BG35_MagicItem_920],\r\n\t// This seems to trigger before the first spell is cast\r\n\t// https://replays.firestoneapp.com/?reviewId=2503f562-e0e1-4564-8218-d36cbf09cbb0&turn=17&action=2\r\n\tonBeforeTavernSpellCast: (trinket: BoardTrinket, input: CastSpellInput) => {\r\n\t\ttrinket.scriptDataNum1 = (trinket.scriptDataNum1 ?? 10) - 1;\r\n\t\tif (trinket.scriptDataNum1 <= 0) {\r\n\t\t\ttrinket.scriptDataNum1 = 10;\r\n\t\t\tinput.hero.globalInfo.TavernSpellAttackBuff += 5;\r\n\t\t\tinput.hero.globalInfo.TavernSpellHealthBuff += 5;\r\n\t\t}\r\n\t},\r\n};\r\n"]}
1
+ {"version":3,"file":"bubble-crown.js","sourceRoot":"","sources":["../../../../src/cards/impl/trinket/bubble-crown.ts"],"names":[],"mappings":";;;AAAA,iEAAuD;AAK1C,QAAA,WAAW,GAAgC;IACvD,OAAO,EAAE,sBAAwC;IAGjD,uBAAuB,EAAE,CAAC,OAAqB,EAAE,KAAqB,EAAE,EAAE;;QAEzE,IAAI,CAAA,MAAA,OAAO,CAAC,IAAI,0CAAG,wBAAO,CAAC,cAAc,CAAC,MAAK,CAAC,EAAE;YACjD,OAAO;SACP;QAgBD,OAAO,CAAC,cAAc,GAAG,CAAC,MAAA,OAAO,CAAC,cAAc,mCAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QAC3D,IAAI,OAAO,CAAC,cAAc,IAAI,CAAC,EAAE;YAChC,OAAO,CAAC,cAAc,GAAG,EAAE,CAAC;YAC5B,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,qBAAqB,IAAI,CAAC,CAAC;YACjD,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,qBAAqB,IAAI,CAAC,CAAC;YACjD,OAAO,CAAC,IAAI,CAAC,wBAAO,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;SACzC;IACF,CAAC;CACD,CAAC","sourcesContent":["import { GameTag } from '@firestone-hs/reference-data';\r\nimport { BoardTrinket } from '../../../bgs-player-entity';\r\nimport { CardIds } from '../../../services/card-ids';\r\nimport { CastSpellInput, OnBeforeTavernSpellCastCard } from '../../card.interface';\r\n\r\nexport const BubbleCrown: OnBeforeTavernSpellCastCard = {\r\n\tcardIds: [CardIds.BubbleCrown_BG35_MagicItem_920],\r\n\t// This seems to trigger before the first spell is cast\r\n\t// https://replays.firestoneapp.com/?reviewId=2503f562-e0e1-4564-8218-d36cbf09cbb0&turn=17&action=2\r\n\tonBeforeTavernSpellCast: (trinket: BoardTrinket, input: CastSpellInput) => {\r\n\t\t// It has already triggered once\r\n\t\tif (trinket.tags?.[GameTag.TRIGGER_VISUAL] === 0) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\t// When we get the board state from the opponent, sometimes we have the trinket at 0, and this seems to mean that\r\n\t\t// it will proc on the next spell (eg https://replays.firestoneapp.com/?reviewId=0cff125a-7419-40c6-8c50-edfba59d1559&turn=17&action=4)\r\n\t\t/*\r\nD 20:39:27.1063034 PowerTaskList.DebugPrintPower() - SHOW_ENTITY - Updating Entity=[entityName=泡泡王冠 id=6141 zone=SETASIDE zonePos=0 cardId=BG35_MagicItem_920 player=4] CardID=BG35_MagicItem_920\r\nD 20:39:27.1063034 PowerTaskList.DebugPrintPower() - tag=TAG_SCRIPT_DATA_NUM_1 value=0\r\n...\r\nD 20:39:27.1643122 GameState.DebugPrintPower() - BLOCK_START BlockType=TRIGGER Entity=[entityName=赶潮纳迦 id=6449 zone=PLAY zonePos=5 cardId=BG34_920 player=12] EffectCardId=System.Collections.Generic.List`1[System.String] EffectIndex=0 Target=0 SubOption=-1 TriggerKeyword=DEATHRATTLE\r\n...\r\nD 20:39:27.1643122 GameState.DebugPrintPower() - BLOCK_START BlockType=TRIGGER Entity=[entityName=泡泡王冠 id=6141 zone=PLAY zonePos=0 cardId=BG35_MagicItem_920 player=12] EffectCardId=System.Collections.Generic.List`1[System.String] EffectIndex=0 Target=0 SubOption=-1 TriggerKeyword=TRIGGER_VISUAL\r\n...\r\nD 20:39:27.1643122 GameState.DebugPrintPower() - TAG_CHANGE Entity=wellwelc tag=TAVERN_SPELL_ATTACK_INCREASE value=5 \r\nD 20:39:27.1643122 GameState.DebugPrintPower() - TAG_CHANGE Entity=wellwelc tag=TAVERN_SPELL_HEALTH_INCREASE value=5 \r\n...\r\n\t\t*/\r\n\t\t// I'm not yet sure if this only happens under specific conditions\r\n\t\ttrinket.scriptDataNum1 = (trinket.scriptDataNum1 ?? 0) - 1;\r\n\t\tif (trinket.scriptDataNum1 <= 0) {\r\n\t\t\ttrinket.scriptDataNum1 = 10;\r\n\t\t\tinput.hero.globalInfo.TavernSpellAttackBuff += 4;\r\n\t\t\tinput.hero.globalInfo.TavernSpellHealthBuff += 4;\r\n\t\t\ttrinket.tags[GameTag.TRIGGER_VISUAL] = 0;\r\n\t\t}\r\n\t},\r\n};\r\n"]}
@@ -14,8 +14,8 @@ exports.LorewalkerScroll = {
14
14
  if (!input.target || input.target.health <= 0 || input.target.definitelyDead)
15
15
  return;
16
16
  const isGreater = trinket.cardId === "BG30_MagicItem_422t";
17
- const attack = isGreater ? 8 : 2;
18
- const health = isGreater ? 8 : 2;
17
+ const attack = isGreater ? 10 : 2;
18
+ const health = isGreater ? 10 : 2;
19
19
  (0, stats_1.modifyStats)(input.target, trinket, attack, health, input.board, input.hero, input.gameState);
20
20
  },
21
21
  };
@@ -1 +1 @@
1
- {"version":3,"file":"lorewalker-scroll.js","sourceRoot":"","sources":["../../../../src/cards/impl/trinket/lorewalker-scroll.ts"],"names":[],"mappings":";;;AAEA,qDAAwD;AAG3C,QAAA,gBAAgB,GAA0B;IACtD,OAAO,EAAE;;;KAGR;IACD,iBAAiB,EAAE,CAAC,OAAqB,EAAE,KAAqB,EAAE,EAAE;QACnE,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,IAAI,EAAE;YAChC,OAAO;SACP;QACD,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,cAAc;YAAE,OAAO;QACrF,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,0BAAuE,CAAC;QACxG,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACjC,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACjC,IAAA,mBAAW,EAAC,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAC9F,CAAC;CACD,CAAC","sourcesContent":["import { BoardTrinket } from '../../../bgs-player-entity';\r\nimport { CardIds } from '../../../services/card-ids';\r\nimport { modifyStats } from '../../../simulation/stats';\r\nimport { CastSpellInput, OnTavernSpellCastCard } from '../../card.interface';\r\n\r\nexport const LorewalkerScroll: OnTavernSpellCastCard = {\r\n\tcardIds: [\r\n\t\tCardIds.LorewalkerScroll_BG30_MagicItem_422,\r\n\t\tCardIds.LorewalkerScroll_LorewalkerScrollToken_BG30_MagicItem_422t,\r\n\t],\r\n\tonTavernSpellCast: (trinket: BoardTrinket, input: CastSpellInput) => {\r\n\t\tif (input.source !== input.hero) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (!input.target || input.target.health <= 0 || input.target.definitelyDead) return;\r\n\t\tconst isGreater = trinket.cardId === CardIds.LorewalkerScroll_LorewalkerScrollToken_BG30_MagicItem_422t;\r\n\t\tconst attack = isGreater ? 8 : 2;\r\n\t\tconst health = isGreater ? 8 : 2;\r\n\t\tmodifyStats(input.target, trinket, attack, health, input.board, input.hero, input.gameState);\r\n\t},\r\n};\r\n"]}
1
+ {"version":3,"file":"lorewalker-scroll.js","sourceRoot":"","sources":["../../../../src/cards/impl/trinket/lorewalker-scroll.ts"],"names":[],"mappings":";;;AAEA,qDAAwD;AAG3C,QAAA,gBAAgB,GAA0B;IACtD,OAAO,EAAE;;;KAGR;IACD,iBAAiB,EAAE,CAAC,OAAqB,EAAE,KAAqB,EAAE,EAAE;QACnE,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,IAAI,EAAE;YAChC,OAAO;SACP;QACD,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,cAAc;YAAE,OAAO;QACrF,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,0BAAuE,CAAC;QACxG,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAClC,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAClC,IAAA,mBAAW,EAAC,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAC9F,CAAC;CACD,CAAC","sourcesContent":["import { BoardTrinket } from '../../../bgs-player-entity';\r\nimport { CardIds } from '../../../services/card-ids';\r\nimport { modifyStats } from '../../../simulation/stats';\r\nimport { CastSpellInput, OnTavernSpellCastCard } from '../../card.interface';\r\n\r\nexport const LorewalkerScroll: OnTavernSpellCastCard = {\r\n\tcardIds: [\r\n\t\tCardIds.LorewalkerScroll_BG30_MagicItem_422,\r\n\t\tCardIds.LorewalkerScroll_LorewalkerScrollToken_BG30_MagicItem_422t,\r\n\t],\r\n\tonTavernSpellCast: (trinket: BoardTrinket, input: CastSpellInput) => {\r\n\t\tif (input.source !== input.hero) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (!input.target || input.target.health <= 0 || input.target.definitelyDead) return;\r\n\t\tconst isGreater = trinket.cardId === CardIds.LorewalkerScroll_LorewalkerScrollToken_BG30_MagicItem_422t;\r\n\t\tconst attack = isGreater ? 10 : 2;\r\n\t\tconst health = isGreater ? 10 : 2;\r\n\t\tmodifyStats(input.target, trinket, attack, health, input.board, input.hero, input.gameState);\r\n\t},\r\n};\r\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@firestone-hs/simulate-bgs-battle",
3
- "version": "1.1.711",
3
+ "version": "1.1.713",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "lint": "eslint --color --fix --ext .ts .",