Spaces:
Running
Running
; | |
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 | |