Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* config/formats.js */
- {
- name: "Linked",
- mod: 'linked',
- ruleset: ['OU']
- }
- /* mods/linked/items.js */
- exports.BattleItems = {
- leppaberry: {
- inherit: true,
- onUpdate: function (pokemon) {
- var move = pokemon.getMoveData(pokemon.getLastMoveAbsolute());
- if (move && move.pp === 0) {
- pokemon.addVolatile('leppaberry');
- pokemon.volatiles['leppaberry'].move = move;
- pokemon.eatItem();
- }
- }
- },
- metronome: {
- inherit: true
- // fine
- }
- };
- /* mods/linked/moves.js */
- exports.BattleMovedex = {
- /**
- * Artificial priority
- *
- */
- pursuit: {
- inherit: true,
- beforeTurnCallback: function (pokemon, target) {
- var linkedMoves = pokemon.getLinkedMoves();
- if (linkedMoves.length) {
- if (linkedMoves[0] === 'pursuit' && linkedMoves[1] !== 'pursuit') return;
- if (linkedMoves[0] !== 'pursuit' && linkedMoves[1] === 'pursuit') return;
- }
- target.side.addSideCondition('pursuit', pokemon);
- if (!target.side.sideConditions['pursuit'].sources) {
- target.side.sideConditions['pursuit'].sources = [];
- }
- target.side.sideConditions['pursuit'].sources.push(pokemon);
- }
- },
- mefirst: {
- inherit: true,
- onHit: function (target, pokemon) {
- var decision = this.willMove(target);
- if (!decision) return false;
- var noMeFirst = {
- chatter:1, counter:1, covet:1, focuspunch:1, mefirst:1, metalburst:1, mirrorcoat:1, struggle:1, thief:1
- };
- // Linked: Me First copies the first move in the link
- var move = this.getMove(decision.linked ? decision.linked[0] : decision.move);
- if (move.category !== 'Status' && !noMeFirst[move]) {
- pokemon.addVolatile('mefirst');
- this.useMove(move, pokemon);
- return;
- }
- return false;
- }
- },
- quash: {
- inherit: true
- // fine
- },
- /**
- * Sucker Punch
- * Will miss on two linked Status moves
- *
- */
- suckerpunch: {
- inherit: true,
- onTryHit: function (target) {
- var decision = this.willMove(target);
- if (!decision || decision.choice !== 'move') return false;
- if (target.volatiles['mustrecharge'] && target.volatiles['mustrecharge'].duration < 2) {
- // duration may not be lower than 2 if Sucker Punch is used as a low-priority move
- // i.e. if Sucker Punch is linked with a negative priority move
- return false;
- }
- if (!decision.linked) {
- if (decision.move.category === 'Status' && decision.move.id !== 'mefirst') return false;
- return;
- }
- for (var i = 0; i < decision.linked.length; i++) {
- var linkedMove = this.getMove(decision.linked[i]);
- if (linkedMove.category !== 'Status' || linkedMove.id === 'mefirst') return;
- }
- return false;
- }
- },
- /**
- * Pledges
- * If two Pledge moves are linked, the joint effect is triggered
- *
- **/
- firepledge: {
- inherit: true
- // awesome
- },
- grasspledge: {
- inherit: true
- // awesome
- },
- waterpledge: {
- inherit: true
- // awesome
- },
- /**
- * Mimic and Sketch
- * When any of them is linked, the link will get updated for the new move
- * They will copy the last absolute single move used by the foe.
- *
- **/
- sketch: {
- inherit: true,
- onHit: function (target, source) {
- var disallowedMoves = {chatter:1, sketch:1, struggle:1};
- var lastMove = target.getLastMoveAbsolute();
- if (source.transformed || !lastMove || disallowedMoves[lastMove] || source.moves.indexOf(lastMove) !== -1) return false;
- var moveslot = source.moves.indexOf('sketch');
- if (moveslot === -1) return false;
- var move = Tools.getMove(lastMove);
- var sketchedMove = {
- move: move.name,
- id: move.id,
- pp: move.pp,
- maxpp: move.pp,
- target: move.target,
- disabled: false,
- used: false
- };
- source.moveset[moveslot] = sketchedMove;
- source.baseMoveset[moveslot] = sketchedMove;
- source.moves[moveslot] = toId(move.name);
- this.add('-activate', source, 'move: Sketch', move.name);
- }
- },
- mimic: {
- inherit: true,
- onHit: function (target, source) {
- var disallowedMoves = {chatter:1, mimic:1, sketch:1, struggle:1, transform:1};
- var lastMove = target.getLastMoveAbsolute();
- if (source.transformed || !lastMove || disallowedMoves[lastMove] || source.moves.indexOf(lastMove) !== -1) return false;
- var moveslot = source.moves.indexOf('mimic');
- if (moveslot === -1) return false;
- var move = Tools.getMove(lastMove);
- source.moveset[moveslot] = {
- move: move.name,
- id: move.id,
- pp: move.pp,
- maxpp: move.pp,
- target: move.target,
- disabled: false,
- used: false
- };
- source.moves[moveslot] = toId(move.name);
- this.add('-start', source, 'Mimic', move.name);
- }
- },
- /**
- * Copycat and Mirror Move
- * Copy/call the last absolute move used by the target
- *
- */
- copycat: {
- inherit: true,
- onHit: function (pokemon) {
- var noCopycat = {assist:1, bestow:1, chatter:1, circlethrow:1, copycat:1, counter:1, covet:1, destinybond:1, detect:1, dragontail:1, endure:1, feint:1, focuspunch:1, followme:1, helpinghand:1, mefirst:1, metronome:1, mimic:1, mirrorcoat:1, mirrormove:1, naturepower:1, protect:1, ragepowder:1, roar:1, sketch:1, sleeptalk:1, snatch:1, struggle:1, switcheroo:1, thief:1, transform:1, trick:1, whirlwind:1};
- var lastMove = pokemon.getLastMoveAbsolute();
- if (!lastMove || noCopycat[lastMove]) return false;
- this.useMove(lastMove, pokemon);
- }
- },
- mirrormove: {
- inherit: true,
- onTryHit: function (target) {
- var noMirrorMove = {acupressure:1, afteryou:1, aromatherapy:1, chatter:1, conversion2:1, counter:1, curse:1, doomdesire:1, feint:1, finalgambit:1, focuspunch:1, futuresight:1, gravity:1, guardsplit:1, hail:1, haze:1, healbell:1, healpulse:1, helpinghand:1, lightscreen:1, luckychant:1, mefirst:1, mimic:1, mirrorcoat:1, mirrormove:1, mist:1, mudsport:1, naturepower:1, perishsong:1, powersplit:1, psychup:1, quickguard:1, raindance:1, reflect:1, reflecttype:1, roleplay:1, safeguard:1, sandstorm:1, sketch:1, spikes:1, spitup:1, stealthrock:1, struggle:1, sunnyday:1, tailwind:1, toxicspikes:1, transform:1, watersport:1, wideguard:1};
- var lastMove = target.getLastMoveAbsolute();
- if (!lastMove || noMirrorMove[lastMove] || this.getMove(lastMove).target === 'self') {
- return false;
- }
- },
- onHit: function (target, source) {
- this.useMove(target.getLastMoveAbsolute(), source);
- }
- },
- /**
- * Disable, Encore and Torment
- * Disabling effects
- *
- */
- disable: {
- inherit: true,
- effect: {
- duration: 4,
- noCopy: true, // doesn't get copied by Baton Pass
- onStart: function (pokemon) {
- var lastMove = pokemon.getLastMoveAbsolute();
- if (!this.willMove(pokemon)) {
- this.effectData.duration++;
- }
- if (!lastMove) {
- this.debug('pokemon hasn\'t moved yet');
- return false;
- }
- var moves = pokemon.moveset;
- for (var i = 0; i < moves.length; i++) {
- if (moves[i].id === lastMove) {
- if (!moves[i].pp) {
- this.debug('Move out of PP');
- return false;
- } else {
- this.add('-start', pokemon, 'Disable', moves[i].move);
- this.effectData.move = lastMove;
- return;
- }
- }
- }
- this.debug('Move doesn\'t exist ???');
- return false;
- },
- onResidualOrder: 14,
- onEnd: function (pokemon) {
- this.add('-end', pokemon, 'Disable');
- },
- onBeforeMove: function (attacker, defender, move) {
- if (move.id === this.effectData.move) {
- this.add('cant', attacker, 'Disable', move);
- return false;
- }
- },
- onModifyPokemon: function (pokemon) {
- var moves = pokemon.moveset;
- for (var i = 0; i < moves.length; i++) {
- if (moves[i].id === this.effectData.move) {
- pokemon.disableMove(moves[i].id);
- }
- }
- }
- }
- },
- encore: {
- inherit: true,
- effect: {
- duration: 3,
- onStart: function (target) {
- var noEncore = {encore:1, mimic:1, mirrormove:1, sketch:1, struggle:1, transform:1};
- var lastMove = target.getLastMoveAbsolute();
- var moveIndex = target.moves.indexOf(lastMove);
- if (!lastMove) {
- // it failed
- delete target.volatiles['encore'];
- return false;
- }
- if (target.hasLinkedMove(lastMove)) {
- var linkedMoves = target.getLinkedMoves();
- if (noEncore[linkedMoves[0]] || noEncore[linkedMoves[1]] || target.moveset[0].pp <= 0 || target.moveset[1].pp <= 0) {
- // it failed
- delete target.volatiles['encore'];
- return false;
- }
- } else {
- if (noEncore[lastMove] || (target.moveset[moveIndex] && target.moveset[moveIndex].pp <= 0)) {
- // it failed
- delete target.volatiles['encore'];
- return false;
- }
- }
- this.effectData.move = lastMove;
- this.add('-start', target, 'Encore');
- if (!this.willMove(target)) {
- this.effectData.duration++;
- }
- },
- onOverrideDecision: function (pokemon, target, move) {
- if (this.willMove(pokemon)) return false;
- if (pokemon.hasLinkedMove(this.effectData.move)) {
- var linkedMoves = pokemon.getLinkedMoves();
- // pass a `sourceEffect` argument to prevent infinite recursion at `runMove`
- this.runMove(linkedMoves[0], pokemon, target, this.effectData);
- return move.id !== linkedMoves[1] ? linkedMoves[1] : void 0; // are we fine with this targetting method? (Doubles/Triples)
- }
- if (move.id !== this.effectData.move) return this.effectData.move;
- },
- onResidualOrder: 13,
- onResidual: function (target) {
- // early termination if you run out of PP
- var lastMove = target.getLastMoveAbsolute();
- var index = target.moves.indexOf(lastMove);
- if (index === -1) return; // no last move
- if (target.hasLinkedMove(lastMove)) {
- if (target.moveset[0].pp <= 0 || target.moveset[1].pp <= 0) {
- delete target.volatiles.encore;
- this.add('-end', target, 'Encore');
- }
- } else {
- if (target.moveset[index].pp <= 0) {
- delete target.volatiles.encore;
- this.add('-end', target, 'Encore');
- }
- }
- },
- onEnd: function (target) {
- this.add('-end', target, 'Encore');
- },
- onModifyPokemon: function (pokemon) {
- if (!this.effectData.move) return; // ??
- if (!pokemon.hasMove(this.effectData.move)) {
- return;
- }
- if (pokemon.hasLinkedMove(this.effectData.move)) {
- // taking advantage of the fact that the first two move slots are reserved to linked moves
- for (var i = 2; i < pokemon.moveset.length; i++) {
- pokemon.disableMove(pokemon.moveset[i].id);
- }
- } else {
- for (var i = 0; i < pokemon.moveset.length; i++) {
- if (pokemon.moveset[i].id !== this.effectData.move) {
- pokemon.disableMove(pokemon.moveset[i].id);
- }
- }
- }
- }
- }
- },
- torment: {
- inherit: true,
- effect: {
- onStart: function (pokemon) {
- this.add('-start', pokemon, 'Torment');
- },
- onEnd: function (pokemon) {
- this.add('-end', pokemon, 'Torment');
- },
- onModifyPokemon: function (pokemon) {
- var lastMove = pokemon.lastMove;
- if (lastMove === 'struggle') return;
- if (Array.isArray(lastMove)) {
- for (var i = 0; i < lastMove.length; i++) {
- pokemon.disableMove(lastMove[i]);
- }
- } else {
- pokemon.disableMove(lastMove);
- }
- }
- }
- },
- /**
- * Spite and Grudge
- * Decrease the PP of the last absolute move used by the target
- * Also, Grudge's effect won't be removed by its linked move, if any
- *
- */
- grudge: {
- inherit: true,
- effect: {
- onStart: function (pokemon) {
- this.add('-singlemove', pokemon, 'Grudge');
- },
- onFaint: function (target, source, effect) {
- this.debug('Grudge detected fainted pokemon');
- if (!source || !effect) return;
- if (effect.effectType === 'Move') {
- var lastMove = source.getLastMoveAbsolute();
- for (var i in source.moveset) {
- if (source.moveset[i].id === lastMove) {
- source.moveset[i].pp = 0;
- this.add('-activate', source, 'Grudge', this.getMove(lastMove).name);
- }
- }
- }
- },
- onBeforeMovePriority: 100,
- onBeforeMove: function (pokemon) {
- if (pokemon.moveThisTurn) return; // Second stage of a Linked move
- this.debug('removing Grudge before attack');
- pokemon.removeVolatile('grudge');
- }
- }
- },
- spite: {
- inherit: true,
- onHit: function (target) {
- var lastMove = target.getLastMoveAbsolute();
- if (target.deductPP(lastMove, 4)) {
- this.add("-activate", target, 'move: Spite', lastMove, 4);
- return;
- }
- return false;
- }
- },
- /**
- * Rollout and Ice Ball
- *
- */
- rollout: {
- inherit: true
- // fine
- },
- iceball: {
- inherit: true
- // fine
- },
- /**
- * Other moves that check `pokemon.lastMove`
- * (may behave counter-intuitively if left unmodded)
- *
- **/
- conversion2: {
- inherit: true,
- onHit: function (target, source) {
- var lastMove = target.getLastMoveAbsolute();
- if (!lastMove) return false;
- var possibleTypes = [];
- var attackType = this.getMove(lastMove).type;
- for (var type in this.data.TypeChart) {
- if (source.hasType(type) || target.hasType(type)) continue;
- var typeCheck = this.data.TypeChart[type].damageTaken[attackType];
- if (typeCheck === 2 || typeCheck === 3) {
- possibleTypes.push(type);
- }
- }
- if (!possibleTypes.length) {
- return false;
- }
- var type = possibleTypes[this.random(possibleTypes.length)];
- if (!source.setType(type)) return false;
- this.add('-start', source, 'typechange', type);
- }
- },
- destinybond: {
- inherit: true,
- effect: {
- onStart: function (pokemon) {
- this.add('-singlemove', pokemon, 'Destiny Bond');
- },
- onFaint: function (target, source, effect) {
- if (!source || !effect) return;
- if (effect.effectType === 'Move' && !effect.isFutureMove) {
- this.add('-activate', target, 'Destiny Bond');
- source.faint();
- }
- },
- onBeforeMovePriority: 100,
- onBeforeMove: function (pokemon, target, move) {
- // Second stage of a Linked move does not remove Destiny Bond
- if (pokemon.moveThisTurn) return;
- this.debug('removing Destiny Bond before attack');
- pokemon.removeVolatile('destinybond');
- }
- }
- },
- trumpcard: {
- inherit: true,
- basePowerCallback: function (pokemon) {
- var move = pokemon.getMoveData(pokemon.getLastMoveAbsolute()); // Account for calling Trump Card via other moves
- switch (move.pp) {
- case 0:
- return 200;
- case 1:
- return 80;
- case 2:
- return 60;
- case 3:
- return 50;
- default:
- return 40;
- }
- }
- },
- uproar: {
- inherit: true
- // fine
- },
- /**
- * Moves that check `pokemon.moveThisTurn`
- * (may behave counter-intuitively if left unmodded)
- *
- **/
- fusionbolt: {
- inherit: true,
- onBasePower: function (basePower, pokemon) {
- var actives = pokemon.side.active;
- for (var i = 0; i < actives.length; i++) {
- if (actives[i] && actives[i].checkMoveThisTurn('fusionflare')) {
- this.debug('double power');
- return this.chainModify(2);
- }
- }
- }
- },
- fusionflare: {
- inherit: true,
- onBasePower: function (basePower, pokemon) {
- var actives = pokemon.side.active;
- for (var i = 0; i < actives.length; i++) {
- if (actives[i] && actives[i].checkMoveThisTurn('fusionbolt')) {
- this.debug('double power');
- return this.chainModify(2);
- }
- }
- }
- },
- /**
- * Moves that should clean the house after running
- * (but aren't doing so in standard for whatever reason)
- */
- beatup: {
- inherit: true,
- onAfterMove: function (pokemon) {
- pokemon.removeVolatile('beatup');
- }
- },
- triplekick: {
- inherit: true,
- onAfterMove: function (pokemon) {
- pokemon.removeVolatile('triplekick');
- }
- },
- /**
- * Moves that should clean the house if they aren't run
- *
- */
- furycutter: {
- inherit: true,
- effect: {
- duration: 2,
- onStart: function () {
- this.effectData.multiplier = 1;
- },
- onRestart: function () {
- if (this.effectData.multiplier < 4) {
- this.effectData.multiplier <<= 1;
- }
- this.effectData.duration = 2;
- },
- onBeforeMove: function (pokemon, target, move) {
- if (move.id !== 'furycutter') pokemon.removeVolatile('furycutter');
- }
- }
- },
- /**
- * First Law of Pokémon Simulation:
- * Always make sure that Sky Drop works
- *
- */
- skydrop: {
- inherit: true,
- effect: {
- duration: 2,
- onDragOut: false,
- onSourceDragOut: false,
- onFoeModifyPokemon: function (defender) {
- if (defender !== this.effectData.source) return;
- defender.trapped = true;
- },
- onFoeBeforeMovePriority: 11,
- onFoeBeforeMove: function (attacker, defender, move) {
- if (attacker === this.effectData.source) {
- this.debug('Sky drop nullifying.');
- return null;
- }
- },
- onRedirectTarget: function (target, source, source2) {
- if (source !== this.effectData.target) return;
- if (this.effectData.source.fainted) return;
- return this.effectData.source;
- },
- onAnyAccuracy: function (accuracy, target, source, move) {
- // both user and target of Sky Drop avoid moves, yet
- // not moves targetting themselves (Linked)
- if (target !== this.effectData.target && target !== this.effectData.source) {
- return;
- }
- if (source === this.effectData.target && target === this.effectData.source) {
- return;
- }
- if (source === target) return;
- if (move.id === 'gust' || move.id === 'twister') {
- return;
- }
- if (move.id === 'skyuppercut' || move.id === 'thunder' || move.id === 'hurricane' || move.id === 'smackdown' || move.id === 'thousandarrows' || move.id === 'helpinghand') {
- return;
- }
- if (source.hasAbility('noguard') || target.hasAbility('noguard')) {
- return;
- }
- return 0;
- },
- onAnyBasePower: function (basePower, target, source, move) {
- if (target !== this.effectData.target && target !== this.effectData.source) {
- return;
- }
- if (source === this.effectData.target && target === this.effectData.source) {
- return;
- }
- if (move.id === 'gust' || move.id === 'twister') {
- return this.chainModify(2);
- }
- },
- onFaint: function (target) {
- if (target.volatiles['skydrop'] && target.volatiles['twoturnmove'].source) {
- this.add('-end', target.volatiles['twoturnmove'].source, 'Sky Drop', '[interrupt]');
- }
- }
- }
- }
- };
- /* mods/linked/scripts.js */
- exports.BattleScripts = {
- runMove: function (move, pokemon, target, sourceEffect) {
- if (!sourceEffect && toId(move) !== 'struggle') {
- var changedMove = this.runEvent('OverrideDecision', pokemon, target, move);
- if (changedMove === false) return; // Linked: Encore hack
- if (changedMove && changedMove !== true) {
- move = changedMove;
- target = null;
- }
- }
- move = this.getMove(move);
- if (!target && target !== false) target = this.resolveTarget(pokemon, move);
- this.setActiveMove(move, pokemon, target);
- // Linked: Pokemon can move more than once per turn
- /* if (pokemon.moveThisTurn) {
- // THIS IS PURELY A SANITY CHECK
- // DO NOT TAKE ADVANTAGE OF THIS TO PREVENT A POKEMON FROM MOVING;
- // USE this.cancelMove INSTEAD
- this.debug('' + pokemon.id + ' INCONSISTENT STATE, ALREADY MOVED: ' + pokemon.moveThisTurn);
- this.clearActiveMove(true);
- return;
- }*/
- if (!this.runEvent('BeforeMove', pokemon, target, move)) {
- // Prevent invulnerability from persisting until the turn ends
- // Linked: make sure that the cancelled move is the correct one.
- if (pokemon.volatiles['twoturnmove'] && pokemon.volatiles['twoturnmove'].move === move.id) {
- pokemon.removeVolatile('twoturnmove');
- }
- this.clearActiveMove(true);
- return;
- }
- if (move.beforeMoveCallback) {
- if (move.beforeMoveCallback.call(this, pokemon, target, move)) {
- this.clearActiveMove(true);
- return;
- }
- }
- pokemon.lastDamage = 0;
- var lockedMove = this.runEvent('LockMove', pokemon);
- if (lockedMove === true) lockedMove = false;
- if (!lockedMove) {
- if (!pokemon.deductPP(move, null, target) && (move.id !== 'struggle')) {
- this.add('cant', pokemon, 'nopp', move);
- this.clearActiveMove(true);
- return;
- }
- }
- pokemon.moveUsed(move);
- this.useMove(move, pokemon, target, sourceEffect);
- this.singleEvent('AfterMove', move, null, pokemon, target, move);
- },
- addQueue: function (decision, noSort, side) {
- if (decision) {
- if (Array.isArray(decision)) {
- for (var i = 0; i < decision.length; i++) {
- this.addQueue(decision[i], noSort);
- }
- return;
- }
- if (!decision.side && side) decision.side = side;
- if (!decision.side && decision.pokemon) decision.side = decision.pokemon.side;
- if (!decision.choice && decision.move) decision.choice = 'move';
- if (!decision.priority) {
- var priorities = {
- 'beforeTurn': 100,
- 'beforeTurnMove': 99,
- 'switch': 6,
- 'runSwitch': 6.1,
- 'megaEvo': 5.9,
- 'residual': -100,
- 'team': 102,
- 'start': 101
- };
- if (priorities[decision.choice]) {
- decision.priority = priorities[decision.choice];
- }
- }
- if (decision.choice === 'move') {
- if (this.getMove(decision.move).beforeTurnCallback) {
- this.addQueue({choice: 'beforeTurnMove', pokemon: decision.pokemon, move: decision.move, targetLoc: decision.targetLoc}, true);
- }
- var linkedMoves = decision.pokemon.getLinkedMoves();
- if (linkedMoves.length) {
- var decisionMove = toId(decision.move);
- var index = linkedMoves.indexOf(decisionMove);
- if (index !== -1) {
- // flag the move as linked here
- decision.linked = linkedMoves;
- if (this.getMove(linkedMoves[1 - index]).beforeTurnCallback) {
- this.addQueue({choice: 'beforeTurnMove', pokemon: decision.pokemon, move: linkedMoves[1 - index], targetLoc: decision.targetLoc}, true);
- }
- }
- }
- } else if (decision.choice === 'switch') {
- if (decision.pokemon.switchFlag && decision.pokemon.switchFlag !== true) {
- decision.pokemon.switchCopyFlag = decision.pokemon.switchFlag;
- }
- decision.pokemon.switchFlag = false;
- if (!decision.speed && decision.pokemon && decision.pokemon.isActive) decision.speed = decision.pokemon.speed;
- }
- if (decision.move) {
- var target;
- if (!decision.targetPosition) {
- // this target is not relevant to Linked (or any other game mode)
- target = this.resolveTarget(decision.pokemon, decision.move);
- decision.targetSide = target.side;
- decision.targetPosition = target.position;
- }
- decision.move = this.getMoveCopy(decision.move);
- if (!decision.priority) {
- var priority = decision.move.priority;
- priority = this.runEvent('ModifyPriority', decision.pokemon, target, decision.move, priority);
- // Linked: if two moves are linked, the effective priority is minimized
- var linkedMoves = decision.pokemon.getLinkedMoves();
- if (linkedMoves.length) {
- var decisionMove = toId(decision.move);
- var index = linkedMoves.indexOf(decisionMove);
- if (index !== -1) {
- var altMove = this.getMoveCopy(linkedMoves[1 - index]);
- var altPriority = altMove.priority;
- altPriority = this.runEvent('ModifyPriority', decision.pokemon, target, altMove, altPriority);
- priority = Math.min(priority, altPriority);
- }
- }
- decision.priority = priority;
- // In Gen 6, Quick Guard blocks moves with artificially enhanced priority.
- if (this.gen > 5) decision.move.priority = priority;
- }
- }
- if (!decision.pokemon && !decision.speed) decision.speed = 1;
- if (!decision.speed && decision.choice === 'switch' && decision.target) decision.speed = decision.target.speed;
- if (!decision.speed) decision.speed = decision.pokemon.speed;
- if (decision.choice === 'switch' && !decision.side.pokemon[0].isActive) {
- // if there's no actives, switches happen before activations
- decision.priority = 6.2;
- }
- this.queue.push(decision);
- }
- if (!noSort) {
- this.queue.sort(this.comparePriority);
- }
- },
- runDecision: function (decision) {
- var pokemon;
- // returns whether or not we ended in a callback
- switch (decision.choice) {
- case 'start':
- // I GIVE UP, WILL WRESTLE WITH EVENT SYSTEM LATER
- var beginCallback = this.getFormat().onBegin;
- if (beginCallback) beginCallback.call(this);
- this.add('start');
- for (var pos = 0; pos < this.p1.active.length; pos++) {
- this.switchIn(this.p1.pokemon[pos], pos);
- }
- for (var pos = 0; pos < this.p2.active.length; pos++) {
- this.switchIn(this.p2.pokemon[pos], pos);
- }
- for (var pos = 0; pos < this.p1.pokemon.length; pos++) {
- pokemon = this.p1.pokemon[pos];
- this.singleEvent('Start', this.getEffect(pokemon.species), pokemon.speciesData, pokemon);
- }
- for (var pos = 0; pos < this.p2.pokemon.length; pos++) {
- pokemon = this.p2.pokemon[pos];
- this.singleEvent('Start', this.getEffect(pokemon.species), pokemon.speciesData, pokemon);
- }
- this.midTurn = true;
- break;
- case 'move':
- if (!decision.pokemon.isActive) return false;
- if (decision.pokemon.fainted) return false;
- if (decision.linked) {
- var linkedMoves = decision.linked;
- var decisionMove = toId(decision.move);
- for (var i = linkedMoves.length - 1; i >= 0; i--) {
- var pseudoDecision = {choice: 'move', move: linkedMoves[i], targetLoc: decision.targetLoc, pokemon: decision.pokemon, targetPosition: decision.targetPosition, targetSide: decision.targetSide};
- this.queue.unshift(pseudoDecision);
- }
- return;
- }
- this.runMove(decision.move, decision.pokemon, this.getTarget(decision), decision.sourceEffect);
- break;
- case 'megaEvo':
- if (this.runMegaEvo) this.runMegaEvo(decision.pokemon);
- break;
- case 'beforeTurnMove':
- if (!decision.pokemon.isActive) return false;
- if (decision.pokemon.fainted) return false;
- this.debug('before turn callback: ' + decision.move.id);
- var target = this.getTarget(decision);
- if (!target) return false;
- decision.move.beforeTurnCallback.call(this, decision.pokemon, target);
- break;
- case 'event':
- this.runEvent(decision.event, decision.pokemon);
- break;
- case 'team':
- var i = parseInt(decision.team[0], 10) - 1;
- if (i >= 6 || i < 0) return;
- if (decision.team[1]) {
- // validate the choice
- var len = decision.side.pokemon.length;
- var newPokemon = [null, null, null, null, null, null].slice(0, len);
- for (var j = 0; j < len; j++) {
- var i = parseInt(decision.team[j], 10) - 1;
- newPokemon[j] = decision.side.pokemon[i];
- }
- var reject = false;
- for (var j = 0; j < len; j++) {
- if (!newPokemon[j]) reject = true;
- }
- if (!reject) {
- for (var j = 0; j < len; j++) {
- newPokemon[j].position = j;
- }
- decision.side.pokemon = newPokemon;
- return;
- }
- }
- if (i === 0) return;
- pokemon = decision.side.pokemon[i];
- if (!pokemon) return;
- decision.side.pokemon[i] = decision.side.pokemon[0];
- decision.side.pokemon[0] = pokemon;
- decision.side.pokemon[i].position = i;
- decision.side.pokemon[0].position = 0;
- // we return here because the update event would crash since there are no active pokemon yet
- return;
- case 'pass':
- if (!decision.priority || decision.priority <= 101) return;
- if (decision.pokemon) {
- decision.pokemon.switchFlag = false;
- }
- break;
- case 'switch':
- if (decision.pokemon) {
- decision.pokemon.beingCalledBack = true;
- var lastMove = this.getMove(decision.pokemon.getLastMoveAbsolute());
- if (lastMove.selfSwitch !== 'copyvolatile') {
- this.runEvent('BeforeSwitchOut', decision.pokemon);
- }
- if (!this.runEvent('SwitchOut', decision.pokemon)) {
- // Warning: DO NOT interrupt a switch-out
- // if you just want to trap a pokemon.
- // To trap a pokemon and prevent it from switching out,
- // (e.g. Mean Look, Magnet Pull) use the 'trapped' flag
- // instead.
- // Note: Nothing in BW or earlier interrupts
- // a switch-out.
- break;
- }
- this.singleEvent('End', this.getAbility(decision.pokemon.ability), decision.pokemon.abilityData, decision.pokemon);
- }
- if (decision.pokemon && !decision.pokemon.hp && !decision.pokemon.fainted) {
- // a pokemon fainted from Pursuit before it could switch
- if (this.gen <= 4) {
- // in gen 2-4, the switch still happens
- decision.priority = -101;
- this.queue.unshift(decision);
- this.debug('Pursuit target fainted');
- break;
- }
- // in gen 5+, the switch is cancelled
- this.debug('A Pokemon can\'t switch between when it runs out of HP and when it faints');
- break;
- }
- if (decision.target.isActive) {
- this.debug('Switch target is already active');
- break;
- }
- this.switchIn(decision.target, decision.pokemon.position);
- break;
- case 'runSwitch':
- this.runEvent('SwitchIn', decision.pokemon);
- if (!decision.pokemon.hp) break;
- decision.pokemon.isStarted = true;
- if (!decision.pokemon.fainted) {
- this.singleEvent('Start', decision.pokemon.getAbility(), decision.pokemon.abilityData, decision.pokemon);
- this.singleEvent('Start', decision.pokemon.getItem(), decision.pokemon.itemData, decision.pokemon);
- }
- break;
- case 'shift':
- if (!decision.pokemon.isActive) return false;
- if (decision.pokemon.fainted) return false;
- this.swapPosition(decision.pokemon, 1);
- break;
- case 'beforeTurn':
- this.eachEvent('BeforeTurn');
- break;
- case 'residual':
- this.add('');
- this.clearActiveMove(true);
- this.residualEvent('Residual');
- break;
- }
- // phazing (Roar, etc)
- var self = this;
- function checkForceSwitchFlag(a) {
- if (!a) return false;
- if (a.hp && a.forceSwitchFlag) {
- self.dragIn(a.side, a.position);
- }
- delete a.forceSwitchFlag;
- }
- this.p1.active.forEach(checkForceSwitchFlag);
- this.p2.active.forEach(checkForceSwitchFlag);
- this.clearActiveMove();
- // fainting
- this.faintMessages();
- if (this.ended) return true;
- // switching (fainted pokemon, U-turn, Baton Pass, etc)
- if (!this.queue.length || (this.gen <= 3 && this.queue[0].choice in {move:1, residual:1})) {
- // in gen 3 or earlier, switching in fainted pokemon is done after
- // every move, rather than only at the end of the turn.
- this.checkFainted();
- } else if (decision.choice === 'pass') {
- this.eachEvent('Update');
- return false;
- }
- function hasSwitchFlag(a) { return a ? a.switchFlag : false; }
- function removeSwitchFlag(a) { if (a) a.switchFlag = false; }
- var p1switch = this.p1.active.any(hasSwitchFlag);
- var p2switch = this.p2.active.any(hasSwitchFlag);
- if (p1switch && !this.canSwitch(this.p1)) {
- this.p1.active.forEach(removeSwitchFlag);
- p1switch = false;
- }
- if (p2switch && !this.canSwitch(this.p2)) {
- this.p2.active.forEach(removeSwitchFlag);
- p2switch = false;
- }
- if (p1switch || p2switch) {
- this.makeRequest('switch');
- return true;
- }
- this.eachEvent('Update');
- return false;
- },
- comparePriority: function (a, b) { // intentionally not in Battle.prototype
- a.priority = a.priority || 0;
- a.subPriority = a.subPriority || 0;
- a.speed = a.speed || 0;
- b.priority = b.priority || 0;
- b.subPriority = b.subPriority || 0;
- b.speed = b.speed || 0;
- if ((typeof a.order === 'number' || typeof b.order === 'number') && a.order !== b.order) {
- if (typeof a.order !== 'number') {
- return -1;
- }
- if (typeof b.order !== 'number') {
- return 1;
- }
- if (b.order - a.order) {
- return -(b.order - a.order);
- }
- }
- if (b.priority - a.priority) {
- return b.priority - a.priority;
- }
- if (b.speed - a.speed) {
- return b.speed - a.speed;
- }
- if (b.subOrder - a.subOrder) {
- return -(b.subOrder - a.subOrder);
- }
- return Math.random() - 0.5;
- },
- pokemon: {
- moveUsed: function (move) {
- var lastMove = this.moveThisTurn ? [this.moveThisTurn, this.battle.getMove(move).id] : this.battle.getMove(move).id;
- this.lastMove = lastMove;
- this.moveThisTurn = lastMove;
- },
- getLastMoveAbsolute: function () {
- if (Array.isArray(this.lastMove)) return this.lastMove[1];
- return this.lastMove;
- },
- checkLastMove: function (move, maybeLinked) {
- move = toId(move);
- if (!maybeLinked) return this.getLastMoveAbsolute() === move;
- if (Array.isArray(this.lastMove)) return this.lastMove.indexOf(move) >= 0;
- return this.lastMove === move;
- },
- checkMoveThisTurn: function (move) {
- move = toId(move);
- if (Array.isArray(this.moveThisTurn)) return this.moveThisTurn.indexOf(move) >= 0;
- return this.moveThisTurn === move;
- },
- getLinkedMoves: function () {
- var linkedMoves = this.moveset.slice(0, 2);
- if (linkedMoves.length !== 2 || linkedMoves[0].pp <= 0 || linkedMoves[1].pp <= 0) return [];
- return linkedMoves.map('id');
- },
- hasLinkedMove: function (move) {
- move = toId(move);
- var linkedMoves = this.getLinkedMoves();
- if (!linkedMoves.length) return;
- return linkedMoves[0] === move || linkedMoves[1] === move;
- },
- hasLinkedMoves: function (move1, move2) {
- var linkedMoves = this.getLinkedMoves();
- if (!linkedMoves.length) return;
- move1 = toId(move1);
- move2 = toId(move2);
- if (linkedMoves[0] === move1 && linkedMoves[1] === move2) return true;
- if (linkedMoves[1] === move2 && linkedMoves[0] === move1) return true;
- return false;
- }
- }
- };
- /* mods/linked/statuses.js */
- exports.BattleStatuses = {
- slp: {
- inherit: true,
- onBeforeMove: function (pokemon, target, move) {
- if (this.effectData.timerDecreased !== this.turn) {
- this.effectData.timerDecreased = this.turn;
- if (pokemon.getAbility().isHalfSleep) {
- pokemon.statusData.time--;
- }
- pokemon.statusData.time--;
- if (pokemon.statusData.time <= 0) {
- pokemon.cureStatus();
- return;
- }
- this.add('cant', pokemon, 'slp');
- }
- if (move.sleepUsable) {
- return;
- }
- return false;
- }
- },
- frz: {
- inherit: true,
- onBeforeMove: function (pokemon, target, move) {
- if (move.thawsUser || this.effectData.durationRolled !== this.turn && this.random(5) === 0) {
- pokemon.cureStatus();
- return;
- }
- if (this.effectData.durationRolled !== this.turn) {
- // no need to display the frozen message twice
- this.effectData.durationRolled = this.turn;
- this.add('cant', pokemon, 'frz');
- }
- return false;
- }
- },
- confusion: {
- inherit: true,
- onBeforeMove: function (pokemon) {
- if (this.effectData.timerDecreased !== this.turn) {
- this.effectData.timerDecreased = this.turn;
- pokemon.volatiles.confusion.time--;
- if (!pokemon.volatiles.confusion.time) {
- pokemon.removeVolatile('confusion');
- return;
- }
- }
- this.add('-activate', pokemon, 'confusion');
- if (this.random(2) === 0) {
- return;
- }
- this.directDamage(this.getDamage(pokemon, pokemon, 40));
- return false;
- }
- },
- flinch: {
- inherit: true,
- onBeforeMove: function (pokemon) {
- if (this.effectData.movePrevented) return false;
- if (!this.runEvent('Flinch', pokemon)) {
- return;
- }
- if (!this.effectData.movePrevented) {
- // no need to display the flinch message twice
- this.effectData.movePrevented = true;
- this.add('cant', pokemon, 'flinch');
- }
- return false;
- }
- },
- mustrecharge: {
- inherit: true,
- onBeforeMove: function (pokemon) {
- if (!this.effectData.movePrevented) {
- // no need to display the recharge message twice
- this.effectData.movePrevented = true;
- this.add('cant', pokemon, 'recharge');
- }
- if (!pokemon.moveThisTurn) pokemon.removeVolatile('mustrecharge');
- return false;
- }
- },
- /**
- * Gems and Auras
- * Make sure that they only boost a single move
- *
- */
- gem: {
- inherit: true,
- onBeforeMove: function (pokemon) {
- if (pokemon.moveThisTurn) pokemon.removeVolatile('gem');
- }
- },
- aura: {
- inherit: true,
- onBeforeMove: function (pokemon) {
- if (pokemon.moveThisTurn) pokemon.removeVolatile('gem');
- }
- }
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement