diff --git a/battle-engine.js b/battle-engine.js index e6d8ee846c..9b9020a002 100644 --- a/battle-engine.js +++ b/battle-engine.js @@ -3012,7 +3012,7 @@ Battle = (function () { flags: {} }; - if (move.affectedByImmunities) { + if (!move.ignoreImmunity || (move.ignoreImmunity !== true && !move.ignoreImmunity[move.type])) { if (!target.runImmunity(move.type, !suppressMessages)) { return false; } @@ -3156,24 +3156,24 @@ Battle = (function () { baseDamage = this.modify(baseDamage, move.stab || 1.5); } // types - var totalTypeMod = 0; + move.typeMod = 0; if (target.negateImmunity[move.type] !== 'IgnoreEffectiveness' || this.getImmunity(move.type, target)) { - totalTypeMod = target.runEffectiveness(move); + move.typeMod = target.runEffectiveness(move); } - totalTypeMod = this.clampIntRange(totalTypeMod, -6, 6); - if (totalTypeMod > 0) { + move.typeMod = this.clampIntRange(move.typeMod, -6, 6); + if (move.typeMod > 0) { if (!suppressMessages) this.add('-supereffective', target); - for (var i = 0; i < totalTypeMod; i++) { + for (var i = 0; i < move.typeMod; i++) { baseDamage *= 2; } } - if (totalTypeMod < 0) { + if (move.typeMod < 0) { if (!suppressMessages) this.add('-resisted', target); - for (var i = 0; i > totalTypeMod; i--) { + for (var i = 0; i > move.typeMod; i--) { baseDamage = Math.floor(baseDamage / 2); } } diff --git a/config/commands.js b/config/commands.js index d5bc334cca..11ad5d4ec1 100644 --- a/config/commands.js +++ b/config/commands.js @@ -1280,8 +1280,8 @@ var commands = exports.commands = { if (!this.canBroadcast()) return; var factor = 0; - if (source.category === "Status" && !source.affectedByImmunities) factor = 1; - if (Tools.getImmunity(source.type || source, defender) || source.affectedByImmunities === false) { + if (source.category === "Status" && (source.ignoreImmunity === true || source.ignoreImmunity[source.type])) factor = 1; + if (Tools.getImmunity(source.type || source, defender) || source.ignoreImmunity === true || source.ignoreImmunity[source.type]) { var totalTypeMod = 0; if (source.effectType !== 'Move' || source.basePower || source.basePowerCallback) { for (var i = 0; i < defender.types.length; i++) { diff --git a/config/formats.js b/config/formats.js index c5ee062c7a..ef5b263386 100644 --- a/config/formats.js +++ b/config/formats.js @@ -2315,7 +2315,7 @@ exports.Formats = [ move.category = 'Special'; move.type = 'Psychic'; move.negateSecondary = true; - move.affectedByImmunities = false; + move.ignoreImmunity = true; delete move.secondaries; move.onTryHit = function (target, pokemon) { this.attrLastMove('[still]'); @@ -2465,7 +2465,7 @@ exports.Formats = [ } if (move.id === 'triattack' && name === 'ascriptmaster') { move.name = 'Spectrum Beam'; - move.affectedByImmunities = false; + move.ignoreImmunity = true; move.basePower = 8; move.critRatio = 1; move.accuracy = 95; @@ -2522,7 +2522,7 @@ exports.Formats = [ move.onHit = function (pokemon) { pokemon.addVolatile('confusion'); }; - move.affectedByImmunities = false; + move.ignoreImmunity = true; move.type = 'Dark'; } if (move.id === 'bugbuzz' && name === 'beowulf') { @@ -2691,9 +2691,7 @@ exports.Formats = [ this.attrLastMove('[still]'); this.add('-anim', source, "Giga Drain", target); }; - if (move.type === 'Ground') { - move.affectedByImmunities = false; - } + move.ignoreImmunity = {'Ground': true}; } if (move.id === 'partingshot' && name === 'hippopotas') { move.name = 'Hazard Pass'; @@ -3250,7 +3248,7 @@ exports.Formats = [ target.ignore['Ability'] = true; }; move.accuracy = true; - move.affectedByImmunities = false; + move.ignoreImmunity = true; move.ignoreDefensive = true; move.ignoreEvasion = true; } diff --git a/data/abilities.js b/data/abilities.js index 30b3c32729..f8cb5c5af7 100644 --- a/data/abilities.js +++ b/data/abilities.js @@ -682,7 +682,7 @@ exports.BattleAbilities = { "filter": { shortDesc: "This Pokemon receives 3/4 damage from supereffective attacks.", onSourceModifyDamage: function (damage, source, target, move) { - if (target.runEffectiveness(move) > 0) { + if (move.typeMod > 0) { this.debug('Filter neutralize'); return this.chainModify(0.75); } @@ -2268,8 +2268,10 @@ exports.BattleAbilities = { shortDesc: "This Pokemon can hit Ghost types with Normal- and Fighting-type moves.", onModifyMovePriority: -5, onModifyMove: function (move) { - if (move.type in {'Fighting':1, 'Normal':1}) { - move.affectedByImmunities = false; + if (!move.ignoreImmunity) move.ignoreImmunity = {}; + if (move.ignoreImmunity !== true) { + move.ignoreImmunity['Fighting'] = true; + move.ignoreImmunity['Normal'] = true; } }, id: "scrappy", @@ -2486,7 +2488,7 @@ exports.BattleAbilities = { "solidrock": { shortDesc: "This Pokemon receives 3/4 damage from supereffective attacks.", onSourceModifyDamage: function (damage, source, target, move) { - if (target.runEffectiveness(move) > 0) { + if (move.typeMod > 0) { this.debug('Solid Rock neutralize'); return this.chainModify(0.75); } @@ -2860,7 +2862,7 @@ exports.BattleAbilities = { "tintedlens": { shortDesc: "This Pokemon's attacks that are not very effective on a target deal double damage.", onModifyDamage: function (damage, source, target, move) { - if (target.runEffectiveness(move) < 0) { + if (move.typeMod < 0) { this.debug('Tinted Lens boost'); return this.chainModify(2); } @@ -3153,7 +3155,7 @@ exports.BattleAbilities = { onTryHit: function (target, source, move) { if (target === source || move.category === 'Status' || move.type === '???' || move.id === 'struggle' || move.isFutureMove) return; this.debug('Wonder Guard immunity: ' + move.id); - if (target.runEffectiveness(move) <= 0) { + if ((target.negateImmunity[move.type] === 'IgnoreEffectiveness' && !this.getImmunity(move.type, target)) || target.runEffectiveness(move) <= 0) { this.add('-activate', target, 'ability: Wonder Guard'); return null; } diff --git a/data/items.js b/data/items.js index 30202d118f..bc157d65db 100644 --- a/data/items.js +++ b/data/items.js @@ -289,7 +289,7 @@ exports.BattleItems = { type: "Steel" }, onSourceModifyDamage: function (damage, source, target, move) { - if (move.type === 'Steel' && target.runEffectiveness(move) > 0 && !target.volatiles['substitute']) { + if (move.type === 'Steel' && move.typeMod > 0 && !target.volatiles['substitute']) { if (target.eatItem()) { this.debug('-50% reduction'); return this.chainModify(0.5); @@ -645,7 +645,7 @@ exports.BattleItems = { type: "Rock" }, onSourceModifyDamage: function (damage, source, target, move) { - if (move.type === 'Rock' && target.runEffectiveness(move) > 0 && !target.volatiles['substitute']) { + if (move.type === 'Rock' && move.typeMod > 0 && !target.volatiles['substitute']) { if (target.eatItem()) { this.debug('-50% reduction'); return this.chainModify(0.5); @@ -832,7 +832,7 @@ exports.BattleItems = { type: "Fighting" }, onSourceModifyDamage: function (damage, source, target, move) { - if (move.type === 'Fighting' && target.runEffectiveness(move) > 0 && !target.volatiles['substitute']) { + if (move.type === 'Fighting' && move.typeMod > 0 && !target.volatiles['substitute']) { if (target.eatItem()) { this.debug('-50% reduction'); return this.chainModify(0.5); @@ -865,7 +865,7 @@ exports.BattleItems = { type: "Flying" }, onSourceModifyDamage: function (damage, source, target, move) { - if (move.type === 'Flying' && target.runEffectiveness(move) > 0 && !target.volatiles['substitute']) { + if (move.type === 'Flying' && move.typeMod > 0 && !target.volatiles['substitute']) { if (target.eatItem()) { this.debug('-50% reduction'); return this.chainModify(0.5); @@ -887,7 +887,7 @@ exports.BattleItems = { type: "Dark" }, onSourceModifyDamage: function (damage, source, target, move) { - if (move.type === 'Dark' && target.runEffectiveness(move) > 0 && !target.volatiles['substitute']) { + if (move.type === 'Dark' && move.typeMod > 0 && !target.volatiles['substitute']) { if (target.eatItem()) { this.debug('-50% reduction'); return this.chainModify(0.5); @@ -1272,8 +1272,8 @@ exports.BattleItems = { basePower: 100, type: "Bug" }, - onSourceBasePower: function (basePower, user, target, move) { - if (move && target.runEffectiveness(move) > 0) { + onSourceModifyDamage: function (damage, source, target, move) { + if (move && move.typeMod > 0) { target.addVolatile('enigmaberry'); } }, @@ -1323,7 +1323,7 @@ exports.BattleItems = { basePower: 10 }, onModifyDamage: function (damage, source, target, move) { - if (move && target.runEffectiveness(move) > 0) { + if (move && move.typeMod > 0) { return this.chainModify(1.2); } }, @@ -1799,7 +1799,7 @@ exports.BattleItems = { type: "Dragon" }, onSourceModifyDamage: function (damage, source, target, move) { - if (move.type === 'Dragon' && target.runEffectiveness(move) > 0 && !target.volatiles['substitute']) { + if (move.type === 'Dragon' && move.typeMod > 0 && !target.volatiles['substitute']) { if (target.eatItem()) { this.debug('-50% reduction'); return this.chainModify(0.5); @@ -2073,7 +2073,7 @@ exports.BattleItems = { type: "Ghost" }, onSourceModifyDamage: function (damage, source, target, move) { - if (move.type === 'Ghost' && target.runEffectiveness(move) > 0 && !target.volatiles['substitute']) { + if (move.type === 'Ghost' && move.typeMod > 0 && !target.volatiles['substitute']) { if (target.eatItem()) { this.debug('-50% reduction'); return this.chainModify(0.5); @@ -2095,7 +2095,7 @@ exports.BattleItems = { type: "Poison" }, onSourceModifyDamage: function (damage, source, target, move) { - if (move.type === 'Poison' && target.runEffectiveness(move) > 0 && !target.volatiles['substitute']) { + if (move.type === 'Poison' && move.typeMod > 0 && !target.volatiles['substitute']) { if (target.eatItem()) { this.debug('-50% reduction'); return this.chainModify(0.5); @@ -3045,7 +3045,7 @@ exports.BattleItems = { type: "Fire" }, onSourceModifyDamage: function (damage, source, target, move) { - if (move.type === 'Fire' && target.runEffectiveness(move) > 0 && !target.volatiles['substitute']) { + if (move.type === 'Fire' && move.typeMod > 0 && !target.volatiles['substitute']) { if (target.eatItem()) { this.debug('-50% reduction'); return this.chainModify(0.5); @@ -3137,7 +3137,7 @@ exports.BattleItems = { type: "Water" }, onSourceModifyDamage: function (damage, source, target, move) { - if (move.type === 'Water' && target.runEffectiveness(move) > 0 && !target.volatiles['substitute']) { + if (move.type === 'Water' && move.typeMod > 0 && !target.volatiles['substitute']) { if (target.eatItem()) { this.debug('-50% reduction'); return this.chainModify(0.5); @@ -3159,7 +3159,7 @@ exports.BattleItems = { type: "Psychic" }, onSourceModifyDamage: function (damage, source, target, move) { - if (move.type === 'Psychic' && target.runEffectiveness(move) > 0 && !target.volatiles['substitute']) { + if (move.type === 'Psychic' && move.typeMod > 0 && !target.volatiles['substitute']) { if (target.eatItem()) { this.debug('-50% reduction'); return this.chainModify(0.5); @@ -3627,7 +3627,7 @@ exports.BattleItems = { type: "Grass" }, onSourceModifyDamage: function (damage, source, target, move) { - if (move.type === 'Grass' && target.runEffectiveness(move) > 0 && !target.volatiles['substitute']) { + if (move.type === 'Grass' && move.typeMod > 0 && !target.volatiles['substitute']) { if (target.eatItem()) { this.debug('-50% reduction'); return this.chainModify(0.5); @@ -3744,7 +3744,7 @@ exports.BattleItems = { type: "Fairy" }, onSourceModifyDamage: function (damage, source, target, move) { - if (move.type === 'Fairy' && target.runEffectiveness(move) > 0 && !target.volatiles['substitute']) { + if (move.type === 'Fairy' && move.typeMod > 0 && !target.volatiles['substitute']) { if (target.eatItem()) { this.debug('-50% reduction'); return this.chainModify(0.5); @@ -4001,7 +4001,7 @@ exports.BattleItems = { type: "Ground" }, onSourceModifyDamage: function (damage, source, target, move) { - if (move.type === 'Ground' && target.runEffectiveness(move) > 0 && !target.volatiles['substitute']) { + if (move.type === 'Ground' && move.typeMod > 0 && !target.volatiles['substitute']) { if (target.eatItem()) { this.debug('-50% reduction'); return this.chainModify(0.5); @@ -4423,7 +4423,7 @@ exports.BattleItems = { type: "Bug" }, onSourceModifyDamage: function (damage, source, target, move) { - if (move.type === 'Bug' && target.runEffectiveness(move) > 0 && !target.volatiles['substitute']) { + if (move.type === 'Bug' && move.typeMod > 0 && !target.volatiles['substitute']) { if (target.eatItem()) { this.debug('-50% reduction'); return this.chainModify(0.5); @@ -4561,7 +4561,7 @@ exports.BattleItems = { type: "Electric" }, onSourceModifyDamage: function (damage, source, target, move) { - if (move.type === 'Electric' && target.runEffectiveness(move) > 0 && !target.volatiles['substitute']) { + if (move.type === 'Electric' && move.typeMod > 0 && !target.volatiles['substitute']) { if (target.eatItem()) { this.debug('-50% reduction'); return this.chainModify(0.5); @@ -4630,7 +4630,7 @@ exports.BattleItems = { basePower: 80 }, onHit: function (target, source, move) { - if (target.hp && move.category !== 'Status' && !move.damage && !move.damageCallback && target.runEffectiveness(move) > 0 && target.useItem()) { + if (target.hp && move.category !== 'Status' && !move.damage && !move.damageCallback && move.typeMod > 0 && target.useItem()) { this.boost({atk: 2, spa: 2}); } }, @@ -4756,7 +4756,7 @@ exports.BattleItems = { type: "Ice" }, onSourceModifyDamage: function (damage, source, target, move) { - if (move.type === 'Ice' && target.runEffectiveness(move) > 0 && !target.volatiles['substitute']) { + if (move.type === 'Ice' && move.typeMod > 0 && !target.volatiles['substitute']) { if (target.eatItem()) { this.debug('-50% reduction'); return this.chainModify(0.5); diff --git a/data/moves.js b/data/moves.js index 4b7f8deea4..286b304ebc 100644 --- a/data/moves.js +++ b/data/moves.js @@ -952,7 +952,7 @@ exports.BattleMovedex = { priority: 1, flags: {contact: 1, protect: 1}, volatileStatus: 'bide', - affectedByImmunities: false, + ignoreImmunity: true, effect: { duration: 3, onLockMove: 'bide', @@ -4991,7 +4991,7 @@ exports.BattleMovedex = { pp: 10, priority: 0, flags: {}, - affectedByImmunities: false, + ignoreImmunity: true, isFutureMove: true, onTryHit: function (target, source) { source.side.addSideCondition('futuremove'); @@ -5007,7 +5007,7 @@ exports.BattleMovedex = { basePower: 120, category: "Special", flags: {}, - affectedByImmunities: true, + ignoreImmunity: false, type: 'Psychic' } }; @@ -14108,17 +14108,13 @@ exports.BattleMovedex = { priority: 0, flags: {protect: 1, mirror: 1, nonsky: 1}, isUnreleased: true, - onModifyMove: function (move) { - if (move.type === 'Ground') { - move.affectedByImmunities = false; - } - }, onTryHit: function (target) { // only the attack that grounds the target ignores effectiveness if (target.negateImmunity['Ground']) return; target.negateImmunity['Ground'] = 'IgnoreEffectiveness'; }, volatileStatus: 'smackdown', + ignoreImmunity: {'Ground': true}, secondary: false, target: "allAdjacentFoes", type: "Ground" @@ -14266,7 +14262,7 @@ exports.BattleMovedex = { priority: 0, flags: {protect: 1, reflectable: 1, mirror: 1}, status: 'par', - affectedByImmunities: true, + ignoreImmunity: false, secondary: false, target: "normal", type: "Electric" diff --git a/data/scripts.js b/data/scripts.js index 20c41efc2c..90b2cc05fe 100644 --- a/data/scripts.js +++ b/data/scripts.js @@ -101,8 +101,8 @@ exports.BattleScripts = { return true; } - if (typeof move.affectedByImmunities === 'undefined') { - move.affectedByImmunities = (move.category !== 'Status'); + if (move.ignoreImmunity === undefined) { + move.ignoreImmunity = (move.category === 'Status'); } var damage = false; @@ -209,12 +209,12 @@ exports.BattleScripts = { return this.moveHit(target, pokemon, move); } - if (move.affectedByImmunities && !target.runImmunity(move.type, true)) { - return false; + if (move.ignoreImmunity === undefined) { + move.ignoreImmunity = (move.category === 'Status'); } - if (typeof move.affectedByImmunities === 'undefined') { - move.affectedByImmunities = (move.category !== 'Status'); + if (move.ignoreImmunity !== true && !move.ignoreImmunity[move.type] && !target.runImmunity(move.type, true)) { + return false; } hitResult = this.runEvent('TryHit', target, pokemon, move); diff --git a/data/statuses.js b/data/statuses.js index 3d6a4b10bc..f28188403a 100644 --- a/data/statuses.js +++ b/data/statuses.js @@ -320,8 +320,8 @@ exports.BattleStatuses = { target.removeVolatile('Protect'); target.removeVolatile('Endure'); - if (typeof posData.moveData.affectedByImmunities === 'undefined') { - posData.moveData.affectedByImmunities = true; + if (posData.moveData.ignoreImmunity === undefined) { + posData.moveData.ignoreImmunity = false; } if (target.hasAbility('wonderguard') && this.gen > 5) { diff --git a/mods/gen1/moves.js b/mods/gen1/moves.js index 2a0b1b3c79..22fd5384ae 100644 --- a/mods/gen1/moves.js +++ b/mods/gen1/moves.js @@ -105,7 +105,7 @@ exports.BattleMovedex = { }, bind: { inherit: true, - affectedByImmunities: false, + ignoreImmunity: true, volatileStatus: 'partiallytrapped', self: { volatileStatus: 'partialtrappinglock' @@ -199,7 +199,7 @@ exports.BattleMovedex = { }, counter: { inherit: true, - affectedByImmunities: false, + ignoreImmunity: true, willCrit: false, damageCallback: function (pokemon, target) { // Counter mechanics on gen 1 might be hard to understand. @@ -368,7 +368,7 @@ exports.BattleMovedex = { }, glare: { inherit: true, - affectedByImmunities: false + ignoreImmunity: true }, growth: { inherit: true, @@ -574,7 +574,7 @@ exports.BattleMovedex = { }, nightshade: { inherit: true, - affectedByImmunities: false, + ignoreImmunity: true, basePower: 1 }, poisonsting: { @@ -713,12 +713,12 @@ exports.BattleMovedex = { }, sandattack: { inherit: true, - affectedByImmunities: false, + ignoreImmunity: true, type: "Normal" }, seismictoss: { inherit: true, - affectedByImmunities: false, + ignoreImmunity: true, basePower: 1 }, selfdestruct: { @@ -852,7 +852,7 @@ exports.BattleMovedex = { }, superfang: { inherit: true, - affectedByImmunities: false, + ignoreImmunity: true, basePower: 1 }, thunder: { @@ -893,7 +893,7 @@ exports.BattleMovedex = { wrap: { inherit: true, accuracy: 85, - affectedByImmunities: false, + ignoreImmunity: true, volatileStatus: 'partiallytrapped', self: { volatileStatus: 'partialtrappinglock' diff --git a/mods/gen1/scripts.js b/mods/gen1/scripts.js index a79604c3dc..13b483c442 100644 --- a/mods/gen1/scripts.js +++ b/mods/gen1/scripts.js @@ -208,8 +208,8 @@ exports.BattleScripts = { return true; } - if (typeof move.affectedByImmunities === 'undefined') { - move.affectedByImmunities = (move.category !== 'Status'); + if (move.ignoreImmunity === undefined) { + move.ignoreImmunity = (move.category === 'Status'); } var damage = false; @@ -291,7 +291,7 @@ exports.BattleScripts = { } // Check if the Pokémon is immune to this move. - if (move.affectedByImmunities && !target.runImmunity(move.type, true)) { + if (move.ignoreImmunity !== true && !move.ignoreImmunity[move.type] && !target.runImmunity(move.type, true)) { damage = false; } @@ -371,8 +371,8 @@ exports.BattleScripts = { var hitResult = true; if (!moveData) moveData = move; - if (typeof move.affectedByImmunities === 'undefined') { - move.affectedByImmunities = (move.category !== 'Status'); + if (move.ignoreImmunity === undefined) { + move.ignoreImmunity = (move.category === 'Status'); } // We get the sub to the target to see if it existed @@ -704,7 +704,7 @@ exports.BattleScripts = { }; // Let's see if the target is immune to the move. - if (move.affectedByImmunities) { + if (move.ignoreImmunity !== true && !move.ignoreImmunity[move.type]) { if (!target.runImmunity(move.type, true)) { return false; } diff --git a/mods/gen1/statuses.js b/mods/gen1/statuses.js index 5ede997f27..9f99da917a 100644 --- a/mods/gen1/statuses.js +++ b/mods/gen1/statuses.js @@ -310,8 +310,8 @@ exports.BattleStatuses = { target.removeVolatile('Protect'); target.removeVolatile('Endure'); - if (typeof posData.moveData.affectedByImmunities === 'undefined') { - posData.moveData.affectedByImmunities = true; + if (posData.moveData.ignoreImmunity === undefined) { + posData.moveData.ignoreImmunity = false; } this.moveHit(target, posData.source, move, posData.moveData); diff --git a/mods/gen2/scripts.js b/mods/gen2/scripts.js index 387771ec96..87c9a6a866 100644 --- a/mods/gen2/scripts.js +++ b/mods/gen2/scripts.js @@ -286,7 +286,7 @@ exports.BattleScripts = { }; // Let's test for immunities. - if (move.affectedByImmunities) { + if (move.ignoreImmunity !== true && !move.ignoreImmunity[move.type]) { if (!target.runImmunity(move.type, true)) { return false; } diff --git a/mods/gen3/moves.js b/mods/gen3/moves.js index a0ea52fef8..7225a2284e 100644 --- a/mods/gen3/moves.js +++ b/mods/gen3/moves.js @@ -357,7 +357,7 @@ exports.BattleMovedex = { glare: { inherit: true, accuracy: 75, - affectedByImmunities: true + ignoreImmunity: false }, growth: { inherit: true, diff --git a/mods/gen5/moves.js b/mods/gen5/moves.js index 0959513903..30dbdba104 100644 --- a/mods/gen5/moves.js +++ b/mods/gen5/moves.js @@ -275,7 +275,7 @@ exports.BattleMovedex = { basePower: 100, category: "Special", flags: {}, - affectedByImmunities: true, + ignoreImmunity: false, type: 'Psychic' } }; diff --git a/mods/gennext/abilities.js b/mods/gennext/abilities.js index 68e7d652b6..ad37c4d70d 100644 --- a/mods/gennext/abilities.js +++ b/mods/gennext/abilities.js @@ -256,19 +256,19 @@ exports.BattleAbilities = { }, "solidrock": { inherit: true, - onFoeBasePower: function (basePower, attacker, defender, move) { - if (defender.runEffectiveness(move) > 0) { + onSourceModifyDamage: function (damage, attacker, defender, move) { + if (move.typeMod > 0) { this.add('-message', "The attack was weakened by Solid Rock!"); - return basePower * 1 / 2; + return this.chainModify(0.5); } } }, "filter": { inherit: true, - onFoeBasePower: function (basePower, attacker, defender, move) { - if (defender.runEffectiveness(move) > 0) { + onSourceModifyDamage: function (damage, attacker, defender, move) { + if (move.typeMod > 0) { this.add('-message', "The attack was weakened by Filter!"); - return basePower * 1 / 2; + return this.chainModify(0.5); } } }, diff --git a/mods/gennext/moves.js b/mods/gennext/moves.js index 5da5643097..952ba6b4e1 100644 --- a/mods/gennext/moves.js +++ b/mods/gennext/moves.js @@ -652,7 +652,7 @@ exports.BattleMovedex = { onBasePower: function (power, user) { if (user.template.id === 'snorlax') return power * 1.5; }, - affectedByImmunities: false + ignoreImmunity: true }, /****************************************************************** Sound-based Normal-type moves: @@ -664,19 +664,19 @@ exports.BattleMovedex = { ******************************************************************/ boomburst: { inherit: true, - affectedByImmunities: false + ignoreImmunity: true }, hypervoice: { inherit: true, - affectedByImmunities: false + ignoreImmunity: true }, round: { inherit: true, - affectedByImmunities: false + ignoreImmunity: true }, uproar: { inherit: true, - affectedByImmunities: false + ignoreImmunity: true }, /****************************************************************** Bonemerang, Bone Rush, Bone Club moves: @@ -688,18 +688,18 @@ exports.BattleMovedex = { ******************************************************************/ bonemerang: { inherit: true, - affectedByImmunities: false, + ignoreImmunity: true, accuracy: true }, bonerush: { inherit: true, basePower: 20, - affectedByImmunities: false, + ignoreImmunity: true, accuracy: true }, boneclub: { inherit: true, - affectedByImmunities: false, + ignoreImmunity: true, accuracy: 90 }, /****************************************************************** @@ -712,7 +712,7 @@ exports.BattleMovedex = { relicsong: { inherit: true, basePower: 60, - affectedByImmunities: false, + ignoreImmunity: true, onHit: function (target, pokemon) { if (pokemon.baseTemplate.species !== 'Meloetta' || pokemon.transformed) { return; @@ -1179,7 +1179,7 @@ exports.BattleMovedex = { category: "Special", isViable: true, priority: 0, - affectedByImmunities: false, + ignoreImmunity: true, onHit: function (target, source) { source.side.addSideCondition('futuremove'); if (source.side.sideConditions['futuremove'].positions[source.position]) { @@ -1194,7 +1194,7 @@ exports.BattleMovedex = { basePower: 80, category: "Special", flags: {}, - affectedByImmunities: false, + ignoreImmunity: true, type: 'Normal' } }; @@ -1875,11 +1875,11 @@ exports.BattleMovedex = { }, acid: { inherit: true, - affectedByImmunities: false + ignoreImmunity: true }, acidspray: { inherit: true, - affectedByImmunities: false + ignoreImmunity: true }, eggbomb: { inherit: true, diff --git a/mods/stadium/scripts.js b/mods/stadium/scripts.js index 1b869cc54c..e3c01b3bbe 100644 --- a/mods/stadium/scripts.js +++ b/mods/stadium/scripts.js @@ -161,7 +161,7 @@ exports.BattleScripts = { } // Check if the Pokémon is immune to this move. - if (move.affectedByImmunities && !target.runImmunity(move.type, true)) { + if (move.ignoreImmunity !== true && !move.ignoreImmunity[move.type] && !target.runImmunity(move.type, true)) { damage = false; } @@ -238,8 +238,8 @@ exports.BattleScripts = { var hitResult = true; if (!moveData) moveData = move; - if (typeof move.affectedByImmunities === 'undefined') { - move.affectedByImmunities = (move.category !== 'Status'); + if (move.ignoreImmunity === undefined) { + move.ignoreImmunity = (move.category === 'Status'); } // We get the sub to the target to see if it existed @@ -398,7 +398,7 @@ exports.BattleScripts = { }; // Let's see if the target is immune to the move. - if (move.affectedByImmunities) { + if (move.ignoreImmunity !== true && !move.ignoreImmunity[move.type]) { if (!target.runImmunity(move.type, true)) { return false; } diff --git a/test/simulator/misc/statusmoves.js b/test/simulator/misc/statusmoves.js new file mode 100644 index 0000000000..83fa554aee --- /dev/null +++ b/test/simulator/misc/statusmoves.js @@ -0,0 +1,35 @@ +var assert = require('assert'); +var battle; + +describe('Most status moves', function () { + afterEach(function () { + battle.destroy(); + }); + + it('should ignore type immunities', function () { + battle = BattleEngine.Battle.construct(); + battle.join('p1', 'Guest 1', 1, [{species: "Smeargle", ability: 'prankster', item: 'leftovers', moves: ['gastroacid', 'glare', 'confuseray', 'sandattack']}]); + battle.join('p2', 'Guest 2', 1, [ + {species: "Klefki", ability: 'magician', happiness: 0, moves: ['return']}, + {species: "Dusknoir", ability: 'frisk', moves: ['shadowpunch']}, + {species: "Slaking", ability: 'truant', moves: ['shadowclaw']}, + {species: "Tornadus", ability: 'prankster', moves: ['tailwind']}, + {species: "Unown", ability: 'levitate', moves: ['hiddenpower']} + ]); + battle.commitDecisions(); + assert.strictEqual(battle.p2.active[0].item, ''); + battle.choose('p1', 'move 2'); + battle.choose('p2', 'switch 2'); + assert.strictEqual(battle.p2.active[0].status, 'par'); + battle.choose('p1', 'move 3'); + battle.choose('p2', 'switch 3'); + assert.ok(battle.p2.active[0].volatiles['confusion']); + battle.choose('p1', 'move 4'); + battle.choose('p2', 'switch 4'); + assert.strictEqual(battle.p2.active[0].boosts['accuracy'], -1); + battle.choose('p1', 'move 4'); + battle.choose('p2', 'switch 5'); + assert.strictEqual(battle.p2.active[0].boosts['accuracy'], -1); + }); +}); + diff --git a/test/simulator/moves/thousandarrows.js b/test/simulator/moves/thousandarrows.js new file mode 100644 index 0000000000..99cff50dbc --- /dev/null +++ b/test/simulator/moves/thousandarrows.js @@ -0,0 +1,78 @@ +var assert = require('assert'); +var battle; + +describe('Thousand Arrows', function () { + afterEach(function () { + battle.destroy(); + }); + + it('should hit Flying-type Pokemon and remove their Ground immunity', function () { + battle = BattleEngine.Battle.construct(); + battle.join('p1', 'Guest 1', 1, [{species: "Zygarde", ability: 'aurabreak', item: 'laggingtail', moves: ['thousandarrows', 'earthquake']}]); + battle.join('p2', 'Guest 2', 1, [{species: "Tropius", ability: 'harvest', moves: ['synthesis']}]); + battle.commitDecisions(); + assert.notStrictEqual(battle.p2.active[0].hp, battle.p2.active[0].maxhp); + battle.choose('p1', 'move earthquake'); + battle.commitDecisions(); + assert.notStrictEqual(battle.p2.active[0].hp, battle.p2.active[0].maxhp); + }); + + it('should ignore type effectiveness on the first hit against Flying-type Pokemon', function () { + battle = BattleEngine.Battle.construct(); + battle.join('p1', 'Guest 1', 1, [{species: "Zygarde", ability: 'aurabreak', item: 'laggingtail', moves: ['thousandarrows']}]); + battle.join('p2', 'Guest 2', 1, [{species: "Ho-Oh", ability: 'pressure', item: 'weaknesspolicy', moves: ['recover']}]); + battle.commitDecisions(); + assert.strictEqual(battle.p2.active[0].boosts.atk, 0); + assert.strictEqual(battle.p2.active[0].boosts.spa, 0); + battle.commitDecisions(); + assert.strictEqual(battle.p2.active[0].boosts.atk, 2); + assert.strictEqual(battle.p2.active[0].boosts.spa, 2); + }); + + it('should hit Pokemon with Levitate and remove their Ground immunity', function () { + battle = BattleEngine.Battle.construct(); + battle.join('p1', 'Guest 1', 1, [{species: "Zygarde", ability: 'aurabreak', item: 'laggingtail', moves: ['thousandarrows', 'earthquake']}]); + battle.join('p2', 'Guest 2', 1, [{species: "Cresselia", ability: 'levitate', moves: ['recover']}]); + battle.commitDecisions(); + assert.notStrictEqual(battle.p2.active[0].hp, battle.p2.active[0].maxhp); + battle.choose('p1', 'move earthquake'); + battle.commitDecisions(); + assert.notStrictEqual(battle.p2.active[0].hp, battle.p2.active[0].maxhp); + }); + + it('should hit non-Flying-type Pokemon with Levitate with standard type effectiveness', function () { + battle = BattleEngine.Battle.construct(); + battle.join('p1', 'Guest 1', 1, [{species: "Zygarde", ability: 'aurabreak', moves: ['thousandarrows', 'earthquake']}]); + battle.join('p2', 'Guest 2', 1, [{species: "Eelektross", ability: 'levitate', item: 'weaknesspolicy', moves: ['thunderwave']}]); + battle.commitDecisions(); + assert.strictEqual(battle.p2.active[0].boosts.atk, 2); + assert.strictEqual(battle.p2.active[0].boosts.spa, 2); + }); + + it('should hit Pokemon with Air Balloon', function () { + battle = BattleEngine.Battle.construct(); + battle.join('p1', 'Guest 1', 1, [{species: "Zygarde", ability: 'aurabreak', item: 'laggingtail', moves: ['thousandarrows', 'earthquake']}]); + battle.join('p2', 'Guest 2', 1, [{species: "Donphan", ability: 'sturdy', item: 'airballoon', moves: ['stealthrock']}]); + battle.commitDecisions(); + assert.notStrictEqual(battle.p2.active[0].hp, battle.p2.active[0].maxhp); + battle.choose('p1', 'move earthquake'); + battle.commitDecisions(); + assert.notStrictEqual(battle.p2.active[0].hp, battle.p2.active[0].maxhp); + }); + + it('should not hit Ground-type Pokemon when affected by Electrify', function () { + battle = BattleEngine.Battle.construct(); + battle.join('p1', 'Guest 1', 1, [{species: "Zygarde", ability: 'aurabreak', item: 'laggingtail', moves: ['thousandarrows', 'earthquake']}]); + battle.join('p2', 'Guest 2', 1, [{species: "Stunfisk", ability: 'limber', moves: ['electrify']}]); + battle.commitDecisions(); + assert.strictEqual(battle.p2.active[0].hp, battle.p2.active[0].maxhp); + }); + + it('should not hit Ghost-type Pokemon when affected by Normalize', function () { + battle = BattleEngine.Battle.construct(); + battle.join('p1', 'Guest 1', 1, [{species: "Zygarde", ability: 'normalize', item: 'laggingtail', moves: ['thousandarrows', 'earthquake']}]); + battle.join('p2', 'Guest 2', 1, [{species: "Dusknoir", ability: 'pressure', moves: ['haze']}]); + battle.commitDecisions(); + assert.strictEqual(battle.p2.active[0].hp, battle.p2.active[0].maxhp); + }); +}); diff --git a/tools.js b/tools.js index 263af1cd6f..7108a5092d 100644 --- a/tools.js +++ b/tools.js @@ -316,6 +316,7 @@ module.exports = (function () { else move.gen = 0; } if (!move.priority) move.priority = 0; + if (!move.ignoreImmunity) move.ignoreImmunity = (move.category === 'Status'); if (!move.flags) move.flags = {}; } return move;