Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds Raging Bull and various fixes #3552

Merged
merged 8 commits into from
Nov 19, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions data/battle_scripts_1.s
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,7 @@ gBattleScriptsForMoveEffects::
.4byte BattleScript_EffectSyrupBomb @ EFFECT_SYRUP_BOMB
.4byte BattleScript_EffectHit @ EFFECT_IVY_CUDGEL
.4byte BattleScript_EffectMaxMove @ EFFECT_MAX_MOVE
.4byte BattleScript_EffectBrickBreak @ EFFECT_RAGING_BULL

BattleScript_EffectSyrupBomb::
setmoveeffect MOVE_EFFECT_SYRUP_BOMB
Expand Down
3 changes: 2 additions & 1 deletion include/constants/battle_move_effects.h
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,8 @@
#define EFFECT_SYRUP_BOMB 411
#define EFFECT_IVY_CUDGEL 412
#define EFFECT_MAX_MOVE 413
#define EFFECT_RAGING_BULL 414

#define NUM_BATTLE_MOVE_EFFECTS 414
#define NUM_BATTLE_MOVE_EFFECTS 415

#endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H
9 changes: 4 additions & 5 deletions src/battle_anim_new.c
Original file line number Diff line number Diff line change
Expand Up @@ -9154,16 +9154,15 @@ void AnimTask_SyrupBomb(u8 taskId)
struct Pokemon *party = GetBattlerParty(gBattleAnimAttacker);
u32 isShiny = IsMonShiny(&party[gBattlerPartyIndexes[gBattleAnimAttacker]]);

gDisableStructs[gBattleAnimTarget].syrupBombIsShiny = isShiny;
if (!(gStatuses4[gBattleAnimTarget] & STATUS4_SYRUP_BOMB))
gDisableStructs[gBattleAnimTarget].syrupBombIsShiny = isShiny;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, you need to test the specific case where the target is first hit by a non-shiny Syrup Bomb and then a shiny one in a link battle. gStatuses4 is never updated on the slave GBA, so the second time the target gets hit by the attack, on one GBA the shiny animation will start to play (since the condition !(gStatuses4[gBattleAnimTarget] & STATUS4_SYRUP_BOMB) will always be true).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, you are correct! Sorry, I didn't fully understand what you meant previously.

What would be a good replacement in this case?

Copy link

@Skeli789 Skeli789 Nov 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Set gDisableStructs[gBattleAnimTarget].syrupBombIsShiny when the status4 is originally set in SetMoveEffect. You've been setting it in the attack animation functions this entire time which has been the problem. The disable struct is passed through for the attack animation, so once you move the shininess setting there, you can change this code to be gBattleAnimArgs[0] = gDisableStructs[gBattleAnimTarget].syrupBombIsShiny.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I pushed a commit with current changes but I can't get it to work
image

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, so this still is not working because of how the special battle animations are set up. Unlike when a move animation is used, the disable struct is not passed along to the special battle animations.

To fix this, copy the line memcpy(&sBattleBuffersTransferData[16], disableStructPtr, sizeof(struct DisableStruct)); from BtlController_EmitMoveAnimation, and add it to BtlController_EmitBattleAnimation, changing the 16 to wherever the current data struct leaves of (and modify the amount of data transferred over). Then, modify all ...HandleBattleAnimation functions to accept the disable struct as well (see how the ...HandleMoveAnimation functions do it). Finally, in the sticky syrup animation, you should be able to access the value via gAnimDisableStructPtr->syrupBombIsShiny.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That worked, thank you!
image
Though I didn't know what I was doing and relied on your description only so not sure if all of it is correct. 😅


gBattleAnimArgs[0] = isShiny;
DestroyAnimVisualTask(taskId);
}

