From 4b29ae39ad6830f8aa0e31d1182a991b338bd722 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Tue, 8 Jun 2021 16:40:47 +0200 Subject: [PATCH 01/10] Allow one mon double battles --- include/battle_controllers.h | 1 + src/battle_controller_player.c | 49 +++++++++++++++++++--------------- src/battle_controllers.c | 36 ++++++++++++------------- src/battle_main.c | 15 ++++++++--- src/battle_message.c | 2 +- 5 files changed, 58 insertions(+), 45 deletions(-) diff --git a/include/battle_controllers.h b/include/battle_controllers.h index 1cedf81fa4..71ca640976 100644 --- a/include/battle_controllers.h +++ b/include/battle_controllers.h @@ -185,6 +185,7 @@ extern struct UnusedControllerStruct gUnusedControllerStruct; void HandleLinkBattleSetup(void); void SetUpBattleVarsAndBirchZigzagoon(void); void InitBattleControllers(void); +bool32 IsValidForBattle(struct Pokemon *mon); void TryReceiveLinkBattleData(void); void PrepareBufferDataTransferLink(u8 bufferId, u16 size, u8 *data); diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index 89f73ffc41..59827ca80b 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -1034,20 +1034,25 @@ static void Intro_DelayAndEnd(void) } } +static bool32 TwoIntroMons(u32 battlerId) // Double battle with both player pokemon active. +{ + return (IsDoubleBattle() && IsValidForBattle(&gPlayerParty[gBattlerPartyIndexes[battlerId ^ BIT_FLANK]])); +} + static void Intro_WaitForShinyAnimAndHealthbox(void) { bool8 healthboxAnimDone = FALSE; // Check if healthbox has finished sliding in - if (!IsDoubleBattle() || (IsDoubleBattle() && (gBattleTypeFlags & BATTLE_TYPE_MULTI))) + if (TwoIntroMons(gActiveBattler) && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) { - if (gSprites[gHealthboxSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy) + if (gSprites[gHealthboxSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy + && gSprites[gHealthboxSpriteIds[gActiveBattler ^ BIT_FLANK]].callback == SpriteCallbackDummy) healthboxAnimDone = TRUE; } else { - if (gSprites[gHealthboxSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy - && gSprites[gHealthboxSpriteIds[gActiveBattler ^ BIT_FLANK]].callback == SpriteCallbackDummy) + if (gSprites[gHealthboxSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy) healthboxAnimDone = TRUE; } @@ -1065,7 +1070,7 @@ static void Intro_WaitForShinyAnimAndHealthbox(void) HandleLowHpMusicChange(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], gActiveBattler); - if (IsDoubleBattle()) + if (TwoIntroMons(gActiveBattler)) HandleLowHpMusicChange(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler ^ BIT_FLANK]], gActiveBattler ^ BIT_FLANK); gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].introEndDelay = 3; @@ -1094,7 +1099,7 @@ static void Intro_TryShinyAnimShowHealthbox(void) { if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].healthboxSlideInStarted) { - if (IsDoubleBattle() && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) + if (TwoIntroMons(gActiveBattler) && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) { UpdateHealthboxAttribute(gHealthboxSpriteIds[gActiveBattler ^ BIT_FLANK], &gPlayerParty[gBattlerPartyIndexes[gActiveBattler ^ BIT_FLANK]], HEALTHBOX_ALL); StartHealthboxSlideIn(gActiveBattler ^ BIT_FLANK); @@ -1125,15 +1130,7 @@ static void Intro_TryShinyAnimShowHealthbox(void) } // Wait for battler anims - if (!IsDoubleBattle() || (IsDoubleBattle() && (gBattleTypeFlags & BATTLE_TYPE_MULTI))) - { - if (gSprites[gBattleControllerData[gActiveBattler]].callback == SpriteCallbackDummy - && gSprites[gBattlerSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy) - { - battlerAnimsDone = TRUE; - } - } - else + if (TwoIntroMons(gActiveBattler) && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) { if (gSprites[gBattleControllerData[gActiveBattler]].callback == SpriteCallbackDummy && gSprites[gBattlerSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy @@ -1143,11 +1140,19 @@ static void Intro_TryShinyAnimShowHealthbox(void) battlerAnimsDone = TRUE; } } + else + { + if (gSprites[gBattleControllerData[gActiveBattler]].callback == SpriteCallbackDummy + && gSprites[gBattlerSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy) + { + battlerAnimsDone = TRUE; + } + } // Clean up if (bgmRestored && battlerAnimsDone) { - if (IsDoubleBattle() && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) + if (TwoIntroMons(gActiveBattler) && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) DestroySprite(&gSprites[gBattleControllerData[gActiveBattler ^ BIT_FLANK]]); DestroySprite(&gSprites[gBattleControllerData[gActiveBattler]]); @@ -3114,12 +3119,7 @@ static void Task_StartSendOutAnim(u8 taskId) u8 savedActiveBattler = gActiveBattler; gActiveBattler = gTasks[taskId].tBattlerId; - if (!IsDoubleBattle() || (gBattleTypeFlags & BATTLE_TYPE_MULTI)) - { - gBattleResources->bufferA[gActiveBattler][1] = gBattlerPartyIndexes[gActiveBattler]; - StartSendOutAnim(gActiveBattler, FALSE); - } - else + if (TwoIntroMons(gActiveBattler) && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) { gBattleResources->bufferA[gActiveBattler][1] = gBattlerPartyIndexes[gActiveBattler]; StartSendOutAnim(gActiveBattler, FALSE); @@ -3129,6 +3129,11 @@ static void Task_StartSendOutAnim(u8 taskId) StartSendOutAnim(gActiveBattler, FALSE); gActiveBattler ^= BIT_FLANK; } + else + { + gBattleResources->bufferA[gActiveBattler][1] = gBattlerPartyIndexes[gActiveBattler]; + StartSendOutAnim(gActiveBattler, FALSE); + } gBattlerControllerFuncs[gActiveBattler] = Intro_TryShinyAnimShowHealthbox; gActiveBattler = savedActiveBattler; DestroyTask(taskId); diff --git a/src/battle_controllers.c b/src/battle_controllers.c index 2fc7cac075..033a121228 100644 --- a/src/battle_controllers.c +++ b/src/battle_controllers.c @@ -588,6 +588,14 @@ static void InitLinkBtlControllers(void) } } +bool32 IsValidForBattle(struct Pokemon *mon) +{ + u32 species = GetMonData(mon, MON_DATA_SPECIES2); + return (species != SPECIES_NONE && species != SPECIES_EGG + && GetMonData(mon, MON_DATA_HP) != 0 + && GetMonData(mon, MON_DATA_IS_EGG) == 0); +} + static void SetBattlePartyIds(void) { s32 i, j; @@ -602,10 +610,7 @@ static void SetBattlePartyIds(void) { if (GET_BATTLER_SIDE2(i) == B_SIDE_PLAYER) { - if (GetMonData(&gPlayerParty[j], MON_DATA_HP) != 0 - && GetMonData(&gPlayerParty[j], MON_DATA_SPECIES2) != SPECIES_NONE - && GetMonData(&gPlayerParty[j], MON_DATA_SPECIES2) != SPECIES_EGG - && GetMonData(&gPlayerParty[j], MON_DATA_IS_EGG) == 0) + if (IsValidForBattle(&gPlayerParty[j])) { gBattlerPartyIndexes[i] = j; break; @@ -613,10 +618,7 @@ static void SetBattlePartyIds(void) } else { - if (GetMonData(&gEnemyParty[j], MON_DATA_HP) != 0 - && GetMonData(&gEnemyParty[j], MON_DATA_SPECIES2) != SPECIES_NONE - && GetMonData(&gEnemyParty[j], MON_DATA_SPECIES2) != SPECIES_EGG - && GetMonData(&gEnemyParty[j], MON_DATA_IS_EGG) == 0) + if (IsValidForBattle(&gEnemyParty[j])) { gBattlerPartyIndexes[i] = j; break; @@ -627,11 +629,7 @@ static void SetBattlePartyIds(void) { if (GET_BATTLER_SIDE2(i) == B_SIDE_PLAYER) { - if (GetMonData(&gPlayerParty[j], MON_DATA_HP) != 0 - && GetMonData(&gPlayerParty[j], MON_DATA_SPECIES) != SPECIES_NONE // Probably a typo by Game Freak. The rest use SPECIES2. - && GetMonData(&gPlayerParty[j], MON_DATA_SPECIES2) != SPECIES_EGG - && GetMonData(&gPlayerParty[j], MON_DATA_IS_EGG) == 0 - && gBattlerPartyIndexes[i - 2] != j) + if (IsValidForBattle(&gPlayerParty[j]) && gBattlerPartyIndexes[i - 2] != j) { gBattlerPartyIndexes[i] = j; break; @@ -639,16 +637,18 @@ static void SetBattlePartyIds(void) } else { - if (GetMonData(&gEnemyParty[j], MON_DATA_HP) != 0 - && GetMonData(&gEnemyParty[j], MON_DATA_SPECIES2) != SPECIES_NONE - && GetMonData(&gEnemyParty[j], MON_DATA_SPECIES2) != SPECIES_EGG - && GetMonData(&gEnemyParty[j], MON_DATA_IS_EGG) == 0 - && gBattlerPartyIndexes[i - 2] != j) + if (IsValidForBattle(&gEnemyParty[j]) && gBattlerPartyIndexes[i - 2] != j) { gBattlerPartyIndexes[i] = j; break; } } + + // No valid mons were found. Add the empty slot. + if (gBattlerPartyIndexes[i - 2] == 0) + gBattlerPartyIndexes[i] = 1; + else + gBattlerPartyIndexes[i] = 0; } } } diff --git a/src/battle_main.c b/src/battle_main.c index 9cf56abf74..f6d1cbe62a 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3454,6 +3454,13 @@ static void TryDoEventsBeforeFirstTurn(void) if (gBattleControllerExecFlags) return; + // Set invalid mons as absent(for example when starting a double battle with only one pokemon). + for (i = 0; i < gBattlersCount; i++) + { + if (gBattleMons[i].hp == 0 || gBattleMons[i].species == SPECIES_NONE) + gAbsentBattlerFlags |= gBitTable[i]; + } + if (gBattleStruct->switchInAbilitiesCounter == 0) { for (i = 0; i < gBattlersCount; i++) @@ -4080,10 +4087,10 @@ static void HandleTurnActionSelectionState(void) } break; case STATE_WAIT_ACTION_CONFIRMED_STANDBY: - if (!(gBattleControllerExecFlags & ((gBitTable[gActiveBattler]) + if (!(gBattleControllerExecFlags & ((gBitTable[gActiveBattler]) | (0xF << 28) - | (gBitTable[gActiveBattler] << 4) - | (gBitTable[gActiveBattler] << 8) + | (gBitTable[gActiveBattler] << 4) + | (gBitTable[gActiveBattler] << 8) | (gBitTable[gActiveBattler] << 12)))) { if (AllAtActionConfirmed()) @@ -4646,7 +4653,7 @@ static void CheckQuickClaw_CustapBerryActivation(void) } } } - + // setup stuff before turns/actions TryClearRageAndFuryCutter(); gCurrentTurnActionNumber = 0; diff --git a/src/battle_message.c b/src/battle_message.c index c4f043e150..8ef2e4702f 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -2560,7 +2560,7 @@ void BufferStringBattle(u16 stringID) case STRINGID_INTROSENDOUT: // poke first send-out if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) { - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && IsValidForBattle(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler ^ BIT_FLANK]])) { if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) stringPtr = sText_InGamePartnerSentOutZGoN; From 540719c48323dd5fe56f585ba5b613f769a78276 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Tue, 8 Jun 2021 22:50:37 +0200 Subject: [PATCH 02/10] Add support for only one enemy pokemon in double battles start --- src/battle_controller_opponent.c | 22 +++++++++++++++------- src/battle_message.c | 4 ++-- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/battle_controller_opponent.c b/src/battle_controller_opponent.c index 4eeef55c3d..928fc310f8 100644 --- a/src/battle_controller_opponent.c +++ b/src/battle_controller_opponent.c @@ -225,12 +225,18 @@ static void Intro_DelayAndEnd(void) } } +static bool32 TwoIntroMons(u32 battlerId) // Double battle with both player pokemon active. +{ + return (IsDoubleBattle() && IsValidForBattle(&gEnemyParty[gBattlerPartyIndexes[battlerId ^ BIT_FLANK]])); +} + static void Intro_WaitForShinyAnimAndHealthbox(void) { bool8 healthboxAnimDone = FALSE; bool8 twoMons; - if (!IsDoubleBattle() || ((IsDoubleBattle() && (gBattleTypeFlags & BATTLE_TYPE_MULTI) && !BATTLE_TWO_VS_ONE_OPPONENT) || (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS))) + twoMons = TwoIntroMons(gActiveBattler); + if (!twoMons || ((twoMons && (gBattleTypeFlags & BATTLE_TYPE_MULTI) && !BATTLE_TWO_VS_ONE_OPPONENT) || (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS))) { if (gSprites[gHealthboxSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy) healthboxAnimDone = TRUE; @@ -292,15 +298,17 @@ static void Intro_TryShinyAnimShowHealthbox(void) { bool32 bgmRestored = FALSE; bool32 battlerAnimsDone = FALSE; + bool32 twoMons; if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].triedShinyMonAnim && !gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].ballAnimActive && !gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].finishedShinyMonAnim) TryShinyAnimation(gActiveBattler, &gEnemyParty[gBattlerPartyIndexes[gActiveBattler]]); + twoMons = TwoIntroMons(gActiveBattler); if (!(gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) && (!(gBattleTypeFlags & BATTLE_TYPE_MULTI) || BATTLE_TWO_VS_ONE_OPPONENT) - && IsDoubleBattle() + && twoMons && !gBattleSpritesDataPtr->healthBoxesData[gActiveBattler ^ BIT_FLANK].triedShinyMonAnim && !gBattleSpritesDataPtr->healthBoxesData[gActiveBattler ^ BIT_FLANK].ballAnimActive && !gBattleSpritesDataPtr->healthBoxesData[gActiveBattler ^ BIT_FLANK].finishedShinyMonAnim) @@ -310,7 +318,7 @@ static void Intro_TryShinyAnimShowHealthbox(void) { if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].healthboxSlideInStarted) { - if (IsDoubleBattle() && (!(gBattleTypeFlags & BATTLE_TYPE_MULTI) || BATTLE_TWO_VS_ONE_OPPONENT)) + if (twoMons && (!(gBattleTypeFlags & BATTLE_TYPE_MULTI) || BATTLE_TWO_VS_ONE_OPPONENT)) { UpdateHealthboxAttribute(gHealthboxSpriteIds[gActiveBattler ^ BIT_FLANK], &gEnemyParty[gBattlerPartyIndexes[gActiveBattler ^ BIT_FLANK]], HEALTHBOX_ALL); StartHealthboxSlideIn(gActiveBattler ^ BIT_FLANK); @@ -342,7 +350,7 @@ static void Intro_TryShinyAnimShowHealthbox(void) bgmRestored = TRUE; } - if (!IsDoubleBattle() || (IsDoubleBattle() && gBattleTypeFlags & BATTLE_TYPE_MULTI && !BATTLE_TWO_VS_ONE_OPPONENT)) + if (!twoMons || (twoMons && gBattleTypeFlags & BATTLE_TYPE_MULTI && !BATTLE_TWO_VS_ONE_OPPONENT)) { if (gSprites[gBattleControllerData[gActiveBattler]].callback == SpriteCallbackDummy && gSprites[gBattlerSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy) @@ -363,7 +371,7 @@ static void Intro_TryShinyAnimShowHealthbox(void) if (bgmRestored && battlerAnimsDone) { - if (IsDoubleBattle() && (!(gBattleTypeFlags & BATTLE_TYPE_MULTI) || BATTLE_TWO_VS_ONE_OPPONENT)) + if (twoMons && (!(gBattleTypeFlags & BATTLE_TYPE_MULTI) || BATTLE_TWO_VS_ONE_OPPONENT)) { DestroySprite(&gSprites[gBattleControllerData[gActiveBattler ^ BIT_FLANK]]); SetBattlerShadowSpriteCallback(gActiveBattler ^ BIT_FLANK, GetMonData(&gEnemyParty[gBattlerPartyIndexes[gActiveBattler ^ BIT_FLANK]], MON_DATA_SPECIES)); @@ -469,7 +477,7 @@ static void SwitchIn_HandleSoundAndEnd(void) { if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].specialAnimActive && !IsCryPlayingOrClearCrySongs()) { - if (gSprites[gBattlerSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy + if (gSprites[gBattlerSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy || gSprites[gBattlerSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy_2) { m4aMPlayVolumeControl(&gMPlayInfo_BGM, 0xFFFF, 0x100); @@ -1892,7 +1900,7 @@ static void Task_StartSendOutAnim(u8 taskId) u8 savedActiveBank = gActiveBattler; gActiveBattler = gTasks[taskId].data[0]; - if ((!IsDoubleBattle() || (gBattleTypeFlags & BATTLE_TYPE_MULTI)) && !BATTLE_TWO_VS_ONE_OPPONENT) + if ((!TwoIntroMons(gActiveBattler) || (gBattleTypeFlags & BATTLE_TYPE_MULTI)) && !BATTLE_TWO_VS_ONE_OPPONENT) { gBattleResources->bufferA[gActiveBattler][1] = gBattlerPartyIndexes[gActiveBattler]; StartSendOutAnim(gActiveBattler, FALSE); diff --git a/src/battle_message.c b/src/battle_message.c index 8ef2e4702f..e77a5e0b46 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -2549,7 +2549,7 @@ void BufferStringBattle(u16 stringID) { if (gBattleTypeFlags & BATTLE_TYPE_LEGENDARY) stringPtr = sText_LegendaryPkmnAppeared; - else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) // interesting, looks like they had something planned for wild double battles + else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && IsValidForBattle(&gEnemyParty[gBattlerPartyIndexes[gActiveBattler ^ BIT_FLANK]])) // interesting, looks like they had something planned for wild double battles stringPtr = sText_TwoWildPkmnAppeared; else if (gBattleTypeFlags & BATTLE_TYPE_WALLY_TUTORIAL) stringPtr = sText_WildPkmnAppearedPause; @@ -2578,7 +2578,7 @@ void BufferStringBattle(u16 stringID) } else { - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && IsValidForBattle(&gEnemyParty[gBattlerPartyIndexes[gActiveBattler ^ BIT_FLANK]])) { if (BATTLE_TWO_VS_ONE_OPPONENT) stringPtr = sText_Trainer1SentOutTwoPkmn; From 2d41f08312e2b1e39b5c964ab2a644a3ee1392ec Mon Sep 17 00:00:00 2001 From: StubbornOne Date: Mon, 21 Jun 2021 14:18:33 +0800 Subject: [PATCH 03/10] Add Telepathy's damage prevention effect --- src/battle_util.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/battle_util.c b/src/battle_util.c index 87f9003e0b..06ccae3b69 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8105,6 +8105,17 @@ static u16 CalcTypeEffectivenessMultiplierInternal(u16 move, u8 moveType, u8 bat RecordAbilityBattle(battlerDef, ABILITY_WONDER_GUARD); } } + if (GetBattlerAbility(battlerDef) == ABILITY_TELEPATHY && battlerDef == BATTLE_PARTNER(battlerAtk)) { + modifier = UQ_4_12(0.0); + if (recordAbilities) + { + gLastUsedAbility = ABILITY_TELEPATHY; + gMoveResultFlags |= MOVE_RESULT_MISSED; + gLastLandedMoves[battlerDef] = 0; + gBattleCommunication[6] = B_MSG_AVOIDED_DMG; + RecordAbilityBattle(battlerDef, ABILITY_TELEPATHY); + } + } return modifier; } From f0cb6190e00b002d00f8ac921a22943de0e3d757 Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Sat, 7 Aug 2021 20:56:10 +1200 Subject: [PATCH 04/10] Implement Burmy form change Burmy changes form based on where it last battled. --- include/battle_util.h | 1 + src/battle_main.c | 1 + src/battle_util.c | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/include/battle_util.h b/include/battle_util.h index e10305e564..521bb2693e 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -138,6 +138,7 @@ bool32 CanFling(u8 battlerId); bool32 IsTelekinesisBannedSpecies(u16 species); bool32 IsHealBlockPreventingMove(u32 battler, u32 move); bool32 HasEnoughHpToEatBerry(u32 battlerId, u32 hpFraction, u32 itemId); +void DoBurmyFormChange(u32 monId); // ability checks bool32 IsRolePlayBannedAbilityAtk(u16 ability); diff --git a/src/battle_main.c b/src/battle_main.c index 94700bf969..d7fb7f6976 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -4879,6 +4879,7 @@ static void HandleEndTurn_FinishBattle(void) { UndoMegaEvolution(i); UndoFormChange(i, B_SIDE_PLAYER, FALSE); + DoBurmyFormChange(i); } gBattleMainFunc = FreeResetData_ReturnToOvOrDoEvolutions; gCB2_AfterEvolution = BattleMainCB2; diff --git a/src/battle_util.c b/src/battle_util.c index 7deebd25e3..19913781dc 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8659,3 +8659,43 @@ bool32 IsEntrainmentTargetOrSimpleBeamBannedAbility(u16 ability) } return FALSE; } + ++void DoBurmyFormChange(u32 monId) +{ + u16 newSpecies, currSpecies; + s32 sentIn; + struct Pokemon *party = gPlayerParty; + + sentIn = gSentPokesToOpponent[(gBattlerFainted & 2) >> 1]; + currSpecies = GetMonData(&party[monId], MON_DATA_SPECIES, NULL); + + if ((gSpeciesToNationalPokedexNum[currSpecies - 1] == SPECIES_BURMY) && (gBitTable[monId] & sentIn)) + { + switch (gBattleTerrain) + { + case BATTLE_TERRAIN_GRASS: + case BATTLE_TERRAIN_LONG_GRASS: + case BATTLE_TERRAIN_POND: + case BATTLE_TERRAIN_MOUNTAIN: + case BATTLE_TERRAIN_PLAIN: + newSpecies = SPECIES_BURMY; + break; + case BATTLE_TERRAIN_CAVE: + case BATTLE_TERRAIN_SAND: + newSpecies = SPECIES_BURMY_SANDY_CLOAK; + break; + case BATTLE_TERRAIN_BUILDING: + newSpecies = SPECIES_BURMY_TRASH_CLOAK; + break; + default: // Don't change form if last battle was water-related + newSpecies = SPECIES_NONE; + break; + } + + if (newSpecies != SPECIES_NONE) + { + SetMonData(&party[monId], MON_DATA_SPECIES, &newSpecies); + CalculateMonStats(&party[monId]); + } + } +} From 6c6363f7cf67a9f12a28a0126e3b4d84dafd6935 Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Sat, 7 Aug 2021 20:59:04 +1200 Subject: [PATCH 05/10] Use form table in species check --- src/battle_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_util.c b/src/battle_util.c index 19913781dc..fa5cb5456a 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8669,7 +8669,7 @@ bool32 IsEntrainmentTargetOrSimpleBeamBannedAbility(u16 ability) sentIn = gSentPokesToOpponent[(gBattlerFainted & 2) >> 1]; currSpecies = GetMonData(&party[monId], MON_DATA_SPECIES, NULL); - if ((gSpeciesToNationalPokedexNum[currSpecies - 1] == SPECIES_BURMY) && (gBitTable[monId] & sentIn)) + if ((GET_BASE_SPECIES_ID(currSpecies) == SPECIES_BURMY) && (gBitTable[monId] & sentIn)) { switch (gBattleTerrain) { From e1ca2af8b3732df237f1025d8eca28c442bdd7f1 Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Sun, 8 Aug 2021 00:52:27 +1200 Subject: [PATCH 06/10] Update src/battle_util.c Fix copy/paste typo Co-authored-by: LOuroboros --- src/battle_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_util.c b/src/battle_util.c index fa5cb5456a..50a2a62230 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8660,7 +8660,7 @@ bool32 IsEntrainmentTargetOrSimpleBeamBannedAbility(u16 ability) return FALSE; } -+void DoBurmyFormChange(u32 monId) +void DoBurmyFormChange(u32 monId) { u16 newSpecies, currSpecies; s32 sentIn; From 30c983d9cac69431e5865ed6559c8c0541ad217f Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Sun, 8 Aug 2021 13:14:51 +1200 Subject: [PATCH 07/10] Define Burmy forms in battle engine Title. BE needs these to compile on its own. --- include/constants/battle_config.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/constants/battle_config.h b/include/constants/battle_config.h index bf31c77b3b..cdeadfbf7c 100644 --- a/include/constants/battle_config.h +++ b/include/constants/battle_config.h @@ -37,6 +37,9 @@ #define SPECIES_ZYGARDE 0 // 50% #define SPECIES_ZYGARDE_10 10011 // 10 % #define SPECIES_ZYGARDE_COMPLETE 10012 // 100 % + #define SPECIES_BURMY 0 + #define SPECIES_BURMY_SANDY_CLOAK 10013 + #define SPECIES_BURMY_TRASH_CLOAK 10014 #endif // Items with peculiar battle effects. From e037cb927652e3e432dce3828d3a3239d1b129a9 Mon Sep 17 00:00:00 2001 From: Ariel Antonitis Date: Mon, 20 Sep 2021 18:28:26 -0400 Subject: [PATCH 08/10] Fixed Nature Power move on different terrains. --- src/battle_script_commands.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 00a52d6c58..e1d51bd05e 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -11301,7 +11301,7 @@ static void Cmd_setcharge(void) static void Cmd_callterrainattack(void) // nature power { gHitMarker &= ~(HITMARKER_ATTACKSTRING_PRINTED); - gCurrentMove = sNaturePowerMoves[gBattleTerrain]; + gCurrentMove = GetNaturePowerMove(); gBattlerTarget = GetMoveTarget(gCurrentMove, 0); BattleScriptPush(gBattleScriptsForMoveEffects[gBattleMoves[gCurrentMove].effect]); gBattlescriptCurrInstr++; @@ -11309,7 +11309,14 @@ static void Cmd_callterrainattack(void) // nature power u16 GetNaturePowerMove(void) { - //TODO terrain + if (gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN) + return MOVE_MOONBLAST; + else if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN) + return MOVE_THUNDERBOLT; + else if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN) + return MOVE_ENERGY_BALL; + else if (gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN) + return MOVE_PSYCHIC; return sNaturePowerMoves[gBattleTerrain]; } From b38761e6a8561622b1f3424735f63ad2f723488e Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Mon, 20 Sep 2021 22:26:02 -0400 Subject: [PATCH 09/10] add fairy to dex search --- src/pokedex.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pokedex.c b/src/pokedex.c index cc469b32f8..9de5e0c744 100644 --- a/src/pokedex.c +++ b/src/pokedex.c @@ -1393,6 +1393,7 @@ static const struct SearchOptionText sDexSearchTypeOptions[NUMBER_OF_MON_TYPES + {gText_DexEmptyString, gTypeNames[TYPE_ICE]}, {gText_DexEmptyString, gTypeNames[TYPE_DRAGON]}, {gText_DexEmptyString, gTypeNames[TYPE_DARK]}, + {gText_DexEmptyString, gTypeNames[TYPE_FAIRY]}, {}, }; @@ -1427,6 +1428,7 @@ static const u8 sDexSearchTypeIds[NUMBER_OF_MON_TYPES] = TYPE_ICE, TYPE_DRAGON, TYPE_DARK, + TYPE_FAIRY, }; // Number pairs are the task data for tracking the cursor pos and scroll offset of each option list From 7571d56140d71869a6959a20dfc0ef7bb5dd1f39 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Tue, 21 Sep 2021 22:57:05 -0300 Subject: [PATCH 10/10] Applied Egg's implementation of telepathy --- src/battle_util.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index 591f0bac0a..bbc045e39e 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8129,27 +8129,18 @@ static u16 CalcTypeEffectivenessMultiplierInternal(u16 move, u8 moveType, u8 bat modifier = UQ_4_12(1.0); } - if (GetBattlerAbility(battlerDef) == ABILITY_WONDER_GUARD && modifier <= UQ_4_12(1.0) && gBattleMoves[move].power) + if (((GetBattlerAbility(battlerDef) == ABILITY_WONDER_GUARD && modifier <= UQ_4_12(1.0)) + || (GetBattlerAbility(battlerDef) == ABILITY_TELEPATHY && battlerDef == BATTLE_PARTNER(battlerAtk))) + && gBattleMoves[move].power) { modifier = UQ_4_12(0.0); if (recordAbilities) { - gLastUsedAbility = ABILITY_WONDER_GUARD; + gLastUsedAbility = gBattleMons[battlerDef].ability; gMoveResultFlags |= MOVE_RESULT_MISSED; gLastLandedMoves[battlerDef] = 0; gBattleCommunication[MISS_TYPE] = B_MSG_AVOIDED_DMG; - RecordAbilityBattle(battlerDef, ABILITY_WONDER_GUARD); - } - } - if (GetBattlerAbility(battlerDef) == ABILITY_TELEPATHY && battlerDef == BATTLE_PARTNER(battlerAtk)) { - modifier = UQ_4_12(0.0); - if (recordAbilities) - { - gLastUsedAbility = ABILITY_TELEPATHY; - gMoveResultFlags |= MOVE_RESULT_MISSED; - gLastLandedMoves[battlerDef] = 0; - gBattleCommunication[6] = B_MSG_AVOIDED_DMG; - RecordAbilityBattle(battlerDef, ABILITY_TELEPATHY); + RecordAbilityBattle(battlerDef, gBattleMons[battlerDef].ability); } }