From c06029bc721119b0efd6e26c24a3f77772dfd77b Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Fri, 25 Jun 2021 13:37:59 -0600 Subject: [PATCH 01/32] add last used ball --- graphics/battle_interface/ability_pop_up.pal | 19 ++ graphics/battle_interface/last_used_ball.png | Bin 0 -> 223 bytes include/battle.h | 2 + include/battle_interface.h | 4 + include/battle_util.h | 1 + include/constants/battle_config.h | 4 + include/global.h | 3 +- include/item_use.h | 1 + src/battle_controller_player.c | 16 +- src/battle_interface.c | 181 +++++++++++++++++++ src/battle_main.c | 4 + src/battle_script_commands.c | 3 +- src/battle_util.c | 11 ++ src/item_use.c | 54 ++++-- src/new_game.c | 2 + 15 files changed, 283 insertions(+), 22 deletions(-) create mode 100644 graphics/battle_interface/ability_pop_up.pal create mode 100644 graphics/battle_interface/last_used_ball.png diff --git a/graphics/battle_interface/ability_pop_up.pal b/graphics/battle_interface/ability_pop_up.pal new file mode 100644 index 0000000000..19895d0bcf --- /dev/null +++ b/graphics/battle_interface/ability_pop_up.pal @@ -0,0 +1,19 @@ +JASC-PAL +0100 +16 +1 177 91 +143 129 149 +103 91 111 +79 65 85 +59 31 81 +103 89 109 +231 239 245 +249 253 255 +0 0 0 +0 0 0 +107 115 115 +74 66 82 +0 0 0 +214 214 206 +132 140 140 +0 0 0 diff --git a/graphics/battle_interface/last_used_ball.png b/graphics/battle_interface/last_used_ball.png new file mode 100644 index 0000000000000000000000000000000000000000..581569cf1bf4ce3f5cee78fcd83a7a34b149d012 GIT binary patch literal 223 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvg8-ipSH_Le)y2(0UQw2Yj+z{f zK*sa;Uw{7n50nRj?BZfCCy?fA*Uq){^Z*&j&Z>)mRF^unv_P&x8 zS#yg)?8er2d6p7uYPU)$efU;Y`E%9Nr%yw_D=__j$HY1FVdQ&MBb@0Cx9FNdN!< literal 0 HcmV?d00001 diff --git a/include/battle.h b/include/battle.h index f009cbe7fb..9a10ae77d6 100644 --- a/include/battle.h +++ b/include/battle.h @@ -37,6 +37,7 @@ #define B_ACTION_CANCEL_PARTNER 12 // when choosing an action #define B_ACTION_NOTHING_FAINTED 13 // when choosing an action #define B_ACTION_DEBUG 20 +#define B_ACTION_THROW_BALL 21 // R to throw last used ball #define B_ACTION_NONE 0xFF #define MAX_TRAINER_ITEMS 4 @@ -586,6 +587,7 @@ struct BattleStruct u16 moveEffect2; // For Knock Off u16 changedSpecies[PARTY_SIZE]; // For Zygarde or future forms when multiple mons can change into the same pokemon. u8 quickClawBattlerId; + u8 ballSpriteIds[2]; // item gfx, window gfx }; #define GET_MOVE_TYPE(move, typeArg) \ diff --git a/include/battle_interface.h b/include/battle_interface.h index 0bcadaaacb..c852b776ad 100644 --- a/include/battle_interface.h +++ b/include/battle_interface.h @@ -93,5 +93,9 @@ u8 GetScaledHPFraction(s16 hp, s16 maxhp, u8 scale); u8 GetHPBarLevel(s16 hp, s16 maxhp); void CreateAbilityPopUp(u8 battlerId, u32 ability, bool32 isDoubleBattle); void DestroyAbilityPopUp(u8 battlerId); +bool32 CanThrowLastUsedBall(void); +void TryHideLastUsedBall(void); +void TryRestoreLastUsedBall(void); +void TryAddLastUsedBallItemSprites(void); #endif // GUARD_BATTLE_INTERFACE_H diff --git a/include/battle_util.h b/include/battle_util.h index 0bf49dadfc..717017c06c 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -46,6 +46,7 @@ struct TypePower extern const struct TypePower gNaturalGiftTable[]; +void HandleAction_ThrowBall(void); void HandleAction_UseMove(void); void HandleAction_Switch(void); void HandleAction_UseItem(void); diff --git a/include/constants/battle_config.h b/include/constants/battle_config.h index fe376da8d2..0f878d3af6 100644 --- a/include/constants/battle_config.h +++ b/include/constants/battle_config.h @@ -151,6 +151,10 @@ #define B_CRITICAL_CAPTURE TRUE // If set to TRUE, Critical Capture will be enabled. #define B_CATCHING_CHARM_BOOST 20 // % boost in Critical Capture odds if player has the Catching Charm. +// Last Used Ball +#define B_LAST_USED_BALL TRUE // If TRUE, the "last used ball" feature from Gen 7 will be implemented +#define B_LAST_USED_BALL_BUTTON R_BUTTON // If last used ball is implemented, this button (or button combo) will trigger throwing the last used ball. + // Other #define B_DOUBLE_WILD_CHANCE 0 // % chance of encountering two Pokémon in a Wild Encounter. #define B_SLEEP_TURNS GEN_7 // In Gen5+, sleep lasts for 1-3 turns instead of 2-5 turns. diff --git a/include/global.h b/include/global.h index e6b0797e76..a5d720eda5 100644 --- a/include/global.h +++ b/include/global.h @@ -490,7 +490,8 @@ struct SaveBlock2 u16 optionsBattleSceneOff:1; // whether battle animations are disabled u16 regionMapZoom:1; // whether the map is zoomed in /*0x18*/ struct Pokedex pokedex; - /*0x90*/ u8 filler_90[0x8]; + /*0x90*/ u16 lastUsedBall; + /*0x92*/ u8 filler_90[0x6]; /*0x98*/ struct Time localTimeOffset; /*0xA0*/ struct Time lastBerryTreeUpdate; /*0xA8*/ u32 gcnLinkFlags; // Read by Pokemon Colosseum/XD diff --git a/include/item_use.h b/include/item_use.h index f577f8d464..42db6ff104 100644 --- a/include/item_use.h +++ b/include/item_use.h @@ -33,5 +33,6 @@ void ItemUseInBattle_EnigmaBerry(u8); void Task_UseDigEscapeRopeOnField(u8 taskId); u8 CanUseDigOrEscapeRopeOnCurMap(void); u8 CheckIfItemIsTMHMOrEvolutionStone(u16 itemId); +u32 CanThrowBall(void); #endif // GUARD_ITEM_USE_H diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index 89f73ffc41..89a044275d 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -249,7 +249,8 @@ static void HandleInputChooseAction(void) if (JOY_NEW(A_BUTTON)) { PlaySE(SE_SELECT); - + TryHideLastUsedBall(); + switch (gActionSelectionCursor[gActiveBattler]) { case 0: @@ -336,6 +337,15 @@ static void HandleInputChooseAction(void) BtlController_EmitTwoReturnValues(1, B_ACTION_DEBUG, 0); PlayerBufferExecCompleted(); } + #if B_LAST_USED_BALL == TRUE + else if (JOY_NEW(B_LAST_USED_BALL_BUTTON) && CanThrowLastUsedBall()) + { + PlaySE(SE_SELECT); + TryHideLastUsedBall(); + BtlController_EmitTwoReturnValues(1, B_ACTION_THROW_BALL, 0); + PlayerBufferExecCompleted(); + } + #endif } static void UnusedEndBounceEffect(void) @@ -372,6 +382,7 @@ static void HandleInputChooseTarget(void) else BtlController_EmitTwoReturnValues(1, 10, gMoveSelectionCursor[gActiveBattler] | (gMultiUsePlayerCursor << 8)); EndBounceEffect(gMultiUsePlayerCursor, BOUNCE_HEALTHBOX); + TryHideLastUsedBall(); HideMegaTriggerSprite(); PlayerBufferExecCompleted(); } @@ -514,6 +525,7 @@ static void HandleInputShowTargets(void) else BtlController_EmitTwoReturnValues(1, 10, gMoveSelectionCursor[gActiveBattler] | (gMultiUsePlayerCursor << 8)); HideMegaTriggerSprite(); + TryHideLastUsedBall(); PlayerBufferExecCompleted(); } else if (gMain.newKeys & B_BUTTON || gPlayerDpadHoldFrames > 59) @@ -606,6 +618,7 @@ static void HandleInputChooseMove(void) else BtlController_EmitTwoReturnValues(1, 10, gMoveSelectionCursor[gActiveBattler] | (gMultiUsePlayerCursor << 8)); HideMegaTriggerSprite(); + TryHideLastUsedBall(); PlayerBufferExecCompleted(); } else if (canSelectTarget == 1) @@ -2691,6 +2704,7 @@ static void PlayerHandleChooseAction(void) for (i = 0; i < 4; i++) ActionSelectionDestroyCursorAt(i); + TryRestoreLastUsedBall(); ActionSelectionCreateCursorAt(gActionSelectionCursor[gActiveBattler], 0); BattleStringExpandPlaceholdersToDisplayedString(gText_WhatWillPkmnDo); BattlePutTextOnWindow(gDisplayedStringBattle, 1); diff --git a/src/battle_interface.c b/src/battle_interface.c index 128f342df3..828b57a2f0 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -27,6 +27,9 @@ #include "constants/battle_config.h" #include "data.h" #include "pokemon_summary_screen.h" +#include "item_icon.h" +#include "item_use.h" +#include "item.h" enum { // Corresponds to gHealthboxElementsGfxTable (and the tables after it) in graphics.c @@ -196,6 +199,9 @@ static u8 CalcBarFilledPixels(s32 maxValue, s32 oldValue, s32 receivedValue, s32 static void SpriteCb_AbilityPopUp(struct Sprite *sprite); static void Task_FreeAbilityPopUpGfx(u8 taskId); +static void SpriteCB_LastUsedBall(struct Sprite *sprite); +static void SpriteCB_LastUsedBallWin(struct Sprite *sprite); + // const rom data static const struct OamData sUnknown_0832C138 = { @@ -812,6 +818,9 @@ u8 CreateBattlerHealthboxSprites(u8 battlerId) gSprites[megaIndicatorSpriteId].invisible = TRUE; } + gBattleStruct->ballSpriteIds[0] = MAX_SPRITES; + gBattleStruct->ballSpriteIds[1] = MAX_SPRITES; + return healthboxLeftSpriteId; } @@ -3128,3 +3137,175 @@ static void Task_FreeAbilityPopUpGfx(u8 taskId) DestroyTask(taskId); } } + +// last used ball +#define LAST_BALL_WINDOW_TAG 0xD721 + +static const struct OamData sOamData_LastUsedBall = +{ + .y = 0, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = SPRITE_SHAPE(32x32), + .x = 0, + .matrixNum = 0, + .size = SPRITE_SIZE(32x32), + .tileNum = 0, + .priority = 1, + .paletteNum = 0, + .affineParam = 0, +}; + +static const struct SpriteTemplate sSpriteTemplate_LastUsedBallWindow = +{ + .tileTag = LAST_BALL_WINDOW_TAG, + .paletteTag = ABILITY_POP_UP_TAG, + .oam = &sOamData_LastUsedBall, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCB_LastUsedBallWin +}; + +static const u8 sLastUsedBallWindowGfx[] = INCBIN_U8("graphics/battle_interface/last_used_ball.4bpp"); +static const struct SpriteSheet sSpriteSheet_LastUsedBallWindow = +{ + sLastUsedBallWindowGfx, sizeof(sLastUsedBallWindowGfx), LAST_BALL_WINDOW_TAG +}; + +#define LAST_USED_BALL_X_F 15 +#define LAST_USED_BALL_X_0 -15 +#define LAST_USED_BALL_Y 68 + +#define LAST_BALL_WIN_X_F (LAST_USED_BALL_X_F - 1) +#define LAST_BALL_WIN_X_0 (LAST_USED_BALL_X_0 - 0) +#define LAST_USED_WIN_Y (LAST_USED_BALL_Y - 8) + +#define sHide data[0] + +bool32 CanThrowLastUsedBall(void) +{ + return (!(CanThrowBall() != 0 + || (gBattleTypeFlags & BATTLE_TYPE_TRAINER) + || !CheckBagHasItem(gSaveBlock2Ptr->lastUsedBall, 1))); +} + + +void TryAddLastUsedBallItemSprites(void) +{ + if (CanThrowBall() != 0 + || (gBattleTypeFlags & BATTLE_TYPE_TRAINER) + || !CheckBagHasItem(gSaveBlock2Ptr->lastUsedBall, 1)) + return; + + // ball + if (gBattleStruct->ballSpriteIds[0] == MAX_SPRITES) + { + gBattleStruct->ballSpriteIds[0] = AddItemIconSprite(102, 102, gSaveBlock2Ptr->lastUsedBall); + gSprites[gBattleStruct->ballSpriteIds[0]].pos1.x = LAST_USED_BALL_X_0; + gSprites[gBattleStruct->ballSpriteIds[0]].pos1.y = LAST_USED_BALL_Y; + gSprites[gBattleStruct->ballSpriteIds[0]].sHide = FALSE; // restore + gSprites[gBattleStruct->ballSpriteIds[0]].callback = SpriteCB_LastUsedBall; + } + + // window + LoadSpritePalette(&sSpritePalette_AbilityPopUp); + if (GetSpriteTileStartByTag(LAST_BALL_WINDOW_TAG) == 0xFFFF) + LoadSpriteSheet(&sSpriteSheet_LastUsedBallWindow); + + if (gBattleStruct->ballSpriteIds[1] == MAX_SPRITES) + { + gBattleStruct->ballSpriteIds[1] = CreateSprite(&sSpriteTemplate_LastUsedBallWindow, + LAST_BALL_WIN_X_0, + LAST_USED_WIN_Y, 5); + gSprites[gBattleStruct->ballSpriteIds[0]].sHide = FALSE; // restore + } +} + +static void DestroyLastUsedBallWinGfx(struct Sprite *sprite) +{ + FreeSpriteTilesByTag(LAST_BALL_WINDOW_TAG); + FreeSpritePaletteByTag(ABILITY_POP_UP_TAG); + DestroySprite(sprite); + gBattleStruct->ballSpriteIds[1] = MAX_SPRITES; +} + +static void DestroyLastUsedBallGfx(struct Sprite *sprite) +{ + FreeSpriteTilesByTag(102); + FreeSpritePaletteByTag(102); + DestroySprite(sprite); + gBattleStruct->ballSpriteIds[0] = MAX_SPRITES; +} + +static void SpriteCB_LastUsedBallWin(struct Sprite *sprite) +{ + if (sprite->sHide) + { + if (sprite->pos1.x != LAST_BALL_WIN_X_0) + sprite->pos1.x--; + + if (sprite->pos1.x == LAST_BALL_WIN_X_0) + DestroyLastUsedBallWinGfx(sprite); + } + else + { + if (sprite->pos1.x != LAST_BALL_WIN_X_F) + sprite->pos1.x++; + } +} + +static void SpriteCB_LastUsedBall(struct Sprite *sprite) +{ + if (sprite->sHide) + { + if (sprite->pos1.x != LAST_USED_BALL_X_0) + sprite->pos1.x--; + + if (sprite->pos1.x == LAST_USED_BALL_X_0) + DestroyLastUsedBallGfx(sprite); + } + else + { + if (sprite->pos1.x != LAST_USED_BALL_X_F) + sprite->pos1.x++; + } +} + +static void TryHideOrRestoreLastUsedBall(u8 caseId) +{ + if (gBattleStruct->ballSpriteIds[0] == MAX_SPRITES) + return; + + switch (caseId) + { + case 0: // hide + if (gBattleStruct->ballSpriteIds[0] != MAX_SPRITES) + gSprites[gBattleStruct->ballSpriteIds[0]].sHide = TRUE; // hide + if (gBattleStruct->ballSpriteIds[1] != MAX_SPRITES) + gSprites[gBattleStruct->ballSpriteIds[1]].sHide = TRUE; // hide + break; + case 1: // restore + if (gBattleStruct->ballSpriteIds[0] != MAX_SPRITES) + gSprites[gBattleStruct->ballSpriteIds[0]].sHide = FALSE; // restore + if (gBattleStruct->ballSpriteIds[1] != MAX_SPRITES) + gSprites[gBattleStruct->ballSpriteIds[1]].sHide = FALSE; // restore + break; + } +} + +void TryHideLastUsedBall(void) +{ + TryHideOrRestoreLastUsedBall(0); +} + +void TryRestoreLastUsedBall(void) +{ + if (gBattleStruct->ballSpriteIds[0] != MAX_SPRITES) + TryHideOrRestoreLastUsedBall(1); + else + TryAddLastUsedBallItemSprites(); +} + diff --git a/src/battle_main.c b/src/battle_main.c index 9cf56abf74..2d4dfa16f4 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -401,6 +401,7 @@ static void (* const sTurnActionsFuncsTable[])(void) = [B_ACTION_TRY_FINISH] = HandleAction_TryFinish, [B_ACTION_FINISHED] = HandleAction_ActionFinished, [B_ACTION_NOTHING_FAINTED] = HandleAction_NothingIsFainted, + [B_ACTION_THROW_BALL] = HandleAction_ThrowBall, }; static void (* const sEndTurnFuncsTable[])(void) = @@ -4053,6 +4054,9 @@ static void HandleTurnActionSelectionState(void) case B_ACTION_SAFARI_BALL: gBattleCommunication[gActiveBattler]++; break; + case B_ACTION_THROW_BALL: + gBattleCommunication[gActiveBattler]++; + break; case B_ACTION_SAFARI_POKEBLOCK: if ((gBattleResources->bufferB[gActiveBattler][1] | (gBattleResources->bufferB[gActiveBattler][2] << 8)) != 0) { diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index c8a393da3d..f5f093cc5c 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -12017,7 +12017,8 @@ static void Cmd_handleballthrow(void) { u32 odds; u8 catchRate; - + + gSaveBlock2Ptr->lastUsedBall = gLastUsedItem; if (gLastUsedItem == ITEM_SAFARI_BALL) catchRate = gBattleStruct->safariCatchFactor * 1275 / 100; else diff --git a/src/battle_util.c b/src/battle_util.c index 87f9003e0b..7a86b659f8 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -742,6 +742,17 @@ void HandleAction_SafariZoneBallThrow(void) gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT; } +void HandleAction_ThrowBall(void) +{ + gBattlerAttacker = gBattlerByTurnOrder[gCurrentTurnActionNumber]; + gBattle_BG0_X = 0; + gBattle_BG0_Y = 0; + gLastUsedItem = gSaveBlock2Ptr->lastUsedBall; + RemoveBagItem(gLastUsedItem, 1); + gBattlescriptCurrInstr = BattleScript_BallThrow; + gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT; +} + void HandleAction_ThrowPokeblock(void) { gBattlerAttacker = gBattlerByTurnOrder[gCurrentTurnActionNumber]; diff --git a/src/item_use.c b/src/item_use.c index 6b1519e9b2..ad7a464996 100755 --- a/src/item_use.c +++ b/src/item_use.c @@ -936,42 +936,58 @@ void ItemUseOutOfBattle_EvolutionStone(u8 taskId) SetUpItemUseCallback(taskId); } -void ItemUseInBattle_PokeBall(u8 taskId) +u32 CanThrowBall(void) { if (IsBattlerAlive(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT)) - && IsBattlerAlive(GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT))) // There are two present pokemon. + && IsBattlerAlive(GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT))) { - static const u8 textCantThrowPokeBall[] = _("Cannot throw a ball!\nThere are two pokemon out there!\p"); - - if (!InBattlePyramid()) - DisplayItemMessage(taskId, 1, textCantThrowPokeBall, BagMenu_InitListsMenu); - else - DisplayItemMessageInBattlePyramid(taskId, textCantThrowPokeBall, Task_CloseBattlePyramidBagMessage); + return 1; // There are two present pokemon. } else if (gBattlerInMenuId == GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT) - && IsBattlerAlive(GetBattlerAtPosition(B_POSITION_PLAYER_LEFT))) // Attempting to throw a ball with the second pokemon while both are alive. + && IsBattlerAlive(GetBattlerAtPosition(B_POSITION_PLAYER_LEFT))) { - static const u8 textCantThrowPokeBall[] = _("Cannot throw a ball!\p"); - - if (!InBattlePyramid()) - DisplayItemMessage(taskId, 1, textCantThrowPokeBall, BagMenu_InitListsMenu); - else - DisplayItemMessageInBattlePyramid(taskId, textCantThrowPokeBall, Task_CloseBattlePyramidBagMessage); + return 2; // Attempting to throw a ball with the second pokemon while both are alive. } - else if (IsPlayerPartyAndPokemonStorageFull() == FALSE) // have room for mon? + else if (IsPlayerPartyAndPokemonStorageFull() == TRUE) { + return 3; // No room for mon + } + + return 0; // usable +} + +static const u8 sText_CantThrowPokeBall_TwoMons[] = _("Cannot throw a ball!\nThere are two pokemon out there!\p"); +static const u8 sText_CantThrowPokeBall[] = _("Cannot throw a ball!\p"); +void ItemUseInBattle_PokeBall(u8 taskId) +{ + switch (CanThrowBall()) + { + case 0: // usable + default: RemoveBagItem(gSpecialVar_ItemId, 1); if (!InBattlePyramid()) Task_FadeAndCloseBagMenu(taskId); else CloseBattlePyramidBag(taskId); - } - else - { + break; + case 1: // There are two present pokemon. + if (!InBattlePyramid()) + DisplayItemMessage(taskId, 1, sText_CantThrowPokeBall_TwoMons, BagMenu_InitListsMenu); + else + DisplayItemMessageInBattlePyramid(taskId, sText_CantThrowPokeBall_TwoMons, Task_CloseBattlePyramidBagMessage); + break; + case 2: // Attempting to throw a ball with the second pokemon while both are alive. + if (!InBattlePyramid()) + DisplayItemMessage(taskId, 1, sText_CantThrowPokeBall_TwoMons, BagMenu_InitListsMenu); + else + DisplayItemMessageInBattlePyramid(taskId, sText_CantThrowPokeBall_TwoMons, Task_CloseBattlePyramidBagMessage); + break; + case 3: // No room for mon if (!InBattlePyramid()) DisplayItemMessage(taskId, 1, gText_BoxFull, BagMenu_InitListsMenu); else DisplayItemMessageInBattlePyramid(taskId, gText_BoxFull, Task_CloseBattlePyramidBagMessage); + break; } } diff --git a/src/new_game.c b/src/new_game.c index 2a950efbc9..c1dd85e90d 100644 --- a/src/new_game.c +++ b/src/new_game.c @@ -45,6 +45,7 @@ #include "berry_powder.h" #include "mevent.h" #include "union_room_chat.h" +#include "constants/items.h" extern const u8 EventScript_ResetAllMapFlags[]; @@ -204,6 +205,7 @@ void NewGameInitData(void) WipeTrainerNameRecords(); ResetTrainerHillResults(); ResetContestLinkResults(); + gSaveBlock2Ptr->lastUsedBall = ITEM_POKE_BALL; } static void ResetMiniGamesRecords(void) From d28ac33b0e8f350d49511257d0d5df10ae2c8352 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Sun, 4 Jul 2021 09:28:59 -0600 Subject: [PATCH 02/32] fix throw last used ball action turn order checks --- src/battle_main.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/battle_main.c b/src/battle_main.c index 2d4dfa16f4..6befbfbf5a 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -4485,7 +4485,9 @@ static void SetActionsAndBattlersTurnOrder(void) { for (gActiveBattler = 0; gActiveBattler < gBattlersCount; gActiveBattler++) { - if (gChosenActionByBattler[gActiveBattler] == B_ACTION_USE_ITEM || gChosenActionByBattler[gActiveBattler] == B_ACTION_SWITCH) + if (gChosenActionByBattler[gActiveBattler] == B_ACTION_USE_ITEM + || gChosenActionByBattler[gActiveBattler] == B_ACTION_SWITCH + || gChosenActionByBattler[gActiveBattler] == B_ACTION_THROW_BALL) { gActionsByTurnOrder[turnOrderId] = gChosenActionByBattler[gActiveBattler]; gBattlerByTurnOrder[turnOrderId] = gActiveBattler; @@ -4494,7 +4496,9 @@ static void SetActionsAndBattlersTurnOrder(void) } for (gActiveBattler = 0; gActiveBattler < gBattlersCount; gActiveBattler++) { - if (gChosenActionByBattler[gActiveBattler] != B_ACTION_USE_ITEM && gChosenActionByBattler[gActiveBattler] != B_ACTION_SWITCH) + if (gChosenActionByBattler[gActiveBattler] != B_ACTION_USE_ITEM + && gChosenActionByBattler[gActiveBattler] != B_ACTION_SWITCH + && gChosenActionByBattler[gActiveBattler] != B_ACTION_THROW_BALL) { gActionsByTurnOrder[turnOrderId] = gChosenActionByBattler[gActiveBattler]; gBattlerByTurnOrder[turnOrderId] = gActiveBattler; @@ -4510,7 +4514,9 @@ static void SetActionsAndBattlersTurnOrder(void) if (gActionsByTurnOrder[i] != B_ACTION_USE_ITEM && gActionsByTurnOrder[j] != B_ACTION_USE_ITEM && gActionsByTurnOrder[i] != B_ACTION_SWITCH - && gActionsByTurnOrder[j] != B_ACTION_SWITCH) + && gActionsByTurnOrder[j] != B_ACTION_SWITCH + && gActionsByTurnOrder[i] != B_ACTION_THROW_BALL + && gActionsByTurnOrder[j] != B_ACTION_THROW_BALL) { if (GetWhoStrikesFirst(battler1, battler2, FALSE)) SwapTurnOrder(i, j); From 542f0accf5a4f0c3dde59e6e76dca98c7ab08db6 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Sun, 4 Jul 2021 10:09:57 -0600 Subject: [PATCH 03/32] fix updating last used ball when run out of item id --- src/battle_interface.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/battle_interface.c b/src/battle_interface.c index 828b57a2f0..b233627d8c 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -729,6 +729,12 @@ u8 GetMegaIndicatorSpriteId(u32 healthboxSpriteId) return gSprites[spriteId].hOther_IndicatorSpriteId; } +static void InitLastUsedBallAssets(void) +{ + gBattleStruct->ballSpriteIds[0] = MAX_SPRITES; + gBattleStruct->ballSpriteIds[1] = MAX_SPRITES; +} + u8 CreateBattlerHealthboxSprites(u8 battlerId) { s16 data6 = 0; @@ -3195,6 +3201,14 @@ bool32 CanThrowLastUsedBall(void) void TryAddLastUsedBallItemSprites(void) { + if (gSaveBlock2Ptr->lastUsedBall != ITEM_NONE && !CheckBagHasItem(gSaveBlock2Ptr->lastUsedBall, 1)) + { + // we're out of the last used ball, so just set it to the first ball in the bag + // we have to compact the bag first bc it is typically only compacted when you open it + CompactItemsInBagPocket(&gBagPockets[BALLS_POCKET]); + gSaveBlock2Ptr->lastUsedBall = gBagPockets[BALLS_POCKET].itemSlots[0].itemId; + } + if (CanThrowBall() != 0 || (gBattleTypeFlags & BATTLE_TYPE_TRAINER) || !CheckBagHasItem(gSaveBlock2Ptr->lastUsedBall, 1)) From 07e3e73372eb6d625a198e07fd4a2360c5d25031 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Sun, 18 Jul 2021 11:20:51 -0600 Subject: [PATCH 04/32] fix ITEM_NONE to 0 for compilation reasons --- src/battle_interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_interface.c b/src/battle_interface.c index b233627d8c..1564881e4f 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -3201,7 +3201,7 @@ bool32 CanThrowLastUsedBall(void) void TryAddLastUsedBallItemSprites(void) { - if (gSaveBlock2Ptr->lastUsedBall != ITEM_NONE && !CheckBagHasItem(gSaveBlock2Ptr->lastUsedBall, 1)) + if (gSaveBlock2Ptr->lastUsedBall != 0 && !CheckBagHasItem(gSaveBlock2Ptr->lastUsedBall, 1)) { // we're out of the last used ball, so just set it to the first ball in the bag // we have to compact the bag first bc it is typically only compacted when you open it From 4ca6d76160b01738d9fcd326643a89828a045b61 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Sun, 25 Jul 2021 14:55:52 -0600 Subject: [PATCH 05/32] add bug bite --- asm/macros/battle_script.inc | 5 ++++ data/battle_scripts_1.s | 5 ++++ include/battle.h | 1 + include/battle_util.h | 1 + include/constants/battle_script_commands.h | 2 ++ src/battle_script_commands.c | 31 ++++++++++++++++++++-- src/battle_util.c | 5 ++++ 7 files changed, 48 insertions(+), 2 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 9fa3fe0c32..953180d91d 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1768,6 +1768,11 @@ .macro tryactivategrimneigh, battler:req various \battler, VARIOUS_TRY_ACTIVATE_GRIM_NEIGH .endm + + .macro consumeberry battler:req, restoreItem=FALSE + various \battler, VARIOUS_CONSUME_BERRY + .byte \restoreItem + .endm @ helpful macros .macro setstatchanger stat:req, stages:req, down:req diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 522ffb7014..d48076e489 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -508,6 +508,11 @@ BattleScript_MoveEffectIncinerate:: BattleScript_MoveEffectBugBite:: printstring STRINGID_BUGBITE waitmessage B_WAIT_TIME_LONG + orword gHitMarker, HITMARKER_NO_ANIMATIONS + setbyte sBERRY_OVERRIDE, TRUE @ override the requirements for eating berries + consumeberry BS_ATTACKER, TRUE @ consume the berry, then restore the item from changedItems + bicword gHitMarker, HITMARKER_NO_ANIMATIONS + setbyte sBERRY_OVERRIDE, FALSE return BattleScript_EffectCoreEnforcer: diff --git a/include/battle.h b/include/battle.h index b51a3d71b1..e822537473 100644 --- a/include/battle.h +++ b/include/battle.h @@ -659,6 +659,7 @@ struct BattleScripting u8 illusionNickHack; // To properly display nick in STRINGID_ENEMYABOUTTOSWITCHPKMN. bool8 fixedPopup; // force ability popup to stick until manually called back u16 abilityPopupOverwrite; + u8 overrideBerryRequirements; }; // rom_80A5C6C diff --git a/include/battle_util.h b/include/battle_util.h index e10305e564..bea6af8480 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -31,6 +31,7 @@ #define ITEMEFFECT_KINGSROCK_SHELLBELL 0x4 #define ITEMEFFECT_TARGET 0x5 #define ITEMEFFECT_ORBS 0x6 +#define ITEMEFFECT_BATTLER_MOVE_END 0x7 // move end effects for just the battler, not whole field #define WEATHER_HAS_EFFECT ((!IsAbilityOnField(ABILITY_CLOUD_NINE) && !IsAbilityOnField(ABILITY_AIR_LOCK))) diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index faaf8f17e0..881bb82e0d 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -37,6 +37,7 @@ #define sILLUSION_NICK_HACK gBattleScripting + 0x32 #define sFIXED_ABILITY_POPUP gBattleScripting + 0x33 #define sABILITY_OVERWRITE gBattleScripting + 0x34 +#define sBERRY_OVERRIDE gBattleScripting + 0x36 #define cMULTISTRING_CHOOSER gBattleCommunication + 5 #define cMISS_TYPE gBattleCommunication + 6 @@ -173,6 +174,7 @@ #define VARIOUS_DESTROY_ABILITY_POPUP 102 #define VARIOUS_TOTEM_BOOST 103 #define VARIOUS_TRY_ACTIVATE_GRIM_NEIGH 104 +#define VARIOUS_CONSUME_BERRY 105 // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index de7105a270..067d0b62e2 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -3284,16 +3284,22 @@ void SetMoveEffect(bool32 primary, u32 certain) } break; case MOVE_EFFECT_BUG_BITE: - if ((gBattleMons[gEffectBattler].item >= FIRST_BERRY_INDEX && gBattleMons[gEffectBattler].item <= LAST_BERRY_INDEX) + if (ItemId_GetPocket(gBattleMons[gEffectBattler].item) == POCKET_BERRIES && GetBattlerAbility(gEffectBattler) != ABILITY_STICKY_HOLD) { + // target loses their berry gLastUsedItem = gBattleMons[gEffectBattler].item; gBattleMons[gEffectBattler].item = 0; CheckSetUnburden(gEffectBattler); - gActiveBattler = gEffectBattler; + BtlController_EmitSetMonData(0, REQUEST_HELDITEM_BATTLE, 0, 2, &gBattleMons[gEffectBattler].item); MarkBattlerForControllerExec(gActiveBattler); + + // attacker temporarily gains their item + gBattleStruct->changedItems[gBattlerAttacker] = gBattleMons[gBattlerAttacker].item; + gBattleMons[gBattlerAttacker].item = gLastUsedItem; + BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_MoveEffectBugBite; } @@ -8422,6 +8428,27 @@ static void Cmd_various(void) gBattlescriptCurrInstr += 7; // exit if loop failed (failsafe) } return; + case VARIOUS_CONSUME_BERRY: + if (ItemId_GetHoldEffect(gBattleMons[gActiveBattler].item) == HOLD_EFFECT_NONE) + { + gBattlescriptCurrInstr += 4; + return; + } + + gBattleScripting.battler = gEffectBattler = gBattlerTarget = gActiveBattler; // cover all berry effect battlerId cases. e.g. ChangeStatBuffs uses target ID + // do move end berry effects for just a single battler, instead of looping through all battlers + if (ItemBattleEffects(ITEMEFFECT_BATTLER_MOVE_END, gActiveBattler, FALSE)) + return; + + if (gBattlescriptCurrInstr[3]) + { + gBattleMons[gActiveBattler].item = gBattleStruct->changedItems[gActiveBattler]; + gBattleStruct->changedItems[gActiveBattler] = ITEM_NONE; + gBattleResources->flags->flags[gActiveBattler] &= ~(RESOURCE_FLAG_UNBURDEN); + } + + gBattlescriptCurrInstr += 4; + return; } gBattlescriptCurrInstr += 3; diff --git a/src/battle_util.c b/src/battle_util.c index 7deebd25e3..6c9e141875 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5385,6 +5385,8 @@ bool32 HasEnoughHpToEatBerry(u32 battlerId, u32 hpFraction, u32 itemId) if (gBattleMons[battlerId].hp == 0) return FALSE; + if (gBattleScripting.overrideBerryRequirements) + return TRUE; // Unnerve prevents consumption of opponents' berries. if (isBerry && IsUnnerveAbilityOnOpposingSide(battlerId)) return FALSE; @@ -6095,11 +6097,14 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) } } break; + case ITEMEFFECT_BATTLER_MOVE_END: + goto DO_ITEMEFFECT_MOVE_END; // this hurts a bit to do, but is an easy solution case ITEMEFFECT_MOVE_END: for (battlerId = 0; battlerId < gBattlersCount; battlerId++) { gLastUsedItem = gBattleMons[battlerId].item; battlerHoldEffect = GetBattlerHoldEffect(battlerId, TRUE); + DO_ITEMEFFECT_MOVE_END: switch (battlerHoldEffect) { case HOLD_EFFECT_MICLE_BERRY: From ab529b4e8934afa152ef54ad0189e8a6df7c06d6 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Tue, 27 Jul 2021 10:31:48 -0600 Subject: [PATCH 06/32] add stuff cheeks --- data/battle_scripts_1.s | 28 +++++++++++++++++++++++++ include/battle_scripts.h | 1 + include/constants/battle_move_effects.h | 1 + include/constants/battle_string_ids.h | 3 ++- src/battle_ai_main.c | 12 ++++------- src/battle_message.c | 2 ++ src/battle_util.c | 17 +++++++++++++++ src/data/battle_moves.h | 2 +- 8 files changed, 56 insertions(+), 10 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index d48076e489..37ae9b7301 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -368,6 +368,30 @@ gBattleScriptsForMoveEffects:: @ 82D86A8 .4byte BattleScript_EffectSleepHit .4byte BattleScript_EffectAttackerDefenseDownHit .4byte BattleScript_EffectBodyPress + .4byte BattleScript_EffectStuffCheeks + +BattleScript_EffectStuffCheeks:: + attackcanceler + attackstring + ppreduce + jumpifnotberry BS_ATTACKER, BattleScript_ButItFailed + attackanimation + waitanimation +BattleScript_StuffCheeksEatBerry: + setbyte sBERRY_OVERRIDE, TRUE + orword gHitMarker, HITMARKER_NO_ANIMATIONS + consumeberry BS_ATTACKER + bicword gHitMarker, HITMARKER_NO_ANIMATIONS + setbyte sBERRY_OVERRIDE, FALSE + setstatchanger STAT_DEF, 2, FALSE + statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_BUFF_ALLOW_PTR, BattleScript_StuffCheeksEnd + setgraphicalstatchangevalues + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_StuffCheeksEnd @ cant raise def + playanimation BS_ATTACKER, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1 + printfromtable gStatUpStringIds + waitmessage B_WAIT_TIME_LONG +BattleScript_StuffCheeksEnd: + goto BattleScript_MoveEnd BattleScript_EffectAttackerDefenseDownHit: setmoveeffect MOVE_EFFECT_DEF_MINUS_1 | MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN @@ -5985,6 +6009,10 @@ BattleScript_SelectingNotAllowedMoveGravity:: printselectionstring STRINGID_GRAVITYPREVENTSUSAGE endselectionscript +BattleScript_SelectingNotAllowedStuffCheeks:: + printselectionstring STRINGID_STUFFCHEEKSCANTSELECT + endselectionscript + BattleScript_SelectingNotAllowedBelch:: printselectionstring STRINGID_BELCHCANTSELECT endselectionscript diff --git a/include/battle_scripts.h b/include/battle_scripts.h index f0712fc435..0b81fc6755 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -295,6 +295,7 @@ extern const u8 BattleScript_ProteanActivates[]; extern const u8 BattleScript_DazzlingProtected[]; extern const u8 BattleScript_MoveUsedPsychicTerrainPrevents[]; extern const u8 BattleScript_MoveUsedPowder[]; +extern const u8 BattleScript_SelectingNotAllowedStuffCheeks[]; extern const u8 BattleScript_SelectingNotAllowedBelch[]; extern const u8 BattleScript_SelectingNotAllowedBelchInPalace[]; extern const u8 BattleScript_PsychicSurgeActivates[]; diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index cbab68b661..2e54e9ef3a 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -352,6 +352,7 @@ #define EFFECT_SLEEP_HIT 346 #define EFFECT_ATTACKER_DEFENSE_DOWN_HIT 347 #define EFFECT_BODY_PRESS 348 +#define EFFECT_STUFF_CHEEKS 349 #define NUM_BATTLE_MOVE_EFFECTS 350 diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index cda8856948..e2b97d4438 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -570,8 +570,9 @@ #define STRINGID_MICLEBERRYACTIVATES 566 #define STRINGID_PKMNSHOOKOFFTHETAUNT 567 #define STRINGID_PKMNGOTOVERITSINFATUATION 568 +#define STRINGID_STUFFCHEEKSCANTSELECT 569 -#define BATTLESTRINGS_COUNT 569 +#define BATTLESTRINGS_COUNT 570 // The below IDs are all indexes into battle message tables, // used to determine which of a set of messages to print. diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 81d97fcab6..da978b4271 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -792,21 +792,17 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) if (!BattlerStatCanRise(battlerAtk, AI_DATA->atkAbility, STAT_ATK) || !HasMoveWithSplit(battlerAtk, SPLIT_PHYSICAL)) score -= 10; break; - case EFFECT_DEFENSE_UP_2: - if (move == MOVE_STUFF_CHEEKS && ItemId_GetPocket(gBattleMons[battlerAtk].item) != POCKET_BERRIES) - score -= 10; + case EFFECT_STUFF_CHEEKS: + if (ItemId_GetPocket(gBattleMons[battlerAtk].item) != POCKET_BERRIES) + return 0; // cannot even select //fallthrough case EFFECT_DEFENSE_UP: + case EFFECT_DEFENSE_UP_2: case EFFECT_DEFENSE_UP_3: case EFFECT_DEFENSE_CURL: if (!BattlerStatCanRise(battlerAtk, AI_DATA->atkAbility, STAT_DEF)) score -= 10; break; - case EFFECT_SPEED_UP: - case EFFECT_SPEED_UP_2: - if (!BattlerStatCanRise(battlerAtk, AI_DATA->atkAbility, STAT_SPEED)) - score -= 10; - break; case EFFECT_SPECIAL_ATTACK_UP: case EFFECT_SPECIAL_ATTACK_UP_2: case EFFECT_SPECIAL_ATTACK_UP_3: diff --git a/src/battle_message.c b/src/battle_message.c index c4f043e150..439f88e29c 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -696,9 +696,11 @@ static const u8 sText_CanActFaster[] = _("{B_ATK_NAME_WITH_PREFIX} can act faste static const u8 sText_MicleBerryActivates[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} boosted the accuracy of its\nnext move using {B_LAST_ITEM}!"); static const u8 sText_PkmnShookOffTheTaunt[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} shook off\nthe taunt!"); static const u8 sText_PkmnGotOverItsInfatuation[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} got over\nits infatuation!"); +static const u8 sText_StuffCheeksCantSelect[] = _("Stuff Cheeks cannot be\nselected without a Berry!\p"); const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { + [STRINGID_STUFFCHEEKSCANTSELECT - 12] = sText_StuffCheeksCantSelect, [STRINGID_PKMNGOTOVERITSINFATUATION - 12] = sText_PkmnGotOverItsInfatuation, [STRINGID_PKMNSHOOKOFFTHETAUNT - 12] = sText_PkmnShookOffTheTaunt, [STRINGID_MICLEBERRYACTIVATES - 12] = sText_MicleBerryActivates, diff --git a/src/battle_util.c b/src/battle_util.c index 6c9e141875..99217ce6fe 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -1708,6 +1708,21 @@ u8 TrySetCantSelectMoveBattleScript(void) limitations++; } } + + if (move == MOVE_STUFF_CHEEKS && ItemId_GetPocket(gBattleMons[gActiveBattler].item) != POCKET_BERRIES) + { + gCurrentMove = move; + if (gBattleTypeFlags & BATTLE_TYPE_PALACE) + { + gPalaceSelectionBattleScripts[gActiveBattler] = BattleScript_SelectingNotAllowedBelchInPalace; + gProtectStructs[gActiveBattler].palaceUnableToUseMove = 1; + } + else + { + gSelectionBattleScripts[gActiveBattler] = BattleScript_SelectingNotAllowedStuffCheeks; + limitations++; + } + } gPotentialItemEffectBattler = gActiveBattler; if (HOLD_EFFECT_CHOICE(holdEffect) && *choicedMove != 0 && *choicedMove != 0xFFFF && *choicedMove != move) @@ -1791,6 +1806,8 @@ u8 CheckMoveLimitations(u8 battlerId, u8 unusableMoves, u8 check) unusableMoves |= gBitTable[i]; else if (gDisableStructs[battlerId].throatChopTimer && gBattleMoves[gBattleMons[battlerId].moves[i]].flags & FLAG_SOUND) unusableMoves |= gBitTable[i]; + else if (gBattleMons[battlerId].moves[i] == MOVE_STUFF_CHEEKS && ItemId_GetPocket(gBattleMons[gActiveBattler].item) != POCKET_BERRIES) + unusableMoves |= gBitTable[i]; } return unusableMoves; } diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 9fc79581f5..416c5b850c 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -10771,7 +10771,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_STUFF_CHEEKS] = { - .effect = EFFECT_DEFENSE_UP_2, + .effect = EFFECT_STUFF_CHEEKS, .power = 0, .type = TYPE_NORMAL, .accuracy = 0, From d3446123461ee5ccfdf803934189244b351b459f Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Thu, 12 Aug 2021 14:49:17 -0600 Subject: [PATCH 07/32] fix last used ball window in wild doubles --- src/battle_interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_interface.c b/src/battle_interface.c index 1564881e4f..28d6bc97c9 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -3183,7 +3183,7 @@ static const struct SpriteSheet sSpriteSheet_LastUsedBallWindow = #define LAST_USED_BALL_X_F 15 #define LAST_USED_BALL_X_0 -15 -#define LAST_USED_BALL_Y 68 +#define LAST_USED_BALL_Y ((IsDoubleBattle()) ? 78 : 68) #define LAST_BALL_WIN_X_F (LAST_USED_BALL_X_F - 1) #define LAST_BALL_WIN_X_0 (LAST_USED_BALL_X_0 - 0) From e4fb9c4593c8f37700005376b55c6e14c7a3a63d Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Tue, 31 Aug 2021 12:51:03 -0400 Subject: [PATCH 08/32] fix throwing ball in wild doubles --- src/battle_main.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/battle_main.c b/src/battle_main.c index c728ae266a..9e08fbbbcf 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -4055,6 +4055,7 @@ static void HandleTurnActionSelectionState(void) gBattleCommunication[gActiveBattler]++; break; case B_ACTION_THROW_BALL: + gBattleStruct->throwingPokeBall = TRUE; gBattleCommunication[gActiveBattler]++; break; case B_ACTION_SAFARI_POKEBLOCK: @@ -4170,6 +4171,13 @@ static void HandleTurnActionSelectionState(void) if (gBattleCommunication[ACTIONS_CONFIRMED_COUNT] == gBattlersCount) { sub_818603C(1); + + if (WILD_DOUBLE_BATTLE && gBattleStruct->throwingPokeBall) { + // if we choose to throw a ball with our second mon, skip the action of the first + // (if we have chosen throw ball with first, second's is already skipped) + gChosenActionByBattler[B_POSITION_PLAYER_LEFT] = B_ACTION_NOTHING_FAINTED; + } + gBattleMainFunc = SetActionsAndBattlersTurnOrder; if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) From 88476e0ac27c7fe44450a3f27feebc588ea95090 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Tue, 31 Aug 2021 12:59:20 -0400 Subject: [PATCH 09/32] remove 2nd case in CanThrowBall --- src/item_use.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/item_use.c b/src/item_use.c index ad7a464996..5a5cd6a521 100755 --- a/src/item_use.c +++ b/src/item_use.c @@ -943,11 +943,14 @@ u32 CanThrowBall(void) { return 1; // There are two present pokemon. } - else if (gBattlerInMenuId == GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT) + /*else if (gBattlerInMenuId == GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT) && IsBattlerAlive(GetBattlerAtPosition(B_POSITION_PLAYER_LEFT))) { + /* * this is removed. instead, selecting a ball to throw with the second mon just clears the action of your first mon. + * see the end of HandleTurnActionSelectionState in battle_main.c + */ return 2; // Attempting to throw a ball with the second pokemon while both are alive. - } + }*/ else if (IsPlayerPartyAndPokemonStorageFull() == TRUE) { return 3; // No room for mon From 39a254f80d240243f6e3a0568d0ae98f3ba0d5a5 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Wed, 1 Sep 2021 07:45:41 -0400 Subject: [PATCH 10/32] fix sprite pos changes --- src/battle_interface.c | 24 ++++++++++++------------ src/item_use.c | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/battle_interface.c b/src/battle_interface.c index e17036faae..5f3eecaac4 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -3218,8 +3218,8 @@ void TryAddLastUsedBallItemSprites(void) if (gBattleStruct->ballSpriteIds[0] == MAX_SPRITES) { gBattleStruct->ballSpriteIds[0] = AddItemIconSprite(102, 102, gSaveBlock2Ptr->lastUsedBall); - gSprites[gBattleStruct->ballSpriteIds[0]].pos1.x = LAST_USED_BALL_X_0; - gSprites[gBattleStruct->ballSpriteIds[0]].pos1.y = LAST_USED_BALL_Y; + gSprites[gBattleStruct->ballSpriteIds[0]].x = LAST_USED_BALL_X_0; + gSprites[gBattleStruct->ballSpriteIds[0]].y = LAST_USED_BALL_Y; gSprites[gBattleStruct->ballSpriteIds[0]].sHide = FALSE; // restore gSprites[gBattleStruct->ballSpriteIds[0]].callback = SpriteCB_LastUsedBall; } @@ -3258,16 +3258,16 @@ static void SpriteCB_LastUsedBallWin(struct Sprite *sprite) { if (sprite->sHide) { - if (sprite->pos1.x != LAST_BALL_WIN_X_0) - sprite->pos1.x--; + if (sprite->x != LAST_BALL_WIN_X_0) + sprite->x--; - if (sprite->pos1.x == LAST_BALL_WIN_X_0) + if (sprite->x == LAST_BALL_WIN_X_0) DestroyLastUsedBallWinGfx(sprite); } else { - if (sprite->pos1.x != LAST_BALL_WIN_X_F) - sprite->pos1.x++; + if (sprite->x != LAST_BALL_WIN_X_F) + sprite->x++; } } @@ -3275,16 +3275,16 @@ static void SpriteCB_LastUsedBall(struct Sprite *sprite) { if (sprite->sHide) { - if (sprite->pos1.x != LAST_USED_BALL_X_0) - sprite->pos1.x--; + if (sprite->x != LAST_USED_BALL_X_0) + sprite->x--; - if (sprite->pos1.x == LAST_USED_BALL_X_0) + if (sprite->x == LAST_USED_BALL_X_0) DestroyLastUsedBallGfx(sprite); } else { - if (sprite->pos1.x != LAST_USED_BALL_X_F) - sprite->pos1.x++; + if (sprite->x != LAST_USED_BALL_X_F) + sprite->x++; } } diff --git a/src/item_use.c b/src/item_use.c index d0aa82b858..63854a1ac1 100755 --- a/src/item_use.c +++ b/src/item_use.c @@ -966,7 +966,7 @@ void ItemUseInBattle_PokeBall(u8 taskId) break; case 1: // There are two present pokemon. if (!InBattlePyramid()) - DisplayItemMessage(taskId, 1, sText_CantThrowPokeBall_TwoMons, BagMenu_InitListsMenu); + DisplayItemMessage(taskId, 1, sText_CantThrowPokeBall_TwoMons, CloseItemMessage); else DisplayItemMessageInBattlePyramid(taskId, sText_CantThrowPokeBall_TwoMons, Task_CloseBattlePyramidBagMessage); break; From 9c94eb6140a0752d5bef391c3679c68af14d5404 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Thu, 16 Sep 2021 10:24:32 -0400 Subject: [PATCH 11/32] but it failed check for rototiller --- asm/macros/battle_script.inc | 10 +++++ data/battle_scripts_1.s | 40 +++++++++++-------- include/battle.h | 1 + include/constants/battle_script_commands.h | 2 + src/battle_script_commands.c | 45 ++++++++++++++++++++++ 5 files changed, 83 insertions(+), 15 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 662bfbf2f5..a2d9407370 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1776,6 +1776,16 @@ .macro pickpocketsteal various 0, VARIOUS_PICKPOCKET .endm + + .macro getrototillertargets ptr:req + various BS_ATTACKER, VARIOUS_GET_ROTOTILLER_TARGETS + .4byte \ptr + .endm + + .macro jumpifnotrototilleraffected battler:req, ptr:req + various \battler, VARIOUS_JUMP_IF_NOT_ROTOTILLER_AFFECTED + .4byte \ptr + .endm @ helpful macros .macro setstatchanger stat:req, stages:req, down:req diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 2d6db5a289..177c657ce3 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -814,27 +814,28 @@ BattleScript_FlowerShieldMoveTargetEnd: moveendto MOVEEND_NEXT_TARGET jumpifnexttargetvalid BattleScript_FlowerShieldLoop end + +BattleScript_RototillerRet:: + + return BattleScript_EffectRototiller: attackcanceler attackstring ppreduce - selectfirstvalidtarget -BattleScript_RototillerLoop: - movevaluescleanup - jumpifnotgrounded BS_TARGET, BattleScript_RototillerNoEffect - jumpiftype BS_TARGET, TYPE_GRASS, BattleScript_RototillerLoop2 -BattleScript_RototillerNoEffect: - pause B_WAIT_TIME_SHORT - printstring STRINGID_NOEFFECTONTARGET - waitmessage B_WAIT_TIME_LONG - goto BattleScript_RototillerMoveTargetEnd -BattleScript_RototillerLoop2: - jumpifstat BS_TARGET, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE, BattleScript_RototillerDoMoveAnim - jumpifstat BS_TARGET, CMP_EQUAL, STAT_SPATK, MAX_STAT_STAGE, BattleScript_RototillerCantRaiseMultipleStats -BattleScript_RototillerDoMoveAnim:: + getrototillertargets BattleScript_ButItFailed + @ at least one battler is affected attackanimation waitanimation + savetarget + setbyte gBattlerTarget, 0 +BattleScript_RototillerLoop: + movevaluescleanup + jumpifstat BS_TARGET, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE, BattleScript_RototillerCheckAffected + jumpifstat BS_TARGET, CMP_EQUAL, STAT_SPATK, MAX_STAT_STAGE, BattleScript_RototillerCantRaiseMultipleStats +BattleScript_RototillerCheckAffected: + jumpifnotrototilleraffected BS_TARGET, BattleScript_RototillerNoEffect +BattleScript_RototillerAffected: setbyte sSTAT_ANIM_PLAYED, FALSE playstatchangeanimation BS_TARGET, BIT_ATK | BIT_SPATK, 0 setstatchanger STAT_ATK, 1, FALSE @@ -850,13 +851,22 @@ BattleScript_RototillerTrySpAtk:: waitmessage B_WAIT_TIME_LONG BattleScript_RototillerMoveTargetEnd: moveendto MOVEEND_NEXT_TARGET - jumpifnexttargetvalid BattleScript_RototillerLoop + addbyte gBattlerTarget, 1 + jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_RototillerLoop end + BattleScript_RototillerCantRaiseMultipleStats: + copybyte gBattlerAttacker, gBattlerTarget printstring STRINGID_STATSWONTINCREASE2 waitmessage B_WAIT_TIME_LONG goto BattleScript_RototillerMoveTargetEnd +BattleScript_RototillerNoEffect: + pause B_WAIT_TIME_SHORT + printstring STRINGID_NOEFFECTONTARGET + waitmessage B_WAIT_TIME_LONG + goto BattleScript_RototillerMoveTargetEnd + BattleScript_EffectBestow: attackcanceler accuracycheck BattleScript_PrintMoveMissed, NO_ACC_CALC_CHECK_LOCK_ON diff --git a/include/battle.h b/include/battle.h index 3fbefe55bd..576884d815 100644 --- a/include/battle.h +++ b/include/battle.h @@ -169,6 +169,7 @@ struct SpecialStatus u8 instructedChosenTarget:3; u8 berryReduced:1; u8 gemBoost:1; + u8 rototillerAffected:1; // to be affected by rototiller u8 gemParam; u8 damagedMons:4; // Mons that have been damaged directly by using a move, includes substitute. u8 dancerUsedMove:1; diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 7e7bb6ca9e..6c5e3872ae 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -174,6 +174,8 @@ #define VARIOUS_TOTEM_BOOST 103 #define VARIOUS_TRY_ACTIVATE_GRIM_NEIGH 104 #define VARIOUS_MOVEEND_ITEM_EFFECTS 105 +#define VARIOUS_GET_ROTOTILLER_TARGETS 106 +#define VARIOUS_JUMP_IF_NOT_ROTOTILLER_AFFECTED 107 // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 05702aec6b..a719db5506 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -7246,6 +7246,21 @@ static u32 GetHighestStatId(u32 battlerId) return highestId; } +static bool32 IsRototillerAffected(u32 battlerId) +{ + if (!IsBattlerAlive(battlerId)) + return FALSE; + if (!IsBattlerGrounded(battlerId)) + return FALSE; // Only grounded battlers affected + if (!IS_BATTLER_OF_TYPE(battlerId, TYPE_GRASS)) + return FALSE; // Only grass types affected + if (gStatuses3[battlerId] & STATUS3_SEMI_INVULNERABLE) + return FALSE; // Rototiller doesn't affected semi-invulnerable battlers + //if (!CompareStat(battlerId, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN) && !CompareStat(battlerId, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN)) + //return FALSE; // Battler unaffected if atk and spatk are maxed + return TRUE; +} + static void Cmd_various(void) { struct Pokemon *mon; @@ -8498,6 +8513,36 @@ static void Cmd_various(void) if (ItemBattleEffects(1, gActiveBattler, FALSE)) return; break; + case VARIOUS_GET_ROTOTILLER_TARGETS: + // Gets the battlers to be affected by rototiller. If there are none, print 'But it failed!' + { + u32 count = 0; + for (i = 0; i < gBattlersCount; i++) + { + if (IsRototillerAffected(i)) + { + gSpecialStatuses[i].rototillerAffected = 1; + count++; + } + } + + if (count == 0) + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); // Rototiller fails + else + gBattlescriptCurrInstr += 7; + } + return; + case VARIOUS_JUMP_IF_NOT_ROTOTILLER_AFFECTED: + if (gSpecialStatuses[gActiveBattler].rototillerAffected) + { + gSpecialStatuses[gActiveBattler].rototillerAffected = 0; + gBattlescriptCurrInstr += 7; + } + else + { + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); // Unaffected by rototiller - print STRINGID_NOEFFECTONTARGET + } + return; } gBattlescriptCurrInstr += 3; From aac7ae359518c3610fb02f91b05b244172208944 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Thu, 16 Sep 2021 10:45:33 -0400 Subject: [PATCH 12/32] add MOVE_TARGET_ALL_BATTLERS --- include/constants/battle.h | 2 + src/battle_controller_player.c | 84 ++++++++++++++++++++++++++++------ src/data/battle_moves.h | 4 +- 3 files changed, 74 insertions(+), 16 deletions(-) diff --git a/include/constants/battle.h b/include/constants/battle.h index 73d5c3debe..53e933944a 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -379,4 +379,6 @@ #define MOVE_TARGET_OPPONENTS_FIELD 0x40 #define MOVE_TARGET_ALLY 0x80 +#define MOVE_TARGET_ALL_BATTLERS (MOVE_TARGET_BOTH | MOVE_TARGET_OPPONENTS_FIELD) + #endif // GUARD_CONSTANTS_BATTLE_H diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index 841e303270..70a8f51e9d 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -485,6 +485,19 @@ static void HandleInputChooseTarget(void) } } +static void HideAllTargets(void) +{ + s32 i; + for (i = 0; i < MAX_BATTLERS_COUNT; i++) + { + if (IsBattlerAlive(i) && gBattleSpritesDataPtr->healthBoxesData[i].healthboxIsBouncing) + { + gSprites[gBattlerSpriteIds[i]].callback = SpriteCb_HideAsMoveTarget; + EndBounceEffect(i, BOUNCE_HEALTHBOX); + } + } +} + static void HideShownTargets(void) { s32 i; @@ -498,6 +511,34 @@ static void HideShownTargets(void) } } +static void HandleInputShowEntireFieldTargets(void) +{ + if (JOY_HELD(DPAD_ANY) && gSaveBlock2Ptr->optionsButtonMode == OPTIONS_BUTTON_MODE_L_EQUALS_A) + gPlayerDpadHoldFrames++; + else + gPlayerDpadHoldFrames = 0; + + if (JOY_NEW(A_BUTTON)) + { + PlaySE(SE_SELECT); + HideAllTargets(); + if (gBattleStruct->mega.playerSelect) + BtlController_EmitTwoReturnValues(1, 10, gMoveSelectionCursor[gActiveBattler] | RET_MEGA_EVOLUTION | (gMultiUsePlayerCursor << 8)); + else + BtlController_EmitTwoReturnValues(1, 10, gMoveSelectionCursor[gActiveBattler] | (gMultiUsePlayerCursor << 8)); + HideMegaTriggerSprite(); + PlayerBufferExecCompleted(); + } + else if (gMain.newKeys & B_BUTTON || gPlayerDpadHoldFrames > 59) + { + PlaySE(SE_SELECT); + HideAllTargets(); + gBattlerControllerFuncs[gActiveBattler] = HandleInputChooseMove; + DoBounceEffect(gActiveBattler, BOUNCE_HEALTHBOX, 7, 1); + DoBounceEffect(gActiveBattler, BOUNCE_MON, 7, 1); + } +} + static void HandleInputShowTargets(void) { if (JOY_HELD(DPAD_ANY) && gSaveBlock2Ptr->optionsButtonMode == OPTIONS_BUTTON_MODE_L_EQUALS_A) @@ -589,27 +630,39 @@ static void HandleInputChooseMove(void) } // Show all available targets for multi-target moves - if (B_SHOW_TARGETS && moveTarget & (MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)) + if (B_SHOW_TARGETS) { - TryShowAsTarget(gMultiUsePlayerCursor); - TryShowAsTarget(BATTLE_PARTNER(gMultiUsePlayerCursor)); - if (moveTarget & MOVE_TARGET_FOES_AND_ALLY) - TryShowAsTarget(BATTLE_PARTNER(gActiveBattler)); - canSelectTarget = 2; + if ((moveTarget & MOVE_TARGET_ALL_BATTLERS) == MOVE_TARGET_ALL_BATTLERS) + { + u32 i = 0; + for (i = 0; i < gBattlersCount; i++) + TryShowAsTarget(i); + + canSelectTarget = 3; + } + else if (moveTarget & (MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)) + { + TryShowAsTarget(gMultiUsePlayerCursor); + TryShowAsTarget(BATTLE_PARTNER(gMultiUsePlayerCursor)); + if (moveTarget & MOVE_TARGET_FOES_AND_ALLY) + TryShowAsTarget(BATTLE_PARTNER(gActiveBattler)); + canSelectTarget = 2; + } } } - - if (canSelectTarget == 0) + + switch (canSelectTarget) { + case 0: + default: if (gBattleStruct->mega.playerSelect) BtlController_EmitTwoReturnValues(1, 10, gMoveSelectionCursor[gActiveBattler] | RET_MEGA_EVOLUTION | (gMultiUsePlayerCursor << 8)); else BtlController_EmitTwoReturnValues(1, 10, gMoveSelectionCursor[gActiveBattler] | (gMultiUsePlayerCursor << 8)); HideMegaTriggerSprite(); PlayerBufferExecCompleted(); - } - else if (canSelectTarget == 1) - { + break; + case 1: gBattlerControllerFuncs[gActiveBattler] = HandleInputChooseTarget; if (moveTarget & (MOVE_TARGET_USER | MOVE_TARGET_USER_OR_SELECTED)) @@ -620,10 +673,13 @@ static void HandleInputChooseMove(void) gMultiUsePlayerCursor = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); gSprites[gBattlerSpriteIds[gMultiUsePlayerCursor]].callback = SpriteCb_ShowAsMoveTarget; - } - else - { + break; + case 2: gBattlerControllerFuncs[gActiveBattler] = HandleInputShowTargets; + break; + case 3: // Entire field + gBattlerControllerFuncs[gActiveBattler] = HandleInputShowEntireFieldTargets; + break; } } else if (JOY_NEW(B_BUTTON) || gPlayerDpadHoldFrames > 59) diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 657341b5ef..a63aca114c 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -8838,7 +8838,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .accuracy = 0, .pp = 10, .secondaryEffectChance = 0, - .target = MOVE_TARGET_FOES_AND_ALLY | MOVE_TARGET_USER, + .target = MOVE_TARGET_ALL_BATTLERS, .priority = 0, .flags = 0, .split = SPLIT_STATUS, @@ -9083,7 +9083,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .accuracy = 0, .pp = 10, .secondaryEffectChance = 0, - .target = MOVE_TARGET_USER | MOVE_TARGET_FOES_AND_ALLY, + .target = MOVE_TARGET_ALL_BATTLERS, .priority = 0, .flags = 0, .split = SPLIT_STATUS, From 3f34fec42fb3aa55173e207c384e3b40f1e46591 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Thu, 23 Sep 2021 12:03:01 -0400 Subject: [PATCH 13/32] change last ball graphic based on config. replace saveblock field with ewram field --- .../battle_interface/last_used_ball_l.png | Bin 0 -> 214 bytes ...ast_used_ball.png => last_used_ball_r.png} | Bin include/battle.h | 1 + src/battle_interface.c | 36 ++++++++++++++---- src/battle_main.c | 1 + src/battle_script_commands.c | 2 +- src/battle_util.c | 2 +- 7 files changed, 32 insertions(+), 10 deletions(-) create mode 100644 graphics/battle_interface/last_used_ball_l.png rename graphics/battle_interface/{last_used_ball.png => last_used_ball_r.png} (100%) diff --git a/graphics/battle_interface/last_used_ball_l.png b/graphics/battle_interface/last_used_ball_l.png new file mode 100644 index 0000000000000000000000000000000000000000..90fcef37398ed2b8bef3c2cc0649bc4ad9a8fac1 GIT binary patch literal 214 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvg8-ipSH_Le)y2(0UQw2Yj+z{f zK*sa;Uw{7n50nRj?BZfCCy?fA*Uq){^Z*&j&Z>)mRHCPgV~EDY^unv_P&x8 zS#yg)?8er2d6p7uYPU)$efU;Y`Lk$&!&Tdk1N(LxH11ySDHySpEAoNZk!hg?jk{ML zNYHg+U~^;L!1<<%`?2$5R*B*OhF;5_9Y;HAOBfhR1(d!8PtREbw2Z;i)z4*}Q$iB} D1m#Ns literal 0 HcmV?d00001 diff --git a/graphics/battle_interface/last_used_ball.png b/graphics/battle_interface/last_used_ball_r.png similarity index 100% rename from graphics/battle_interface/last_used_ball.png rename to graphics/battle_interface/last_used_ball_r.png diff --git a/include/battle.h b/include/battle.h index 54693a33b7..0becc4dd4a 100644 --- a/include/battle.h +++ b/include/battle.h @@ -890,5 +890,6 @@ extern u8 gNumberOfMovesToChoose; extern u8 gBattleControllerData[MAX_BATTLERS_COUNT]; extern bool8 gHasFetchedBall; extern u8 gLastUsedBall; +extern u16 gLastThrownBall; #endif // GUARD_BATTLE_H diff --git a/src/battle_interface.c b/src/battle_interface.c index 5f3eecaac4..4a3d1eaec5 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -30,6 +30,7 @@ #include "item_icon.h" #include "item_use.h" #include "item.h" +#include "constants/items.h" enum { // Corresponds to gHealthboxElementsGfxTable (and the tables after it) in graphics.c @@ -3175,7 +3176,11 @@ static const struct SpriteTemplate sSpriteTemplate_LastUsedBallWindow = .callback = SpriteCB_LastUsedBallWin }; -static const u8 sLastUsedBallWindowGfx[] = INCBIN_U8("graphics/battle_interface/last_used_ball.4bpp"); +#if B_LAST_USED_BALL_BUTTON == R_BUTTON + static const u8 sLastUsedBallWindowGfx[] = INCBIN_U8("graphics/battle_interface/last_used_ball_r.4bpp"); +#else + static const u8 sLastUsedBallWindowGfx[] = INCBIN_U8("graphics/battle_interface/last_used_ball_r.4bpp"); +#endif static const struct SpriteSheet sSpriteSheet_LastUsedBallWindow = { sLastUsedBallWindowGfx, sizeof(sLastUsedBallWindowGfx), LAST_BALL_WINDOW_TAG @@ -3193,31 +3198,39 @@ static const struct SpriteSheet sSpriteSheet_LastUsedBallWindow = bool32 CanThrowLastUsedBall(void) { - return (!(CanThrowBall() != 0 - || (gBattleTypeFlags & BATTLE_TYPE_TRAINER) - || !CheckBagHasItem(gSaveBlock2Ptr->lastUsedBall, 1))); + #if B_LAST_USED_BALL == FALSE + return FALSE; + #else + return (!(CanThrowBall() != 0 + || (gBattleTypeFlags & BATTLE_TYPE_TRAINER) + || !CheckBagHasItem(gLastThrownBall, 1))); + #endif } void TryAddLastUsedBallItemSprites(void) { - if (gSaveBlock2Ptr->lastUsedBall != 0 && !CheckBagHasItem(gSaveBlock2Ptr->lastUsedBall, 1)) + #if B_LAST_USED_BALL == TRUE + if (gLastThrownBall == 0) + gLastThrownBall = ITEM_POKE_BALL; + + if (gLastThrownBall != 0 && !CheckBagHasItem(gLastThrownBall, 1)) { // we're out of the last used ball, so just set it to the first ball in the bag // we have to compact the bag first bc it is typically only compacted when you open it CompactItemsInBagPocket(&gBagPockets[BALLS_POCKET]); - gSaveBlock2Ptr->lastUsedBall = gBagPockets[BALLS_POCKET].itemSlots[0].itemId; + gLastThrownBall = gBagPockets[BALLS_POCKET].itemSlots[0].itemId; } if (CanThrowBall() != 0 || (gBattleTypeFlags & BATTLE_TYPE_TRAINER) - || !CheckBagHasItem(gSaveBlock2Ptr->lastUsedBall, 1)) + || !CheckBagHasItem(gLastThrownBall, 1)) return; // ball if (gBattleStruct->ballSpriteIds[0] == MAX_SPRITES) { - gBattleStruct->ballSpriteIds[0] = AddItemIconSprite(102, 102, gSaveBlock2Ptr->lastUsedBall); + gBattleStruct->ballSpriteIds[0] = AddItemIconSprite(102, 102, gLastThrownBall); gSprites[gBattleStruct->ballSpriteIds[0]].x = LAST_USED_BALL_X_0; gSprites[gBattleStruct->ballSpriteIds[0]].y = LAST_USED_BALL_Y; gSprites[gBattleStruct->ballSpriteIds[0]].sHide = FALSE; // restore @@ -3236,6 +3249,7 @@ void TryAddLastUsedBallItemSprites(void) LAST_USED_WIN_Y, 5); gSprites[gBattleStruct->ballSpriteIds[0]].sHide = FALSE; // restore } + #endif } static void DestroyLastUsedBallWinGfx(struct Sprite *sprite) @@ -3290,6 +3304,7 @@ static void SpriteCB_LastUsedBall(struct Sprite *sprite) static void TryHideOrRestoreLastUsedBall(u8 caseId) { + #if B_LAST_USED_BALL == TRUE if (gBattleStruct->ballSpriteIds[0] == MAX_SPRITES) return; @@ -3308,18 +3323,23 @@ static void TryHideOrRestoreLastUsedBall(u8 caseId) gSprites[gBattleStruct->ballSpriteIds[1]].sHide = FALSE; // restore break; } + #endif } void TryHideLastUsedBall(void) { + #if B_LAST_USED_BALL == TRUE TryHideOrRestoreLastUsedBall(0); + #endif } void TryRestoreLastUsedBall(void) { + #if B_LAST_USED_BALL == TRUE if (gBattleStruct->ballSpriteIds[0] != MAX_SPRITES) TryHideOrRestoreLastUsedBall(1); else TryAddLastUsedBallItemSprites(); + #endif } diff --git a/src/battle_main.c b/src/battle_main.c index b1cc8bbc4a..b8b013635c 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -230,6 +230,7 @@ EWRAM_DATA u16 gPartnerSpriteId = 0; EWRAM_DATA struct TotemBoost gTotemBoosts[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA bool8 gHasFetchedBall = FALSE; EWRAM_DATA u8 gLastUsedBall = 0; +EWRAM_DATA u16 gLastThrownBall = 0; // IWRAM common vars void (*gPreBattleCallback1)(void); diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index cd64a2497e..313f478784 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -12021,7 +12021,7 @@ static void Cmd_handleballthrow(void) u32 odds; u8 catchRate; - gSaveBlock2Ptr->lastUsedBall = gLastUsedItem; + gLastThrownBall = gLastUsedItem; if (gLastUsedItem == ITEM_SAFARI_BALL) catchRate = gBattleStruct->safariCatchFactor * 1275 / 100; else diff --git a/src/battle_util.c b/src/battle_util.c index 04070bf7ec..f482d40ddf 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -759,7 +759,7 @@ void HandleAction_ThrowBall(void) gBattlerAttacker = gBattlerByTurnOrder[gCurrentTurnActionNumber]; gBattle_BG0_X = 0; gBattle_BG0_Y = 0; - gLastUsedItem = gSaveBlock2Ptr->lastUsedBall; + gLastUsedItem = gLastThrownBall; RemoveBagItem(gLastUsedItem, 1); gBattlescriptCurrInstr = BattleScript_BallThrow; gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT; From 768598b1545b361a3a5f3e312a2d66c2d510f1a3 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Thu, 23 Sep 2021 12:22:36 -0400 Subject: [PATCH 14/32] fix bad merge --- include/battle_util.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/battle_util.h b/include/battle_util.h index d01ca3411d..15b238b17d 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -48,7 +48,6 @@ struct TypePower extern const struct TypePower gNaturalGiftTable[]; void HandleAction_ThrowBall(void); -bool32 IsAffectedByFollowMe(u32 battlerAtk, u32 defSide); bool32 IsAffectedByFollowMe(u32 battlerAtk, u32 defSide, u32 move); void HandleAction_UseMove(void); void HandleAction_Switch(void); From 3925c07c1a2e7c6b3803e66f49f4af316fe26aec Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Thu, 23 Sep 2021 13:20:32 -0400 Subject: [PATCH 15/32] fix l graphic --- src/battle_interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_interface.c b/src/battle_interface.c index 4a3d1eaec5..63a05860d3 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -3179,7 +3179,7 @@ static const struct SpriteTemplate sSpriteTemplate_LastUsedBallWindow = #if B_LAST_USED_BALL_BUTTON == R_BUTTON static const u8 sLastUsedBallWindowGfx[] = INCBIN_U8("graphics/battle_interface/last_used_ball_r.4bpp"); #else - static const u8 sLastUsedBallWindowGfx[] = INCBIN_U8("graphics/battle_interface/last_used_ball_r.4bpp"); + static const u8 sLastUsedBallWindowGfx[] = INCBIN_U8("graphics/battle_interface/last_used_ball_l.4bpp"); #endif static const struct SpriteSheet sSpriteSheet_LastUsedBallWindow = { From 728756052160a844db62cd746b39666a42215b7e Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Fri, 1 Oct 2021 18:28:51 -0300 Subject: [PATCH 16/32] Fixed confuse berries affecting the wrong battler. --- data/battle_scripts_1.s | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index f1f5995ffb..2ce0adf684 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -8041,22 +8041,22 @@ BattleScript_BerryConfuseHealEnd2_Anim: end2 BattleScript_BerryConfuseHealRet:: - jumpifability BS_SCRIPTING, ABILITY_RIPEN, BattleScript_BerryConfuseHealRet_AbilityPopup + jumpifability BS_ATTACKER, ABILITY_RIPEN, BattleScript_BerryConfuseHealRet_AbilityPopup goto BattleScript_BerryConfuseHealRet_Anim BattleScript_BerryConfuseHealRet_AbilityPopup: call BattleScript_AbilityPopUp BattleScript_BerryConfuseHealRet_Anim: - playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT, NULL + playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT, NULL printstring STRINGID_PKMNSITEMRESTOREDHEALTH waitmessage B_WAIT_TIME_LONG orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE - healthbarupdate BS_SCRIPTING - datahpupdate BS_SCRIPTING + healthbarupdate BS_ATTACKER + datahpupdate BS_ATTACKER printstring STRINGID_FORXCOMMAYZ waitmessage B_WAIT_TIME_LONG setmoveeffect MOVE_EFFECT_CONFUSION | MOVE_EFFECT_AFFECTS_USER seteffectprimary - removeitem BS_SCRIPTING + removeitem BS_ATTACKER return BattleScript_BerryStatRaiseEnd2:: From 1ad8448532c33f0962e1bfe8c6838ccc22b23686 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Wed, 6 Oct 2021 13:54:33 -0400 Subject: [PATCH 17/32] remove saveblock field --- include/global.h | 3 +-- src/new_game.c | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/include/global.h b/include/global.h index a0aa45d3d0..53a6175a27 100644 --- a/include/global.h +++ b/include/global.h @@ -485,8 +485,7 @@ struct SaveBlock2 u16 optionsBattleSceneOff:1; // whether battle animations are disabled u16 regionMapZoom:1; // whether the map is zoomed in /*0x18*/ struct Pokedex pokedex; - /*0x90*/ u16 lastUsedBall; - /*0x92*/ u8 filler_90[0x6]; + /*0x90*/ u8 filler_90[0x8]; /*0x98*/ struct Time localTimeOffset; /*0xA0*/ struct Time lastBerryTreeUpdate; /*0xA8*/ u32 gcnLinkFlags; // Read by Pokemon Colosseum/XD diff --git a/src/new_game.c b/src/new_game.c index c1dd85e90d..e0453c9ad3 100644 --- a/src/new_game.c +++ b/src/new_game.c @@ -205,7 +205,6 @@ void NewGameInitData(void) WipeTrainerNameRecords(); ResetTrainerHillResults(); ResetContestLinkResults(); - gSaveBlock2Ptr->lastUsedBall = ITEM_POKE_BALL; } static void ResetMiniGamesRecords(void) From 3d24fd5f3094a20cf1325607148323e397a6f00c Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Wed, 6 Oct 2021 13:56:04 -0400 Subject: [PATCH 18/32] last ball defaults to first bag pocket item --- src/battle_interface.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/battle_interface.c b/src/battle_interface.c index c1f76c6ce6..b3bb981c70 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -3206,10 +3206,8 @@ bool32 CanThrowLastUsedBall(void) void TryAddLastUsedBallItemSprites(void) { #if B_LAST_USED_BALL == TRUE - if (gLastThrownBall == 0) - gLastThrownBall = ITEM_POKE_BALL; - - if (gLastThrownBall != 0 && !CheckBagHasItem(gLastThrownBall, 1)) + if ((gLastThrownBall == 0 + || (gLastThrownBall != 0 && !CheckBagHasItem(gLastThrownBall, 1))) { // we're out of the last used ball, so just set it to the first ball in the bag // we have to compact the bag first bc it is typically only compacted when you open it From 33d19d4e348a5bdf0009ebe488e61a78684ca00a Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Wed, 6 Oct 2021 14:19:15 -0400 Subject: [PATCH 19/32] syntax fix --- src/battle_interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_interface.c b/src/battle_interface.c index b3bb981c70..0e33455ac3 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -3206,7 +3206,7 @@ bool32 CanThrowLastUsedBall(void) void TryAddLastUsedBallItemSprites(void) { #if B_LAST_USED_BALL == TRUE - if ((gLastThrownBall == 0 + if (gLastThrownBall == 0 || (gLastThrownBall != 0 && !CheckBagHasItem(gLastThrownBall, 1))) { // we're out of the last used ball, so just set it to the first ball in the bag From 11f4f0f08e42a2d6b9c0ba56b9938e755601ea7e Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Wed, 6 Oct 2021 14:41:48 -0400 Subject: [PATCH 20/32] update move data to those that target all battlers --- src/data/battle_moves.h | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index a63aca114c..98b30951e4 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -1789,7 +1789,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .accuracy = 0, .pp = 30, .secondaryEffectChance = 0, - .target = MOVE_TARGET_USER, + .target = MOVE_TARGET_ALL_BATTLERS, .priority = 0, .flags = FLAG_PROTECT_AFFECTED, .split = SPLIT_STATUS, @@ -3100,7 +3100,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .accuracy = 0, .pp = 5, .secondaryEffectChance = 0, - .target = MOVE_TARGET_USER, + .target = MOVE_TARGET_ALL_BATTLERS, .priority = 0, .flags = FLAG_SOUND, .split = SPLIT_STATUS, @@ -3204,7 +3204,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .accuracy = 0, .pp = 10, .secondaryEffectChance = 0, - .target = MOVE_TARGET_USER, + .target = MOVE_TARGET_ALL_BATTLERS, .priority = 0, .flags = 0, .split = SPLIT_STATUS, @@ -3804,7 +3804,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .accuracy = 0, .pp = 5, .secondaryEffectChance = 0, - .target = MOVE_TARGET_USER, + .target = MOVE_TARGET_ALL_BATTLERS, .priority = 0, .flags = 0, .split = SPLIT_STATUS, @@ -3818,7 +3818,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .accuracy = 0, .pp = 5, .secondaryEffectChance = 0, - .target = MOVE_TARGET_USER, + .target = MOVE_TARGET_ALL_BATTLERS, .priority = 0, .flags = 0, .split = SPLIT_STATUS, @@ -4125,7 +4125,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .accuracy = 0, .pp = 10, .secondaryEffectChance = 0, - .target = MOVE_TARGET_USER, + .target = MOVE_TARGET_ALL_BATTLERS, .priority = 0, .flags = FLAG_PROTECT_AFFECTED, .split = SPLIT_STATUS, @@ -4768,7 +4768,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .accuracy = 100, .pp = 15, .secondaryEffectChance = 0, - .target = MOVE_TARGET_USER, + .target = MOVE_TARGET_ALL_BATTLERS, .priority = 0, .flags = 0, .split = SPLIT_STATUS, @@ -5504,7 +5504,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .accuracy = 100, .pp = 15, .secondaryEffectChance = 0, - .target = MOVE_TARGET_USER, + .target = MOVE_TARGET_ALL_BATTLERS, .priority = 0, .flags = 0, .split = SPLIT_STATUS, @@ -5661,7 +5661,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .accuracy = 0, .pp = 5, .secondaryEffectChance = 0, - .target = MOVE_TARGET_USER, + .target = MOVE_TARGET_ALL_BATTLERS, .priority = 0, .flags = 0, .split = SPLIT_STATUS, @@ -6875,7 +6875,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .accuracy = 0, .pp = 5, .secondaryEffectChance = 0, - .target = MOVE_TARGET_USER, + .target = MOVE_TARGET_ALL_BATTLERS, .priority = -7, .flags = FLAG_MIRROR_MOVE_AFFECTED, .split = SPLIT_STATUS, @@ -7478,7 +7478,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .accuracy = 0, .pp = 10, .secondaryEffectChance = 0, - .target = MOVE_TARGET_USER, + .target = MOVE_TARGET_ALL_BATTLERS, .flags = FLAG_MIRROR_MOVE_AFFECTED, .split = SPLIT_STATUS, }, @@ -7570,7 +7570,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .accuracy = 0, .pp = 10, .secondaryEffectChance = 0, - .target = MOVE_TARGET_USER, + .target = MOVE_TARGET_ALL_BATTLERS, .flags = FLAG_MIRROR_MOVE_AFFECTED, .split = SPLIT_STATUS, }, @@ -8932,7 +8932,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .accuracy = 0, .pp = 25, .secondaryEffectChance = 0, - .target = MOVE_TARGET_USER, + .target = MOVE_TARGET_ALL_BATTLERS, .priority = 1, .flags = 0, .split = SPLIT_STATUS, @@ -9097,7 +9097,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .accuracy = 0, .pp = 10, .secondaryEffectChance = 0, - .target = MOVE_TARGET_USER, + .target = MOVE_TARGET_ALL_BATTLERS, .priority = 0, .flags = 0, .split = SPLIT_STATUS, @@ -9111,7 +9111,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .accuracy = 0, .pp = 10, .secondaryEffectChance = 0, - .target = MOVE_TARGET_USER, + .target = MOVE_TARGET_ALL_BATTLERS, .priority = 0, .flags = 0, .split = SPLIT_STATUS, @@ -9195,7 +9195,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .accuracy = 0, .pp = 10, .secondaryEffectChance = 0, - .target = MOVE_TARGET_USER, + .target = MOVE_TARGET_ALL_BATTLERS, .priority = 0, .flags = FLAG_MIRROR_MOVE_AFFECTED, .split = SPLIT_STATUS, @@ -9445,7 +9445,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .accuracy = 0, .pp = 10, .secondaryEffectChance = 0, - .target = MOVE_TARGET_USER, + .target = MOVE_TARGET_ALL_BATTLERS, .priority = 0, .flags = 0, .split = SPLIT_STATUS, @@ -9965,7 +9965,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .accuracy = 0, .pp = 10, .secondaryEffectChance = 0, - .target = MOVE_TARGET_USER, + .target = MOVE_TARGET_ALL_BATTLERS, .priority = 0, .flags = 0, .split = SPLIT_STATUS, @@ -10848,7 +10848,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .accuracy = 0, .pp = 10, .secondaryEffectChance = 0, - .target = MOVE_TARGET_USER, + .target = MOVE_TARGET_ALL_BATTLERS, .priority = 0, .flags = 0, .split = SPLIT_STATUS, @@ -10904,7 +10904,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .accuracy = 100, .pp = 10, .secondaryEffectChance = 0, - .target = MOVE_TARGET_USER, + .target = MOVE_TARGET_ALL_BATTLERS, .priority = 0, .flags = FLAG_MIRROR_MOVE_AFFECTED, .split = SPLIT_STATUS, From 5f5df066d618a6383dc2858460d5e2076f18d7a5 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Wed, 6 Oct 2021 15:18:42 -0400 Subject: [PATCH 21/32] fix perish song + soundproof --- data/battle_scripts_1.s | 1 + src/battle_util.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 0615e12398..0939b5b186 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -3878,6 +3878,7 @@ BattleScript_PerishSongLoopIncrement:: goto BattleScript_MoveEnd BattleScript_PerishSongBlocked:: + copybyte sBATTLER, gBattlerTarget printstring STRINGID_PKMNSXBLOCKSY2 waitmessage B_WAIT_TIME_LONG goto BattleScript_PerishSongLoopIncrement diff --git a/src/battle_util.c b/src/battle_util.c index a709aaf9e9..cd5997f1f8 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -4458,7 +4458,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move } break; case ABILITYEFFECT_MOVES_BLOCK: // 2 - if ((gLastUsedAbility == ABILITY_SOUNDPROOF && gBattleMoves[move].flags & FLAG_SOUND) + if ((gLastUsedAbility == ABILITY_SOUNDPROOF && gBattleMoves[move].flags & FLAG_SOUND && gCurrentMove != MOVE_PERISH_SONG) || (gLastUsedAbility == ABILITY_BULLETPROOF && gBattleMoves[move].flags & FLAG_BALLISTIC)) { if (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS) From 1afc43a0e8259ad1b1f025f544cfec1884c68fdb Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Wed, 6 Oct 2021 15:30:44 -0400 Subject: [PATCH 22/32] fix DoesSubstituteBlockMove calls --- src/battle_script_commands.c | 6 +++--- src/battle_util.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 12f7763e3f..35c5fee1aa 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -5139,7 +5139,7 @@ static void Cmd_moveend(void) // Attacker is the damage-dealer, battler is mon to be switched out if (IsBattlerAlive(battler) && GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_EJECT_BUTTON - && !DoesSubstituteBlockMove(gCurrentMove, gBattlerAttacker, battler) + && !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) && (gSpecialStatuses[battler].physicalDmg != 0 || gSpecialStatuses[battler].specialDmg != 0) && CountUsablePartyMons(battler) > 0) // Has mon to switch into { @@ -5173,7 +5173,7 @@ static void Cmd_moveend(void) // Attacker is the one to be switched out, battler is one with red card if (battler != gBattlerAttacker && IsBattlerAlive(battler) - && !DoesSubstituteBlockMove(gCurrentMove, gBattlerAttacker, battler) + && !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) && GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_RED_CARD && (gSpecialStatuses[battler].physicalDmg != 0 || gSpecialStatuses[battler].specialDmg != 0) && CanBattlerSwitch(gBattlerAttacker)) @@ -5240,7 +5240,7 @@ static void Cmd_moveend(void) if (battler != gBattlerAttacker // Cannot pickpocket yourself && GetBattlerAbility(battler) == ABILITY_PICKPOCKET // Target must have pickpocket ability && BATTLER_DAMAGED(battler) // Target needs to have been damaged - && !DoesSubstituteBlockMove(gCurrentMove, gBattlerAttacker, battler) // Subsitute unaffected + && !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) // Subsitute unaffected && IsBattlerAlive(battler) // Battler must be alive to pickpocket && gBattleMons[battler].item == ITEM_NONE // Pickpocketer can't have an item already && CanStealItem(battler, gBattlerAttacker, gBattleMons[gBattlerAttacker].item)) // Cannot steal plates, mega stones, etc diff --git a/src/battle_util.c b/src/battle_util.c index a709aaf9e9..31e5e14fc4 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -6810,7 +6810,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) if (TARGET_TURN_DAMAGED && (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)) && IsMoveMakingContact(gCurrentMove, gBattlerAttacker) - && !DoesSubstituteBlockMove(gCurrentMove, gBattlerAttacker, battlerId) + && !DoesSubstituteBlockMove(gBattlerAttacker, battlerId, gCurrentMove) && IsBattlerAlive(gBattlerAttacker) && CanStealItem(gBattlerAttacker, gBattlerTarget, gBattleMons[gBattlerTarget].item) && gBattleMons[gBattlerAttacker].item == ITEM_NONE) From db0d9f62358f8dfd44ff4bd5e5042c5f451a9762 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Fri, 8 Oct 2021 08:22:49 -0400 Subject: [PATCH 23/32] sound moves targeting user not blocked by own soundproof --- 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 cd5997f1f8..81389effde 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -4458,7 +4458,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move } break; case ABILITYEFFECT_MOVES_BLOCK: // 2 - if ((gLastUsedAbility == ABILITY_SOUNDPROOF && gBattleMoves[move].flags & FLAG_SOUND && gCurrentMove != MOVE_PERISH_SONG) + if ((gLastUsedAbility == ABILITY_SOUNDPROOF && gBattleMoves[move].flags & FLAG_SOUND && !(gBattleMoves[move].target & MOVE_TARGET_USER)) || (gLastUsedAbility == ABILITY_BULLETPROOF && gBattleMoves[move].flags & FLAG_BALLISTIC)) { if (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS) From 274e964d9144a9b2c64710d8a4b0150e06899fde Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Sat, 9 Oct 2021 15:05:01 +1300 Subject: [PATCH 24/32] Fix Safety Googles Fix typo and update gLastUsedItem before calling the safety goggles battle script. --- data/battle_scripts_1.s | 2 +- include/constants/battle_string_ids.h | 2 +- include/constants/hold_effects.h | 2 +- src/battle_ai_util.c | 10 +++++----- src/battle_debug.c | 4 ++-- src/battle_message.c | 4 ++-- src/battle_script_commands.c | 4 ++-- src/battle_util.c | 7 ++++--- 8 files changed, 18 insertions(+), 17 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 67f7762aca..38538747b2 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -6797,7 +6797,7 @@ BattleScript_PowderMoveNoEffect:: pause B_WAIT_TIME_SHORT jumpiftype BS_TARGET, TYPE_GRASS, BattleScript_PowderMoveNoEffectPrint jumpifability BS_TARGET, ABILITY_OVERCOAT, BattleScript_PowderMoveNoEffectOvercoat - printstring STRINGID_SAFETYGOOGLESPROTECTED + printstring STRINGID_SAFETYGOGGLESPROTECTED goto BattleScript_PowderMoveNoEffectWaitMsg BattleScript_PowderMoveNoEffectOvercoat: call BattleScript_AbilityPopUp diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index b74c9cd141..e8fe7e3590 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -523,7 +523,7 @@ #define STRINGID_GRASSYTERRAINHEALS 519 #define STRINGID_ELECTRICTERRAINPREVENTS 520 #define STRINGID_PSYCHICTERRAINPREVENTS 521 -#define STRINGID_SAFETYGOOGLESPROTECTED 522 +#define STRINGID_SAFETYGOGGLESPROTECTED 522 #define STRINGID_FLOWERVEILPROTECTED 523 #define STRINGID_SWEETVEILPROTECTED 524 #define STRINGID_AROMAVEILPROTECTED 525 diff --git a/include/constants/hold_effects.h b/include/constants/hold_effects.h index 3dc4a1389e..d7d74d3e1b 100644 --- a/include/constants/hold_effects.h +++ b/include/constants/hold_effects.h @@ -130,7 +130,7 @@ // Gen6 hold effects #define HOLD_EFFECT_FAIRY_POWER 139 #define HOLD_EFFECT_MEGA_STONE 140 -#define HOLD_EFFECT_SAFETY_GOOGLES 141 +#define HOLD_EFFECT_SAFETY_GOGGLES 141 #define HOLD_EFFECT_LUMINOUS_MOSS 142 #define HOLD_EFFECT_SNOWBALL 143 #define HOLD_EFFECT_WEAKNESS_POLICY 144 diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 95d979e943..fef6e6c6ff 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -643,7 +643,7 @@ bool32 IsAffectedByPowder(u8 battler, u16 ability, u16 holdEffect) { if ((B_POWDER_GRASS >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GRASS)) || ability == ABILITY_OVERCOAT - || holdEffect == HOLD_EFFECT_SAFETY_GOOGLES) + || holdEffect == HOLD_EFFECT_SAFETY_GOGGLES) return FALSE; return TRUE; } @@ -1448,7 +1448,7 @@ bool32 ShouldSetSandstorm(u8 battler, u16 ability, u16 holdEffect) || ability == ABILITY_SAND_FORCE || ability == ABILITY_OVERCOAT || ability == ABILITY_MAGIC_GUARD - || holdEffect == HOLD_EFFECT_SAFETY_GOOGLES + || holdEffect == HOLD_EFFECT_SAFETY_GOGGLES || IS_BATTLER_OF_TYPE(battler, TYPE_ROCK) || IS_BATTLER_OF_TYPE(battler, TYPE_STEEL) || IS_BATTLER_OF_TYPE(battler, TYPE_GROUND) @@ -1473,7 +1473,7 @@ bool32 ShouldSetHail(u8 battler, u16 ability, u16 holdEffect) || ability == ABILITY_SLUSH_RUSH || ability == ABILITY_MAGIC_GUARD || ability == ABILITY_OVERCOAT - || holdEffect == HOLD_EFFECT_SAFETY_GOOGLES + || holdEffect == HOLD_EFFECT_SAFETY_GOGGLES || IS_BATTLER_OF_TYPE(battler, TYPE_ICE) || HasMove(battler, MOVE_BLIZZARD) || HasMoveEffect(battler, EFFECT_AURORA_VEIL) @@ -2273,7 +2273,7 @@ static u32 GetWeatherDamage(u8 battlerId) { if (BattlerAffectedBySandstorm(battlerId, ability) && !(gStatuses3[battlerId] & (STATUS3_UNDERGROUND | STATUS3_UNDERWATER)) - && holdEffect != HOLD_EFFECT_SAFETY_GOOGLES) + && holdEffect != HOLD_EFFECT_SAFETY_GOGGLES) { damage = gBattleMons[battlerId].maxHP / 16; if (damage == 0) @@ -2284,7 +2284,7 @@ static u32 GetWeatherDamage(u8 battlerId) { if (BattlerAffectedByHail(battlerId, ability) && !(gStatuses3[battlerId] & (STATUS3_UNDERGROUND | STATUS3_UNDERWATER)) - && holdEffect != HOLD_EFFECT_SAFETY_GOOGLES) + && holdEffect != HOLD_EFFECT_SAFETY_GOGGLES) { damage = gBattleMons[battlerId].maxHP / 16; if (damage == 0) diff --git a/src/battle_debug.c b/src/battle_debug.c index b9cfcdc033..ce5aa4a97f 100644 --- a/src/battle_debug.c +++ b/src/battle_debug.c @@ -1951,7 +1951,7 @@ static const u8 sText_HoldEffectAbsorbBulb[] = _("Absorb Bulb"); static const u8 sText_HoldEffectCellBattery[] = _("Cell Battery"); static const u8 sText_HoldEffectFairyPower[] = _("Fairy Power"); static const u8 sText_HoldEffectMegaStone[] = _("Mega Stone"); -static const u8 sText_HoldEffectSafetyGoogles[] = _("Safety Googles"); +static const u8 sText_HoldEffectSafetyGoggles[] = _("Safety Goggles"); static const u8 sText_HoldEffectLuminousMoss[] = _("Luminous Moss"); static const u8 sText_HoldEffectSnowball[] = _("Snowball"); static const u8 sText_HoldEffectWeaknessPolicy[] = _("Weakness Policy"); @@ -2091,7 +2091,7 @@ static const u8 *const sHoldEffectNames[] = [HOLD_EFFECT_CELL_BATTERY] = sText_HoldEffectCellBattery, [HOLD_EFFECT_FAIRY_POWER] = sText_HoldEffectFairyPower, [HOLD_EFFECT_MEGA_STONE] = sText_HoldEffectMegaStone, - [HOLD_EFFECT_SAFETY_GOOGLES] = sText_HoldEffectSafetyGoogles, + [HOLD_EFFECT_SAFETY_GOGGLES] = sText_HoldEffectSafetyGoggles, [HOLD_EFFECT_LUMINOUS_MOSS] = sText_HoldEffectLuminousMoss, [HOLD_EFFECT_SNOWBALL] = sText_HoldEffectSnowball, [HOLD_EFFECT_WEAKNESS_POLICY] = sText_HoldEffectWeaknessPolicy, diff --git a/src/battle_message.c b/src/battle_message.c index f8df8f4b8f..69463ce690 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -653,7 +653,7 @@ static const u8 sText_MistyTerrainPreventsStatus[] = _("{B_DEF_NAME_WITH_PREFIX} static const u8 sText_GrassyTerrainHeals[] = _("{B_ATK_NAME_WITH_PREFIX} is healed\nby the grassy terrain!"); static const u8 sText_ElectricTerrainPreventsSleep[] = _("{B_DEF_NAME_WITH_PREFIX} surrounds itself\nwith electrified terrain!"); static const u8 sText_PsychicTerrainPreventsPriority[] = _("{B_DEF_NAME_WITH_PREFIX} surrounds itself\nwith psychic terrain!"); -static const u8 sText_SafetyGooglesProtected[] = _("{B_DEF_NAME_WITH_PREFIX} is not affected\nthanks to its {B_LAST_ITEM}!"); +static const u8 sText_SafetyGogglesProtected[] = _("{B_DEF_NAME_WITH_PREFIX} is not affected\nthanks to its {B_LAST_ITEM}!"); static const u8 sText_FlowerVeilProtected[] = _("{B_DEF_NAME_WITH_PREFIX} surrounded itself\nwith a veil of petals!"); static const u8 sText_SweetVeilProtected[] = _("{B_DEF_NAME_WITH_PREFIX} surrounded itself\nwith a veil of sweetness!"); static const u8 sText_AromaVeilProtected[] = _("{B_DEF_NAME_WITH_PREFIX} is protected\nby an aromatic veil!"); @@ -780,7 +780,7 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = [STRINGID_AROMAVEILPROTECTED - 12] = sText_AromaVeilProtected, [STRINGID_SWEETVEILPROTECTED - 12] = sText_SweetVeilProtected, [STRINGID_FLOWERVEILPROTECTED - 12] = sText_FlowerVeilProtected, - [STRINGID_SAFETYGOOGLESPROTECTED - 12] = sText_SafetyGooglesProtected, + [STRINGID_SAFETYGOGGLESPROTECTED - 12] = sText_SafetyGogglesProtected, [STRINGID_SPECTRALTHIEFSTEAL - 12] = sText_SpectralThiefSteal, [STRINGID_BELCHCANTSELECT - 12] = sText_BelchCantUse, [STRINGID_TRAINER1LOSETEXT - 12] = sText_Trainer1LoseText, diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 3b627a0203..5e5d197504 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -10129,7 +10129,7 @@ static void Cmd_weatherdamage(void) && ability != ABILITY_SAND_RUSH && ability != ABILITY_OVERCOAT && !(gStatuses3[gBattlerAttacker] & (STATUS3_UNDERGROUND | STATUS3_UNDERWATER)) - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_SAFETY_GOOGLES) + && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_SAFETY_GOGGLES) { gBattleMoveDamage = gBattleMons[gBattlerAttacker].maxHP / 16; if (gBattleMoveDamage == 0) @@ -10154,7 +10154,7 @@ static void Cmd_weatherdamage(void) && ability != ABILITY_OVERCOAT && ability != ABILITY_ICE_BODY && !(gStatuses3[gBattlerAttacker] & (STATUS3_UNDERGROUND | STATUS3_UNDERWATER)) - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_SAFETY_GOOGLES) + && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_SAFETY_GOGGLES) { gBattleMoveDamage = gBattleMons[gBattlerAttacker].maxHP / 16; if (gBattleMoveDamage == 0) diff --git a/src/battle_util.c b/src/battle_util.c index 01ee1a6914..34855ecd3b 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3386,9 +3386,10 @@ u8 AtkCanceller_UnableToUseMove(void) gBattlerAbility = gBattlerTarget; effect = 1; } - else if (GetBattlerHoldEffect(gBattlerTarget, TRUE) == HOLD_EFFECT_SAFETY_GOOGLES) + else if (GetBattlerHoldEffect(gBattlerTarget, TRUE) == HOLD_EFFECT_SAFETY_GOGGLES) { - RecordItemEffectBattle(gBattlerTarget, HOLD_EFFECT_SAFETY_GOOGLES); + RecordItemEffectBattle(gBattlerTarget, HOLD_EFFECT_SAFETY_GOGGLES); + gLastUsedItem = gBattleMons[gBattlerTarget].item; effect = 1; } @@ -4882,7 +4883,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move case ABILITY_EFFECT_SPORE: if (!IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GRASS) && GetBattlerAbility(gBattlerAttacker) != ABILITY_OVERCOAT - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_SAFETY_GOOGLES) + && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_SAFETY_GOGGLES) { i = Random() % 3; if (i == 0) From 01f563cb5e11c3ba3f38a6084fd9abadd1413f5e Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Sun, 10 Oct 2021 08:46:31 -0300 Subject: [PATCH 25/32] Fix infinite loop --- data/battle_scripts_1.s | 22 +++++++++++----------- src/battle_util.c | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 2ce0adf684..883b90200d 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -8022,41 +8022,41 @@ BattleScript_HangedOnMsgRet: return BattleScript_BerryConfuseHealEnd2:: - jumpifability BS_ATTACKER, ABILITY_RIPEN, BattleScript_BerryConfuseHealEnd2_AbilityPopup + jumpifability BS_SCRIPTING, ABILITY_RIPEN, BattleScript_BerryConfuseHealEnd2_AbilityPopup goto BattleScript_BerryConfuseHealEnd2_Anim BattleScript_BerryConfuseHealEnd2_AbilityPopup: call BattleScript_AbilityPopUp BattleScript_BerryConfuseHealEnd2_Anim: - playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT, NULL + playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT, NULL printstring STRINGID_PKMNSITEMRESTOREDHEALTH waitmessage B_WAIT_TIME_LONG orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_SCRIPTING + datahpupdate BS_SCRIPTING printstring STRINGID_FORXCOMMAYZ waitmessage B_WAIT_TIME_LONG setmoveeffect MOVE_EFFECT_CONFUSION | MOVE_EFFECT_AFFECTS_USER seteffectprimary - removeitem BS_ATTACKER + removeitem BS_SCRIPTING end2 BattleScript_BerryConfuseHealRet:: - jumpifability BS_ATTACKER, ABILITY_RIPEN, BattleScript_BerryConfuseHealRet_AbilityPopup + jumpifability BS_SCRIPTING, ABILITY_RIPEN, BattleScript_BerryConfuseHealRet_AbilityPopup goto BattleScript_BerryConfuseHealRet_Anim BattleScript_BerryConfuseHealRet_AbilityPopup: call BattleScript_AbilityPopUp BattleScript_BerryConfuseHealRet_Anim: - playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT, NULL + playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT, NULL printstring STRINGID_PKMNSITEMRESTOREDHEALTH waitmessage B_WAIT_TIME_LONG orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE - healthbarupdate BS_ATTACKER - datahpupdate BS_ATTACKER + healthbarupdate BS_SCRIPTING + datahpupdate BS_SCRIPTING printstring STRINGID_FORXCOMMAYZ waitmessage B_WAIT_TIME_LONG - setmoveeffect MOVE_EFFECT_CONFUSION | MOVE_EFFECT_AFFECTS_USER + setmoveeffect MOVE_EFFECT_CONFUSION | MOVE_EFFECT_CERTAIN seteffectprimary - removeitem BS_ATTACKER + removeitem BS_TARGET return BattleScript_BerryStatRaiseEnd2:: diff --git a/src/battle_util.c b/src/battle_util.c index 20e5d91d1a..b3fb71cf60 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5574,7 +5574,7 @@ static u8 HealConfuseBerry(u32 battlerId, u32 itemId, u8 flavorId, bool32 end2) gBattleMoveDamage *= 2; gBattlerAbility = battlerId; } - + gBattleScripting.battler = battlerId; if (end2) { if (GetFlavorRelationByPersonality(gBattleMons[battlerId].personality, flavorId) < 0) From c3f8b77d8259be1190e49f55ba5532c5c72de041 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Sun, 10 Oct 2021 20:26:38 -0300 Subject: [PATCH 26/32] Setting for pre-Gen6 Hidden Power Damage. --- include/constants/battle_config.h | 1 + src/battle_util.c | 16 ++++++++++++++++ src/data/battle_moves.h | 2 +- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/include/constants/battle_config.h b/include/constants/battle_config.h index bcf4491f94..bce49719ee 100644 --- a/include/constants/battle_config.h +++ b/include/constants/battle_config.h @@ -123,6 +123,7 @@ #define B_CRASH_IF_TARGET_IMMUNE GEN_7 // In Gen4+, The user of Jump Kick or High Jump Kick will "keep going and crash" if it attacks a target that is immune to the move. #define B_TAILWIND_TIMER GEN_7 // In Gen5+, Tailwind lasts 4 turns instead of 3. #define B_MEMENTO_FAIL GEN_7 // In Gen4+, Memento fails if there is no target or if the target is protected or behind substitute. But not if Atk/Sp. Atk are at -6. +#define B_HIDDEN_POWER_DMG GEN_7 // In Gen6+, Hidden Power's base power was set to always be 60. Before, it was determined by the mon's IVs. // Ability settings #define B_ABILITY_WEATHER GEN_7 // In Gen6+, ability-induced weather lasts 5 turns. Before, it lasted until the battle ended or until it was changed by a move or a different weather-affecting ability. diff --git a/src/battle_util.c b/src/battle_util.c index 263d7f96de..88a5cc2039 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -7658,6 +7658,22 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef) basePower *= 2; #endif break; + case EFFECT_HIDDEN_POWER: + { + #if B_HIDDEN_POWER_DMG < GEN_6 + u8 powerBits; + + powerBits = ((gBattleMons[gBattlerAttacker].hpIV & 2) >> 1) + | ((gBattleMons[gBattlerAttacker].attackIV & 2) << 0) + | ((gBattleMons[gBattlerAttacker].defenseIV & 2) << 1) + | ((gBattleMons[gBattlerAttacker].speedIV & 2) << 2) + | ((gBattleMons[gBattlerAttacker].spAttackIV & 2) << 3) + | ((gBattleMons[gBattlerAttacker].spDefenseIV & 2) << 4); + + basePower = (40 * powerBits) / 63 + 30; + #endif + break; + } } // move-specific base power changes diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 1aa8c4dfd6..8d21889582 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -3753,7 +3753,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_HIDDEN_POWER] = { - #if B_UPDATED_MOVE_DATA >= GEN_6 + #if B_HIDDEN_POWER_DMG >= GEN_6 .power = 60, #else .power = 1, From fcada4fcad924a905560a726beb49733c3278382 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Sun, 10 Oct 2021 19:54:17 -0400 Subject: [PATCH 27/32] handle rototiller + prankster --- data/battle_scripts_1.s | 4 ---- include/battle_util.h | 2 +- src/battle_script_commands.c | 19 ++++++++++--------- src/battle_util.c | 25 +++++++++++++++---------- 4 files changed, 26 insertions(+), 24 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 3d9c66bd68..9ed0d1fcc9 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -942,10 +942,6 @@ BattleScript_FlowerShieldMoveTargetEnd: jumpifnexttargetvalid BattleScript_FlowerShieldLoop end -BattleScript_RototillerRet:: - - return - BattleScript_EffectRototiller: attackcanceler attackstring diff --git a/include/battle_util.h b/include/battle_util.h index 612a2e6d9a..43f66db6b7 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -152,7 +152,7 @@ bool32 CompareStat(u8 battlerId, u8 statId, u8 cmpTo, u8 cmpKind); bool32 TryRoomService(u8 battlerId); void BufferStatChange(u8 battlerId, u8 statId, u8 stringId); void DoBurmyFormChange(u32 monId); -bool32 BlocksPrankster(u16 move, u8 battlerPrankster, u8 battlerDef); +bool32 BlocksPrankster(u16 move, u8 battlerPrankster, u8 battlerDef, bool32 checkTarget); // ability checks bool32 IsRolePlayBannedAbilityAtk(u16 ability); diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 339e5bd996..e70b990eb3 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1416,7 +1416,7 @@ static void Cmd_attackcanceler(void) gProtectStructs[gBattlerTarget].bounceMove = 0; gProtectStructs[gBattlerTarget].usesBouncedMove = 1; gBattleCommunication[MULTISTRING_CHOOSER] = 0; - if (BlocksPrankster(gCurrentMove, gBattlerTarget, gBattlerAttacker)) + if (BlocksPrankster(gCurrentMove, gBattlerTarget, gBattlerAttacker, TRUE)) { // Opponent used a prankster'd magic coat -> reflected status move should fail against a dark-type attacker gBattlerTarget = gBattlerAttacker; @@ -7345,8 +7345,8 @@ static bool32 IsRototillerAffected(u32 battlerId) return FALSE; // Only grass types affected if (gStatuses3[battlerId] & STATUS3_SEMI_INVULNERABLE) return FALSE; // Rototiller doesn't affected semi-invulnerable battlers - //if (!CompareStat(battlerId, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN) && !CompareStat(battlerId, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN)) - //return FALSE; // Battler unaffected if atk and spatk are maxed + if (BlocksPrankster(MOVE_ROTOTILLER, gBattlerAttacker, battlerId, FALSE)) + return FALSE; return TRUE; } @@ -8757,21 +8757,22 @@ static void Cmd_various(void) } gFieldStatuses &= ~STATUS_FIELD_TERRAIN_ANY; // remove the terrain break; - case VARIOUS_JUMP_IF_PRANKSTER_BLOCKED: - if (BlocksPrankster(gCurrentMove, gBattlerAttacker, gActiveBattler)) + case VARIOUS_JUMP_IF_PRANKSTER_BLOCKED: + if (BlocksPrankster(gCurrentMove, gBattlerAttacker, gActiveBattler, TRUE)) gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); else gBattlescriptCurrInstr += 7; return; - case VARIOUS_GET_ROTOTILLER_TARGETS: + case VARIOUS_GET_ROTOTILLER_TARGETS: // Gets the battlers to be affected by rototiller. If there are none, print 'But it failed!' { u32 count = 0; for (i = 0; i < gBattlersCount; i++) { + gSpecialStatuses[i].rototillerAffected = FALSE; if (IsRototillerAffected(i)) { - gSpecialStatuses[i].rototillerAffected = 1; + gSpecialStatuses[i].rototillerAffected = TRUE; count++; } } @@ -8785,7 +8786,7 @@ static void Cmd_various(void) case VARIOUS_JUMP_IF_NOT_ROTOTILLER_AFFECTED: if (gSpecialStatuses[gActiveBattler].rototillerAffected) { - gSpecialStatuses[gActiveBattler].rototillerAffected = 0; + gSpecialStatuses[gActiveBattler].rototillerAffected = FALSE; gBattlescriptCurrInstr += 7; } else @@ -10954,7 +10955,7 @@ static void Cmd_trysetperishsong(void) { if (gStatuses3[i] & STATUS3_PERISH_SONG || GetBattlerAbility(i) == ABILITY_SOUNDPROOF - || BlocksPrankster(gCurrentMove, gBattlerAttacker, i)) + || BlocksPrankster(gCurrentMove, gBattlerAttacker, i, TRUE)) { notAffectedCount++; } diff --git a/src/battle_util.c b/src/battle_util.c index a709aaf9e9..40a100796e 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3421,7 +3421,7 @@ u8 AtkCanceller_UnableToUseMove(void) gBattleStruct->atkCancellerTracker++; break; case CANCELLER_PRANKSTER: - if (BlocksPrankster(gCurrentMove, gBattlerAttacker, gBattlerTarget) + if (BlocksPrankster(gCurrentMove, gBattlerAttacker, gBattlerTarget, TRUE) && !(IS_MOVE_STATUS(gCurrentMove) && GetBattlerAbility(gBattlerTarget) == ABILITY_MAGIC_BOUNCE)) { if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE) || !(gBattleMoves[gCurrentMove].target & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))) @@ -9344,16 +9344,21 @@ void DoBurmyFormChange(u32 monId) } } -bool32 BlocksPrankster(u16 move, u8 battlerPrankster, u8 battlerDef) +bool32 BlocksPrankster(u16 move, u8 battlerPrankster, u8 battlerDef, bool32 checkTarget) { #if B_PRANKSTER_DARK_TYPES >= GEN_7 - if (gProtectStructs[battlerPrankster].pranksterElevated - && GetBattlerSide(battlerPrankster) != GetBattlerSide(battlerDef) - && !(gBattleMoves[gCurrentMove].target & (MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_DEPENDS)) // Don't block hazards, assist-type moves - && IS_BATTLER_OF_TYPE(battlerDef, TYPE_DARK) // Only Dark-types can block Prankster'd - && !(gStatuses3[battlerDef] & STATUS3_SEMI_INVULNERABLE)) - return TRUE; - else - #endif + if (!gProtectStructs[battlerPrankster].pranksterElevated) return FALSE; + if (GetBattlerSide(battlerPrankster) == GetBattlerSide(battlerDef)) + return FALSE; + if (checkTarget && (gBattleMoves[move].target & (MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_DEPENDS))) + return FALSE; + if (!IS_BATTLER_OF_TYPE(battlerDef, TYPE_DARK)) + return FALSE; + if (gStatuses3[battlerDef] & STATUS3_SEMI_INVULNERABLE) + return FALSE; + + return TRUE; + #endif + return FALSE; } From 11626d5043e94f9e82c458eb60ff49f19476e6bd Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Tue, 12 Oct 2021 07:53:28 -0400 Subject: [PATCH 28/32] fix memento fail condition --- src/battle_script_commands.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 2c017b2df5..5d483aa3ed 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -11520,7 +11520,7 @@ static void Cmd_jumpifattackandspecialattackcannotfall(void) // memento && gBattleMons[gBattlerTarget].statStages[STAT_SPATK] == MIN_STAT_STAGE && gBattleCommunication[MISS_TYPE] != B_MSG_PROTECTED) #else - if (gBattleCommunication[MISS_TYPE] != B_MSG_PROTECTED + if (gBattleCommunication[MISS_TYPE] == B_MSG_PROTECTED || gStatuses3[gBattlerTarget] & STATUS3_SEMI_INVULNERABLE || IsBattlerProtected(gBattlerTarget, gCurrentMove) || DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove)) From b447d582cd6f929acc7aaeba3eb313dfe7df3891 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Wed, 13 Oct 2021 09:04:03 -0400 Subject: [PATCH 29/32] fix terrain timer decrementing and bg changing with anims disabled --- src/battle_script_commands.c | 31 ++++++++++++++++--------------- src/battle_util.c | 6 +++--- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 2c017b2df5..6852dee1ea 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -4527,12 +4527,13 @@ static void Cmd_endselectionscript(void) static void Cmd_playanimation(void) { const u16* argumentPtr; + u8 animId = gBattlescriptCurrInstr[2]; gActiveBattler = GetBattlerForBattleScript(gBattlescriptCurrInstr[1]); argumentPtr = T2_READ_PTR(gBattlescriptCurrInstr + 3); #if B_TERRAIN_BG_CHANGE == FALSE - if (gBattlescriptCurrInstr[2] == B_ANIM_RESTORE_BG) + if (animId == B_ANIM_RESTORE_BG) { // workaround for .if not working gBattlescriptCurrInstr += 7; @@ -4540,28 +4541,28 @@ static void Cmd_playanimation(void) } #endif - if (gBattlescriptCurrInstr[2] == B_ANIM_STATS_CHANGE - || gBattlescriptCurrInstr[2] == B_ANIM_SNATCH_MOVE - || gBattlescriptCurrInstr[2] == B_ANIM_MEGA_EVOLUTION - || gBattlescriptCurrInstr[2] == B_ANIM_ILLUSION_OFF - || gBattlescriptCurrInstr[2] == B_ANIM_FORM_CHANGE - || gBattlescriptCurrInstr[2] == B_ANIM_SUBSTITUTE_FADE) + if (animId == B_ANIM_STATS_CHANGE + || animId == B_ANIM_SNATCH_MOVE + || animId == B_ANIM_MEGA_EVOLUTION + || animId == B_ANIM_ILLUSION_OFF + || animId == B_ANIM_FORM_CHANGE + || animId == B_ANIM_SUBSTITUTE_FADE) { - BtlController_EmitBattleAnimation(0, gBattlescriptCurrInstr[2], *argumentPtr); + BtlController_EmitBattleAnimation(0, animId, *argumentPtr); MarkBattlerForControllerExec(gActiveBattler); gBattlescriptCurrInstr += 7; } - else if (gHitMarker & HITMARKER_NO_ANIMATIONS) + else if (gHitMarker & HITMARKER_NO_ANIMATIONS && animId != B_ANIM_RESTORE_BG) { BattleScriptPush(gBattlescriptCurrInstr + 7); gBattlescriptCurrInstr = BattleScript_Pausex20; } - else if (gBattlescriptCurrInstr[2] == B_ANIM_RAIN_CONTINUES - || gBattlescriptCurrInstr[2] == B_ANIM_SUN_CONTINUES - || gBattlescriptCurrInstr[2] == B_ANIM_SANDSTORM_CONTINUES - || gBattlescriptCurrInstr[2] == B_ANIM_HAIL_CONTINUES) + else if (animId == B_ANIM_RAIN_CONTINUES + || animId == B_ANIM_SUN_CONTINUES + || animId == B_ANIM_SANDSTORM_CONTINUES + || animId == B_ANIM_HAIL_CONTINUES) { - BtlController_EmitBattleAnimation(0, gBattlescriptCurrInstr[2], *argumentPtr); + BtlController_EmitBattleAnimation(0, animId, *argumentPtr); MarkBattlerForControllerExec(gActiveBattler); gBattlescriptCurrInstr += 7; } @@ -4571,7 +4572,7 @@ static void Cmd_playanimation(void) } else { - BtlController_EmitBattleAnimation(0, gBattlescriptCurrInstr[2], *argumentPtr); + BtlController_EmitBattleAnimation(0, animId, *argumentPtr); MarkBattlerForControllerExec(gActiveBattler); gBattlescriptCurrInstr += 7; } diff --git a/src/battle_util.c b/src/battle_util.c index 68e7876986..68e52f49d9 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -2234,7 +2234,7 @@ u8 DoFieldEndTurnEffects(void) break; case ENDTURN_ELECTRIC_TERRAIN: if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN - && ((!gFieldStatuses & STATUS_FIELD_TERRAIN_PERMANENT) && --gFieldTimers.electricTerrainTimer == 0)) + && (!(gFieldStatuses & STATUS_FIELD_TERRAIN_PERMANENT) && --gFieldTimers.electricTerrainTimer == 0)) { gFieldStatuses &= ~(STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_TERRAIN_PERMANENT); BattleScriptExecute(BattleScript_ElectricTerrainEnds); @@ -2244,7 +2244,7 @@ u8 DoFieldEndTurnEffects(void) break; case ENDTURN_MISTY_TERRAIN: if (gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN - && ((!gFieldStatuses & STATUS_FIELD_TERRAIN_PERMANENT) && --gFieldTimers.mistyTerrainTimer == 0)) + && (!(gFieldStatuses & STATUS_FIELD_TERRAIN_PERMANENT) && --gFieldTimers.mistyTerrainTimer == 0)) { gFieldStatuses &= ~(STATUS_FIELD_MISTY_TERRAIN); BattleScriptExecute(BattleScript_MistyTerrainEnds); @@ -2266,7 +2266,7 @@ u8 DoFieldEndTurnEffects(void) break; case ENDTURN_PSYCHIC_TERRAIN: if (gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN - && ((!gFieldStatuses & STATUS_FIELD_TERRAIN_PERMANENT) && --gFieldTimers.psychicTerrainTimer == 0)) + && (!(gFieldStatuses & STATUS_FIELD_TERRAIN_PERMANENT) && --gFieldTimers.psychicTerrainTimer == 0)) { gFieldStatuses &= ~(STATUS_FIELD_PSYCHIC_TERRAIN); BattleScriptExecute(BattleScript_PsychicTerrainEnds); From 7f2efb66190eb7351d8fae56b5e436d5d419dcb2 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Wed, 13 Oct 2021 18:39:24 -0400 Subject: [PATCH 30/32] format fixes, fix healing berries from printing message at full hp --- data/battle_scripts_1.s | 8 ++++---- src/battle_util.c | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index e842ddc394..cda99c54d3 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -380,7 +380,7 @@ gBattleScriptsForMoveEffects:: .4byte BattleScript_EffectHit @ EFFECT_SNIPE_SHOT .4byte BattleScript_EffectTripleHit @ EFFECT_TRIPLE_HIT .4byte BattleScript_EffectRecoilHP25 @ EFFECT_RECOIL_HP_25 - .4byte BattleScript_EffectStuffCheeks @ EFFECT_STUFF_CHEEKS + .4byte BattleScript_EffectStuffCheeks @ EFFECT_STUFF_CHEEKS BattleScript_EffectStuffCheeks:: attackcanceler @@ -398,7 +398,7 @@ BattleScript_StuffCheeksEatBerry: setstatchanger STAT_DEF, 2, FALSE statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_BUFF_ALLOW_PTR, BattleScript_StuffCheeksEnd setgraphicalstatchangevalues - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_StuffCheeksEnd @ cant raise def + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_StuffCheeksEnd @ cant raise def playanimation BS_ATTACKER, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1 printfromtable gStatUpStringIds waitmessage B_WAIT_TIME_LONG @@ -661,8 +661,8 @@ BattleScript_MoveEffectBugBite:: printstring STRINGID_BUGBITE waitmessage B_WAIT_TIME_LONG orword gHitMarker, HITMARKER_NO_ANIMATIONS - setbyte sBERRY_OVERRIDE, TRUE @ override the requirements for eating berries - consumeberry BS_ATTACKER, TRUE @ consume the berry, then restore the item from changedItems + setbyte sBERRY_OVERRIDE, TRUE @ override the requirements for eating berries + consumeberry BS_ATTACKER, TRUE @ consume the berry, then restore the item from changedItems bicword gHitMarker, HITMARKER_NO_ANIMATIONS setbyte sBERRY_OVERRIDE, FALSE return diff --git a/src/battle_util.c b/src/battle_util.c index 6ecc755f6f..88350b7c48 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5862,7 +5862,8 @@ u8 TryHandleSeed(u8 battler, u32 terrainFlag, u8 statId, u16 itemId, bool32 exec static u8 ItemHealHp(u32 battlerId, u32 itemId, bool32 end2, bool32 percentHeal) { - if (HasEnoughHpToEatBerry(battlerId, 2, itemId)) + if (HasEnoughHpToEatBerry(battlerId, 2, itemId) + && !(gBattleScripting.overrideBerryRequirements && gBattleMons[battlerId].hp == gBattleMons[battlerId].maxHP)) { if (percentHeal) gBattleMoveDamage = (gBattleMons[battlerId].maxHP * GetBattlerHoldEffectParam(battlerId) / 100) * -1; From bb8d0e3d6b87d02d93e4bcbad10518e34f936b20 Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Thu, 14 Oct 2021 16:18:11 +1300 Subject: [PATCH 31/32] Fix Battle Bond Battle Bond Greninja transforms only after a KO, and doesn't revert when switched out. --- asm/macros/battle_script.inc | 4 ++++ data/battle_scripts_1.s | 1 + include/constants/battle_script_commands.h | 1 + src/battle_script_commands.c | 13 +++++++++++++ src/battle_util.c | 18 +++--------------- 5 files changed, 22 insertions(+), 15 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 4d8fe03658..7ed108bde6 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1825,6 +1825,10 @@ various BS_ATTACKER, VARIOUS_TRY_TO_CLEAR_PRIMAL_WEATHER .endm + .macro tryactivatebattlebond battler:req + various \battler, VARIOUS_TRY_ACTIVATE_BATTLE_BOND + .endm + @ helpful macros .macro setstatchanger stat:req, stages:req, down:req setbyte sSTATCHANGER \stat | \stages << 3 | \down << 7 diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index e1fb47930d..9ec90e3df9 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -5288,6 +5288,7 @@ BattleScript_FaintTarget:: tryactivatemoxie BS_ATTACKER @ and chilling neigh, as one ice rider tryactivatebeastboost BS_ATTACKER tryactivategrimneigh BS_ATTACKER @ and as one shadow rider + tryactivatebattlebond BS_ATTACKER trytrainerslidefirstdownmsg BS_TARGET return diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index d61eabbf84..29236c7b00 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -185,6 +185,7 @@ #define VARIOUS_REMOVE_TERRAIN 113 #define VARIOUS_JUMP_IF_PRANKSTER_BLOCKED 114 #define VARIOUS_TRY_TO_CLEAR_PRIMAL_WEATHER 115 +#define VARIOUS_TRY_ACTIVATE_BATTLE_BOND 116 // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 2c017b2df5..472487e09c 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -8822,6 +8822,19 @@ static void Cmd_various(void) } break; } + case VARIOUS_TRY_ACTIVATE_BATTLE_BOND: + if (gBattleMons[gBattlerAttacker].species == SPECIES_GRENINJA_BATTLE_BOND + && HasAttackerFaintedTarget() + && CalculateEnemyPartyCount() > 1) + { + PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[gBattlerAttacker].species); + gBattleStruct->changedSpecies[gBattlerPartyIndexes[gBattlerAttacker]] = gBattleMons[gBattlerAttacker].species; + gBattleMons[gBattlerAttacker].species = SPECIES_GRENINJA_ASH; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_BattleBondActivatesOnMoveEndAttacker; + return; + } + break; } gBattlescriptCurrInstr += 3; diff --git a/src/battle_util.c b/src/battle_util.c index 68e7876986..e4b8f9cf34 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5147,18 +5147,6 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move effect++; } break; - case ABILITY_BATTLE_BOND: - if (gBattleMons[gBattlerAttacker].species == SPECIES_GRENINJA_BATTLE_BOND - && gBattleResults.opponentFaintCounter != 0 - && CalculateEnemyPartyCount() > 1) - { - PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[gBattlerAttacker].species); - gBattleStruct->changedSpecies[gBattlerPartyIndexes[gBattlerAttacker]] = gBattleMons[gBattlerAttacker].species; - gBattleMons[gBattlerAttacker].species = SPECIES_GRENINJA_ASH; - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_BattleBondActivatesOnMoveEndAttacker; - } - break; } break; case ABILITYEFFECT_MOVE_END_OTHER: // Abilities that activate on *another* battler's moveend: Dancer, Soul-Heart, Receiver, Symbiosis @@ -8846,6 +8834,7 @@ void UndoFormChange(u32 monId, u32 side, bool32 isSwitchingOut) static const u16 species[][2] = // changed form id, default form id { {SPECIES_MIMIKYU_BUSTED, SPECIES_MIMIKYU}, + {SPECIES_GRENINJA_ASH, SPECIES_GRENINJA_BATTLE_BOND}, {SPECIES_AEGISLASH_BLADE, SPECIES_AEGISLASH}, {SPECIES_DARMANITAN_ZEN_MODE, SPECIES_DARMANITAN}, {SPECIES_MINIOR, SPECIES_MINIOR_CORE_RED}, @@ -8858,11 +8847,10 @@ void UndoFormChange(u32 monId, u32 side, bool32 isSwitchingOut) {SPECIES_WISHIWASHI_SCHOOL, SPECIES_WISHIWASHI}, {SPECIES_CRAMORANT_GORGING, SPECIES_CRAMORANT}, {SPECIES_CRAMORANT_GULPING, SPECIES_CRAMORANT}, - {SPECIES_GRENINJA_ASH, SPECIES_GRENINJA_BATTLE_BOND}, }; - if (isSwitchingOut) // Don't revert Mimikyu Busted when switching out - i = 1; + if (isSwitchingOut) // Don't revert Mimikyu Busted or Ash-Greninja when switching out + i = 2; else i = 0; From 85dd7ff63c40778538ece6d465f42a28a232b252 Mon Sep 17 00:00:00 2001 From: BuffelSaft Date: Thu, 14 Oct 2021 16:40:18 +1300 Subject: [PATCH 32/32] Fix Storm Drain/Dive bug If Storm Drain is triggered by dive it should clear the attacker's semi-invulnerable status. --- data/battle_scripts_1.s | 1 + 1 file changed, 1 insertion(+) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 616fe21f1e..c70bddcd4b 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -7525,6 +7525,7 @@ BattleScript_MoveStatDrain:: waitanimation printstring STRINGID_TARGETABILITYSTATRAISE waitmessage B_WAIT_TIME_LONG + clearsemiinvulnerablebit tryfaintmon BS_ATTACKER, FALSE, NULL goto BattleScript_MoveEnd