public void ForceTurn(RbyTurn playerTurn, RbyTurn enemyTurn = null, bool speedTieWin = true) { bool useItem = Items[playerTurn.Move] != null; if (useItem) { if (playerTurn.Target != null) { UseItem(playerTurn.Move, playerTurn.Target, playerTurn.Target2); } else { UseItem(playerTurn.Move, playerTurn.Flags); } } else if ((playerTurn.Flags & Switch) != 0) { BattleMenu(1, 0); ChooseMenuItem(FindPokemon(playerTurn.Move)); ChooseMenuItem(0); } else if (EnemyMon.UsingTrappingMove) { if (CpuRead("wTopMenuItemX") != 0x9 || CpuRead("wCurrentMenuItem") != 0) { MenuPress(Joypad.Left | Joypad.Up); } } else if (!BattleMon.ThrashingAbout && !BattleMon.Invulnerable) { if (CurrentMenuType != MenuType.Fight) { BattleMenu(0, 0); } int moveIndex = FindBattleMove(playerTurn.Move); // Reusing 'ChooseMenuItem' code, because the final AdvanceFrame advances past 'SelectEnemyMove.done', // and I don't have a good solution for this problem right now. RunUntil("_Joypad", "HandleMenuInput_.getJoypadState"); var scroll = CalcScroll(moveIndex, CpuRead("wCurrentMenuItem"), CpuRead("wNumMovesMinusOne"), true); for (int i = 0; i < scroll.Amount; i++) { MenuPress(scroll.Input); } if ((CpuRead("hJoyLast") & (byte)Joypad.A) != 0) { Press(Joypad.None); } Inject(Joypad.A); } if (!(EnemyMon.StoringEnergy | EnemyMon.ChargingUp | EnemyMon.UsingRage | EnemyMon.Frozen | EnemyMon.UsingTrappingMove)) { Hold(Joypad.A, SYM["SelectEnemyMove.done"]); A = enemyTurn != null && enemyTurn.Move != "" ? Moves[enemyTurn.Move].Id : 0; } bool playerFirst; int speedtie = Hold(Joypad.A, SYM["MainInBattleLoop.speedEqual"] + 9, SYM["MainInBattleLoop.enemyMovesFirst"], SYM["MainInBattleLoop.playerMovesFirst"]); if (speedtie == SYM["MainInBattleLoop.enemyMovesFirst"]) { playerFirst = false; } else if (speedtie == SYM["MainInBattleLoop.playerMovesFirst"]) { playerFirst = true; } else { A = speedTieWin ? 0x00 : 0xff; playerFirst = speedTieWin; } if (playerFirst) { if (!useItem) { ForceTurnInternal(playerTurn); } else { RunUntil(SYM["MainInBattleLoop.playerMovesFirst"] + 6); } if (enemyTurn != null) { ForceTurnInternal(enemyTurn); } } else { Debug.Assert(enemyTurn != null, "No enemy turn was specified even though the opponent moved first!"); ForceTurnInternal(enemyTurn); if (!useItem) { ForceTurnInternal(playerTurn); } } CurrentMenuType = MenuType.None; // Semi-terrible code to get around thrash. TODO: fix if (BattleMon.ThrashingAbout) { if (EnemyMon.HP == 0) { if (EnemyParty.Where(mon => mon.HP > 0).Count() > 1) { ClearTextUntil(Joypad.None, SYM["PlayCry"]); } else { ClearText(); } } } else if (!BattleMon.Invulnerable) { ClearText(); } }