"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, {
          sourceEffect: action.sourceEffect,
          zMove: action.zmove,
          maxMove: action.maxMove,
          originalTarget: 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 "runSwitch":
        this.actions.runSwitch(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.fieldEvent("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, options) {
      pokemon.activeMoveActions++;
      const zMove = options?.zMove;
      const maxMove = options?.maxMove;
      const externalMove = options?.externalMove;
      const originalTarget = options?.originalTarget;
      let sourceEffect = options?.sourceEffect;
      let target = this.battle.getTarget(pokemon, maxMove || zMove || moveOrMoveName, targetLoc, originalTarget);
      let baseMove = this.dex.getActiveMove(moveOrMoveName);
      const priority = baseMove.priority;
      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);
          baseMove.priority = priority;
          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.abilityState.effectOrder - a.abilityState.effectOrder);
        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),
            { sourceEffect: this.dex.abilities.get("dancer"), externalMove: 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, (deprecated)
          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