diff --git a/src/battle-scene.ts b/src/battle-scene.ts
index 66b966270fd..dec6abb4f30 100644
--- a/src/battle-scene.ts
+++ b/src/battle-scene.ts
@@ -16,7 +16,7 @@ import { TextStyle, addTextObject, getTextColor } from "./ui/text";
 import { allMoves } from "./data/move";
 import { ModifierPoolType, getDefaultModifierTypeForTier, getEnemyModifierTypesForWave, getLuckString, getLuckTextTint, getModifierPoolForType, getModifierType, getPartyLuckValue, modifierTypes } from "./modifier/modifier-type";
 import AbilityBar from "./ui/ability-bar";
-import { BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, IncrementMovePriorityAbAttr, PostBattleInitAbAttr, applyAbAttrs, applyPostBattleInitAbAttrs } from "./data/ability";
+import { BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, ChangeMovePriorityAbAttr, PostBattleInitAbAttr, applyAbAttrs, applyPostBattleInitAbAttrs } from "./data/ability";
 import { allAbilities } from "./data/ability";
 import Battle, { BattleType, FixedBattleConfig } from "./battle";
 import { GameMode, GameModes, getGameMode } from "./game-mode";
@@ -2121,7 +2121,7 @@ export default class BattleScene extends SceneBase {
 
   pushMovePhase(movePhase: MovePhase, priorityOverride?: integer): void {
     const movePriority = new Utils.IntegerHolder(priorityOverride !== undefined ? priorityOverride : movePhase.move.getMove().priority);
-    applyAbAttrs(IncrementMovePriorityAbAttr, movePhase.pokemon, null, movePhase.move.getMove(), movePriority);
+    applyAbAttrs(ChangeMovePriorityAbAttr, movePhase.pokemon, null, movePhase.move.getMove(), movePriority);
     const lowerPriorityPhase = this.phaseQueue.find(p => p instanceof MovePhase && p.move.getMove().priority < movePriority.value);
     if (lowerPriorityPhase) {
       this.phaseQueue.splice(this.phaseQueue.indexOf(lowerPriorityPhase), 0, movePhase);
diff --git a/src/data/ability.ts b/src/data/ability.ts
index 0605cb7aa20..7e270f4d3f2 100644
--- a/src/data/ability.ts
+++ b/src/data/ability.ts
@@ -525,7 +525,7 @@ export class FieldPriorityMoveImmunityAbAttr extends PreDefendAbAttr {
   applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean {
     const attackPriority = new Utils.IntegerHolder(move.priority);
     applyMoveAttrs(IncrementMovePriorityAttr,attacker,null,move,attackPriority);
-    applyAbAttrs(IncrementMovePriorityAbAttr, attacker, null, move, attackPriority);
+    applyAbAttrs(ChangeMovePriorityAbAttr, attacker, null, move, attackPriority);
 
     if (move.moveTarget===MoveTarget.USER || move.moveTarget===MoveTarget.NEAR_ALLY) {
       return false;
@@ -2682,23 +2682,32 @@ export class BlockOneHitKOAbAttr extends AbAttr {
   }
 }
 
-export class IncrementMovePriorityAbAttr extends AbAttr {
-  private moveIncrementFunc: (pokemon: Pokemon, move: Move) => boolean;
-  private increaseAmount: integer;
+/**
+ * This governs abilities that alter the priority of moves
+ * Abilities: Prankster, Gale Wings, Triage, Mycelium Might, Stall
+ * Note - Quick Claw has a separate and distinct implementation outside of priority
+ */
+export class ChangeMovePriorityAbAttr extends AbAttr {
+  private moveFunc: (pokemon: Pokemon, move: Move) => boolean;
+  private changeAmount: number;
 
-  constructor(moveIncrementFunc: (pokemon: Pokemon, move: Move) => boolean, increaseAmount = 1) {
+  /**
+   * @param {(pokemon, move) => boolean} moveFunc applies priority-change to moves within a provided category
+   * @param {number} changeAmount the amount of priority added or subtracted
+   */
+  constructor(moveFunc: (pokemon: Pokemon, move: Move) => boolean, changeAmount: number) {
     super(true);
 
-    this.moveIncrementFunc = moveIncrementFunc;
-    this.increaseAmount = increaseAmount;
+    this.moveFunc = moveFunc;
+    this.changeAmount = changeAmount;
   }
 
   apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean {
-    if (!this.moveIncrementFunc(pokemon, args[0] as Move)) {
+    if (!this.moveFunc(pokemon, args[0] as Move)) {
       return false;
     }
 
-    (args[1] as Utils.IntegerHolder).value += this.increaseAmount;
+    (args[1] as Utils.IntegerHolder).value += this.changeAmount;
     return true;
   }
 }
@@ -4092,6 +4101,41 @@ export class BypassSpeedChanceAbAttr extends AbAttr {
   }
 }
 
+/**
+ * This attribute checks if a Pokemon's move meets a provided condition to determine if the Pokemon can use Quick Claw
+ * It was created because Pokemon with the ability Mycelium Might cannot access Quick Claw's benefits when using status moves.
+*/
+export class PreventBypassSpeedChanceAbAttr extends AbAttr {
+  private condition: ((pokemon: Pokemon, move: Move) => boolean);
+
+  /**
+   * @param {function} condition - checks if a move meets certain conditions
+   */
+  constructor(condition: (pokemon: Pokemon, move: Move) => boolean) {
+    super(true);
+    this.condition = condition;
+  }
+
+  /**
+   * @argument {boolean} bypassSpeed - determines if a Pokemon is able to bypass speed at the moment
+   * @argument {boolean} canCheckHeldItems - determines if a Pokemon has access to Quick Claw's effects or not
+   */
+  apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean {
+    const bypassSpeed = args[0] as Utils.BooleanHolder;
+    const canCheckHeldItems = args[1] as Utils.BooleanHolder;
+
+    const turnCommand = pokemon.scene.currentBattle.turnCommands[pokemon.getBattlerIndex()];
+    const isCommandFight = turnCommand?.command === Command.FIGHT;
+    const move = turnCommand?.move?.move ? allMoves[turnCommand.move.move] : null;
+    if (this.condition(pokemon, move!) && isCommandFight) {
+      bypassSpeed.value = false;
+      canCheckHeldItems.value = false;
+      return false;
+    }
+    return true;
+  }
+}
+
 async function applyAbAttrsInternal<TAttr extends AbAttr>(
   attrType: Constructor<TAttr>,
   pokemon: Pokemon | null,
@@ -4613,7 +4657,7 @@ export function initAbilities() {
       .attr(AlwaysHitAbAttr)
       .attr(DoubleBattleChanceAbAttr),
     new Ability(Abilities.STALL, 4)
-      .unimplemented(),
+      .attr(ChangeMovePriorityAbAttr, (pokemon, move: Move) => true, -0.5),
     new Ability(Abilities.TECHNICIAN, 4)
       .attr(MovePowerBoostAbAttr, (user, target, move) => {
         const power = new Utils.NumberHolder(move.power);
@@ -4790,7 +4834,7 @@ export function initAbilities() {
       .attr(TypeImmunityStatChangeAbAttr, Type.GRASS, BattleStat.ATK, 1)
       .ignorable(),
     new Ability(Abilities.PRANKSTER, 5)
-      .attr(IncrementMovePriorityAbAttr, (pokemon, move: Move) => move.category === MoveCategory.STATUS),
+      .attr(ChangeMovePriorityAbAttr, (pokemon, move: Move) => move.category === MoveCategory.STATUS, 1),
     new Ability(Abilities.SAND_FORCE, 5)
       .attr(MoveTypePowerBoostAbAttr, Type.ROCK, 1.3)
       .attr(MoveTypePowerBoostAbAttr, Type.GROUND, 1.3)
@@ -4855,7 +4899,7 @@ export function initAbilities() {
       .attr(UnsuppressableAbilityAbAttr)
       .attr(NoFusionAbilityAbAttr),
     new Ability(Abilities.GALE_WINGS, 6)
-      .attr(IncrementMovePriorityAbAttr, (pokemon, move) => pokemon.isFullHp() && move.type === Type.FLYING),
+      .attr(ChangeMovePriorityAbAttr, (pokemon, move) => pokemon.isFullHp() && move.type === Type.FLYING, 1),
     new Ability(Abilities.MEGA_LAUNCHER, 6)
       .attr(MovePowerBoostAbAttr, (user, target, move) => move.hasFlag(MoveFlags.PULSE_MOVE), 1.5),
     new Ability(Abilities.GRASS_PELT, 6)
@@ -4944,7 +4988,7 @@ export function initAbilities() {
     new Ability(Abilities.LIQUID_VOICE, 7)
       .attr(MoveTypeChangeAttr, Type.WATER, 1, (user, target, move) => move.hasFlag(MoveFlags.SOUND_BASED)),
     new Ability(Abilities.TRIAGE, 7)
-      .attr(IncrementMovePriorityAbAttr, (pokemon, move) => move.hasFlag(MoveFlags.TRIAGE_MOVE), 3),
+      .attr(ChangeMovePriorityAbAttr, (pokemon, move) => move.hasFlag(MoveFlags.TRIAGE_MOVE), 3),
     new Ability(Abilities.GALVANIZE, 7)
       .attr(MoveTypeChangeAttr, Type.ELECTRIC, 1.2, (user, target, move) => move.type === Type.NORMAL),
     new Ability(Abilities.SURGE_SURFER, 7)
@@ -5299,8 +5343,9 @@ export function initAbilities() {
       .partial() // Healing not blocked by Heal Block
       .ignorable(),
     new Ability(Abilities.MYCELIUM_MIGHT, 9)
-      .attr(MoveAbilityBypassAbAttr, (pokemon, move: Move) => move.category === MoveCategory.STATUS)
-      .partial(),
+      .attr(ChangeMovePriorityAbAttr, (pokemon, move) => move.category === MoveCategory.STATUS, -0.5)
+      .attr(PreventBypassSpeedChanceAbAttr, (pokemon, move) => move.category === MoveCategory.STATUS)
+      .attr(MoveAbilityBypassAbAttr, (pokemon, move: Move) => move.category === MoveCategory.STATUS),
     new Ability(Abilities.MINDS_EYE, 9)
       .attr(IgnoreTypeImmunityAbAttr, Type.GHOST, [Type.NORMAL, Type.FIGHTING])
       .attr(ProtectStatAbAttr, BattleStat.ACC)
diff --git a/src/data/terrain.ts b/src/data/terrain.ts
index d0b2fb53d3e..e29344ffea2 100644
--- a/src/data/terrain.ts
+++ b/src/data/terrain.ts
@@ -2,7 +2,7 @@ import Pokemon from "../field/pokemon";
 import Move from "./move";
 import { Type } from "./type";
 import * as Utils from "../utils";
-import { IncrementMovePriorityAbAttr, applyAbAttrs } from "./ability";
+import { ChangeMovePriorityAbAttr, applyAbAttrs } from "./ability";
 import { ProtectAttr } from "./move";
 import { BattlerIndex } from "#app/battle.js";
 import i18next from "i18next";
@@ -59,7 +59,7 @@ export class Terrain {
     case TerrainType.PSYCHIC:
       if (!move.hasAttr(ProtectAttr)) {
         const priority = new Utils.IntegerHolder(move.priority);
-        applyAbAttrs(IncrementMovePriorityAbAttr, user, null, move, priority);
+        applyAbAttrs(ChangeMovePriorityAbAttr, user, null, move, priority);
         // Cancels move if the move has positive priority and targets a Pokemon grounded on the Psychic Terrain
         return priority.value > 0 && user.getOpponents().some(o => targets.includes(o.getBattlerIndex()) && o.isGrounded());
       }
diff --git a/src/phases.ts b/src/phases.ts
index 3550b3f599c..5b66ee3e771 100644
--- a/src/phases.ts
+++ b/src/phases.ts
@@ -25,7 +25,7 @@ import { Starter } from "./ui/starter-select-ui-handler";
 import { Gender } from "./data/gender";
 import { Weather, WeatherType, getRandomWeatherType, getTerrainBlockMessage, getWeatherDamageMessage, getWeatherLapseMessage } from "./data/weather";
 import { ArenaTagSide, ArenaTrapTag, MistTag, TrickRoomTag } from "./data/arena-tag";
-import { CheckTrappedAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, BlockRedirectAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, IncrementMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr, IncreasePpAbAttr, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr, PreventBerryUseAbAttr, StatChangeCopyAbAttr, PokemonTypeChangeAbAttr, applyPreAttackAbAttrs, applyPostMoveUsedAbAttrs, PostMoveUsedAbAttr, MaxMultiHitAbAttr, HealFromBerryUseAbAttr, IgnoreMoveEffectsAbAttr, BlockStatusDamageAbAttr, BypassSpeedChanceAbAttr, AddSecondStrikeAbAttr } from "./data/ability";
+import { CheckTrappedAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, BlockRedirectAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, ChangeMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, PreventBypassSpeedChanceAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr, IncreasePpAbAttr, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr, PreventBerryUseAbAttr, StatChangeCopyAbAttr, PokemonTypeChangeAbAttr, applyPreAttackAbAttrs, applyPostMoveUsedAbAttrs, PostMoveUsedAbAttr, MaxMultiHitAbAttr, HealFromBerryUseAbAttr, IgnoreMoveEffectsAbAttr, BlockStatusDamageAbAttr, BypassSpeedChanceAbAttr, AddSecondStrikeAbAttr } from "./data/ability";
 import { Unlockables, getUnlockableName } from "./system/unlockables";
 import { getBiomeKey } from "./field/arena";
 import { BattleType, BattlerIndex, TurnCommand } from "./battle";
@@ -2315,8 +2315,12 @@ export class TurnStartPhase extends FieldPhase {
 
     this.scene.getField(true).filter(p => p.summonData).map(p => {
       const bypassSpeed = new Utils.BooleanHolder(false);
+      const canCheckHeldItems = new Utils.BooleanHolder(true);
       applyAbAttrs(BypassSpeedChanceAbAttr, p, null, bypassSpeed);
-      this.scene.applyModifiers(BypassSpeedChanceModifier, p.isPlayer(), p, bypassSpeed);
+      applyAbAttrs(PreventBypassSpeedChanceAbAttr, p, null, bypassSpeed, canCheckHeldItems);
+      if (canCheckHeldItems.value) {
+        this.scene.applyModifiers(BypassSpeedChanceModifier, p.isPlayer(), p, bypassSpeed);
+      }
       battlerBypassSpeed[p.getBattlerIndex()] = bypassSpeed;
     });
 
@@ -2342,10 +2346,15 @@ export class TurnStartPhase extends FieldPhase {
         applyMoveAttrs(IncrementMovePriorityAttr, this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === a)!, null, aMove, aPriority); //TODO: is the bang correct here?
         applyMoveAttrs(IncrementMovePriorityAttr, this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === b)!, null, bMove, bPriority); //TODO: is the bang correct here?
 
-        applyAbAttrs(IncrementMovePriorityAbAttr, this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === a)!, null, aMove, aPriority); //TODO: is the bang correct here?
-        applyAbAttrs(IncrementMovePriorityAbAttr, this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === b)!, null, bMove, bPriority); //TODO: is the bang correct here?
+        applyAbAttrs(ChangeMovePriorityAbAttr, this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === a)!, null, aMove, aPriority); //TODO: is the bang correct here?
+        applyAbAttrs(ChangeMovePriorityAbAttr, this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === b)!, null, bMove, bPriority); //TODO: is the bang correct here?
 
         if (aPriority.value !== bPriority.value) {
+          const bracketDifference = Math.ceil(aPriority.value) - Math.ceil(bPriority.value);
+          const hasSpeedDifference = battlerBypassSpeed[a].value !== battlerBypassSpeed[b].value;
+          if (bracketDifference === 0 && hasSpeedDifference) {
+            return battlerBypassSpeed[a].value ? -1 : 1;
+          }
           return aPriority.value < bPriority.value ? 1 : -1;
         }
       }
diff --git a/src/test/abilities/mycelium_might.test.ts b/src/test/abilities/mycelium_might.test.ts
new file mode 100644
index 00000000000..d519eb67626
--- /dev/null
+++ b/src/test/abilities/mycelium_might.test.ts
@@ -0,0 +1,105 @@
+import { MovePhase, TurnEndPhase } from "#app/phases";
+import GameManager from "#test/utils/gameManager";
+import { getMovePosition } from "#test/utils/gameManagerUtils";
+import { Abilities } from "#enums/abilities";
+import { BattleStat } from "#app/data/battle-stat";
+import { Moves } from "#enums/moves";
+import { Species } from "#enums/species";
+import Phaser from "phaser";
+import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
+
+
+describe("Abilities - Mycelium Might", () => {
+  let phaserGame: Phaser.Game;
+  let game: GameManager;
+
+  beforeAll(() => {
+    phaserGame = new Phaser.Game({
+      type: Phaser.HEADLESS,
+    });
+  });
+
+  afterEach(() => {
+    game.phaseInterceptor.restoreOg();
+  });
+
+  beforeEach(() => {
+    game = new GameManager(phaserGame);
+    game.override.battleType("single");
+    game.override.disableCrits();
+    game.override.enemySpecies(Species.SHUCKLE);
+    game.override.enemyAbility(Abilities.CLEAR_BODY);
+    game.override.enemyMoveset([Moves.QUICK_ATTACK, Moves.QUICK_ATTACK, Moves.QUICK_ATTACK, Moves.QUICK_ATTACK]);
+    game.override.ability(Abilities.MYCELIUM_MIGHT);
+    game.override.moveset([Moves.QUICK_ATTACK, Moves.BABY_DOLL_EYES]);
+  });
+
+  /**
+   * Bulbapedia References:
+   * https://bulbapedia.bulbagarden.net/wiki/Mycelium_Might_(Ability)
+   * https://bulbapedia.bulbagarden.net/wiki/Priority
+   * https://www.smogon.com/forums/threads/scarlet-violet-battle-mechanics-research.3709545/page-24
+   **/
+
+  it("If a Pokemon with Mycelium Might uses a status move, it will always move last but the status move will ignore protective abilities", async() => {
+    await game.startBattle([ Species.REGIELEKI ]);
+
+    const leadIndex = game.scene.getPlayerPokemon()!.getBattlerIndex();
+    const enemyPokemon = game.scene.getEnemyPokemon();
+    const enemyIndex = enemyPokemon?.getBattlerIndex();
+
+    game.doAttack(getMovePosition(game.scene, 0, Moves.BABY_DOLL_EYES));
+
+    await game.phaseInterceptor.to(MovePhase, false);
+    // The opponent Pokemon (without Mycelium Might) goes first despite having lower speed than the player Pokemon.
+    expect((game.scene.getCurrentPhase() as MovePhase).pokemon.getBattlerIndex()).toBe(enemyIndex);
+
+    await game.phaseInterceptor.run(MovePhase);
+    await game.phaseInterceptor.to(MovePhase, false);
+
+    // The player Pokemon (with Mycelium Might) goes last despite having higher speed than the opponent.
+    expect((game.scene.getCurrentPhase() as MovePhase).pokemon.getBattlerIndex()).toBe(leadIndex);
+    await game.phaseInterceptor.to(TurnEndPhase);
+    expect(enemyPokemon?.summonData.battleStats[BattleStat.ATK]).toBe(-1);
+  }, 20000);
+
+  it("Pokemon with Mycelium Might will go first if a status move that is in a higher priority bracket than the opponent's move is used", async() => {
+    game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]);
+    await game.startBattle([ Species.REGIELEKI ]);
+
+    const leadIndex = game.scene.getPlayerPokemon()!.getBattlerIndex();
+    const enemyPokemon = game.scene.getEnemyPokemon();
+    const enemyIndex = enemyPokemon?.getBattlerIndex();
+
+    game.doAttack(getMovePosition(game.scene, 0, Moves.BABY_DOLL_EYES));
+
+    await game.phaseInterceptor.to(MovePhase, false);
+    // The player Pokemon (with M.M.) goes first because its move is still within a higher priority bracket than its opponent.
+    expect((game.scene.getCurrentPhase() as MovePhase).pokemon.getBattlerIndex()).toBe(leadIndex);
+
+    await game.phaseInterceptor.run(MovePhase);
+    await game.phaseInterceptor.to(MovePhase, false);
+    // The enemy Pokemon goes second because its move is in a lower priority bracket.
+    expect((game.scene.getCurrentPhase() as MovePhase).pokemon.getBattlerIndex()).toBe(enemyIndex);
+    await game.phaseInterceptor.to(TurnEndPhase);
+    expect(enemyPokemon?.summonData.battleStats[BattleStat.ATK]).toBe(-1);
+  }, 20000);
+
+  it("Order is established normally if the Pokemon uses a non-status move", async() => {
+    await game.startBattle([ Species.REGIELEKI ]);
+
+    const leadIndex = game.scene.getPlayerPokemon()!.getBattlerIndex();
+    const enemyIndex = game.scene.getEnemyPokemon()!.getBattlerIndex();
+
+    game.doAttack(getMovePosition(game.scene, 0, Moves.QUICK_ATTACK));
+
+    await game.phaseInterceptor.to(MovePhase, false);
+    // The player Pokemon (with M.M.) goes first because it has a higher speed and did not use a status move.
+    expect((game.scene.getCurrentPhase() as MovePhase).pokemon.getBattlerIndex()).toBe(leadIndex);
+
+    await game.phaseInterceptor.run(MovePhase);
+    await game.phaseInterceptor.to(MovePhase, false);
+    // The enemy Pokemon (without M.M.) goes second because its speed is lower.
+    expect((game.scene.getCurrentPhase() as MovePhase).pokemon.getBattlerIndex()).toBe(enemyIndex);
+  }, 20000);
+});
diff --git a/src/test/abilities/stall.test.ts b/src/test/abilities/stall.test.ts
new file mode 100644
index 00000000000..44519064300
--- /dev/null
+++ b/src/test/abilities/stall.test.ts
@@ -0,0 +1,95 @@
+import { MovePhase } from "#app/phases";
+import GameManager from "#test/utils/gameManager";
+import { getMovePosition } from "#test/utils/gameManagerUtils";
+import { Abilities } from "#enums/abilities";
+import { Moves } from "#enums/moves";
+import { Species } from "#enums/species";
+import Phaser from "phaser";
+import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
+
+
+describe("Abilities - Stall", () => {
+  let phaserGame: Phaser.Game;
+  let game: GameManager;
+
+  beforeAll(() => {
+    phaserGame = new Phaser.Game({
+      type: Phaser.HEADLESS,
+    });
+  });
+
+  afterEach(() => {
+    game.phaseInterceptor.restoreOg();
+  });
+
+  beforeEach(() => {
+    game = new GameManager(phaserGame);
+    game.override.battleType("single");
+    game.override.disableCrits();
+    game.override.enemySpecies(Species.REGIELEKI);
+    game.override.enemyAbility(Abilities.STALL);
+    game.override.enemyMoveset([Moves.QUICK_ATTACK, Moves.QUICK_ATTACK, Moves.QUICK_ATTACK, Moves.QUICK_ATTACK]);
+    game.override.moveset([Moves.QUICK_ATTACK, Moves.TACKLE]);
+  });
+
+  /**
+   * Bulbapedia References:
+   * https://bulbapedia.bulbagarden.net/wiki/Stall_(Ability)
+   * https://bulbapedia.bulbagarden.net/wiki/Priority
+   **/
+
+  it("Pokemon with Stall should move last in its priority bracket regardless of speed", async() => {
+    await game.startBattle([ Species.SHUCKLE ]);
+
+    const leadIndex = game.scene.getPlayerPokemon()!.getBattlerIndex();
+    const enemyIndex = game.scene.getEnemyPokemon()!.getBattlerIndex();
+
+    game.doAttack(getMovePosition(game.scene, 0, Moves.QUICK_ATTACK));
+
+    await game.phaseInterceptor.to(MovePhase, false);
+    // The player Pokemon (without Stall) goes first despite having lower speed than the opponent.
+    expect((game.scene.getCurrentPhase() as MovePhase).pokemon.getBattlerIndex()).toBe(leadIndex);
+
+    await game.phaseInterceptor.run(MovePhase);
+    await game.phaseInterceptor.to(MovePhase, false);
+    // The opponent Pokemon (with Stall) goes last despite having higher speed than the player Pokemon.
+    expect((game.scene.getCurrentPhase() as MovePhase).pokemon.getBattlerIndex()).toBe(enemyIndex);
+  }, 20000);
+
+  it("Pokemon with Stall will go first if a move that is in a higher priority bracket than the opponent's move is used", async() => {
+    await game.startBattle([ Species.SHUCKLE ]);
+
+    const leadIndex = game.scene.getPlayerPokemon()!.getBattlerIndex();
+    const enemyIndex = game.scene.getEnemyPokemon()!.getBattlerIndex();
+
+    game.doAttack(getMovePosition(game.scene, 0, Moves.TACKLE));
+
+    await game.phaseInterceptor.to(MovePhase, false);
+    // The opponent Pokemon (with Stall) goes first because its move is still within a higher priority bracket than its opponent.
+    expect((game.scene.getCurrentPhase() as MovePhase).pokemon.getBattlerIndex()).toBe(enemyIndex);
+
+    await game.phaseInterceptor.run(MovePhase);
+    await game.phaseInterceptor.to(MovePhase, false);
+    // The player Pokemon goes second because its move is in a lower priority bracket.
+    expect((game.scene.getCurrentPhase() as MovePhase).pokemon.getBattlerIndex()).toBe(leadIndex);
+  }, 20000);
+
+  it("If both Pokemon have stall and use the same move, speed is used to determine who goes first.", async() => {
+    game.override.ability(Abilities.STALL);
+    await game.startBattle([ Species.SHUCKLE ]);
+
+    const leadIndex = game.scene.getPlayerPokemon()!.getBattlerIndex();
+    const enemyIndex = game.scene.getEnemyPokemon()!.getBattlerIndex();
+
+    game.doAttack(getMovePosition(game.scene, 0, Moves.TACKLE));
+
+    await game.phaseInterceptor.to(MovePhase, false);
+    // The opponent Pokemon (with Stall) goes first because it has a higher speed.
+    expect((game.scene.getCurrentPhase() as MovePhase).pokemon.getBattlerIndex()).toBe(enemyIndex);
+
+    await game.phaseInterceptor.run(MovePhase);
+    await game.phaseInterceptor.to(MovePhase, false);
+    // The player Pokemon (with Stall) goes second because its speed is lower.
+    expect((game.scene.getCurrentPhase() as MovePhase).pokemon.getBattlerIndex()).toBe(leadIndex);
+  }, 20000);
+});