From 8d5ba6c6d16d5d5868c7016de21bb954f5e7dcc4 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Wed, 9 Aug 2023 09:15:42 +0200 Subject: [PATCH 1/7] allow ai vs ai battles --- asm/macros/event.inc | 7 +++++++ include/config/battle.h | 1 + src/battle_ai_util.c | 3 +++ src/battle_controllers.c | 13 +++++++++++-- src/battle_main.c | 12 +++++++++--- 5 files changed, 31 insertions(+), 5 deletions(-) diff --git a/asm/macros/event.inc b/asm/macros/event.inc index 78d3037ae..7ca1c3d96 100644 --- a/asm/macros/event.inc +++ b/asm/macros/event.inc @@ -2018,3 +2018,10 @@ setvar VAR_0x8002, \tryMultiple special TrySpecialOverworldEvo .endm + + .macro ai_vs_ai_battle trainer1:req, trainer2:req + setflag B_FLAG_AI_VS_AI_BATTLE + setvar VAR_0x8004, trainer1 + callnative CreateTrainerPartyForPlayer + trainerbattle_no_intro trainer2, NULL + .endm diff --git a/include/config/battle.h b/include/config/battle.h index 68cab28b6..3a173138b 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -156,6 +156,7 @@ #define B_SMART_WILD_AI_FLAG 0 // If not 0, you can set this flag in a script to enable smart wild pokemon #define B_FLAG_NO_BAG_USE 0 // If this flag is set, the ability to use the bag in battle is disabled. #define B_FLAG_NO_CATCHING 0 // If this flag is set, the ability to catch wild Pokémon is disabled. +#define B_FLAG_AI_VS_AI_BATTLE 0 // If this flag is set, the player's mons will be controlled by the ai next battles. // Var Settings // To use the following features in scripting, replace the 0s with the var ID you're assigning it to. diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index b9b0ef0cf..8d35e98ff 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -8,6 +8,7 @@ #include "battle_ai_switch_items.h" #include "battle_factory.h" #include "battle_setup.h" +#include "event_data.h" #include "data.h" #include "item.h" #include "pokemon.h" @@ -445,6 +446,8 @@ bool32 BattlerHasAi(u32 battlerId) switch (GetBattlerPosition(battlerId)) { case B_POSITION_PLAYER_LEFT: + if (FlagGet(B_FLAG_AI_VS_AI_BATTLE)) + return TRUE; default: return FALSE; case B_POSITION_OPPONENT_LEFT: diff --git a/src/battle_controllers.c b/src/battle_controllers.c index d7ca18c6a..8888249f2 100644 --- a/src/battle_controllers.c +++ b/src/battle_controllers.c @@ -6,6 +6,7 @@ #include "battle_message.h" #include "battle_setup.h" #include "cable_club.h" +#include "event_data.h" #include "link.h" #include "link_rfu.h" #include "party_menu.h" @@ -170,6 +171,8 @@ static void InitSinglePlayerBtlControllers(void) gBattlerControllerFuncs[0] = SetControllerToSafari; else if (gBattleTypeFlags & BATTLE_TYPE_WALLY_TUTORIAL) gBattlerControllerFuncs[0] = SetControllerToWally; + else if (FlagGet(B_FLAG_AI_VS_AI_BATTLE)) + gBattlerControllerFuncs[0] = SetControllerToPlayerPartner; else gBattlerControllerFuncs[0] = SetControllerToPlayer; @@ -221,13 +224,19 @@ static void InitSinglePlayerBtlControllers(void) { gBattleMainFunc = BeginBattleIntro; - gBattlerControllerFuncs[0] = SetControllerToPlayer; + if (FlagGet(B_FLAG_AI_VS_AI_BATTLE)) + gBattlerControllerFuncs[0] = SetControllerToPlayerPartner; + else + gBattlerControllerFuncs[0] = SetControllerToPlayer; gBattlerPositions[0] = B_POSITION_PLAYER_LEFT; gBattlerControllerFuncs[1] = SetControllerToOpponent; gBattlerPositions[1] = B_POSITION_OPPONENT_LEFT; - gBattlerControllerFuncs[2] = SetControllerToPlayer; + if (FlagGet(B_FLAG_AI_VS_AI_BATTLE)) + gBattlerControllerFuncs[2] = SetControllerToPlayerPartner; + else + gBattlerControllerFuncs[2] = SetControllerToPlayer; gBattlerPositions[2] = B_POSITION_PLAYER_RIGHT; gBattlerControllerFuncs[3] = SetControllerToOpponent; diff --git a/src/battle_main.c b/src/battle_main.c index ace56189c..17d741ee2 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -565,8 +565,8 @@ static void CB2_InitBattleInternal(void) gBattle_BG3_X = 0; gBattle_BG3_Y = 0; -#if DEBUG_OVERWORLD_MENU == FALSE - +#if DEBUG_OVERWORLD_MENU == FALSE + gBattleTerrain = BattleSetup_GetTerrainId(); #else if (!gIsDebugBattle) @@ -594,7 +594,7 @@ static void CB2_InitBattleInternal(void) else SetMainCallback2(CB2_HandleStartBattle); -#if DEBUG_OVERWORLD_MENU == FALSE +#if DEBUG_OVERWORLD_MENU == FALSE if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED))) { CreateNPCTrainerParty(&gEnemyParty[0], gTrainerBattleOpponent_A, TRUE); @@ -2145,6 +2145,12 @@ static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum, bool8 fir return retVal; } +void CreateTrainerPartyForPlayer(void) +{ + ZeroPlayerPartyMons(); + CreateNPCTrainerPartyFromTrainer(gPlayerParty, &gTrainers[gSpecialVar_0x8004], TRUE, 0); +} + void VBlankCB_Battle(void) { // Change gRngSeed every vblank unless the battle could be recorded. From a0c34813f1d7812800e1be1e31c89e2ec7865e90 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Wed, 9 Aug 2023 09:34:41 +0200 Subject: [PATCH 2/7] small fixes --- asm/macros/event.inc | 4 ++-- src/battle_main.c | 3 ++- src/battle_util.c | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/asm/macros/event.inc b/asm/macros/event.inc index 7ca1c3d96..d2d8f8ca6 100644 --- a/asm/macros/event.inc +++ b/asm/macros/event.inc @@ -2021,7 +2021,7 @@ .macro ai_vs_ai_battle trainer1:req, trainer2:req setflag B_FLAG_AI_VS_AI_BATTLE - setvar VAR_0x8004, trainer1 + setvar VAR_0x8004, \trainer1 callnative CreateTrainerPartyForPlayer - trainerbattle_no_intro trainer2, NULL + trainerbattle_no_intro \trainer2, NULL .endm diff --git a/src/battle_main.c b/src/battle_main.c index 17d741ee2..452277bc0 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -2148,7 +2148,8 @@ static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum, bool8 fir void CreateTrainerPartyForPlayer(void) { ZeroPlayerPartyMons(); - CreateNPCTrainerPartyFromTrainer(gPlayerParty, &gTrainers[gSpecialVar_0x8004], TRUE, 0); + gPartnerTrainerId = gSpecialVar_0x8004; + CreateNPCTrainerPartyFromTrainer(gPlayerParty, &gTrainers[gSpecialVar_0x8004], TRUE, BATTLE_TYPE_TRAINER); } void VBlankCB_Battle(void) diff --git a/src/battle_util.c b/src/battle_util.c index 2f200026b..b8e9697e2 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -7949,7 +7949,7 @@ u8 IsMonDisobedient(void) if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK)) return 0; - if (GetBattlerSide(gBattlerAttacker) == B_SIDE_OPPONENT) + if (BattlerHasAi(gBattlerAttacker)) return 0; if (IsBattlerModernFatefulEncounter(gBattlerAttacker)) // only false if illegal Mew or Deoxys From d0fe75b06ad9fc49e6b9afd52a978b401823aaec Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Wed, 9 Aug 2023 09:57:42 +0200 Subject: [PATCH 3/7] fixes --- src/battle_ai_util.c | 5 ++++- src/battle_controller_player_partner.c | 12 ++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 8d35e98ff..b27501c19 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -453,7 +453,10 @@ bool32 BattlerHasAi(u32 battlerId) case B_POSITION_OPPONENT_LEFT: return TRUE; case B_POSITION_PLAYER_RIGHT: - return ((gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) != 0); + if ((gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) || FlagGet(B_FLAG_AI_VS_AI_BATTLE)) + return TRUE; + else + return FALSE; case B_POSITION_OPPONENT_RIGHT: return TRUE; } diff --git a/src/battle_controller_player_partner.c b/src/battle_controller_player_partner.c index 3a4beeca9..996ac15a5 100644 --- a/src/battle_controller_player_partner.c +++ b/src/battle_controller_player_partner.c @@ -11,6 +11,7 @@ #include "battle_z_move.h" #include "bg.h" #include "data.h" +#include "event_data.h" #include "item_use.h" #include "link.h" #include "main.h" @@ -1316,6 +1317,12 @@ static void PlayerPartnerHandleDrawTrainerPic(void) xPos = 90; yPos = (8 - gTrainerBackPicCoords[trainerPicId].size) * 4 + 80; } + else if (FlagGet(B_FLAG_AI_VS_AI_BATTLE)) + { + trainerPicId = gTrainers[gPartnerTrainerId].trainerPic; + xPos = 60; + yPos = (8 - gTrainerFrontPicCoords[trainerPicId].size) * 4 + 80; + } else { trainerPicId = GetFrontierTrainerFrontSpriteId(gPartnerTrainerId); @@ -1823,6 +1830,11 @@ static void PlayerPartnerHandleIntroTrainerBallThrow(void) u8 spriteId = gPartnerSpriteId; LoadCompressedPalette(gTrainerBackPicPaletteTable[spriteId].data, 0x100 + paletteNum * 16, 32); } + else if (FlagGet(B_FLAG_AI_VS_AI_BATTLE)) + { + u8 spriteId = gTrainers[gPartnerTrainerId].trainerPic; + LoadCompressedPalette(gTrainerFrontPicPaletteTable[spriteId].data, OBJ_PLTT_ID(paletteNum), PLTT_SIZE_4BPP); + } else { u8 spriteId = GetFrontierTrainerFrontSpriteId(gPartnerTrainerId); From fec8f14fffb4c20bdf28c711e4f312a15a5d2846 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Wed, 9 Aug 2023 15:57:22 +0200 Subject: [PATCH 4/7] IsAiAiBattle function --- include/battle_ai_util.h | 1 + src/battle_ai_switch_items.c | 3 +++ src/battle_ai_util.c | 9 +++++++-- src/battle_controller_player_partner.c | 5 ++--- src/battle_controllers.c | 8 ++++---- 5 files changed, 17 insertions(+), 9 deletions(-) diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index fd55a99f7..5f077fe0c 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -9,6 +9,7 @@ bool32 AI_RandLessThan(u8 val); void RecordLastUsedMoveByTarget(void); +bool32 IsAiVsAiBattle(void); bool32 BattlerHasAi(u32 battlerId); bool32 IsAiBattlerAware(u32 battlerId); void ClearBattlerMoveHistory(u8 battlerId); diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index d815d3f8b..67f3e2dd8 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -1001,6 +1001,9 @@ static bool8 ShouldUseItem(void) u8 validMons = 0; bool8 shouldUse = FALSE; + if (IsAiVsAiBattle()) + return FALSE; + // If teaming up with player and Pokemon is on the right, or Pokemon is currently held by Sky Drop if ((gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && GetBattlerPosition(gActiveBattler) == B_POSITION_PLAYER_RIGHT) || gStatuses3[gActiveBattler] & STATUS3_SKY_DROPPED) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index b27501c19..6d7b74b3b 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -441,19 +441,24 @@ void RecordLastUsedMoveByTarget(void) RecordKnownMove(gBattlerTarget, gLastMoves[gBattlerTarget]); } +bool32 IsAiVsAiBattle(void) +{ + return (B_FLAG_AI_VS_AI_BATTLE && FlagGet(B_FLAG_AI_VS_AI_BATTLE)); +} + bool32 BattlerHasAi(u32 battlerId) { switch (GetBattlerPosition(battlerId)) { case B_POSITION_PLAYER_LEFT: - if (FlagGet(B_FLAG_AI_VS_AI_BATTLE)) + if (IsAiVsAiBattle()) return TRUE; default: return FALSE; case B_POSITION_OPPONENT_LEFT: return TRUE; case B_POSITION_PLAYER_RIGHT: - if ((gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) || FlagGet(B_FLAG_AI_VS_AI_BATTLE)) + if ((gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) || IsAiVsAiBattle()) return TRUE; else return FALSE; diff --git a/src/battle_controller_player_partner.c b/src/battle_controller_player_partner.c index 996ac15a5..67e475e51 100644 --- a/src/battle_controller_player_partner.c +++ b/src/battle_controller_player_partner.c @@ -11,7 +11,6 @@ #include "battle_z_move.h" #include "bg.h" #include "data.h" -#include "event_data.h" #include "item_use.h" #include "link.h" #include "main.h" @@ -1317,7 +1316,7 @@ static void PlayerPartnerHandleDrawTrainerPic(void) xPos = 90; yPos = (8 - gTrainerBackPicCoords[trainerPicId].size) * 4 + 80; } - else if (FlagGet(B_FLAG_AI_VS_AI_BATTLE)) + else if (IsAiVsAiBattle()) { trainerPicId = gTrainers[gPartnerTrainerId].trainerPic; xPos = 60; @@ -1830,7 +1829,7 @@ static void PlayerPartnerHandleIntroTrainerBallThrow(void) u8 spriteId = gPartnerSpriteId; LoadCompressedPalette(gTrainerBackPicPaletteTable[spriteId].data, 0x100 + paletteNum * 16, 32); } - else if (FlagGet(B_FLAG_AI_VS_AI_BATTLE)) + else if (IsAiVsAiBattle()) { u8 spriteId = gTrainers[gPartnerTrainerId].trainerPic; LoadCompressedPalette(gTrainerFrontPicPaletteTable[spriteId].data, OBJ_PLTT_ID(paletteNum), PLTT_SIZE_4BPP); diff --git a/src/battle_controllers.c b/src/battle_controllers.c index 8888249f2..397dda6d8 100644 --- a/src/battle_controllers.c +++ b/src/battle_controllers.c @@ -1,12 +1,12 @@ #include "global.h" #include "battle.h" #include "battle_ai_main.h" +#include "battle_ai_util.h" #include "battle_anim.h" #include "battle_controllers.h" #include "battle_message.h" #include "battle_setup.h" #include "cable_club.h" -#include "event_data.h" #include "link.h" #include "link_rfu.h" #include "party_menu.h" @@ -171,7 +171,7 @@ static void InitSinglePlayerBtlControllers(void) gBattlerControllerFuncs[0] = SetControllerToSafari; else if (gBattleTypeFlags & BATTLE_TYPE_WALLY_TUTORIAL) gBattlerControllerFuncs[0] = SetControllerToWally; - else if (FlagGet(B_FLAG_AI_VS_AI_BATTLE)) + else if (IsAiVsAiBattle()) gBattlerControllerFuncs[0] = SetControllerToPlayerPartner; else gBattlerControllerFuncs[0] = SetControllerToPlayer; @@ -224,7 +224,7 @@ static void InitSinglePlayerBtlControllers(void) { gBattleMainFunc = BeginBattleIntro; - if (FlagGet(B_FLAG_AI_VS_AI_BATTLE)) + if (IsAiVsAiBattle()) gBattlerControllerFuncs[0] = SetControllerToPlayerPartner; else gBattlerControllerFuncs[0] = SetControllerToPlayer; @@ -233,7 +233,7 @@ static void InitSinglePlayerBtlControllers(void) gBattlerControllerFuncs[1] = SetControllerToOpponent; gBattlerPositions[1] = B_POSITION_OPPONENT_LEFT; - if (FlagGet(B_FLAG_AI_VS_AI_BATTLE)) + if (IsAiVsAiBattle()) gBattlerControllerFuncs[2] = SetControllerToPlayerPartner; else gBattlerControllerFuncs[2] = SetControllerToPlayer; From 5f7819f6972dd46b89afb56d1489c2586c8a617c Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Wed, 9 Aug 2023 16:03:02 +0200 Subject: [PATCH 5/7] no exp for ai mons --- src/battle_script_commands.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index aa5276805..bf37aad90 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -4068,7 +4068,9 @@ static void Cmd_getexp(void) switch (gBattleScripting.getexpState) { case 0: // check if should receive exp at all - if (GetBattlerSide(gBattlerFainted) != B_SIDE_OPPONENT || (gBattleTypeFlags & + if (GetBattlerSide(gBattlerFainted) != B_SIDE_OPPONENT + || IsAiVsAiBattle() + || (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_TRAINER_HILL From 03f82a7a98a0ff1ec4b1d6c883b9ccc2762348ad Mon Sep 17 00:00:00 2001 From: Philipp AUER Date: Thu, 31 Aug 2023 01:16:02 +0200 Subject: [PATCH 6/7] [Makefile] make -fanalyzer optional (#3265) Co-authored-by: sbird --- Makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3787bbe5d..80ee5303d 100644 --- a/Makefile +++ b/Makefile @@ -42,6 +42,7 @@ MAKER_CODE := 01 REVISION := 0 MODERN ?= 0 TEST ?= 0 +ANALYZE ?= 0 ifeq (modern,$(MAKECMDGOALS)) MODERN := 1 @@ -118,7 +119,10 @@ LIBPATH := -L ../../tools/agbcc/lib LIB := $(LIBPATH) -lgcc -lc -L../../libagbsyscall -lagbsyscall else CC1 = $(shell $(PATH_MODERNCC) --print-prog-name=cc1) -quiet -override CFLAGS += -mthumb -mthumb-interwork -O2 -mabi=apcs-gnu -mtune=arm7tdmi -march=armv4t -fno-toplevel-reorder -Wno-pointer-to-int-cast -std=gnu17 -fanalyzer +override CFLAGS += -mthumb -mthumb-interwork -O2 -mabi=apcs-gnu -mtune=arm7tdmi -march=armv4t -fno-toplevel-reorder -Wno-pointer-to-int-cast -std=gnu17 +ifeq ($(ANALYZE),1) +override CFLAGS += -fanalyzer +endif ROM := $(MODERN_ROM_NAME) OBJ_DIR := $(MODERN_OBJ_DIR_NAME) LIBPATH := -L "$(dir $(shell $(PATH_MODERNCC) -mthumb -print-file-name=libgcc.a))" -L "$(dir $(shell $(PATH_MODERNCC) -mthumb -print-file-name=libnosys.a))" -L "$(dir $(shell $(PATH_MODERNCC) -mthumb -print-file-name=libc.a))" From 82c65d37e737dae3e1c7314253ece14664c4f562 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Thu, 31 Aug 2023 03:00:59 -0400 Subject: [PATCH 7/7] Fixed 2v1 handling when debug menu is enabled (#3223) --- src/battle_main.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/src/battle_main.c b/src/battle_main.c index d26fc325f..ecbd0ba83 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -565,13 +565,12 @@ static void CB2_InitBattleInternal(void) gBattle_BG3_X = 0; gBattle_BG3_Y = 0; -#if DEBUG_OVERWORLD_MENU == FALSE - - gBattleTerrain = BattleSetup_GetTerrainId(); -#else +#if DEBUG_OVERWORLD_MENU == TRUE if (!gIsDebugBattle) - gBattleTerrain = BattleSetup_GetTerrainId(); #endif + { + gBattleTerrain = BattleSetup_GetTerrainId(); + } if (gBattleTypeFlags & BATTLE_TYPE_RECORDED) gBattleTerrain = BATTLE_TERRAIN_BUILDING; @@ -594,27 +593,19 @@ static void CB2_InitBattleInternal(void) else SetMainCallback2(CB2_HandleStartBattle); -#if DEBUG_OVERWORLD_MENU == FALSE - if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED))) - { - CreateNPCTrainerParty(&gEnemyParty[0], gTrainerBattleOpponent_A, TRUE); - if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS && !BATTLE_TWO_VS_ONE_OPPONENT) - CreateNPCTrainerParty(&gEnemyParty[PARTY_SIZE / 2], gTrainerBattleOpponent_B, FALSE); - SetWildMonHeldItem(); - CalculateEnemyPartyCount(); - } -#else +#if DEBUG_OVERWORLD_MENU == TRUE if (!gIsDebugBattle) +#endif { if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED))) { CreateNPCTrainerParty(&gEnemyParty[0], gTrainerBattleOpponent_A, TRUE); - if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) + if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS && !BATTLE_TWO_VS_ONE_OPPONENT) CreateNPCTrainerParty(&gEnemyParty[PARTY_SIZE / 2], gTrainerBattleOpponent_B, FALSE); SetWildMonHeldItem(); + CalculateEnemyPartyCount(); } } -#endif gMain.inBattle = TRUE; gSaveBlock2Ptr->frontier.disableRecordBattle = FALSE;