Spaces:
Paused
Paused
| ; | |
| var __defProp = Object.defineProperty; | |
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | |
| var __getOwnPropNames = Object.getOwnPropertyNames; | |
| var __hasOwnProp = Object.prototype.hasOwnProperty; | |
| var __export = (target, all) => { | |
| for (var name in all) | |
| __defProp(target, name, { get: all[name], enumerable: true }); | |
| }; | |
| var __copyProps = (to, from, except, desc) => { | |
| if (from && typeof from === "object" || typeof from === "function") { | |
| for (let key of __getOwnPropNames(from)) | |
| if (!__hasOwnProp.call(to, key) && key !== except) | |
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | |
| } | |
| return to; | |
| }; | |
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | |
| var battle_queue_exports = {}; | |
| __export(battle_queue_exports, { | |
| BattleQueue: () => BattleQueue, | |
| default: () => battle_queue_default | |
| }); | |
| module.exports = __toCommonJS(battle_queue_exports); | |
| /** | |
| * Simulator Battle Action Queue | |
| * Pokemon Showdown - http://pokemonshowdown.com/ | |
| * | |
| * The action queue is the core of the battle simulation. A rough overview of | |
| * the core battle loop: | |
| * | |
| * - chosen moves/switches are added to the action queue | |
| * - the action queue is sorted in speed/priority order | |
| * - we go through the action queue | |
| * - repeat | |
| * | |
| * @license MIT | |
| */ | |
| class BattleQueue { | |
| constructor(battle) { | |
| this.battle = battle; | |
| this.list = []; | |
| const queueScripts = battle.format.queue || battle.dex.data.Scripts.queue; | |
| if (queueScripts) | |
| Object.assign(this, queueScripts); | |
| } | |
| shift() { | |
| return this.list.shift(); | |
| } | |
| peek(end) { | |
| return this.list[end ? this.list.length - 1 : 0]; | |
| } | |
| push(action) { | |
| return this.list.push(action); | |
| } | |
| unshift(action) { | |
| return this.list.unshift(action); | |
| } | |
| [Symbol.iterator]() { | |
| return this.list[Symbol.iterator](); | |
| } | |
| entries() { | |
| return this.list.entries(); | |
| } | |
| /** | |
| * Takes an ActionChoice, and fills it out into a full Action object. | |
| * | |
| * Returns an array of Actions because some ActionChoices (like mega moves) | |
| * resolve to two Actions (mega evolution + use move) | |
| */ | |
| resolveAction(action, midTurn = false) { | |
| if (!action) | |
| throw new Error(`Action not passed to resolveAction`); | |
| if (action.choice === "pass") | |
| return []; | |
| const actions = [action]; | |
| if (!action.side && action.pokemon) | |
| action.side = action.pokemon.side; | |
| if (!action.move && action.moveid) | |
| action.move = this.battle.dex.getActiveMove(action.moveid); | |
| if (!action.order) { | |
| const orders = { | |
| team: 1, | |
| start: 2, | |
| instaswitch: 3, | |
| beforeTurn: 4, | |
| beforeTurnMove: 5, | |
| revivalblessing: 6, | |
| runSwitch: 101, | |
| switch: 103, | |
| megaEvo: 104, | |
| megaEvoX: 104, | |
| megaEvoY: 104, | |
| runDynamax: 105, | |
| terastallize: 106, | |
| priorityChargeMove: 107, | |
| shift: 200, | |
| // default is 200 (for moves) | |
| residual: 300 | |
| }; | |
| if (action.choice in orders) { | |
| action.order = orders[action.choice]; | |
| } else { | |
| action.order = 200; | |
| if (!["move", "event"].includes(action.choice)) { | |
| throw new Error(`Unexpected orderless action ${action.choice}`); | |
| } | |
| } | |
| } | |
| if (!midTurn) { | |
| if (action.choice === "move") { | |
| if (!action.maxMove && !action.zmove && action.move.beforeTurnCallback) { | |
| actions.unshift(...this.resolveAction({ | |
| choice: "beforeTurnMove", | |
| pokemon: action.pokemon, | |
| move: action.move, | |
| targetLoc: action.targetLoc | |
| })); | |
| } | |
| if (action.mega && !action.pokemon.isSkyDropped()) { | |
| actions.unshift(...this.resolveAction({ | |
| choice: "megaEvo", | |
| pokemon: action.pokemon | |
| })); | |
| } | |
| if (action.megax && !action.pokemon.isSkyDropped()) { | |
| actions.unshift(...this.resolveAction({ | |
| choice: "megaEvoX", | |
| pokemon: action.pokemon | |
| })); | |
| } | |
| if (action.megay && !action.pokemon.isSkyDropped()) { | |
| actions.unshift(...this.resolveAction({ | |
| choice: "megaEvoY", | |
| pokemon: action.pokemon | |
| })); | |
| } | |
| if (action.terastallize && !action.pokemon.terastallized) { | |
| actions.unshift(...this.resolveAction({ | |
| choice: "terastallize", | |
| pokemon: action.pokemon | |
| })); | |
| } | |
| if (action.maxMove && !action.pokemon.volatiles["dynamax"]) { | |
| actions.unshift(...this.resolveAction({ | |
| choice: "runDynamax", | |
| pokemon: action.pokemon | |
| })); | |
| } | |
| if (!action.maxMove && !action.zmove && action.move.priorityChargeCallback) { | |
| actions.unshift(...this.resolveAction({ | |
| choice: "priorityChargeMove", | |
| pokemon: action.pokemon, | |
| move: action.move | |
| })); | |
| } | |
| action.fractionalPriority = this.battle.runEvent("FractionalPriority", action.pokemon, null, action.move, 0); | |
| } else if (["switch", "instaswitch"].includes(action.choice)) { | |
| if (typeof action.pokemon.switchFlag === "string") { | |
| action.sourceEffect = this.battle.dex.moves.get(action.pokemon.switchFlag); | |
| } | |
| action.pokemon.switchFlag = false; | |
| } | |
| } | |
| const deferPriority = this.battle.gen === 7 && action.mega && action.mega !== "done"; | |
| if (action.move) { | |
| let target = null; | |
| action.move = this.battle.dex.getActiveMove(action.move); | |
| if (!action.targetLoc) { | |
| target = this.battle.getRandomTarget(action.pokemon, action.move); | |
| if (target) | |
| action.targetLoc = action.pokemon.getLocOf(target); | |
| } | |
| action.originalTarget = action.pokemon.getAtLoc(action.targetLoc); | |
| } | |
| if (!deferPriority) | |
| this.battle.getActionSpeed(action); | |
| return actions; | |
| } | |
| /** | |
| * Makes the passed action happen next (skipping speed order). | |
| */ | |
| prioritizeAction(action, sourceEffect) { | |
| for (const [i, curAction] of this.list.entries()) { | |
| if (curAction === action) { | |
| this.list.splice(i, 1); | |
| break; | |
| } | |
| } | |
| action.sourceEffect = sourceEffect; | |
| action.order = 3; | |
| this.list.unshift(action); | |
| } | |
| /** | |
| * Changes a pokemon's action, and inserts its new action | |
| * in priority order. | |
| * | |
| * You'd normally want the OverrideAction event (which doesn't | |
| * change priority order). | |
| */ | |
| changeAction(pokemon, action) { | |
| this.cancelAction(pokemon); | |
| if (!action.pokemon) | |
| action.pokemon = pokemon; | |
| this.insertChoice(action); | |
| } | |
| addChoice(choices) { | |
| if (!Array.isArray(choices)) | |
| choices = [choices]; | |
| for (const choice of choices) { | |
| const resolvedChoices = this.resolveAction(choice); | |
| this.list.push(...resolvedChoices); | |
| for (const resolvedChoice of resolvedChoices) { | |
| if (resolvedChoice && resolvedChoice.choice === "move" && resolvedChoice.move.id !== "recharge") { | |
| resolvedChoice.pokemon.side.lastSelectedMove = resolvedChoice.move.id; | |
| } | |
| } | |
| } | |
| } | |
| willAct() { | |
| for (const action of this.list) { | |
| if (["move", "switch", "instaswitch", "shift"].includes(action.choice)) { | |
| return action; | |
| } | |
| } | |
| return null; | |
| } | |
| willMove(pokemon) { | |
| if (pokemon.fainted) | |
| return null; | |
| for (const action of this.list) { | |
| if (action.choice === "move" && action.pokemon === pokemon) { | |
| return action; | |
| } | |
| } | |
| return null; | |
| } | |
| cancelAction(pokemon) { | |
| const oldLength = this.list.length; | |
| for (let i = 0; i < this.list.length; i++) { | |
| if (this.list[i].pokemon === pokemon) { | |
| this.list.splice(i, 1); | |
| i--; | |
| } | |
| } | |
| return this.list.length !== oldLength; | |
| } | |
| cancelMove(pokemon) { | |
| for (const [i, action] of this.list.entries()) { | |
| if (action.choice === "move" && action.pokemon === pokemon) { | |
| this.list.splice(i, 1); | |
| return true; | |
| } | |
| } | |
| return false; | |
| } | |
| willSwitch(pokemon) { | |
| for (const action of this.list) { | |
| if (["switch", "instaswitch"].includes(action.choice) && action.pokemon === pokemon) { | |
| return action; | |
| } | |
| } | |
| return null; | |
| } | |
| /** | |
| * Inserts the passed action into the action queue when it normally | |
| * would have happened (sorting by priority/speed), without | |
| * re-sorting the existing actions. | |
| */ | |
| insertChoice(choices, midTurn = false) { | |
| if (Array.isArray(choices)) { | |
| for (const choice2 of choices) { | |
| this.insertChoice(choice2); | |
| } | |
| return; | |
| } | |
| const choice = choices; | |
| if (choice.pokemon) { | |
| choice.pokemon.updateSpeed(); | |
| } | |
| const actions = this.resolveAction(choice, midTurn); | |
| let firstIndex = null; | |
| let lastIndex = null; | |
| for (const [i, curAction] of this.list.entries()) { | |
| const compared = this.battle.comparePriority(actions[0], curAction); | |
| if (compared <= 0 && firstIndex === null) { | |
| firstIndex = i; | |
| } | |
| if (compared < 0) { | |
| lastIndex = i; | |
| break; | |
| } | |
| } | |
| if (firstIndex === null) { | |
| this.list.push(...actions); | |
| } else { | |
| if (lastIndex === null) | |
| lastIndex = this.list.length; | |
| const index = firstIndex === lastIndex ? firstIndex : this.battle.random(firstIndex, lastIndex + 1); | |
| this.list.splice(index, 0, ...actions); | |
| } | |
| } | |
| clear() { | |
| this.list = []; | |
| } | |
| debug(action) { | |
| if (action) { | |
| return `${action.order || ""}:${action.priority || ""}:${action.speed || ""}:${action.subOrder || ""} - ${action.choice}${action.pokemon ? " " + action.pokemon : ""}${action.move ? " " + action.move : ""}`; | |
| } | |
| return this.list.map( | |
| (queueAction) => this.debug(queueAction) | |
| ).join("\n") + "\n"; | |
| } | |
| sort() { | |
| this.battle.speedSort(this.list); | |
| return this; | |
| } | |
| } | |
| var battle_queue_default = BattleQueue; | |
| //# sourceMappingURL=battle-queue.js.map | |