diff --git a/data/moves.js b/data/moves.js index b4dbc3b8a85d..d6bd3f93f129 100644 --- a/data/moves.js +++ b/data/moves.js @@ -945,8 +945,11 @@ let BattleMovedex = { accuracy: 100, basePower: 60, basePowerCallback: function (pokemon, target, move) { - if (target.lastDamage > 0 && pokemon.lastAttackedBy && pokemon.lastAttackedBy.thisTurn && pokemon.lastAttackedBy.pokemon === target) { - this.debug('Boosted for getting hit by ' + pokemon.lastAttackedBy.move); + let hurtByTarget = pokemon.hurtBy.some(p => + p.source === target && p.damage > 0 && p.thisTurn + ); + if (hurtByTarget) { + this.debug('Boosted for getting hit by ' + target); return move.basePower * 2; } return move.basePower; @@ -13390,8 +13393,11 @@ let BattleMovedex = { accuracy: 100, basePower: 60, basePowerCallback: function (pokemon, target, move) { - if (target.lastDamage > 0 && pokemon.lastAttackedBy && pokemon.lastAttackedBy.thisTurn && pokemon.lastAttackedBy.pokemon === target) { - this.debug('Boosted for getting hit by ' + pokemon.lastAttackedBy.move); + let hurtByTarget = pokemon.hurtBy.some(p => + p.source === target && p.damage > 0 && p.thisTurn + ); + if (hurtByTarget) { + this.debug('Boosted for getting hit by ' + target); return move.basePower * 2; } return move.basePower; diff --git a/mods/gen1/moves.js b/mods/gen1/moves.js index 030222389c78..c2197a43a220 100644 --- a/mods/gen1/moves.js +++ b/mods/gen1/moves.js @@ -967,11 +967,12 @@ let BattleMovedex = { } this.runEvent('AfterSubDamage', target, source, move, damage); // Add here counter damage - if (!target.lastAttackedBy) { - target.lastAttackedBy = {pokemon: source, move: move.id, thisTurn: true, damage: damage}; + let lastHurtBy = target.getLastHurtBy(); + if (!lastHurtBy) { + target.hurtBy.push({source: source, move: move.id, damage: damage, thisTurn: true}); } else { - target.lastAttackedBy.move = move.id; - target.lastAttackedBy.damage = damage; + lastHurtBy.move = move.id; + lastHurtBy.damage = damage; } return 0; }, diff --git a/mods/gen2/moves.js b/mods/gen2/moves.js index 287529c3b533..d229a92fe3b6 100644 --- a/mods/gen2/moves.js +++ b/mods/gen2/moves.js @@ -144,9 +144,9 @@ let BattleMovedex = { inherit: true, desc: "Deals damage to the opposing Pokemon equal to twice the HP lost by the user from a physical attack this turn. This move considers Hidden Power as Normal type, and only the last hit of a multi-hit attack is counted. Fails if the user moves first, if the user was not hit by a physical attack this turn, or if the user did not lose HP from the attack. If the opposing Pokemon used Fissure or Horn Drill and missed, this move deals 65535 damage.", damageCallback: function (pokemon, target) { - if (pokemon.lastAttackedBy && pokemon.lastAttackedBy.thisTurn && pokemon.lastAttackedBy.move && (this.getCategory(pokemon.lastAttackedBy.move) === 'Physical' || this.getMove(pokemon.lastAttackedBy.move).id === 'hiddenpower') && - (!target.lastMove || target.lastMove.id !== 'sleeptalk')) { - return 2 * pokemon.lastAttackedBy.damage; + let lastHurtBy = pokemon.getLastHurtBy(); + if (lastHurtBy && lastHurtBy.move && lastHurtBy.thisTurn && (this.getCategory(lastHurtBy.move) === 'Physical' || this.getMove(lastHurtBy.move).id === 'hiddenpower') && (!target.lastMove || target.lastMove.id !== 'sleeptalk')) { + return 2 * lastHurtBy.damage; } return false; }, @@ -493,9 +493,9 @@ let BattleMovedex = { inherit: true, desc: "Deals damage to the opposing Pokemon equal to twice the HP lost by the user from a special attack this turn. This move considers Hidden Power as Normal type, and only the last hit of a multi-hit attack is counted. Fails if the user moves first, if the user was not hit by a special attack this turn, or if the user did not lose HP from the attack.", damageCallback: function (pokemon, target) { - if (pokemon.lastAttackedBy && pokemon.lastAttackedBy.thisTurn && pokemon.lastAttackedBy.move && this.getCategory(pokemon.lastAttackedBy.move) === 'Special' && - this.getMove(pokemon.lastAttackedBy.move).id !== 'hiddenpower' && (!target.lastMove || target.lastMove.id !== 'sleeptalk')) { - return 2 * pokemon.lastAttackedBy.damage; + let lastHurtBy = pokemon.getLastHurtBy(); + if (lastHurtBy && lastHurtBy.move && lastHurtBy.thisTurn && this.getCategory(lastHurtBy.move) === 'Special' && this.getMove(lastHurtBy.move).id !== 'hiddenpower' && (!target.lastMove || target.lastMove.id !== 'sleeptalk')) { + return 2 * lastHurtBy.damage; } return false; }, diff --git a/mods/gen3/moves.js b/mods/gen3/moves.js index 87b1144a1f76..8b0f9c99d1b9 100644 --- a/mods/gen3/moves.js +++ b/mods/gen3/moves.js @@ -187,9 +187,10 @@ let BattleMovedex = { inherit: true, desc: "Deals damage to the last opposing Pokemon to hit the user with a physical attack this turn equal to twice the HP lost by the user from that attack. If that opposing Pokemon's position is no longer in use and there is another opposing Pokemon on the field, the damage is done to it instead. This move considers Hidden Power as Normal type, and only the last hit of a multi-hit attack is counted. Fails if the user was not hit by an opposing Pokemon's physical attack this turn, or if the user did not lose HP from the attack.", damageCallback: function (pokemon) { - if (pokemon.lastAttackedBy && pokemon.lastAttackedBy.thisTurn && pokemon.lastAttackedBy.move && (this.getCategory(pokemon.lastAttackedBy.move) === 'Physical' || this.getMove(pokemon.lastAttackedBy.move).id === 'hiddenpower')) { + let lastHurtBy = pokemon.getLastHurtBy(); + if (lastHurtBy && lastHurtBy.move && lastHurtBy.thisTurn && (this.getCategory(lastHurtBy.move) === 'Physical' || this.getMove(lastHurtBy.move).id === 'hiddenpower')) { // @ts-ignore - return 2 * pokemon.lastAttackedBy.damage; + return 2 * lastHurtBy.damage; } return false; }, @@ -557,10 +558,11 @@ let BattleMovedex = { onTryHit: function () { }, onHit: function (pokemon) { let noMirror = ['assist', 'curse', 'doomdesire', 'focuspunch', 'futuresight', 'magiccoat', 'metronome', 'mimic', 'mirrormove', 'naturepower', 'psychup', 'roleplay', 'sketch', 'sleeptalk', 'spikes', 'spitup', 'taunt', 'teeterdance', 'transform']; - if (!pokemon.lastAttackedBy || !pokemon.lastAttackedBy.pokemon.lastMove || !pokemon.lastAttackedBy.move || noMirror.includes(pokemon.lastAttackedBy.move) || !pokemon.lastAttackedBy.pokemon.hasMove(pokemon.lastAttackedBy.move)) { + let lastHurtBy = pokemon.getLastHurtBy(); + if (!lastHurtBy || !lastHurtBy.source.lastMove || !lastHurtBy.move || noMirror.includes(lastHurtBy.move) || !lastHurtBy.source.hasMove(lastHurtBy.move)) { return false; } - this.useMove(pokemon.lastAttackedBy.move, pokemon); + this.useMove(lastHurtBy.move, pokemon); }, target: "self", }, diff --git a/mods/gen4/moves.js b/mods/gen4/moves.js index 86865799e7a4..cb345fd98865 100644 --- a/mods/gen4/moves.js +++ b/mods/gen4/moves.js @@ -1105,10 +1105,11 @@ let BattleMovedex = { onTryHit: function () { }, onHit: function (pokemon) { let noMirror = ['acupressure', 'aromatherapy', 'assist', 'chatter', 'copycat', 'counter', 'curse', 'doomdesire', 'feint', 'focuspunch', 'futuresight', 'gravity', 'hail', 'haze', 'healbell', 'helpinghand', 'lightscreen', 'luckychant', 'magiccoat', 'mefirst', 'metronome', 'mimic', 'mirrorcoat', 'mirrormove', 'mist', 'mudsport', 'naturepower', 'perishsong', 'psychup', 'raindance', 'reflect', 'roleplay', 'safeguard', 'sandstorm', 'sketch', 'sleeptalk', 'snatch', 'spikes', 'spitup', 'stealthrock', 'struggle', 'sunnyday', 'tailwind', 'toxicspikes', 'transform', 'watersport']; - if (!pokemon.lastAttackedBy || !pokemon.lastAttackedBy.pokemon.lastMove || !pokemon.lastAttackedBy.move || noMirror.includes(pokemon.lastAttackedBy.move) || !pokemon.lastAttackedBy.pokemon.hasMove(pokemon.lastAttackedBy.move)) { - return false; + let lastHurtBy = pokemon.getLastHurtBy(); + if (!lastHurtBy || !lastHurtBy.source.lastMove || !lastHurtBy.move || noMirror.includes(lastHurtBy.move) || !lastHurtBy.source.hasMove(lastHurtBy.move)) { + return false; } - this.useMove(pokemon.lastAttackedBy.move, pokemon); + this.useMove(lastHurtBy.move, pokemon); }, target: "self", }, diff --git a/mods/gennext/moves.js b/mods/gennext/moves.js index fb86f27b48ec..7d74c9ee4614 100644 --- a/mods/gennext/moves.js +++ b/mods/gennext/moves.js @@ -977,9 +977,12 @@ let BattleMovedex = { avalanche: { inherit: true, basePowerCallback: function (pokemon, source) { - if ((source.lastDamage > 0 && pokemon.lastAttackedBy && pokemon.lastAttackedBy.thisTurn)) { - this.debug('Boosted for getting hit by ' + pokemon.lastAttackedBy.move); - return this.isWeather('hail') ? 180 : 120; + let lastHurtBy = pokemon.getLastHurtBy(); + if (lastHurtBy) { + if (lastHurtBy.damage > 0 && lastHurtBy.thisTurn) { + this.debug('Boosted for getting hit by ' + lastHurtBy.move); + return this.isWeather('hail') ? 180 : 120; + } } return this.isWeather('hail') ? 90 : 60; }, diff --git a/mods/stadium/moves.js b/mods/stadium/moves.js index cf3d148ef42e..276bc28c477d 100644 --- a/mods/stadium/moves.js +++ b/mods/stadium/moves.js @@ -159,11 +159,12 @@ let BattleMovedex = { } this.runEvent('AfterSubDamage', target, source, move, damage); // Add here counter damage - if (!target.lastAttackedBy) { - target.lastAttackedBy = {pokemon: source, move: move.id, thisTurn: true, damage: damage}; + let lastHurtBy = target.getLastHurtBy(); + if (!lastHurtBy) { + target.hurtBy.push({source: source, move: move.id, damage: damage, thisTurn: true}); } else { - target.lastAttackedBy.move = move.id; - target.lastAttackedBy.damage = damage; + lastHurtBy.move = move.id; + lastHurtBy.damage = damage; } return 0; }, diff --git a/sim/battle.js b/sim/battle.js index 0d098f5f2c85..323fc800775d 100644 --- a/sim/battle.js +++ b/sim/battle.js @@ -1545,13 +1545,16 @@ class Battle extends Dex.ModdedDex { this.runEvent('DisableMove', pokemon); if (!pokemon.ateBerry) pokemon.disableMove('belch'); - if (pokemon.lastAttackedBy) { - if (pokemon.lastAttackedBy.pokemon.isActive) { - pokemon.lastAttackedBy.thisTurn = false; + // If it was an illusion, it's not any more + if (pokemon.getLastHurtBy() && this.gen >= 7) pokemon.knownType = true; + + for (let i = pokemon.hurtBy.length - 1; i >= 0; i--) { + let attack = pokemon.hurtBy[i]; + if (attack.source.isActive) { + attack.thisTurn = false; } else { - pokemon.lastAttackedBy = null; + pokemon.hurtBy.slice(pokemon.hurtBy.indexOf(attack), 1); } - if (this.gen >= 7) pokemon.knownType = true; // If it was an illusion, it's not any more } if (this.gen >= 7) { diff --git a/sim/pokemon.js b/sim/pokemon.js index cc8a939b8dc7..d7edcde14c63 100644 --- a/sim/pokemon.js +++ b/sim/pokemon.js @@ -155,8 +155,8 @@ class Pokemon { this.moveThisTurnResult = undefined; this.lastDamage = 0; - /**@type {?{pokemon: Pokemon, damage: number, thisTurn: boolean, move?: string}} */ - this.lastAttackedBy = null; + /**@type {{source: Pokemon, damage: number, thisTurn: boolean, move?: string}[]} */ + this.hurtBy = []; this.usedItemThisTurn = false; this.newlySwitched = false; this.beingCalledBack = false; @@ -611,12 +611,18 @@ class Pokemon { gotAttacked(move, damage, source) { if (!damage) damage = 0; move = this.battle.getMove(move); - this.lastAttackedBy = { - pokemon: source, + let lastHurtBy = { + source: source, damage: damage, move: move.id, thisTurn: true, }; + this.hurtBy.push(lastHurtBy); + } + + getLastHurtBy() { + if (this.hurtBy.length === 0) return undefined; + return this.hurtBy[this.hurtBy.length - 1]; } /** @@ -1032,7 +1038,7 @@ class Pokemon { this.moveThisTurn = ''; this.lastDamage = 0; - this.lastAttackedBy = null; + this.hurtBy = []; this.newlySwitched = true; this.beingCalledBack = false;