Advertisement
Guest User

Linked

a guest
Jan 24th, 2015
238
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /* config/formats.js */
  2.  
  3. {
  4.     name: "Linked",
  5.  
  6.     mod: 'linked',
  7.     ruleset: ['OU']
  8. }
  9.  
  10. /* mods/linked/items.js */
  11.  
  12. exports.BattleItems = {
  13.     leppaberry: {
  14.         inherit: true,
  15.         onUpdate: function (pokemon) {
  16.             var move = pokemon.getMoveData(pokemon.getLastMoveAbsolute());
  17.             if (move && move.pp === 0) {
  18.                 pokemon.addVolatile('leppaberry');
  19.                 pokemon.volatiles['leppaberry'].move = move;
  20.                 pokemon.eatItem();
  21.             }
  22.         }
  23.     },
  24.     metronome: {
  25.         inherit: true
  26.         // fine
  27.     }
  28. };
  29.  
  30. /* mods/linked/moves.js */
  31.  
  32. exports.BattleMovedex = {
  33.     /**
  34.      * Artificial priority
  35.      *
  36.      */
  37.     pursuit: {
  38.         inherit: true,
  39.         beforeTurnCallback: function (pokemon, target) {
  40.             var linkedMoves = pokemon.getLinkedMoves();
  41.             if (linkedMoves.length) {
  42.                 if (linkedMoves[0] === 'pursuit' && linkedMoves[1] !== 'pursuit') return;
  43.                 if (linkedMoves[0] !== 'pursuit' && linkedMoves[1] === 'pursuit') return;
  44.             }
  45.  
  46.             target.side.addSideCondition('pursuit', pokemon);
  47.             if (!target.side.sideConditions['pursuit'].sources) {
  48.                 target.side.sideConditions['pursuit'].sources = [];
  49.             }
  50.             target.side.sideConditions['pursuit'].sources.push(pokemon);
  51.         }
  52.     },
  53.     mefirst: {
  54.         inherit: true,
  55.         onHit: function (target, pokemon) {
  56.             var decision = this.willMove(target);
  57.             if (!decision) return false;
  58.             var noMeFirst = {
  59.                 chatter:1, counter:1, covet:1, focuspunch:1, mefirst:1, metalburst:1, mirrorcoat:1, struggle:1, thief:1
  60.             };
  61.             // Linked: Me First copies the first move in the link
  62.             var move = this.getMove(decision.linked ? decision.linked[0] : decision.move);
  63.             if (move.category !== 'Status' && !noMeFirst[move]) {
  64.                 pokemon.addVolatile('mefirst');
  65.                 this.useMove(move, pokemon);
  66.                 return;
  67.             }
  68.             return false;
  69.         }
  70.     },
  71.     quash: {
  72.         inherit: true
  73.         // fine
  74.     },
  75.  
  76.     /**
  77.      *  Sucker Punch
  78.      *  Will miss on two linked Status moves
  79.      *
  80.      */
  81.  
  82.     suckerpunch: {
  83.         inherit: true,
  84.         onTryHit: function (target) {
  85.             var decision = this.willMove(target);
  86.             if (!decision || decision.choice !== 'move') return false;
  87.             if (target.volatiles['mustrecharge'] && target.volatiles['mustrecharge'].duration < 2) {
  88.                 // duration may not be lower than 2 if Sucker Punch is used as a low-priority move
  89.                 // i.e. if Sucker Punch is linked with a negative priority move
  90.                 return false;
  91.             }
  92.             if (!decision.linked) {
  93.                 if (decision.move.category === 'Status' && decision.move.id !== 'mefirst') return false;
  94.                 return;
  95.             }
  96.  
  97.             for (var i = 0; i < decision.linked.length; i++) {
  98.                 var linkedMove = this.getMove(decision.linked[i]);
  99.                 if (linkedMove.category !== 'Status' || linkedMove.id === 'mefirst') return;
  100.             }
  101.             return false;
  102.         }
  103.     },
  104.  
  105.  
  106.     /**
  107.      * Pledges
  108.      * If two Pledge moves are linked, the joint effect is triggered
  109.      *
  110.      **/
  111.  
  112.     firepledge: {
  113.         inherit: true
  114.         // awesome
  115.     },
  116.     grasspledge: {
  117.         inherit: true
  118.         // awesome
  119.     },
  120.     waterpledge: {
  121.         inherit: true
  122.         // awesome
  123.     },
  124.  
  125.     /**
  126.      * Mimic and Sketch
  127.      * When any of them is linked, the link will get updated for the new move
  128.      * They will copy the last absolute single move used by the foe.
  129.      *
  130.      **/
  131.  
  132.     sketch: {
  133.         inherit: true,
  134.         onHit: function (target, source) {
  135.             var disallowedMoves = {chatter:1, sketch:1, struggle:1};
  136.             var lastMove = target.getLastMoveAbsolute();
  137.             if (source.transformed || !lastMove || disallowedMoves[lastMove] || source.moves.indexOf(lastMove) !== -1) return false;
  138.             var moveslot = source.moves.indexOf('sketch');
  139.             if (moveslot === -1) return false;
  140.             var move = Tools.getMove(lastMove);
  141.             var sketchedMove = {
  142.                 move: move.name,
  143.                 id: move.id,
  144.                 pp: move.pp,
  145.                 maxpp: move.pp,
  146.                 target: move.target,
  147.                 disabled: false,
  148.                 used: false
  149.             };
  150.             source.moveset[moveslot] = sketchedMove;
  151.             source.baseMoveset[moveslot] = sketchedMove;
  152.             source.moves[moveslot] = toId(move.name);
  153.             this.add('-activate', source, 'move: Sketch', move.name);
  154.         }
  155.     },
  156.     mimic: {
  157.         inherit: true,
  158.         onHit: function (target, source) {
  159.             var disallowedMoves = {chatter:1, mimic:1, sketch:1, struggle:1, transform:1};
  160.             var lastMove = target.getLastMoveAbsolute();
  161.             if (source.transformed || !lastMove || disallowedMoves[lastMove] || source.moves.indexOf(lastMove) !== -1) return false;
  162.             var moveslot = source.moves.indexOf('mimic');
  163.             if (moveslot === -1) return false;
  164.             var move = Tools.getMove(lastMove);
  165.             source.moveset[moveslot] = {
  166.                 move: move.name,
  167.                 id: move.id,
  168.                 pp: move.pp,
  169.                 maxpp: move.pp,
  170.                 target: move.target,
  171.                 disabled: false,
  172.                 used: false
  173.             };
  174.             source.moves[moveslot] = toId(move.name);
  175.             this.add('-start', source, 'Mimic', move.name);
  176.         }
  177.     },
  178.  
  179.     /**
  180.      * Copycat and Mirror Move
  181.      * Copy/call the last absolute move used by the target
  182.      *
  183.      */
  184.  
  185.     copycat: {
  186.         inherit: true,
  187.         onHit: function (pokemon) {
  188.             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};
  189.             var lastMove = pokemon.getLastMoveAbsolute();
  190.             if (!lastMove || noCopycat[lastMove]) return false;
  191.             this.useMove(lastMove, pokemon);
  192.         }
  193.     },
  194.     mirrormove: {
  195.         inherit: true,
  196.         onTryHit: function (target) {
  197.             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};
  198.             var lastMove = target.getLastMoveAbsolute();
  199.             if (!lastMove || noMirrorMove[lastMove] || this.getMove(lastMove).target === 'self') {
  200.                 return false;
  201.             }
  202.         },
  203.         onHit: function (target, source) {
  204.             this.useMove(target.getLastMoveAbsolute(), source);
  205.         }
  206.     },
  207.  
  208.     /**
  209.      * Disable, Encore and Torment
  210.      * Disabling effects
  211.      *
  212.      */
  213.  
  214.     disable: {
  215.         inherit: true,
  216.         effect: {
  217.             duration: 4,
  218.             noCopy: true, // doesn't get copied by Baton Pass
  219.             onStart: function (pokemon) {
  220.                 var lastMove = pokemon.getLastMoveAbsolute();
  221.                 if (!this.willMove(pokemon)) {
  222.                     this.effectData.duration++;
  223.                 }
  224.                 if (!lastMove) {
  225.                     this.debug('pokemon hasn\'t moved yet');
  226.                     return false;
  227.                 }
  228.                 var moves = pokemon.moveset;
  229.                 for (var i = 0; i < moves.length; i++) {
  230.                     if (moves[i].id === lastMove) {
  231.                         if (!moves[i].pp) {
  232.                             this.debug('Move out of PP');
  233.                             return false;
  234.                         } else {
  235.                             this.add('-start', pokemon, 'Disable', moves[i].move);
  236.                             this.effectData.move = lastMove;
  237.                             return;
  238.                         }
  239.                     }
  240.                 }
  241.                 this.debug('Move doesn\'t exist ???');
  242.                 return false;
  243.             },
  244.             onResidualOrder: 14,
  245.             onEnd: function (pokemon) {
  246.                 this.add('-end', pokemon, 'Disable');
  247.             },
  248.             onBeforeMove: function (attacker, defender, move) {
  249.                 if (move.id === this.effectData.move) {
  250.                     this.add('cant', attacker, 'Disable', move);
  251.                     return false;
  252.                 }
  253.             },
  254.             onModifyPokemon: function (pokemon) {
  255.                 var moves = pokemon.moveset;
  256.                 for (var i = 0; i < moves.length; i++) {
  257.                     if (moves[i].id === this.effectData.move) {
  258.                         pokemon.disableMove(moves[i].id);
  259.                     }
  260.                 }
  261.             }
  262.         }
  263.     },
  264.     encore: {
  265.         inherit: true,
  266.         effect: {
  267.             duration: 3,
  268.             onStart: function (target) {
  269.                 var noEncore = {encore:1, mimic:1, mirrormove:1, sketch:1, struggle:1, transform:1};
  270.                 var lastMove = target.getLastMoveAbsolute();
  271.                 var moveIndex = target.moves.indexOf(lastMove);
  272.                 if (!lastMove) {
  273.                     // it failed
  274.                     delete target.volatiles['encore'];
  275.                     return false;              
  276.                 }
  277.                 if (target.hasLinkedMove(lastMove)) {
  278.                     var linkedMoves = target.getLinkedMoves();
  279.                     if (noEncore[linkedMoves[0]] || noEncore[linkedMoves[1]] || target.moveset[0].pp <= 0 || target.moveset[1].pp <= 0) {
  280.                         // it failed
  281.                         delete target.volatiles['encore'];
  282.                         return false;                  
  283.                     }
  284.                 } else {
  285.                     if (noEncore[lastMove] || (target.moveset[moveIndex] && target.moveset[moveIndex].pp <= 0)) {
  286.                         // it failed
  287.                         delete target.volatiles['encore'];
  288.                         return false;
  289.                     }
  290.                 }
  291.                 this.effectData.move = lastMove;
  292.                 this.add('-start', target, 'Encore');
  293.                 if (!this.willMove(target)) {
  294.                     this.effectData.duration++;
  295.                 }
  296.             },
  297.             onOverrideDecision: function (pokemon, target, move) {
  298.                 if (this.willMove(pokemon)) return false;
  299.                 if (pokemon.hasLinkedMove(this.effectData.move)) {
  300.                     var linkedMoves = pokemon.getLinkedMoves();
  301.                     // pass a `sourceEffect` argument to prevent infinite recursion at `runMove`
  302.                     this.runMove(linkedMoves[0], pokemon, target, this.effectData);
  303.                     return move.id !== linkedMoves[1] ? linkedMoves[1] : void 0; // are we fine with this targetting method? (Doubles/Triples)
  304.                 }
  305.                 if (move.id !== this.effectData.move) return this.effectData.move;
  306.             },
  307.             onResidualOrder: 13,
  308.             onResidual: function (target) {
  309.                 // early termination if you run out of PP
  310.                 var lastMove = target.getLastMoveAbsolute();
  311.  
  312.                 var index = target.moves.indexOf(lastMove);
  313.                 if (index === -1) return; // no last move
  314.  
  315.                 if (target.hasLinkedMove(lastMove)) {
  316.                     if (target.moveset[0].pp <= 0 || target.moveset[1].pp <= 0) {
  317.                         delete target.volatiles.encore;
  318.                         this.add('-end', target, 'Encore');
  319.                     }
  320.                 } else {
  321.                     if (target.moveset[index].pp <= 0) {
  322.                         delete target.volatiles.encore;
  323.                         this.add('-end', target, 'Encore');
  324.                     }
  325.                 }
  326.             },
  327.             onEnd: function (target) {
  328.                 this.add('-end', target, 'Encore');
  329.             },
  330.             onModifyPokemon: function (pokemon) {
  331.                 if (!this.effectData.move) return; // ??
  332.                 if (!pokemon.hasMove(this.effectData.move)) {
  333.                     return;
  334.                 }
  335.                 if (pokemon.hasLinkedMove(this.effectData.move)) {
  336.                     // taking advantage of the fact that the first two move slots are reserved to linked moves
  337.                     for (var i = 2; i < pokemon.moveset.length; i++) {
  338.                         pokemon.disableMove(pokemon.moveset[i].id);
  339.                     }                  
  340.                 } else {
  341.                     for (var i = 0; i < pokemon.moveset.length; i++) {
  342.                         if (pokemon.moveset[i].id !== this.effectData.move) {
  343.                             pokemon.disableMove(pokemon.moveset[i].id);
  344.                         }
  345.                     }
  346.                 }
  347.             }
  348.         }
  349.     },
  350.     torment: {
  351.         inherit: true,
  352.         effect: {
  353.             onStart: function (pokemon) {
  354.                 this.add('-start', pokemon, 'Torment');
  355.             },
  356.             onEnd: function (pokemon) {
  357.                 this.add('-end', pokemon, 'Torment');
  358.             },
  359.             onModifyPokemon: function (pokemon) {
  360.                 var lastMove = pokemon.lastMove;
  361.                 if (lastMove === 'struggle') return;
  362.  
  363.                 if (Array.isArray(lastMove)) {
  364.                     for (var i = 0; i < lastMove.length; i++) {
  365.                         pokemon.disableMove(lastMove[i]);
  366.                     }
  367.                 } else {
  368.                     pokemon.disableMove(lastMove);
  369.                 }
  370.             }
  371.         }
  372.     },
  373.  
  374.     /**
  375.      * Spite and Grudge
  376.      * Decrease the PP of the last absolute move used by the target
  377.      * Also, Grudge's effect won't be removed by its linked move, if any
  378.      *
  379.      */
  380.  
  381.     grudge: {
  382.         inherit: true,
  383.         effect: {
  384.             onStart: function (pokemon) {
  385.                 this.add('-singlemove', pokemon, 'Grudge');
  386.             },
  387.             onFaint: function (target, source, effect) {
  388.                 this.debug('Grudge detected fainted pokemon');
  389.                 if (!source || !effect) return;
  390.                 if (effect.effectType === 'Move') {
  391.                     var lastMove = source.getLastMoveAbsolute();
  392.                     for (var i in source.moveset) {
  393.                         if (source.moveset[i].id === lastMove) {
  394.                             source.moveset[i].pp = 0;
  395.                             this.add('-activate', source, 'Grudge', this.getMove(lastMove).name);
  396.                         }
  397.                     }
  398.                 }
  399.             },
  400.             onBeforeMovePriority: 100,
  401.             onBeforeMove: function (pokemon) {
  402.                 if (pokemon.moveThisTurn) return; // Second stage of a Linked move
  403.                 this.debug('removing Grudge before attack');
  404.                 pokemon.removeVolatile('grudge');
  405.             }
  406.         }
  407.     },
  408.     spite: {
  409.         inherit: true,
  410.         onHit: function (target) {
  411.             var lastMove = target.getLastMoveAbsolute();
  412.             if (target.deductPP(lastMove, 4)) {
  413.                 this.add("-activate", target, 'move: Spite', lastMove, 4);
  414.                 return;
  415.             }
  416.             return false;
  417.         }
  418.     },
  419.  
  420.     /**
  421.      * Rollout and Ice Ball
  422.      *
  423.      */
  424.  
  425.     rollout: {
  426.         inherit: true
  427.         // fine
  428.     },
  429.     iceball: {
  430.         inherit: true
  431.         // fine
  432.     },
  433.  
  434.     /**
  435.      * Other moves that check `pokemon.lastMove`
  436.      * (may behave counter-intuitively if left unmodded)
  437.      *
  438.      **/
  439.  
  440.     conversion2: {
  441.         inherit: true,
  442.         onHit: function (target, source) {
  443.             var lastMove = target.getLastMoveAbsolute();
  444.             if (!lastMove) return false;
  445.             var possibleTypes = [];
  446.             var attackType = this.getMove(lastMove).type;
  447.             for (var type in this.data.TypeChart) {
  448.                 if (source.hasType(type) || target.hasType(type)) continue;
  449.                 var typeCheck = this.data.TypeChart[type].damageTaken[attackType];
  450.                 if (typeCheck === 2 || typeCheck === 3) {
  451.                     possibleTypes.push(type);
  452.                 }
  453.             }
  454.             if (!possibleTypes.length) {
  455.                 return false;
  456.             }
  457.             var type = possibleTypes[this.random(possibleTypes.length)];
  458.  
  459.             if (!source.setType(type)) return false;
  460.             this.add('-start', source, 'typechange', type);
  461.         }
  462.     },
  463.     destinybond: {
  464.         inherit: true,
  465.         effect: {
  466.             onStart: function (pokemon) {
  467.                 this.add('-singlemove', pokemon, 'Destiny Bond');
  468.             },
  469.             onFaint: function (target, source, effect) {
  470.                 if (!source || !effect) return;
  471.                 if (effect.effectType === 'Move' && !effect.isFutureMove) {
  472.                     this.add('-activate', target, 'Destiny Bond');
  473.                     source.faint();
  474.                 }
  475.             },
  476.             onBeforeMovePriority: 100,
  477.             onBeforeMove: function (pokemon, target, move) {
  478.                 // Second stage of a Linked move does not remove Destiny Bond
  479.                 if (pokemon.moveThisTurn) return;
  480.                 this.debug('removing Destiny Bond before attack');
  481.                 pokemon.removeVolatile('destinybond');
  482.             }
  483.         }
  484.     },
  485.     trumpcard: {
  486.         inherit: true,
  487.         basePowerCallback: function (pokemon) {
  488.             var move = pokemon.getMoveData(pokemon.getLastMoveAbsolute()); // Account for calling Trump Card via other moves
  489.             switch (move.pp) {
  490.             case 0:
  491.                 return 200;
  492.             case 1:
  493.                 return 80;
  494.             case 2:
  495.                 return 60;
  496.             case 3:
  497.                 return 50;
  498.             default:
  499.                 return 40;
  500.             }
  501.         }
  502.     },
  503.     uproar: {
  504.         inherit: true
  505.         // fine
  506.     },
  507.  
  508.     /**
  509.      * Moves that check `pokemon.moveThisTurn`
  510.      * (may behave counter-intuitively if left unmodded)
  511.      *
  512.      **/
  513.  
  514.      fusionbolt: {
  515.         inherit: true,
  516.         onBasePower: function (basePower, pokemon) {
  517.             var actives = pokemon.side.active;
  518.             for (var i = 0; i < actives.length; i++) {
  519.                 if (actives[i] && actives[i].checkMoveThisTurn('fusionflare')) {
  520.                     this.debug('double power');
  521.                     return this.chainModify(2);
  522.                 }
  523.             }
  524.         }
  525.      },
  526.      fusionflare: {
  527.         inherit: true,
  528.         onBasePower: function (basePower, pokemon) {
  529.             var actives = pokemon.side.active;
  530.             for (var i = 0; i < actives.length; i++) {
  531.                 if (actives[i] && actives[i].checkMoveThisTurn('fusionbolt')) {
  532.                     this.debug('double power');
  533.                     return this.chainModify(2);
  534.                 }
  535.             }
  536.         }
  537.      },
  538.  
  539.     /**
  540.      * Moves that should clean the house after running
  541.      * (but aren't doing so in standard for whatever reason)
  542.      */
  543.  
  544.     beatup: {
  545.         inherit: true,
  546.         onAfterMove: function (pokemon) {
  547.             pokemon.removeVolatile('beatup');
  548.         }
  549.     },
  550.     triplekick: {
  551.         inherit: true,
  552.         onAfterMove: function (pokemon) {
  553.             pokemon.removeVolatile('triplekick');
  554.         }
  555.     },
  556.  
  557.     /**
  558.      * Moves that should clean the house if they aren't run
  559.      *
  560.      */
  561.  
  562.      furycutter: {
  563.         inherit: true,
  564.         effect: {
  565.             duration: 2,
  566.             onStart: function () {
  567.                 this.effectData.multiplier = 1;
  568.             },
  569.             onRestart: function () {
  570.                 if (this.effectData.multiplier < 4) {
  571.                     this.effectData.multiplier <<= 1;
  572.                 }
  573.                 this.effectData.duration = 2;
  574.             },
  575.             onBeforeMove: function (pokemon, target, move) {
  576.                 if (move.id !== 'furycutter') pokemon.removeVolatile('furycutter');
  577.             }
  578.         }
  579.      },
  580.  
  581.     /**
  582.      * First Law of Pokémon Simulation:
  583.      * Always make sure that Sky Drop works
  584.      *
  585.      */
  586.  
  587.      skydrop: {
  588.         inherit: true,
  589.         effect: {
  590.             duration: 2,
  591.             onDragOut: false,
  592.             onSourceDragOut: false,
  593.             onFoeModifyPokemon: function (defender) {
  594.                 if (defender !== this.effectData.source) return;
  595.                 defender.trapped = true;
  596.             },
  597.             onFoeBeforeMovePriority: 11,
  598.             onFoeBeforeMove: function (attacker, defender, move) {
  599.                 if (attacker === this.effectData.source) {
  600.                     this.debug('Sky drop nullifying.');
  601.                     return null;
  602.                 }
  603.             },
  604.             onRedirectTarget: function (target, source, source2) {
  605.                 if (source !== this.effectData.target) return;
  606.                 if (this.effectData.source.fainted) return;
  607.                 return this.effectData.source;
  608.             },
  609.             onAnyAccuracy: function (accuracy, target, source, move) {
  610.                 // both user and target of Sky Drop avoid moves, yet
  611.                 // not moves targetting themselves (Linked)
  612.  
  613.                 if (target !== this.effectData.target && target !== this.effectData.source) {
  614.                     return;
  615.                 }
  616.                 if (source === this.effectData.target && target === this.effectData.source) {
  617.                     return;
  618.                 }
  619.                 if (source === target) return;
  620.  
  621.                 if (move.id === 'gust' || move.id === 'twister') {
  622.                     return;
  623.                 }
  624.                 if (move.id === 'skyuppercut' || move.id === 'thunder' || move.id === 'hurricane' || move.id === 'smackdown' || move.id === 'thousandarrows' || move.id === 'helpinghand') {
  625.                     return;
  626.                 }
  627.                 if (source.hasAbility('noguard') || target.hasAbility('noguard')) {
  628.                     return;
  629.                 }
  630.                 return 0;
  631.             },
  632.             onAnyBasePower: function (basePower, target, source, move) {
  633.                 if (target !== this.effectData.target && target !== this.effectData.source) {
  634.                     return;
  635.                 }
  636.                 if (source === this.effectData.target && target === this.effectData.source) {
  637.                     return;
  638.                 }
  639.                 if (move.id === 'gust' || move.id === 'twister') {
  640.                     return this.chainModify(2);
  641.                 }
  642.             },
  643.             onFaint: function (target) {
  644.                 if (target.volatiles['skydrop'] && target.volatiles['twoturnmove'].source) {
  645.                     this.add('-end', target.volatiles['twoturnmove'].source, 'Sky Drop', '[interrupt]');
  646.                 }
  647.             }
  648.         }
  649.     }
  650. };
  651.  
  652. /* mods/linked/scripts.js */
  653.  
  654. exports.BattleScripts = {
  655.     runMove: function (move, pokemon, target, sourceEffect) {
  656.         if (!sourceEffect && toId(move) !== 'struggle') {
  657.             var changedMove = this.runEvent('OverrideDecision', pokemon, target, move);
  658.             if (changedMove === false) return; // Linked: Encore hack
  659.             if (changedMove && changedMove !== true) {
  660.                 move = changedMove;
  661.                 target = null;
  662.             }
  663.         }
  664.         move = this.getMove(move);
  665.         if (!target && target !== false) target = this.resolveTarget(pokemon, move);
  666.  
  667.         this.setActiveMove(move, pokemon, target);
  668.  
  669.         // Linked: Pokemon can move more than once per turn
  670.         /* if (pokemon.moveThisTurn) {
  671.             // THIS IS PURELY A SANITY CHECK
  672.             // DO NOT TAKE ADVANTAGE OF THIS TO PREVENT A POKEMON FROM MOVING;
  673.             // USE this.cancelMove INSTEAD
  674.             this.debug('' + pokemon.id + ' INCONSISTENT STATE, ALREADY MOVED: ' + pokemon.moveThisTurn);
  675.             this.clearActiveMove(true);
  676.             return;
  677.         }*/
  678.         if (!this.runEvent('BeforeMove', pokemon, target, move)) {
  679.             // Prevent invulnerability from persisting until the turn ends
  680.             // Linked: make sure that the cancelled move is the correct one.
  681.             if (pokemon.volatiles['twoturnmove'] && pokemon.volatiles['twoturnmove'].move === move.id) {
  682.                 pokemon.removeVolatile('twoturnmove');
  683.             }
  684.             this.clearActiveMove(true);
  685.             return;
  686.         }
  687.         if (move.beforeMoveCallback) {
  688.             if (move.beforeMoveCallback.call(this, pokemon, target, move)) {
  689.                 this.clearActiveMove(true);
  690.                 return;
  691.             }
  692.         }
  693.         pokemon.lastDamage = 0;
  694.         var lockedMove = this.runEvent('LockMove', pokemon);
  695.         if (lockedMove === true) lockedMove = false;
  696.         if (!lockedMove) {
  697.             if (!pokemon.deductPP(move, null, target) && (move.id !== 'struggle')) {
  698.                 this.add('cant', pokemon, 'nopp', move);
  699.                 this.clearActiveMove(true);
  700.                 return;
  701.             }
  702.         }
  703.         pokemon.moveUsed(move);
  704.         this.useMove(move, pokemon, target, sourceEffect);
  705.         this.singleEvent('AfterMove', move, null, pokemon, target, move);
  706.     },
  707.     addQueue: function (decision, noSort, side) {
  708.         if (decision) {
  709.             if (Array.isArray(decision)) {
  710.                 for (var i = 0; i < decision.length; i++) {
  711.                     this.addQueue(decision[i], noSort);
  712.                 }
  713.                 return;
  714.             }
  715.             if (!decision.side && side) decision.side = side;
  716.             if (!decision.side && decision.pokemon) decision.side = decision.pokemon.side;
  717.             if (!decision.choice && decision.move) decision.choice = 'move';
  718.             if (!decision.priority) {
  719.                 var priorities = {
  720.                     'beforeTurn': 100,
  721.                     'beforeTurnMove': 99,
  722.                     'switch': 6,
  723.                     'runSwitch': 6.1,
  724.                     'megaEvo': 5.9,
  725.                     'residual': -100,
  726.                     'team': 102,
  727.                     'start': 101
  728.                 };
  729.                 if (priorities[decision.choice]) {
  730.                     decision.priority = priorities[decision.choice];
  731.                 }
  732.             }
  733.             if (decision.choice === 'move') {
  734.                 if (this.getMove(decision.move).beforeTurnCallback) {
  735.                     this.addQueue({choice: 'beforeTurnMove', pokemon: decision.pokemon, move: decision.move, targetLoc: decision.targetLoc}, true);
  736.                 }
  737.  
  738.                 var linkedMoves = decision.pokemon.getLinkedMoves();
  739.                 if (linkedMoves.length) {
  740.                     var decisionMove = toId(decision.move);
  741.                     var index = linkedMoves.indexOf(decisionMove);
  742.                     if (index !== -1) {
  743.                         // flag the move as linked here
  744.                         decision.linked = linkedMoves;
  745.                         if (this.getMove(linkedMoves[1 - index]).beforeTurnCallback) {
  746.                             this.addQueue({choice: 'beforeTurnMove', pokemon: decision.pokemon, move: linkedMoves[1 - index], targetLoc: decision.targetLoc}, true);
  747.                         }
  748.                     }
  749.                 }
  750.             } else if (decision.choice === 'switch') {
  751.                 if (decision.pokemon.switchFlag && decision.pokemon.switchFlag !== true) {
  752.                     decision.pokemon.switchCopyFlag = decision.pokemon.switchFlag;
  753.                 }
  754.                 decision.pokemon.switchFlag = false;
  755.                 if (!decision.speed && decision.pokemon && decision.pokemon.isActive) decision.speed = decision.pokemon.speed;
  756.             }
  757.             if (decision.move) {
  758.                 var target;
  759.  
  760.                 if (!decision.targetPosition) {
  761.                     // this target is not relevant to Linked (or any other game mode)
  762.                     target = this.resolveTarget(decision.pokemon, decision.move);
  763.                     decision.targetSide = target.side;
  764.                     decision.targetPosition = target.position;
  765.                 }
  766.  
  767.                 decision.move = this.getMoveCopy(decision.move);
  768.                 if (!decision.priority) {
  769.                     var priority = decision.move.priority;
  770.                     priority = this.runEvent('ModifyPriority', decision.pokemon, target, decision.move, priority);
  771.  
  772.                     // Linked: if two moves are linked, the effective priority is minimized
  773.                     var linkedMoves = decision.pokemon.getLinkedMoves();
  774.                     if (linkedMoves.length) {
  775.                         var decisionMove = toId(decision.move);
  776.                         var index = linkedMoves.indexOf(decisionMove);
  777.                         if (index !== -1) {
  778.                             var altMove = this.getMoveCopy(linkedMoves[1 - index]);
  779.                             var altPriority = altMove.priority;
  780.                             altPriority = this.runEvent('ModifyPriority', decision.pokemon, target, altMove, altPriority);
  781.                             priority = Math.min(priority, altPriority);
  782.                         }
  783.                     }
  784.  
  785.                     decision.priority = priority;
  786.                     // In Gen 6, Quick Guard blocks moves with artificially enhanced priority.
  787.                     if (this.gen > 5) decision.move.priority = priority;
  788.                 }
  789.             }
  790.             if (!decision.pokemon && !decision.speed) decision.speed = 1;
  791.             if (!decision.speed && decision.choice === 'switch' && decision.target) decision.speed = decision.target.speed;
  792.             if (!decision.speed) decision.speed = decision.pokemon.speed;
  793.  
  794.             if (decision.choice === 'switch' && !decision.side.pokemon[0].isActive) {
  795.                 // if there's no actives, switches happen before activations
  796.                 decision.priority = 6.2;
  797.             }
  798.  
  799.             this.queue.push(decision);
  800.         }
  801.         if (!noSort) {
  802.             this.queue.sort(this.comparePriority);
  803.         }
  804.     },
  805.     runDecision: function (decision) {
  806.         var pokemon;
  807.  
  808.         // returns whether or not we ended in a callback
  809.         switch (decision.choice) {
  810.         case 'start':
  811.             // I GIVE UP, WILL WRESTLE WITH EVENT SYSTEM LATER
  812.             var beginCallback = this.getFormat().onBegin;
  813.             if (beginCallback) beginCallback.call(this);
  814.  
  815.             this.add('start');
  816.             for (var pos = 0; pos < this.p1.active.length; pos++) {
  817.                 this.switchIn(this.p1.pokemon[pos], pos);
  818.             }
  819.             for (var pos = 0; pos < this.p2.active.length; pos++) {
  820.                 this.switchIn(this.p2.pokemon[pos], pos);
  821.             }
  822.             for (var pos = 0; pos < this.p1.pokemon.length; pos++) {
  823.                 pokemon = this.p1.pokemon[pos];
  824.                 this.singleEvent('Start', this.getEffect(pokemon.species), pokemon.speciesData, pokemon);
  825.             }
  826.             for (var pos = 0; pos < this.p2.pokemon.length; pos++) {
  827.                 pokemon = this.p2.pokemon[pos];
  828.                 this.singleEvent('Start', this.getEffect(pokemon.species), pokemon.speciesData, pokemon);
  829.             }
  830.             this.midTurn = true;
  831.             break;
  832.         case 'move':
  833.             if (!decision.pokemon.isActive) return false;
  834.             if (decision.pokemon.fainted) return false;
  835.             if (decision.linked) {
  836.                 var linkedMoves = decision.linked;
  837.                 var decisionMove = toId(decision.move);
  838.                 for (var i = linkedMoves.length - 1; i >= 0; i--) {
  839.                     var pseudoDecision = {choice: 'move', move: linkedMoves[i], targetLoc: decision.targetLoc, pokemon: decision.pokemon, targetPosition: decision.targetPosition, targetSide: decision.targetSide};
  840.                     this.queue.unshift(pseudoDecision);
  841.                 }
  842.                 return;
  843.             }
  844.             this.runMove(decision.move, decision.pokemon, this.getTarget(decision), decision.sourceEffect);
  845.             break;
  846.         case 'megaEvo':
  847.             if (this.runMegaEvo) this.runMegaEvo(decision.pokemon);
  848.             break;
  849.         case 'beforeTurnMove':
  850.             if (!decision.pokemon.isActive) return false;
  851.             if (decision.pokemon.fainted) return false;
  852.             this.debug('before turn callback: ' + decision.move.id);
  853.             var target = this.getTarget(decision);
  854.             if (!target) return false;
  855.             decision.move.beforeTurnCallback.call(this, decision.pokemon, target);
  856.             break;
  857.         case 'event':
  858.             this.runEvent(decision.event, decision.pokemon);
  859.             break;
  860.         case 'team':
  861.             var i = parseInt(decision.team[0], 10) - 1;
  862.             if (i >= 6 || i < 0) return;
  863.  
  864.             if (decision.team[1]) {
  865.                 // validate the choice
  866.                 var len = decision.side.pokemon.length;
  867.                 var newPokemon = [null, null, null, null, null, null].slice(0, len);
  868.                 for (var j = 0; j < len; j++) {
  869.                     var i = parseInt(decision.team[j], 10) - 1;
  870.                     newPokemon[j] = decision.side.pokemon[i];
  871.                 }
  872.                 var reject = false;
  873.                 for (var j = 0; j < len; j++) {
  874.                     if (!newPokemon[j]) reject = true;
  875.                 }
  876.                 if (!reject) {
  877.                     for (var j = 0; j < len; j++) {
  878.                         newPokemon[j].position = j;
  879.                     }
  880.                     decision.side.pokemon = newPokemon;
  881.                     return;
  882.                 }
  883.             }
  884.  
  885.             if (i === 0) return;
  886.             pokemon = decision.side.pokemon[i];
  887.             if (!pokemon) return;
  888.             decision.side.pokemon[i] = decision.side.pokemon[0];
  889.             decision.side.pokemon[0] = pokemon;
  890.             decision.side.pokemon[i].position = i;
  891.             decision.side.pokemon[0].position = 0;
  892.             // we return here because the update event would crash since there are no active pokemon yet
  893.             return;
  894.         case 'pass':
  895.             if (!decision.priority || decision.priority <= 101) return;
  896.             if (decision.pokemon) {
  897.                 decision.pokemon.switchFlag = false;
  898.             }
  899.             break;
  900.         case 'switch':
  901.             if (decision.pokemon) {
  902.                 decision.pokemon.beingCalledBack = true;
  903.                 var lastMove = this.getMove(decision.pokemon.getLastMoveAbsolute());
  904.                 if (lastMove.selfSwitch !== 'copyvolatile') {
  905.                     this.runEvent('BeforeSwitchOut', decision.pokemon);
  906.                 }
  907.                 if (!this.runEvent('SwitchOut', decision.pokemon)) {
  908.                     // Warning: DO NOT interrupt a switch-out
  909.                     // if you just want to trap a pokemon.
  910.                     // To trap a pokemon and prevent it from switching out,
  911.                     // (e.g. Mean Look, Magnet Pull) use the 'trapped' flag
  912.                     // instead.
  913.  
  914.                     // Note: Nothing in BW or earlier interrupts
  915.                     // a switch-out.
  916.                     break;
  917.                 }
  918.                 this.singleEvent('End', this.getAbility(decision.pokemon.ability), decision.pokemon.abilityData, decision.pokemon);
  919.             }
  920.             if (decision.pokemon && !decision.pokemon.hp && !decision.pokemon.fainted) {
  921.                 // a pokemon fainted from Pursuit before it could switch
  922.                 if (this.gen <= 4) {
  923.                     // in gen 2-4, the switch still happens
  924.                     decision.priority = -101;
  925.                     this.queue.unshift(decision);
  926.                     this.debug('Pursuit target fainted');
  927.                     break;
  928.                 }
  929.                 // in gen 5+, the switch is cancelled
  930.                 this.debug('A Pokemon can\'t switch between when it runs out of HP and when it faints');
  931.                 break;
  932.             }
  933.             if (decision.target.isActive) {
  934.                 this.debug('Switch target is already active');
  935.                 break;
  936.             }
  937.             this.switchIn(decision.target, decision.pokemon.position);
  938.             break;
  939.         case 'runSwitch':
  940.             this.runEvent('SwitchIn', decision.pokemon);
  941.             if (!decision.pokemon.hp) break;
  942.             decision.pokemon.isStarted = true;
  943.             if (!decision.pokemon.fainted) {
  944.                 this.singleEvent('Start', decision.pokemon.getAbility(), decision.pokemon.abilityData, decision.pokemon);
  945.                 this.singleEvent('Start', decision.pokemon.getItem(), decision.pokemon.itemData, decision.pokemon);
  946.             }
  947.             break;
  948.         case 'shift':
  949.             if (!decision.pokemon.isActive) return false;
  950.             if (decision.pokemon.fainted) return false;
  951.             this.swapPosition(decision.pokemon, 1);
  952.             break;
  953.         case 'beforeTurn':
  954.             this.eachEvent('BeforeTurn');
  955.             break;
  956.         case 'residual':
  957.             this.add('');
  958.             this.clearActiveMove(true);
  959.             this.residualEvent('Residual');
  960.             break;
  961.         }
  962.  
  963.         // phazing (Roar, etc)
  964.  
  965.         var self = this;
  966.         function checkForceSwitchFlag(a) {
  967.             if (!a) return false;
  968.             if (a.hp && a.forceSwitchFlag) {
  969.                 self.dragIn(a.side, a.position);
  970.             }
  971.             delete a.forceSwitchFlag;
  972.         }
  973.         this.p1.active.forEach(checkForceSwitchFlag);
  974.         this.p2.active.forEach(checkForceSwitchFlag);
  975.  
  976.         this.clearActiveMove();
  977.  
  978.         // fainting
  979.  
  980.         this.faintMessages();
  981.         if (this.ended) return true;
  982.  
  983.         // switching (fainted pokemon, U-turn, Baton Pass, etc)
  984.  
  985.         if (!this.queue.length || (this.gen <= 3 && this.queue[0].choice in {move:1, residual:1})) {
  986.             // in gen 3 or earlier, switching in fainted pokemon is done after
  987.             // every move, rather than only at the end of the turn.
  988.             this.checkFainted();
  989.         } else if (decision.choice === 'pass') {
  990.             this.eachEvent('Update');
  991.             return false;
  992.         }
  993.  
  994.         function hasSwitchFlag(a) { return a ? a.switchFlag : false; }
  995.         function removeSwitchFlag(a) { if (a) a.switchFlag = false; }
  996.         var p1switch = this.p1.active.any(hasSwitchFlag);
  997.         var p2switch = this.p2.active.any(hasSwitchFlag);
  998.  
  999.         if (p1switch && !this.canSwitch(this.p1)) {
  1000.             this.p1.active.forEach(removeSwitchFlag);
  1001.             p1switch = false;
  1002.         }
  1003.         if (p2switch && !this.canSwitch(this.p2)) {
  1004.             this.p2.active.forEach(removeSwitchFlag);
  1005.             p2switch = false;
  1006.         }
  1007.  
  1008.         if (p1switch || p2switch) {
  1009.             this.makeRequest('switch');
  1010.             return true;
  1011.         }
  1012.  
  1013.         this.eachEvent('Update');
  1014.  
  1015.         return false;
  1016.     },
  1017.     comparePriority: function (a, b) { // intentionally not in Battle.prototype
  1018.         a.priority = a.priority || 0;
  1019.         a.subPriority = a.subPriority || 0;
  1020.         a.speed = a.speed || 0;
  1021.         b.priority = b.priority || 0;
  1022.         b.subPriority = b.subPriority || 0;
  1023.         b.speed = b.speed || 0;
  1024.         if ((typeof a.order === 'number' || typeof b.order === 'number') && a.order !== b.order) {
  1025.             if (typeof a.order !== 'number') {
  1026.                 return -1;
  1027.             }
  1028.             if (typeof b.order !== 'number') {
  1029.                 return 1;
  1030.             }
  1031.             if (b.order - a.order) {
  1032.                 return -(b.order - a.order);
  1033.             }
  1034.         }
  1035.         if (b.priority - a.priority) {
  1036.             return b.priority - a.priority;
  1037.         }
  1038.         if (b.speed - a.speed) {
  1039.             return b.speed - a.speed;
  1040.         }
  1041.         if (b.subOrder - a.subOrder) {
  1042.             return -(b.subOrder - a.subOrder);
  1043.         }
  1044.         return Math.random() - 0.5;
  1045.     },
  1046.     pokemon: {
  1047.         moveUsed: function (move) {
  1048.             var lastMove = this.moveThisTurn ? [this.moveThisTurn, this.battle.getMove(move).id] : this.battle.getMove(move).id;
  1049.             this.lastMove = lastMove;
  1050.             this.moveThisTurn = lastMove;
  1051.         },
  1052.         getLastMoveAbsolute: function () {
  1053.             if (Array.isArray(this.lastMove)) return this.lastMove[1];
  1054.             return this.lastMove;
  1055.         },
  1056.         checkLastMove: function (move, maybeLinked) {
  1057.             move = toId(move);
  1058.             if (!maybeLinked) return this.getLastMoveAbsolute() === move;
  1059.             if (Array.isArray(this.lastMove)) return this.lastMove.indexOf(move) >= 0;
  1060.             return this.lastMove === move;
  1061.         },
  1062.         checkMoveThisTurn: function (move) {
  1063.             move = toId(move);
  1064.             if (Array.isArray(this.moveThisTurn)) return this.moveThisTurn.indexOf(move) >= 0;
  1065.             return this.moveThisTurn === move;
  1066.         },
  1067.         getLinkedMoves: function () {
  1068.             var linkedMoves = this.moveset.slice(0, 2);
  1069.             if (linkedMoves.length !== 2 || linkedMoves[0].pp <= 0 || linkedMoves[1].pp <= 0) return [];
  1070.             return linkedMoves.map('id');
  1071.         },
  1072.         hasLinkedMove: function (move) {
  1073.             move = toId(move);
  1074.             var linkedMoves = this.getLinkedMoves();
  1075.             if (!linkedMoves.length) return;
  1076.  
  1077.             return linkedMoves[0] === move || linkedMoves[1] === move;
  1078.         },
  1079.         hasLinkedMoves: function (move1, move2) {
  1080.             var linkedMoves = this.getLinkedMoves();
  1081.             if (!linkedMoves.length) return;
  1082.  
  1083.             move1 = toId(move1);
  1084.             move2 = toId(move2);
  1085.             if (linkedMoves[0] === move1 && linkedMoves[1] === move2) return true;
  1086.             if (linkedMoves[1] === move2 && linkedMoves[0] === move1) return true;
  1087.             return false;
  1088.         }
  1089.     }
  1090. };
  1091.  
  1092. /* mods/linked/statuses.js */
  1093.  
  1094. exports.BattleStatuses = {
  1095.     slp: {
  1096.         inherit: true,
  1097.         onBeforeMove: function (pokemon, target, move) {
  1098.             if (this.effectData.timerDecreased !== this.turn) {
  1099.                 this.effectData.timerDecreased = this.turn;
  1100.                 if (pokemon.getAbility().isHalfSleep) {
  1101.                     pokemon.statusData.time--;
  1102.                 }
  1103.                 pokemon.statusData.time--;
  1104.                 if (pokemon.statusData.time <= 0) {
  1105.                     pokemon.cureStatus();
  1106.                     return;
  1107.                 }
  1108.                 this.add('cant', pokemon, 'slp');
  1109.             }
  1110.             if (move.sleepUsable) {
  1111.                 return;
  1112.             }
  1113.             return false;
  1114.         }
  1115.     },
  1116.     frz: {
  1117.         inherit: true,
  1118.         onBeforeMove: function (pokemon, target, move) {
  1119.             if (move.thawsUser || this.effectData.durationRolled !== this.turn && this.random(5) === 0) {
  1120.                 pokemon.cureStatus();
  1121.                 return;
  1122.             }
  1123.             if (this.effectData.durationRolled !== this.turn) {
  1124.                 // no need to display the frozen message twice
  1125.                 this.effectData.durationRolled = this.turn;
  1126.                 this.add('cant', pokemon, 'frz');
  1127.             }
  1128.             return false;
  1129.         }
  1130.     },
  1131.     confusion: {
  1132.         inherit: true,
  1133.         onBeforeMove: function (pokemon) {
  1134.             if (this.effectData.timerDecreased !== this.turn) {
  1135.                 this.effectData.timerDecreased = this.turn;
  1136.                 pokemon.volatiles.confusion.time--;
  1137.                 if (!pokemon.volatiles.confusion.time) {
  1138.                     pokemon.removeVolatile('confusion');
  1139.                     return;
  1140.                 }
  1141.             }
  1142.             this.add('-activate', pokemon, 'confusion');
  1143.             if (this.random(2) === 0) {
  1144.                 return;
  1145.             }
  1146.             this.directDamage(this.getDamage(pokemon, pokemon, 40));
  1147.             return false;
  1148.         }
  1149.     },
  1150.     flinch: {
  1151.         inherit: true,
  1152.         onBeforeMove: function (pokemon) {
  1153.             if (this.effectData.movePrevented) return false;
  1154.             if (!this.runEvent('Flinch', pokemon)) {
  1155.                 return;
  1156.             }
  1157.             if (!this.effectData.movePrevented) {
  1158.                 // no need to display the flinch message twice
  1159.                 this.effectData.movePrevented = true;
  1160.                 this.add('cant', pokemon, 'flinch');
  1161.             }
  1162.             return false;
  1163.         }
  1164.     }, 
  1165.     mustrecharge: {
  1166.         inherit: true,
  1167.         onBeforeMove: function (pokemon) {
  1168.             if (!this.effectData.movePrevented) {
  1169.                 // no need to display the recharge message twice
  1170.                 this.effectData.movePrevented = true;
  1171.                 this.add('cant', pokemon, 'recharge');
  1172.             }
  1173.             if (!pokemon.moveThisTurn) pokemon.removeVolatile('mustrecharge');
  1174.             return false;
  1175.         }
  1176.     },
  1177.  
  1178.     /**
  1179.      * Gems and Auras
  1180.      * Make sure that they only boost a single move
  1181.      *
  1182.      */
  1183.  
  1184.     gem: {
  1185.         inherit: true,
  1186.         onBeforeMove: function (pokemon) {
  1187.             if (pokemon.moveThisTurn) pokemon.removeVolatile('gem');
  1188.         }
  1189.     },
  1190.     aura: {
  1191.         inherit: true,
  1192.         onBeforeMove: function (pokemon) {
  1193.             if (pokemon.moveThisTurn) pokemon.removeVolatile('gem');
  1194.         }
  1195.     }
  1196. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement