559 lines
21 KiB
JavaScript
559 lines
21 KiB
JavaScript
"use strict";
|
|
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 scripts_exports = {};
|
|
__export(scripts_exports, {
|
|
Scripts: () => Scripts
|
|
});
|
|
module.exports = __toCommonJS(scripts_exports);
|
|
const Scripts = {
|
|
inherit: "gen8",
|
|
gen: 8,
|
|
getActionSpeed(action) {
|
|
if (action.choice === "move") {
|
|
let move = action.move;
|
|
if (action.zmove) {
|
|
const zMoveName = this.actions.getZMove(action.move, action.pokemon, true);
|
|
if (zMoveName) {
|
|
const zMove = this.dex.getActiveMove(zMoveName);
|
|
if (zMove.exists && zMove.isZ) {
|
|
move = zMove;
|
|
}
|
|
}
|
|
}
|
|
if (action.maxMove) {
|
|
const maxMoveName = this.actions.getMaxMove(action.maxMove, action.pokemon);
|
|
if (maxMoveName) {
|
|
const maxMove = this.actions.getActiveMaxMove(action.move, action.pokemon);
|
|
if (maxMove.exists && maxMove.isMax) {
|
|
move = maxMove;
|
|
}
|
|
}
|
|
}
|
|
let priority = this.dex.moves.get(move.id).priority;
|
|
priority = this.singleEvent("ModifyPriority", move, null, action.pokemon, null, null, priority);
|
|
priority = this.runEvent("ModifyPriority", action.pokemon, null, move, priority);
|
|
const linkedMoves = action.pokemon.getLinkedMoves();
|
|
let linkIndex = -1;
|
|
if (linkedMoves.length && !move.isZ && !move.isMax && (linkIndex = linkedMoves.indexOf(this.toID(action.move))) >= 0) {
|
|
const linkedActions = action.linked || linkedMoves.map((moveid) => this.dex.getActiveMove(moveid));
|
|
const altMove = linkedActions[1 - linkIndex];
|
|
const thisPriority = this.runEvent("ModifyPriority", action.pokemon, null, linkedActions[linkIndex], priority);
|
|
const thatPriority = this.runEvent("ModifyPriority", action.pokemon, null, altMove, altMove.priority);
|
|
priority = Math.min(thisPriority, thatPriority);
|
|
action.priority = priority + action.fractionalPriority;
|
|
if (this.gen > 5) {
|
|
linkedActions[linkIndex].priority = priority;
|
|
altMove.priority = priority;
|
|
}
|
|
} else {
|
|
action.priority = priority + action.fractionalPriority;
|
|
if (this.gen > 5)
|
|
action.move.priority = priority;
|
|
}
|
|
}
|
|
if (!action.pokemon) {
|
|
action.speed = 1;
|
|
} else {
|
|
action.speed = action.pokemon.getActionSpeed();
|
|
}
|
|
},
|
|
runAction(action) {
|
|
const pokemonOriginalHP = action.pokemon?.hp;
|
|
let residualPokemon = [];
|
|
switch (action.choice) {
|
|
case "start": {
|
|
for (const side of this.sides) {
|
|
if (side.pokemonLeft)
|
|
side.pokemonLeft = side.pokemon.length;
|
|
}
|
|
this.add("start");
|
|
if (this.format.onBattleStart)
|
|
this.format.onBattleStart.call(this);
|
|
for (const rule of this.ruleTable.keys()) {
|
|
if ("+*-!".includes(rule.charAt(0)))
|
|
continue;
|
|
const subFormat = this.dex.formats.get(rule);
|
|
if (subFormat.onBattleStart)
|
|
subFormat.onBattleStart.call(this);
|
|
}
|
|
for (const side of this.sides) {
|
|
for (let i = 0; i < side.active.length; i++) {
|
|
if (!side.pokemonLeft) {
|
|
side.active[i] = side.pokemon[i];
|
|
side.active[i].fainted = true;
|
|
side.active[i].hp = 0;
|
|
} else {
|
|
this.actions.switchIn(side.pokemon[i], i);
|
|
}
|
|
}
|
|
}
|
|
for (const pokemon of this.getAllPokemon()) {
|
|
this.singleEvent("Start", this.dex.conditions.getByID(pokemon.species.id), pokemon.speciesState, pokemon);
|
|
}
|
|
this.midTurn = true;
|
|
break;
|
|
}
|
|
case "move":
|
|
if (!action.pokemon.isActive)
|
|
return false;
|
|
if (action.pokemon.fainted)
|
|
return false;
|
|
if (action.linked) {
|
|
const linkedMoves = action.linked;
|
|
for (let i = linkedMoves.length - 1; i >= 0; i--) {
|
|
const validTarget = this.validTargetLoc(action.targetLoc, action.pokemon, linkedMoves[i].target);
|
|
const targetLoc = validTarget ? action.targetLoc : 0;
|
|
const pseudoAction = {
|
|
choice: "move",
|
|
priority: action.priority,
|
|
speed: action.speed,
|
|
pokemon: action.pokemon,
|
|
targetLoc,
|
|
moveid: linkedMoves[i].id,
|
|
move: linkedMoves[i],
|
|
mega: action.mega,
|
|
order: action.order,
|
|
fractionalPriority: action.fractionalPriority,
|
|
originalTarget: action.originalTarget
|
|
};
|
|
this.queue.unshift(pseudoAction);
|
|
}
|
|
return;
|
|
}
|
|
this.actions.runMove(
|
|
action.move,
|
|
action.pokemon,
|
|
action.targetLoc,
|
|
action.sourceEffect,
|
|
action.zmove,
|
|
void 0,
|
|
action.maxMove,
|
|
action.originalTarget
|
|
);
|
|
break;
|
|
case "megaEvo":
|
|
this.actions.runMegaEvo(action.pokemon);
|
|
break;
|
|
case "runDynamax":
|
|
action.pokemon.addVolatile("dynamax");
|
|
action.pokemon.side.dynamaxUsed = true;
|
|
if (action.pokemon.side.allySide)
|
|
action.pokemon.side.allySide.dynamaxUsed = true;
|
|
break;
|
|
case "beforeTurnMove": {
|
|
if (!action.pokemon.isActive)
|
|
return false;
|
|
if (action.pokemon.fainted)
|
|
return false;
|
|
this.debug("before turn callback: " + action.move.id);
|
|
const target = this.getTarget(action.pokemon, action.move, action.targetLoc);
|
|
if (!target)
|
|
return false;
|
|
if (!action.move.beforeTurnCallback)
|
|
throw new Error(`beforeTurnMove has no beforeTurnCallback`);
|
|
action.move.beforeTurnCallback.call(this, action.pokemon, target);
|
|
break;
|
|
}
|
|
case "event":
|
|
this.runEvent(action.event, action.pokemon);
|
|
break;
|
|
case "team":
|
|
if (action.index === 0) {
|
|
action.pokemon.side.pokemon = [];
|
|
}
|
|
action.pokemon.side.pokemon.push(action.pokemon);
|
|
action.pokemon.position = action.index;
|
|
return;
|
|
case "pass":
|
|
return;
|
|
case "instaswitch":
|
|
case "switch":
|
|
if (action.choice === "switch" && action.pokemon.status) {
|
|
this.singleEvent("CheckShow", this.dex.abilities.getByID("naturalcure"), null, action.pokemon);
|
|
}
|
|
if (this.actions.switchIn(action.target, action.pokemon.position, action.sourceEffect) === "pursuitfaint") {
|
|
if (this.gen <= 4) {
|
|
this.hint("Previously chosen switches continue in Gen 2-4 after a Pursuit target faints.");
|
|
action.priority = -101;
|
|
this.queue.unshift(action);
|
|
break;
|
|
} else {
|
|
this.hint("A Pokemon can't switch between when it runs out of HP and when it faints");
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case "runUnnerve":
|
|
this.singleEvent("PreStart", action.pokemon.getAbility(), action.pokemon.abilityState, action.pokemon);
|
|
break;
|
|
case "runSwitch":
|
|
this.actions.runSwitch(action.pokemon);
|
|
break;
|
|
case "runPrimal":
|
|
if (!action.pokemon.transformed) {
|
|
this.singleEvent("Primal", action.pokemon.getItem(), action.pokemon.itemState, action.pokemon);
|
|
}
|
|
break;
|
|
case "shift":
|
|
if (!action.pokemon.isActive)
|
|
return false;
|
|
if (action.pokemon.fainted)
|
|
return false;
|
|
this.swapPosition(action.pokemon, 1);
|
|
break;
|
|
case "beforeTurn":
|
|
this.eachEvent("BeforeTurn");
|
|
break;
|
|
case "residual":
|
|
this.add("");
|
|
this.clearActiveMove(true);
|
|
this.updateSpeed();
|
|
residualPokemon = this.getAllActive().map((pokemon) => [pokemon, pokemon.getUndynamaxedHP()]);
|
|
this.residualEvent("Residual");
|
|
this.add("upkeep");
|
|
break;
|
|
}
|
|
for (const side of this.sides) {
|
|
for (const pokemon of side.active) {
|
|
if (pokemon.forceSwitchFlag) {
|
|
if (pokemon.hp)
|
|
this.actions.dragIn(pokemon.side, pokemon.position);
|
|
pokemon.forceSwitchFlag = false;
|
|
}
|
|
}
|
|
}
|
|
this.clearActiveMove();
|
|
this.faintMessages();
|
|
if (this.ended)
|
|
return true;
|
|
if (!this.queue.peek() || this.gen <= 3 && ["move", "residual"].includes(this.queue.peek().choice)) {
|
|
this.checkFainted();
|
|
} else if (action.choice === "megaEvo" && this.gen === 7) {
|
|
this.eachEvent("Update");
|
|
for (const [i, queuedAction] of this.queue.list.entries()) {
|
|
if (queuedAction.pokemon === action.pokemon && queuedAction.choice === "move") {
|
|
this.queue.list.splice(i, 1);
|
|
queuedAction.mega = "done";
|
|
this.queue.insertChoice(queuedAction, true);
|
|
break;
|
|
}
|
|
}
|
|
return false;
|
|
} else if (this.queue.peek()?.choice === "instaswitch") {
|
|
return false;
|
|
}
|
|
if (this.gen >= 5) {
|
|
this.eachEvent("Update");
|
|
for (const [pokemon, originalHP] of residualPokemon) {
|
|
const maxhp = pokemon.getUndynamaxedHP(pokemon.maxhp);
|
|
if (pokemon.hp && pokemon.getUndynamaxedHP() <= maxhp / 2 && originalHP > maxhp / 2) {
|
|
this.runEvent("EmergencyExit", pokemon);
|
|
}
|
|
}
|
|
}
|
|
if (action.choice === "runSwitch") {
|
|
const pokemon = action.pokemon;
|
|
if (pokemon.hp && pokemon.hp <= pokemon.maxhp / 2 && pokemonOriginalHP > pokemon.maxhp / 2) {
|
|
this.runEvent("EmergencyExit", pokemon);
|
|
}
|
|
}
|
|
const switches = this.sides.map(
|
|
(side) => side.active.some((pokemon) => pokemon && !!pokemon.switchFlag)
|
|
);
|
|
for (let i = 0; i < this.sides.length; i++) {
|
|
if (switches[i] && !this.canSwitch(this.sides[i])) {
|
|
for (const pokemon of this.sides[i].active) {
|
|
pokemon.switchFlag = false;
|
|
}
|
|
switches[i] = false;
|
|
} else if (switches[i]) {
|
|
for (const pokemon of this.sides[i].active) {
|
|
if (pokemon.switchFlag && !pokemon.skipBeforeSwitchOutEventFlag) {
|
|
this.runEvent("BeforeSwitchOut", pokemon);
|
|
pokemon.skipBeforeSwitchOutEventFlag = true;
|
|
this.faintMessages();
|
|
if (this.ended)
|
|
return true;
|
|
if (pokemon.fainted) {
|
|
switches[i] = this.sides[i].active.some((sidePokemon) => sidePokemon && !!sidePokemon.switchFlag);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (const playerSwitch of switches) {
|
|
if (playerSwitch) {
|
|
this.makeRequest("switch");
|
|
return true;
|
|
}
|
|
}
|
|
if (this.gen < 5)
|
|
this.eachEvent("Update");
|
|
if (this.gen >= 8 && this.queue.peek()?.choice === "move") {
|
|
this.updateSpeed();
|
|
for (const queueAction of this.queue.list) {
|
|
if (queueAction.pokemon)
|
|
this.getActionSpeed(queueAction);
|
|
}
|
|
this.queue.sort();
|
|
}
|
|
return false;
|
|
},
|
|
actions: {
|
|
runMove(moveOrMoveName, pokemon, targetLoc, sourceEffect, zMove, externalMove, maxMove, originalTarget) {
|
|
pokemon.activeMoveActions++;
|
|
let target = this.battle.getTarget(pokemon, maxMove || zMove || moveOrMoveName, targetLoc, originalTarget);
|
|
let baseMove = this.dex.getActiveMove(moveOrMoveName);
|
|
const pranksterBoosted = baseMove.pranksterBoosted;
|
|
if (baseMove.id !== "struggle" && !zMove && !maxMove && !externalMove) {
|
|
const changedMove = this.battle.runEvent("OverrideAction", pokemon, target, baseMove);
|
|
if (changedMove && changedMove !== true) {
|
|
baseMove = this.dex.getActiveMove(changedMove);
|
|
if (pranksterBoosted)
|
|
baseMove.pranksterBoosted = pranksterBoosted;
|
|
target = this.battle.getRandomTarget(pokemon, baseMove);
|
|
}
|
|
}
|
|
let move = baseMove;
|
|
if (zMove) {
|
|
move = this.getActiveZMove(baseMove, pokemon);
|
|
} else if (maxMove) {
|
|
move = this.getActiveMaxMove(baseMove, pokemon);
|
|
}
|
|
move.isExternal = externalMove;
|
|
this.battle.setActiveMove(move, pokemon, target);
|
|
const willTryMove = this.battle.runEvent("BeforeMove", pokemon, target, move);
|
|
if (!willTryMove) {
|
|
if (pokemon.volatiles["twoturnmove"]?.move === move.id) {
|
|
pokemon.removeVolatile("twoturnmove");
|
|
}
|
|
this.battle.runEvent("MoveAborted", pokemon, target, move);
|
|
this.battle.clearActiveMove(true);
|
|
pokemon.moveThisTurnResult = willTryMove;
|
|
return;
|
|
}
|
|
if (move.beforeMoveCallback) {
|
|
if (move.beforeMoveCallback.call(this.battle, pokemon, target, move)) {
|
|
this.battle.clearActiveMove(true);
|
|
pokemon.moveThisTurnResult = false;
|
|
return;
|
|
}
|
|
}
|
|
pokemon.lastDamage = 0;
|
|
let lockedMove;
|
|
if (!externalMove) {
|
|
lockedMove = this.battle.runEvent("LockMove", pokemon);
|
|
if (lockedMove === true)
|
|
lockedMove = false;
|
|
if (!lockedMove) {
|
|
if (!pokemon.deductPP(baseMove, null, target) && move.id !== "struggle") {
|
|
this.battle.add("cant", pokemon, "nopp", move);
|
|
const gameConsole = [
|
|
null,
|
|
"Game Boy",
|
|
"Game Boy Color",
|
|
"Game Boy Advance",
|
|
"DS",
|
|
"DS",
|
|
"3DS",
|
|
"3DS"
|
|
][this.battle.gen] || "Switch";
|
|
this.battle.hint(`This is not a bug, this is really how it works on the ${gameConsole}; try it yourself if you don't believe us.`);
|
|
this.battle.clearActiveMove(true);
|
|
pokemon.moveThisTurnResult = false;
|
|
return;
|
|
}
|
|
} else {
|
|
sourceEffect = this.dex.conditions.get("lockedmove");
|
|
}
|
|
pokemon.moveUsed(move, targetLoc);
|
|
}
|
|
const noLock = externalMove && !pokemon.volatiles.lockedmove;
|
|
if (zMove) {
|
|
if (pokemon.illusion) {
|
|
this.battle.singleEvent("End", this.dex.abilities.get("Illusion"), pokemon.abilityState, pokemon);
|
|
}
|
|
this.battle.add("-zpower", pokemon);
|
|
pokemon.side.zMoveUsed = true;
|
|
}
|
|
const moveDidSomething = this.useMove(baseMove, pokemon, target, sourceEffect, zMove, maxMove);
|
|
this.battle.lastSuccessfulMoveThisTurn = moveDidSomething ? this.battle.activeMove && this.battle.activeMove.id : null;
|
|
if (this.battle.activeMove)
|
|
move = this.battle.activeMove;
|
|
this.battle.singleEvent("AfterMove", move, null, pokemon, target, move);
|
|
this.battle.runEvent("AfterMove", pokemon, target, move);
|
|
if (move.flags["dance"] && moveDidSomething && !move.isExternal) {
|
|
const dancers = [];
|
|
for (const currentPoke of this.battle.getAllActive()) {
|
|
if (pokemon === currentPoke)
|
|
continue;
|
|
if (currentPoke.hasAbility("dancer") && !currentPoke.isSemiInvulnerable()) {
|
|
dancers.push(currentPoke);
|
|
}
|
|
}
|
|
dancers.sort(
|
|
(a, b) => -(b.storedStats["spe"] - a.storedStats["spe"]) || b.abilityOrder - a.abilityOrder
|
|
);
|
|
for (const dancer of dancers) {
|
|
if (this.battle.faintMessages())
|
|
break;
|
|
if (dancer.fainted)
|
|
continue;
|
|
this.battle.add("-activate", dancer, "ability: Dancer");
|
|
const dancersTarget = !target.isAlly(dancer) && pokemon.isAlly(dancer) ? target : pokemon;
|
|
this.runMove(move.id, dancer, dancer.getLocOf(dancersTarget), this.dex.abilities.get("dancer"), void 0, true);
|
|
}
|
|
}
|
|
if (noLock && pokemon.volatiles["lockedmove"])
|
|
delete pokemon.volatiles["lockedmove"];
|
|
this.battle.faintMessages();
|
|
this.battle.checkWin();
|
|
}
|
|
},
|
|
queue: {
|
|
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,
|
|
runUnnerve: 100,
|
|
runSwitch: 101,
|
|
runPrimal: 102,
|
|
switch: 103,
|
|
megaEvo: 104,
|
|
runDynamax: 105,
|
|
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.maxMove && !action.pokemon.volatiles["dynamax"]) {
|
|
actions.unshift(...this.resolveAction({
|
|
choice: "runDynamax",
|
|
pokemon: action.pokemon
|
|
}));
|
|
}
|
|
action.fractionalPriority = this.battle.runEvent("FractionalPriority", action.pokemon, null, action.move, 0);
|
|
const linkedMoves = action.pokemon.getLinkedMoves();
|
|
if (linkedMoves.length && !(action.pokemon.getItem().isChoice || action.pokemon.hasAbility("gorillatactics")) && !action.zmove && !action.maxMove) {
|
|
const decisionMove = this.battle.toID(action.move);
|
|
if (linkedMoves.includes(decisionMove)) {
|
|
action.linked = linkedMoves.map((moveid) => this.battle.dex.getActiveMove(moveid));
|
|
const linkedOtherMove = action.linked[1 - linkedMoves.indexOf(decisionMove)];
|
|
if (linkedOtherMove.beforeTurnCallback) {
|
|
this.addChoice({
|
|
choice: "beforeTurnMove",
|
|
pokemon: action.pokemon,
|
|
move: linkedOtherMove,
|
|
targetLoc: action.targetLoc
|
|
});
|
|
}
|
|
}
|
|
}
|
|
} 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;
|
|
}
|
|
},
|
|
pokemon: {
|
|
moveUsed(move, targetLoc) {
|
|
if (!this.moveThisTurn)
|
|
this.m.lastMoveAbsolute = move;
|
|
this.lastMove = move;
|
|
this.moveThisTurn = move.id;
|
|
this.lastMoveTargetLoc = targetLoc;
|
|
},
|
|
getLinkedMoves(ignoreDisabled) {
|
|
const linkedMoves = this.moveSlots.slice(0, 2);
|
|
if (linkedMoves.length !== 2 || linkedMoves[0].pp <= 0 || linkedMoves[1].pp <= 0)
|
|
return [];
|
|
const ret = [linkedMoves[0].id, linkedMoves[1].id];
|
|
if (ignoreDisabled)
|
|
return ret;
|
|
if (!this.ateBerry && ret.includes("belch"))
|
|
return [];
|
|
if (this.hasItem("assaultvest") && (this.battle.dex.moves.get(ret[0]).category === "Status" || this.battle.dex.moves.get(ret[1]).category === "Status")) {
|
|
return [];
|
|
}
|
|
return ret;
|
|
},
|
|
hasLinkedMove(moveid) {
|
|
const linkedMoves = this.getLinkedMoves(true);
|
|
if (!linkedMoves.length)
|
|
return false;
|
|
return linkedMoves.some((x) => x === moveid);
|
|
}
|
|
}
|
|
};
|
|
//# sourceMappingURL=scripts.js.map
|