void AnimTask_StickySyrup(u8 taskId)
{
if (gDisableStructs[gBattleAnimTarget].syrupBombIsShiny)
gBattleAnimArgs[0] = TRUE;
else
gBattleAnimArgs[0] = FALSE;
gBattleAnimArgs[0] = gDisableStructs[gBattleAnimTarget].syrupBombIsShiny;
DestroyAnimVisualTask(taskId);
}
7 changes: 7 additions & 0 deletions src/battle_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -5647,6 +5647,13 @@ void SetTypeBeforeUsingMove(u32 move, u32 battlerAtk)
else if (gBattleMons[battlerAtk].type3 != TYPE_MYSTERY)
gBattleStruct->dynamicMoveType = gBattleMons[battlerAtk].type3 | F_DYNAMIC_TYPE_2;
}
else if (gBattleMoves[move].effect == EFFECT_RAGING_BULL
&& (gBattleMons[battlerAtk].species == SPECIES_TAUROS_PALDEAN_COMBAT_BREED
|| gBattleMons[battlerAtk].species == SPECIES_TAUROS_PALDEAN_BLAZE_BREED
|| gBattleMons[battlerAtk].species == SPECIES_TAUROS_PALDEAN_AQUA_BREED))
{
gBattleStruct->dynamicMoveType = gBattleMons[battlerAtk].type2 | F_DYNAMIC_TYPE_2;
}
else if (gBattleMoves[move].effect == EFFECT_NATURAL_GIFT)
{
if (ItemId_GetPocket(gBattleMons[battlerAtk].item) == POCKET_BERRIES)
Expand Down
12 changes: 9 additions & 3 deletions src/battle_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -4116,7 +4116,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
{
u32 effect = 0;
u32 moveType, move;
u32 side;
u32 i, j;
struct Pokemon *mon;

if (gBattleTypeFlags & BATTLE_TYPE_SAFARI)
return 0;
Expand Down Expand Up @@ -4704,12 +4706,15 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
}
break;
case ABILITY_ZERO_TO_HERO:
side = GetBattlerSide(battler);
mon = &GetSideParty(side)[gBattlerPartyIndexes[battler]];

if (!gSpecialStatuses[battler].switchInAbilityDone
&& gBattleMons[battler].species == SPECIES_PALAFIN_HERO
&& !gBattleStruct->transformZeroToHero[gBattlerPartyIndexes[battler]][GetBattlerSide(battler)])
&& GetMonData(mon, MON_DATA_SPECIES) == SPECIES_PALAFIN_HERO
&& !gBattleStruct->transformZeroToHero[gBattlerPartyIndexes[battler]][side])
{
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
gBattleStruct->transformZeroToHero[gBattlerPartyIndexes[battler]][GetBattlerSide(battler)] = TRUE;
gBattleStruct->transformZeroToHero[gBattlerPartyIndexes[battler]][side] = TRUE;
BattleScriptPushCursorAndCallback(BattleScript_ZeroToHeroActivates);
effect++;
}
Expand Down Expand Up @@ -5262,6 +5267,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
case ABILITY_STANCE_CHANGE:
case ABILITY_WONDER_GUARD:
case ABILITY_ZEN_MODE:
case ABILITY_ZERO_TO_HERO:
break;
default:
if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_ABILITY_SHIELD)
Expand Down
2 changes: 1 addition & 1 deletion src/data/battle_moves.h
Original file line number Diff line number Diff line change
Expand Up @@ -13863,7 +13863,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] =

[MOVE_RAGING_BULL] =
{
.effect = EFFECT_PLACEHOLDER, // EFFECT_RAGING_BULL
.effect = EFFECT_RAGING_BULL,
.power = 90,
.type = TYPE_NORMAL,
.accuracy = 100,
Expand Down
40 changes: 40 additions & 0 deletions test/battle/ability/zero_to_hero.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,46 @@ SINGLE_BATTLE_TEST("Role Play, Skill Swap, and Entrainment fail if either Pokém
}
}

SINGLE_BATTLE_TEST("Transform doesn't apply the heroic transformation message when copying Palafin")
{
GIVEN {
PLAYER(SPECIES_PALAFIN_ZERO) { Ability(ABILITY_ZERO_TO_HERO); }
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { SWITCH(player, 1); }
TURN { SWITCH(player, 0); MOVE(opponent, MOVE_TRANSFORM); }
} SCENE {
ABILITY_POPUP(player, ABILITY_ZERO_TO_HERO);
MESSAGE("Palafin underwent a heroic transformation!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_TRANSFORM, opponent);
MESSAGE("Foe Wobbuffet transformed into Palafin!");
NOT ABILITY_POPUP(opponent, ABILITY_ZERO_TO_HERO);
} THEN { EXPECT_EQ(player->species, SPECIES_PALAFIN_HERO); }
}

SINGLE_BATTLE_TEST("Imposter doesn't apply the heroic transformation message when copying Palafin")
{
GIVEN {
PLAYER(SPECIES_PALAFIN_ZERO) { Ability(ABILITY_ZERO_TO_HERO); }
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_DITTO) { Ability(ABILITY_IMPOSTER); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { SWITCH(player, 1); SWITCH(opponent, 1); }
TURN { SWITCH(player, 0); SWITCH(opponent, 0); }
} SCENE {
ABILITY_POPUP(player, ABILITY_ZERO_TO_HERO);
MESSAGE("Palafin underwent a heroic transformation!");
ABILITY_POPUP(opponent, ABILITY_IMPOSTER);
MESSAGE("Foe Ditto transformed into Palafin using Imposter!");
NONE_OF {
ABILITY_POPUP(opponent, ABILITY_ZERO_TO_HERO);
MESSAGE("Foe Ditto underwent a heroic transformation!");
}
} THEN { EXPECT_EQ(player->species, SPECIES_PALAFIN_HERO); }
}

// Write Trace test and move this one to that file (including every other ability that can't be copied)
SINGLE_BATTLE_TEST("Zero to Hero cannot be copied by Trace")
{
Expand Down
160 changes: 160 additions & 0 deletions test/battle/move_effect/brick_break.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
#include "global.h"
#include "test/battle.h"

ASSUMPTIONS
{
ASSUME(gBattleMoves[MOVE_BRICK_BREAK].effect == EFFECT_BRICK_BREAK);
ASSUME(gBattleMoves[MOVE_SNOWSCAPE].effect == EFFECT_SNOWSCAPE);
ASSUME(gBattleMoves[MOVE_LIGHT_SCREEN].effect == EFFECT_LIGHT_SCREEN);
ASSUME(gBattleMoves[MOVE_REFLECT].effect == EFFECT_REFLECT);
ASSUME(gBattleMoves[MOVE_AURORA_VEIL].effect == EFFECT_AURORA_VEIL);
}

SINGLE_BATTLE_TEST("Brick Break removes Light Screen, Reflect and Aurora Veil from the target's side of the field")
{
u16 move;

PARAMETRIZE { move = MOVE_LIGHT_SCREEN; }
PARAMETRIZE { move = MOVE_REFLECT; }
PARAMETRIZE { move = MOVE_AURORA_VEIL; }

GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_SNOWSCAPE); }
TURN { MOVE(opponent, move); MOVE(player, MOVE_BRICK_BREAK); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SNOWSCAPE, player);
ANIMATION(ANIM_TYPE_MOVE, move, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_BRICK_BREAK, player);
MESSAGE("The wall shattered!");
HP_BAR(opponent);
}
}

SINGLE_BATTLE_TEST("Brick Break doesn't remove Light Screen, Reflect and Aurora Veil if the target is immune")
{
u16 move;

PARAMETRIZE { move = MOVE_LIGHT_SCREEN; }
PARAMETRIZE { move = MOVE_REFLECT; }
PARAMETRIZE { move = MOVE_AURORA_VEIL; }

KNOWN_FAILING;
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_GASTLY);
} WHEN {
TURN { MOVE(player, MOVE_SNOWSCAPE); }
TURN { MOVE(opponent, move); MOVE(player, MOVE_BRICK_BREAK); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SNOWSCAPE, player);
ANIMATION(ANIM_TYPE_MOVE, move, opponent);
NONE_OF {
ANIMATION(ANIM_TYPE_MOVE, MOVE_BRICK_BREAK, player);
MESSAGE("The wall shattered!");
HP_BAR(opponent);
}
}
}

