Merge pull request #1728 from ascriptmaster/move-fixes

Move refactor: moves/items that ignore immunity/effectiveness
This commit is contained in:
Guangcong Luo 2015-04-14 17:05:22 +00:00
commit 54947b665f
20 changed files with 213 additions and 103 deletions

View File

@ -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);
}
}

View File

@ -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++) {

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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"

View File

@ -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);

View File

@ -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) {

View File

@ -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'

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -357,7 +357,7 @@ exports.BattleMovedex = {
glare: {
inherit: true,
accuracy: 75,
affectedByImmunities: true
ignoreImmunity: false
},
growth: {
inherit: true,

View File

@ -275,7 +275,7 @@ exports.BattleMovedex = {
basePower: 100,
category: "Special",
flags: {},
affectedByImmunities: true,
ignoreImmunity: false,
type: 'Psychic'
}
};

View File

@ -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);
}
}
},

View File

@ -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,

View File

@ -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;
}

View File

@ -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);
});
});

View File

@ -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);
});
});

View File

@ -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;