Guest User

PS! Linked scripts.js

a guest
Jul 13th, 2016
108
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /* mods/linked/scripts.js */
  2.  
  3. 'use strict';
  4.  
  5. exports.BattleScripts = {
  6.     runMove: function (move, pokemon, target, sourceEffect) {
  7.         if (!sourceEffect && toId(move) !== 'struggle') {
  8.             let changedMove = this.runEvent('OverrideDecision', pokemon, target, move);
  9.             if (changedMove && changedMove !== true) {
  10.                 move = changedMove;
  11.                 target = null;
  12.             }
  13.         }
  14.         move = this.getMove(move);
  15.         if (!target && target !== false) target = this.resolveTarget(pokemon, move);
  16.  
  17.         this.setActiveMove(move, pokemon, target);
  18.  
  19.         // Linked: Pokemon can move more than once per turn
  20.         /* if (pokemon.moveThisTurn) {
  21.             // THIS IS PURELY A SANITY CHECK
  22.             // DO NOT TAKE ADVANTAGE OF THIS TO PREVENT A POKEMON FROM MOVING;
  23.             // USE this.cancelMove INSTEAD
  24.             this.debug('' + pokemon.id + ' INCONSISTENT STATE, ALREADY MOVED: ' + pokemon.moveThisTurn);
  25.             this.clearActiveMove(true);
  26.             return;
  27.         }*/
  28.         if (!this.runEvent('BeforeMove', pokemon, target, move)) {
  29.             // Prevent invulnerability from persisting until the turn ends
  30.             // Linked: make sure that the cancelled move is the correct one.
  31.             if (pokemon.volatiles['twoturnmove'] && pokemon.volatiles['twoturnmove'].move === move.id) {
  32.                 pokemon.removeVolatile('twoturnmove');
  33.             }
  34.             this.clearActiveMove(true);
  35.             return;
  36.         }
  37.         if (move.beforeMoveCallback) {
  38.             if (move.beforeMoveCallback.call(this, pokemon, target, move)) {
  39.                 this.clearActiveMove(true);
  40.                 return;
  41.             }
  42.         }
  43.         pokemon.lastDamage = 0;
  44.         let lockedMove = this.runEvent('LockMove', pokemon);
  45.         if (lockedMove === true) lockedMove = false;
  46.         if (!lockedMove) {
  47.             if (!pokemon.deductPP(move, null, target) && (move.id !== 'struggle')) {
  48.                 this.add('cant', pokemon, 'nopp', move);
  49.                 this.clearActiveMove(true);
  50.                 return;
  51.             }
  52.         }
  53.         pokemon.moveUsed(move);
  54.         this.useMove(move, pokemon, target, sourceEffect);
  55.         this.singleEvent('AfterMove', move, null, pokemon, target, move);
  56.     },
  57.     addQueue: function (decision, noResolve) {
  58.         if (Array.isArray(decision)) {
  59.             for (let i = 0; i < decision.length; i++) {
  60.                 this.addQueue(decision[i], noResolve);
  61.             }
  62.             return;
  63.         }
  64.  
  65.         if (!noResolve) {
  66.             let decisions = this.resolveDecision(decision);
  67.             for (let i = 0; i < decisions.length; i++) {
  68.                 this.addQueue(decisions[i], decisions[i] === decision);
  69.             }
  70.             return;
  71.         }
  72.  
  73.         this.queue.push(decision);
  74.     },
  75.     insertQueue: function (decision, noResolve) {
  76.         if (Array.isArray(decision)) {
  77.             for (let i = 0; i < decision.length; i++) {
  78.                 this.insertQueue(decision[i], noResolve);
  79.             }
  80.             return;
  81.         }
  82.  
  83.         if (!noResolve) {
  84.             let decisions = this.resolveDecision(decision);
  85.             for (let i = 0; i < decisions.length; i++) {
  86.                 this.insertQueue(decisions[i], decisions[i] === decision);
  87.             }
  88.             return;
  89.         }
  90.  
  91.         for (let i = 0; i <= this.queue.length; i++) {
  92.             if (i === this.queue.length) {
  93.                 this.queue.push(decision);
  94.                 break;
  95.             } else if (this.comparePriority(decision, this.queue[i]) < 0) {
  96.                 this.queue.splice(i, 0, decision);
  97.                 break;
  98.             }
  99.         }
  100.     },
  101.     resolveDecision: function (decision) {
  102.         let decisions = [decision];
  103.         if (!decision.side && decision.pokemon) decision.side = decision.pokemon.side;
  104.         if (!decision.choice && decision.move) decision.choice = 'move';
  105.         if (!decision.priority) {
  106.             let priorities = {
  107.                 'beforeTurn': 100,
  108.                 'beforeTurnMove': 99,
  109.                 'switch': 6,
  110.                 'runSwitch': 6.1,
  111.                 'megaEvo': 5.9,
  112.                 'residual': -100,
  113.                 'team': 102,
  114.                 'start': 101,
  115.             };
  116.             if (priorities[decision.choice]) {
  117.                 decision.priority = priorities[decision.choice];
  118.             }
  119.         }
  120.         if (decision.choice === 'move') {
  121.             if (this.getMove(decision.move).beforeTurnCallback) {
  122.                 decisions.unshift({choice: 'beforeTurnMove', pokemon: decision.pokemon, move: decision.move, targetLoc: decision.targetLoc});
  123.             }
  124.  
  125.             let linkedMoves = decision.pokemon.getLinkedMoves();
  126.             if (linkedMoves.length && !linkedMoves.disabled) {
  127.                 let decisionMove = toId(decision.move);
  128.                 let index = linkedMoves.indexOf(decisionMove);
  129.                 if (index !== -1) {
  130.                     // flag the move as linked here
  131.                     decision.linked = linkedMoves;
  132.                     if (this.getMove(linkedMoves[1 - index]).beforeTurnCallback) {
  133.                         decisions.unshift({choice: 'beforeTurnMove', pokemon: decision.pokemon, move: linkedMoves[1 - index], targetLoc: decision.targetLoc});
  134.                     }
  135.                 }
  136.             }
  137.         } else if (decision.choice === 'switch' || decision.choice === 'instaswitch') {
  138.             if (decision.pokemon.switchFlag && decision.pokemon.switchFlag !== true) {
  139.                 decision.pokemon.switchCopyFlag = decision.pokemon.switchFlag;
  140.             }
  141.             decision.pokemon.switchFlag = false;
  142.             if (!decision.speed && decision.pokemon && decision.pokemon.isActive) decision.speed = decision.pokemon.speed;
  143.         }
  144.         if (decision.move) {
  145.             let target;
  146.  
  147.             if (!decision.targetPosition) {
  148.                 // this target is not relevant to Linked (or any other game mode)
  149.                 target = this.resolveTarget(decision.pokemon, decision.move);
  150.                 decision.targetSide = target.side;
  151.                 decision.targetPosition = target.position;
  152.             }
  153.  
  154.             decision.move = this.getMoveCopy(decision.move);
  155.             if (!decision.priority) {
  156.                 let priority = decision.move.priority;
  157.                 priority = this.runEvent('ModifyPriority', decision.pokemon, target, decision.move, priority);
  158.  
  159.                 // Linked: if two moves are linked, the effective priority is minimized
  160.                 let linkedMoves = decision.pokemon.getLinkedMoves();
  161.                 if (linkedMoves.length && !linkedMoves.disabled) {
  162.                     let decisionMove = toId(decision.move);
  163.                     let index = linkedMoves.indexOf(decisionMove);
  164.                     if (index !== -1) {
  165.                         let altMove = this.getMoveCopy(linkedMoves[1 - index]);
  166.                         let altPriority = this.runEvent('ModifyPriority', decision.pokemon, target, altMove, altMove.priority);
  167.                         priority = Math.min(priority, altPriority);
  168.                     }
  169.                 }
  170.  
  171.                 decision.priority = priority;
  172.                 // In Gen 6, Quick Guard blocks moves with artificially enhanced priority.
  173.                 if (this.gen > 5) decision.move.priority = priority;
  174.             }
  175.         }
  176.         if (!decision.pokemon && !decision.speed) decision.speed = 1;
  177.         if (!decision.speed && (decision.choice === 'switch' || decision.choice === 'instaswitch') && decision.target) decision.speed = decision.target.speed;
  178.         if (!decision.speed) decision.speed = decision.pokemon.speed;
  179.         return decisions;
  180.     },
  181.     runDecision: function (decision) {
  182.         this.currentDecision = decision;
  183.  
  184.         // returns whether or not we ended in a callback
  185.         switch (decision.choice) {
  186.         case 'start': {
  187.             // I GIVE UP, WILL WRESTLE WITH EVENT SYSTEM LATER
  188.             let format = this.getFormat();
  189.  
  190.             // Remove Pokémon duplicates remaining after `team` decisions.
  191.             this.p1.pokemon = this.p1.pokemon.slice(0, this.p1.pokemonLeft);
  192.             this.p2.pokemon = this.p2.pokemon.slice(0, this.p2.pokemonLeft);
  193.  
  194.             if (format.teamLength && format.teamLength.battle) {
  195.                 // Trim the team: not all of the Pokémon brought to Preview will battle.
  196.                 this.p1.pokemon = this.p1.pokemon.slice(0, format.teamLength.battle);
  197.                 this.p1.pokemonLeft = this.p1.pokemon.length;
  198.                 this.p2.pokemon = this.p2.pokemon.slice(0, format.teamLength.battle);
  199.                 this.p2.pokemonLeft = this.p2.pokemon.length;
  200.             }
  201.  
  202.             this.add('start');
  203.             for (let pos = 0; pos < this.p1.active.length; pos++) {
  204.                 this.switchIn(this.p1.pokemon[pos], pos);
  205.             }
  206.             for (let pos = 0; pos < this.p2.active.length; pos++) {
  207.                 this.switchIn(this.p2.pokemon[pos], pos);
  208.             }
  209.             for (let pos = 0; pos < this.p1.pokemon.length; pos++) {
  210.                 let pokemon = this.p1.pokemon[pos];
  211.                 this.singleEvent('Start', this.getEffect(pokemon.species), pokemon.speciesData, pokemon);
  212.             }
  213.             for (let pos = 0; pos < this.p2.pokemon.length; pos++) {
  214.                 let pokemon = this.p2.pokemon[pos];
  215.                 this.singleEvent('Start', this.getEffect(pokemon.species), pokemon.speciesData, pokemon);
  216.             }
  217.             this.midTurn = true;
  218.             break;
  219.         }
  220.  
  221.         case 'move': {
  222.             if (!decision.pokemon.isActive) return false;
  223.             if (decision.pokemon.fainted) return false;
  224.             if (decision.linked) {
  225.                 let linkedMoves = decision.linked;
  226.                 for (let i = linkedMoves.length - 1; i >= 0; i--) {
  227.                     let pseudoDecision = {choice: 'move', move: linkedMoves[i], targetLoc: decision.targetLoc, pokemon: decision.pokemon, targetPosition: decision.targetPosition, targetSide: decision.targetSide};
  228.                     this.queue.unshift(pseudoDecision);
  229.                 }
  230.                 return;
  231.             }
  232.             this.runMove(decision.move, decision.pokemon, this.getTarget(decision), decision.sourceEffect);
  233.             break;
  234.         }
  235.  
  236.         case 'megaEvo':
  237.             if (decision.pokemon.canMegaEvo) this.runMegaEvo(decision.pokemon);
  238.             break;
  239.         case 'beforeTurnMove': {
  240.             if (!decision.pokemon.isActive) return false;
  241.             if (decision.pokemon.fainted) return false;
  242.             this.debug('before turn callback: ' + decision.move.id);
  243.             let target = this.getTarget(decision);
  244.             if (!target) return false;
  245.             decision.move.beforeTurnCallback.call(this, decision.pokemon, target);
  246.             break;
  247.         }
  248.  
  249.         case 'event':
  250.             this.runEvent(decision.event, decision.pokemon);
  251.             break;
  252.         case 'team': {
  253.             decision.side.pokemon.splice(decision.index, 0, decision.pokemon);
  254.             decision.pokemon.position = decision.index;
  255.             // we return here because the update event would crash since there are no active pokemon yet
  256.             return;
  257.         }
  258.  
  259.         case 'pass':
  260.             if (!decision.priority || decision.priority <= 101) return;
  261.             if (decision.pokemon) {
  262.                 decision.pokemon.switchFlag = false;
  263.             }
  264.             break;
  265.         case 'instaswitch':
  266.         case 'switch':
  267.             if (decision.pokemon) {
  268.                 decision.pokemon.beingCalledBack = true;
  269.                 let lastMove = this.getMove(decision.pokemon.getLastMoveAbsolute());
  270.                 if (lastMove.selfSwitch !== 'copyvolatile') {
  271.                     this.runEvent('BeforeSwitchOut', decision.pokemon);
  272.                     if (this.gen >= 5) {
  273.                         this.eachEvent('Update');
  274.                     }
  275.                 }
  276.                 if (!this.runEvent('SwitchOut', decision.pokemon)) {
  277.                     // Warning: DO NOT interrupt a switch-out
  278.                     // if you just want to trap a pokemon.
  279.                     // To trap a pokemon and prevent it from switching out,
  280.                     // (e.g. Mean Look, Magnet Pull) use the 'trapped' flag
  281.                     // instead.
  282.  
  283.                     // Note: Nothing in BW or earlier interrupts
  284.                     // a switch-out.
  285.                     break;
  286.                 }
  287.                 this.singleEvent('End', this.getAbility(decision.pokemon.ability), decision.pokemon.abilityData, decision.pokemon);
  288.             }
  289.             if (decision.pokemon && !decision.pokemon.hp && !decision.pokemon.fainted) {
  290.                 // a pokemon fainted from Pursuit before it could switch
  291.                 if (this.gen <= 4) {
  292.                     // in gen 2-4, the switch still happens
  293.                     decision.priority = -101;
  294.                     this.queue.unshift(decision);
  295.                     this.debug('Pursuit target fainted');
  296.                     break;
  297.                 }
  298.                 // in gen 5+, the switch is cancelled
  299.                 this.debug('A Pokemon can\'t switch between when it runs out of HP and when it faints');
  300.                 break;
  301.             }
  302.             if (decision.target.isActive) {
  303.                 this.debug('Switch target is already active');
  304.                 break;
  305.             }
  306.             if (decision.choice === 'switch' && decision.pokemon.activeTurns === 1) {
  307.                 let foeActive = decision.pokemon.side.foe.active;
  308.                 for (let i = 0; i < foeActive.length; i++) {
  309.                     if (foeActive[i].isStale >= 2) {
  310.                         decision.pokemon.isStaleCon++;
  311.                         decision.pokemon.isStaleSource = 'switch';
  312.                         break;
  313.                     }
  314.                 }
  315.             }
  316.             this.switchIn(decision.target, decision.pokemon.position);
  317.             break;
  318.         case 'runSwitch':
  319.             this.runEvent('SwitchIn', decision.pokemon);
  320.             if (this.gen <= 2 && !decision.pokemon.side.faintedThisTurn && decision.pokemon.draggedIn !== this.turn) this.runEvent('AfterSwitchInSelf', decision.pokemon);
  321.             if (!decision.pokemon.hp) break;
  322.             decision.pokemon.isStarted = true;
  323.             if (!decision.pokemon.fainted) {
  324.                 this.singleEvent('Start', decision.pokemon.getAbility(), decision.pokemon.abilityData, decision.pokemon);
  325.                 this.singleEvent('Start', decision.pokemon.getItem(), decision.pokemon.itemData, decision.pokemon);
  326.             }
  327.             delete decision.pokemon.draggedIn;
  328.             break;
  329.         case 'shift':
  330.             if (!decision.pokemon.isActive) return false;
  331.             if (decision.pokemon.fainted) return false;
  332.             decision.pokemon.activeTurns--;
  333.             this.swapPosition(decision.pokemon, 1);
  334.             let foeActive = decision.pokemon.side.foe.active;
  335.             for (let i = 0; i < foeActive.length; i++) {
  336.                 if (foeActive[i].isStale >= 2) {
  337.                     decision.pokemon.isStaleCon++;
  338.                     decision.pokemon.isStaleSource = 'switch';
  339.                     break;
  340.                 }
  341.             }
  342.             break;
  343.         case 'beforeTurn':
  344.             this.eachEvent('BeforeTurn');
  345.             break;
  346.         case 'residual':
  347.             this.add('');
  348.             this.clearActiveMove(true);
  349.             this.residualEvent('Residual');
  350.             break;
  351.         }
  352.  
  353.         // phazing (Roar, etc)
  354.  
  355.         let self = this;
  356.         function checkForceSwitchFlag(a) {
  357.             if (!a) return false;
  358.             if (a.hp && a.forceSwitchFlag) {
  359.                 self.dragIn(a.side, a.position);
  360.             }
  361.             delete a.forceSwitchFlag;
  362.         }
  363.         this.p1.active.forEach(checkForceSwitchFlag);
  364.         this.p2.active.forEach(checkForceSwitchFlag);
  365.  
  366.         this.clearActiveMove();
  367.  
  368.         // fainting
  369.  
  370.         this.faintMessages();
  371.         if (this.ended) return true;
  372.  
  373.         // switching (fainted pokemon, U-turn, Baton Pass, etc)
  374.  
  375.         if (!this.queue.length || (this.gen <= 3 && this.queue[0].choice in {move:1, residual:1})) {
  376.             // in gen 3 or earlier, switching in fainted pokemon is done after
  377.             // every move, rather than only at the end of the turn.
  378.             this.checkFainted();
  379.         } else if (decision.choice === 'pass') {
  380.             this.eachEvent('Update');
  381.             return false;
  382.         }
  383.  
  384.         let p1switch = this.p1.active.some(mon => mon && mon.switchFlag);
  385.         let p2switch = this.p2.active.some(mon => mon && mon.switchFlag);
  386.  
  387.         if (p1switch && !this.canSwitch(this.p1)) {
  388.             for (let i = 0; i < this.p1.active.length; i++) {
  389.                 this.p1.active[i].switchFlag = false;
  390.             }
  391.             p1switch = false;
  392.         }
  393.         if (p2switch && !this.canSwitch(this.p2)) {
  394.             for (let i = 0; i < this.p2.active.length; i++) {
  395.                 this.p2.active[i].switchFlag = false;
  396.             }
  397.             p2switch = false;
  398.         }
  399.  
  400.         if (p1switch || p2switch) {
  401.             if (this.gen >= 5) {
  402.                 this.eachEvent('Update');
  403.             }
  404.             this.makeRequest('switch');
  405.             return true;
  406.         }
  407.  
  408.         this.eachEvent('Update');
  409.  
  410.         return false;
  411.     },
  412.     comparePriority: function (a, b) { // intentionally not in Battle.prototype
  413.         a.priority = a.priority || 0;
  414.         a.subPriority = a.subPriority || 0;
  415.         a.speed = a.speed || 0;
  416.         b.priority = b.priority || 0;
  417.         b.subPriority = b.subPriority || 0;
  418.         b.speed = b.speed || 0;
  419.         if ((typeof a.order === 'number' || typeof b.order === 'number') && a.order !== b.order) {
  420.             if (typeof a.order !== 'number') {
  421.                 return -1;
  422.             }
  423.             if (typeof b.order !== 'number') {
  424.                 return 1;
  425.             }
  426.             if (b.order - a.order) {
  427.                 return -(b.order - a.order);
  428.             }
  429.         }
  430.         if (b.priority - a.priority) {
  431.             return b.priority - a.priority;
  432.         }
  433.         if (b.speed - a.speed) {
  434.             return b.speed - a.speed;
  435.         }
  436.         if (b.subOrder - a.subOrder) {
  437.             return -(b.subOrder - a.subOrder);
  438.         }
  439.         return Math.random() - 0.5;
  440.     },
  441.     pokemon: {
  442.         moveUsed: function (move) { // overrided
  443.             let lastMove = this.moveThisTurn ? [this.moveThisTurn, this.battle.getMove(move).id] : this.battle.getMove(move).id;
  444.             this.lastMove = lastMove;
  445.             this.moveThisTurn = lastMove;
  446.         },
  447.         getLastMoveAbsolute: function () { // used
  448.             if (Array.isArray(this.lastMove)) return this.lastMove[1];
  449.             return this.lastMove;
  450.         },
  451.         checkMoveThisTurn: function (move) {
  452.             move = toId(move);
  453.             if (Array.isArray(this.moveThisTurn)) return this.moveThisTurn.indexOf(move) >= 0;
  454.             return this.moveThisTurn === move;
  455.         },
  456.         getLinkedMoves: function () {
  457.             let linkedMoves = this.moveset.slice(0, 2);
  458.             if (linkedMoves.length !== 2 || linkedMoves[0].pp <= 0 || linkedMoves[1].pp <= 0) return [];
  459.             let ret = [toId(linkedMoves[0]), toId(linkedMoves[1])];
  460.  
  461.             // Disabling effects which won't abort execution of moves already added to battle event loop.
  462.             if (!this.ateBerry && ret.indexOf('belch') >= 0) {
  463.                 ret.disabled = true;
  464.             } else if (this.hasItem('assaultvest') && (this.battle.getMove(ret[0]).category === 'Status' || this.battle.getMove(ret[1]).category === 'Status')) {
  465.                 ret.disabled = true;
  466.             }
  467.             return ret;
  468.         },
  469.         hasLinkedMove: function (move) {
  470.             move = toId(move);
  471.             let linkedMoves = this.getLinkedMoves();
  472.             if (!linkedMoves.length) return;
  473.  
  474.             return linkedMoves[0] === move || linkedMoves[1] === move;
  475.         },
  476.     },
  477. };
Add Comment
Please, Sign In to add comment