SINGLE_BATTLE_TEST("Brick Break doesn't remove Light Screen, Reflect and Aurora Veil if the target Protected")
{
u16 move;

PARAMETRIZE { move = MOVE_LIGHT_SCREEN; }
PARAMETRIZE { move = MOVE_REFLECT; }
PARAMETRIZE { move = MOVE_AURORA_VEIL; }

GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_SNOWSCAPE); MOVE(opponent, move); }
TURN { MOVE(player, MOVE_BRICK_BREAK); MOVE(opponent, MOVE_PROTECT); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SNOWSCAPE, player);
ANIMATION(ANIM_TYPE_MOVE, move, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_PROTECT, opponent);
NONE_OF {
ANIMATION(ANIM_TYPE_MOVE, MOVE_BRICK_BREAK, player);
MESSAGE("The wall shattered!");
HP_BAR(opponent);
}
}
}

SINGLE_BATTLE_TEST("Brick Break doesn't remove Light Screen, Reflect and Aurora Veil if it misses")
{
u16 move;

PARAMETRIZE { move = MOVE_LIGHT_SCREEN; }
PARAMETRIZE { move = MOVE_REFLECT; }
PARAMETRIZE { move = MOVE_AURORA_VEIL; }

GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_BRIGHT_POWDER); }
} WHEN {
TURN { MOVE(player, MOVE_SNOWSCAPE); MOVE(opponent, move); }
TURN { MOVE(player, MOVE_BRICK_BREAK, hit: FALSE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SNOWSCAPE, player);
ANIMATION(ANIM_TYPE_MOVE, move, opponent);
NONE_OF {
ANIMATION(ANIM_TYPE_MOVE, MOVE_BRICK_BREAK, player);
MESSAGE("The wall shattered!");
HP_BAR(opponent);
}
}
}

DOUBLE_BATTLE_TEST("Brick Break can remove Light Screen, Reflect and Aurora Veil on users side")
{
u16 move;

PARAMETRIZE { move = MOVE_LIGHT_SCREEN; }
PARAMETRIZE { move = MOVE_REFLECT; }
PARAMETRIZE { move = MOVE_AURORA_VEIL; }

GIVEN {
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN {
MOVE(opponentLeft, MOVE_SNOWSCAPE);
MOVE(playerLeft, move);
MOVE(playerRight, MOVE_BRICK_BREAK, target: playerLeft);
}
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SNOWSCAPE, opponentLeft);
ANIMATION(ANIM_TYPE_MOVE, move, playerLeft);
ANIMATION(ANIM_TYPE_MOVE, MOVE_BRICK_BREAK, playerRight);
MESSAGE("The wall shattered!");
HP_BAR(playerLeft);
}
}

SINGLE_BATTLE_TEST("Move Raging Bull changes it's type depending on the Tauros Form")
{
u16 speciesPlayer;
u16 speciesOpponent;

PARAMETRIZE { speciesPlayer = SPECIES_TAUROS_PALDEAN_COMBAT_BREED; speciesOpponent = SPECIES_CHARIZARD; }
PARAMETRIZE { speciesPlayer = SPECIES_TAUROS_PALDEAN_BLAZE_BREED; speciesOpponent = SPECIES_BLASTOISE; }
PARAMETRIZE { speciesPlayer = SPECIES_TAUROS_PALDEAN_AQUA_BREED; speciesOpponent = SPECIES_VENUSAUR; }

GIVEN {
PLAYER(speciesPlayer);
OPPONENT(speciesOpponent);
} WHEN {
TURN { MOVE(player, MOVE_RAGING_BULL); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_RAGING_BULL, player);
HP_BAR(opponent);
MESSAGE("It's not very effective…");
}
}
Loading