diff --git a/include/battle.h b/include/battle.h index bc6031665..45534126e 100644 --- a/include/battle.h +++ b/include/battle.h @@ -542,6 +542,7 @@ struct BattleStruct u16 hpBefore[MAX_BATTLERS_COUNT]; // Hp of battlers before using a move. For Berserk bool8 spriteIgnore0Hp; struct Illusion illusion[MAX_BATTLERS_COUNT]; + s8 aiFinalScore[MAX_BATTLERS_COUNT][MAX_BATTLERS_COUNT][MAX_MON_MOVES]; // AI, target, moves to make debugging easier }; #define GET_MOVE_TYPE(move, typeArg) \ diff --git a/include/battle_ai_script_commands.h b/include/battle_ai_script_commands.h index 9f6654a46..ef927f88b 100644 --- a/include/battle_ai_script_commands.h +++ b/include/battle_ai_script_commands.h @@ -15,6 +15,7 @@ void BattleAI_SetupFlags(void); void BattleAI_SetupAIData(u8 defaultScoreMoves); u8 BattleAI_ChooseMoveOrAction(void); bool32 IsTruantMonVulnerable(u32 battlerAI, u32 opposingBattler); +bool32 IsBattlerAIControlled(u32 battlerId); void ClearBattlerMoveHistory(u8 battlerId); void RecordAbilityBattle(u8 battlerId, u8 abilityId); void ClearBattlerAbilityHistory(u8 battlerId); diff --git a/src/battle_ai_script_commands.c b/src/battle_ai_script_commands.c index 3cc1566a0..1c8fb6b0d 100644 --- a/src/battle_ai_script_commands.c +++ b/src/battle_ai_script_commands.c @@ -429,7 +429,7 @@ void BattleAI_SetupAIData(u8 defaultScoreMoves) u8 BattleAI_ChooseMoveOrAction(void) { - u16 savedCurrentMove = gCurrentMove; + u32 savedCurrentMove = gCurrentMove; u8 ret; if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) @@ -470,7 +470,7 @@ static u8 ChooseMoveOrAction_Singles(void) { u8 currentMoveArray[MAX_MON_MOVES]; u8 consideredMoveArray[MAX_MON_MOVES]; - u8 numOfBestMoves; + u32 numOfBestMoves; s32 i, id; u32 flags = AI_THINKING_STRUCT->aiFlags; @@ -488,6 +488,9 @@ static u8 ChooseMoveOrAction_Singles(void) AI_THINKING_STRUCT->movesetIndex = 0; } + for (i = 0; i < MAX_MON_MOVES; i++) + gBattleStruct->aiFinalScore[sBattler_AI][gBattlerTarget][i] = AI_THINKING_STRUCT->score[i]; + // Check special AI actions. if (AI_THINKING_STRUCT->aiAction & AI_ACTION_FLEE) return AI_CHOICE_FLEE; @@ -649,6 +652,9 @@ static u8 ChooseMoveOrAction_Doubles(void) mostViableMovesScores[0] = mostViableMovesScores[0]; // Needed to match. } } + + for (j = 0; j < MAX_MON_MOVES; j++) + gBattleStruct->aiFinalScore[sBattler_AI][gBattlerTarget][j] = AI_THINKING_STRUCT->score[j]; } } @@ -738,7 +744,7 @@ static void RecordLastUsedMoveByTarget(void) } } -static bool32 IsBattlerAIControlled(u32 battlerId) +bool32 IsBattlerAIControlled(u32 battlerId) { switch (GetBattlerPosition(battlerId)) { @@ -748,10 +754,7 @@ static bool32 IsBattlerAIControlled(u32 battlerId) case B_POSITION_OPPONENT_LEFT: return TRUE; case B_POSITION_PLAYER_RIGHT: - if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) - return FALSE; - else - return TRUE; + return ((gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) != 0); case B_POSITION_OPPONENT_RIGHT: return TRUE; } diff --git a/src/battle_debug.c b/src/battle_debug.c index fa88e5708..4b86b9963 100644 --- a/src/battle_debug.c +++ b/src/battle_debug.c @@ -7,6 +7,7 @@ #include "menu_helpers.h" #include "scanline_effect.h" #include "palette.h" +#include "pokemon_icon.h" #include "sprite.h" #include "item.h" #include "task.h" @@ -17,7 +18,10 @@ #include "text_window.h" #include "international_string_util.h" #include "strings.h" +#include "battle_ai_script_commands.h" #include "list_menu.h" +#include "decompress.h" +#include "trainer_pokemon_sprites.h" #include "malloc.h" #include "string_util.h" #include "util.h" @@ -65,6 +69,12 @@ struct BattleDebugMenu struct BattleDebugModifyArrows modifyArrows; const struct BitfieldInfo *bitfield; bool8 battlerWasChanged[MAX_BATTLERS_COUNT]; + + u8 aiBattlerId; + u8 aiViewState; + u8 aiIconSpriteIds[MAX_BATTLERS_COUNT]; + u8 aiMonSpriteId; + u8 aiMovesWindowId; }; struct __attribute__((__packed__)) BitfieldInfo @@ -521,8 +531,8 @@ static const struct BgTemplate sBgTemplates[] = }, { .bg = 1, - .charBaseIndex = 2, - .mapBaseIndex = 29, + .charBaseIndex = 10, + .mapBaseIndex = 20, .screenSize = 0, .paletteMode = 0, .priority = 0, @@ -571,6 +581,7 @@ static void UpdateBattlerValue(struct BattleDebugMenu *data); static void UpdateMonData(struct BattleDebugMenu *data); static u8 *GetSideStatusValue(struct BattleDebugMenu *data, bool32 changeStatus, bool32 statusTrue); static bool32 TryMoveDigit(struct BattleDebugModifyArrows *modArrows, bool32 moveUp); +static void SwitchToDebugView(u8 taskId); // code static struct BattleDebugMenu *GetStructPtr(u8 taskId) @@ -673,6 +684,121 @@ void CB2_BattleDebugMenu(void) } } +static void PutMovesPointsText(struct BattleDebugMenu *data) +{ + u32 i, j, count; + u8 *text = malloc(0x50); + + FillWindowPixelBuffer(data->aiMovesWindowId, 0x11); + for (i = 0; i < MAX_MON_MOVES; i++) + { + text[0] = CHAR_SPACE; + StringCopy(text + 1, gMoveNames[gBattleMons[data->aiBattlerId].moves[i]]); + AddTextPrinterParameterized(data->aiMovesWindowId, 1, text, 0, i * 15, 0, NULL); + for (count = 0, j = 0; j < MAX_BATTLERS_COUNT; j++) + { + if (data->aiIconSpriteIds[j] == 0xFF) + continue; + ConvertIntToDecimalStringN(text, + gBattleStruct->aiFinalScore[data->aiBattlerId][gSprites[data->aiIconSpriteIds[j]].data[0]][i], + STR_CONV_MODE_RIGHT_ALIGN, 3); + AddTextPrinterParameterized(data->aiMovesWindowId, 1, text, 83 + count * 54, i * 15, 0, NULL); + count++; + } + } + + CopyWindowToVram(data->aiMovesWindowId, 3); + free(text); +} + +static void Task_ShowAiPoints(u8 taskId) +{ + u32 i, count; + struct WindowTemplate winTemplate; + struct BattleDebugMenu *data = GetStructPtr(taskId); + + switch (data->aiViewState) + { + case 0: + HideBg(0); + ShowBg(1); + + // Swap battler if it's player mon + data->aiBattlerId = data->battlerId; + while (!IsBattlerAIControlled(data->aiBattlerId)) + { + if (++data->aiBattlerId >= gBattlersCount) + data->aiBattlerId = 0; + } + + LoadMonIconPalettes(); + for (count = 0, i = 0; i < MAX_BATTLERS_COUNT; i++) + { + if (i != data->aiBattlerId && IsBattlerAlive(i)) + { + data->aiIconSpriteIds[i] = CreateMonIcon(gBattleMons[i].species, + SpriteCallbackDummy, + 95 + (count * 60), 17, 0, 0, FALSE); + gSprites[data->aiIconSpriteIds[i]].data[0] = i; // battler id + count++; + } + else + { + data->aiIconSpriteIds[i] = 0xFF; + } + } + data->aiMonSpriteId = CreateMonPicSprite_HandleDeoxys(gBattleMons[data->aiBattlerId].species, + gBattleMons[data->aiBattlerId].otId, + gBattleMons[data->aiBattlerId].personality, + TRUE, + 39, 130, 15, 0xFFFF); + data->aiViewState++; + break; + // Put text + case 1: + winTemplate = CreateWindowTemplate(1, 0, 4, 27, 14, 15, 0x200); + data->aiMovesWindowId = AddWindow(&winTemplate); + PutWindowTilemap(data->aiMovesWindowId); + PutMovesPointsText(data); + + data->aiViewState++; + break; + // Input + case 2: + if (gMain.newKeys & (SELECT_BUTTON | B_BUTTON)) + { + SwitchToDebugView(taskId); + HideBg(1); + ShowBg(0); + return; + } + break; + } +} + +static void SwitchToAiPointsView(u8 taskId) +{ + gTasks[taskId].func = Task_ShowAiPoints; + GetStructPtr(taskId)->aiViewState = 0; +} + +static void SwitchToDebugView(u8 taskId) +{ + u32 i; + struct BattleDebugMenu *data = GetStructPtr(taskId); + + FreeMonIconPalettes(); + for (i = 0; i < MAX_BATTLERS_COUNT; i++) + { + if (data->aiIconSpriteIds[i] != 0xFF) + FreeAndDestroyMonIconSprite(&gSprites[data->aiIconSpriteIds[i]]); + } + FreeAndDestroyMonPicSprite(data->aiMonSpriteId); + RemoveWindow(data->aiMovesWindowId); + + gTasks[taskId].func = Task_DebugMenuProcessInput; +} + static void Task_DebugMenuFadeIn(u8 taskId) { if (!gPaletteFade.active) @@ -712,6 +838,11 @@ static void Task_DebugMenuProcessInput(u8 taskId) listItemId = ListMenu_ProcessInput(data->mainListTaskId); if (listItemId != LIST_CANCEL && listItemId != LIST_NOTHING_CHOSEN && listItemId < LIST_ITEM_COUNT) { + if (listItemId == LIST_ITEM_AI_MOVES_PTS && gMain.newKeys & A_BUTTON) + { + SwitchToAiPointsView(taskId); + return; + } data->currentMainListItemId = listItemId; // Create the secondary menu list. @@ -906,8 +1037,7 @@ static void CreateSecondaryListMenu(struct BattleDebugMenu *data) itemsCount = ARRAY_COUNT(sSideStatusListItems); break; case LIST_ITEM_AI_MOVES_PTS: - itemsCount = 4; - break; + return; } data->secondaryListItemCount = itemsCount; @@ -966,7 +1096,6 @@ static void PrintSecondaryEntries(struct BattleDebugMenu *data) { case LIST_ITEM_MOVES: case LIST_ITEM_PP: - case LIST_ITEM_AI_MOVES_PTS: for (i = 0; i < 4; i++) { PadString(gMoveNames[gBattleMons[data->battlerId].moves[i]], text); @@ -1338,14 +1467,6 @@ static void SetUpModifyArrows(struct BattleDebugMenu *data) data->modifyArrows.typeOfVal = VAL_U8; data->modifyArrows.currValue = gBattleMons[data->battlerId].pp[data->currentSecondaryListItemId]; break; - case LIST_ITEM_AI_MOVES_PTS: - data->modifyArrows.minValue = 0; - data->modifyArrows.maxValue = 255; - data->modifyArrows.maxDigits = 3; - data->modifyArrows.modifiedValPtr = gBattleResources->ai->score; - data->modifyArrows.typeOfVal = VAL_S8; - data->modifyArrows.currValue = gBattleResources->ai->score[data->currentSecondaryListItemId]; - break; case LIST_ITEM_HELD_ITEM: data->modifyArrows.minValue = 0; data->modifyArrows.maxValue = ITEMS_COUNT - 1; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 5b0193382..f292d16d9 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -10741,7 +10741,7 @@ static void Cmd_tryswapabilities(void) // skill swap return; } - if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)) + if (gMoveResultFlags & MOVE_RESULT_NO_EFFECT) { gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); }