06.03.25 master to upcoming merge (#6388)

This commit is contained in:
Bassoonian 2025-03-06 18:45:39 +01:00 committed by GitHub
commit 440c2eb893
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 199 additions and 74 deletions

View File

@ -67,7 +67,7 @@ Also, *please follow the Pull Request template and feel free to discuss how the
- Fairy Type (configurable).
- Physical/Special/Status Category (configurable).
- New moves and abilities up to Scarlet and Violet.
- Custom Contest data up to SwSh, newer moves are WIP. ([source](https://pokemonurpg.com/info/contests/rse-move-list/))
- Custom Contest data up to SwSh, newer moves are WIP. ([source](https://web.archive.org/web/20240910012333/https://pokemonurpg.com/info/contests/rse-move-list/))
- Battle gimmick support:
- Mega Evolution
- Primal Reversion

View File

@ -2376,6 +2376,10 @@
callnative BS_SwapStats
.byte \stat
.endm
.macro restoresavedmove
callnative BS_RestoreSavedMove
.endm
@ helpful macros
.macro setstatchanger stat:req, stages:req, down:req

View File

@ -6045,6 +6045,8 @@ BattleScript_RoarSuccessSwitch::
BattleScript_RoarSuccessSwitch_Ret:
swapattackerwithtarget @ continuation of RedCardActivates
restoretarget
restoreattacker
restoresavedmove
setbyte sSWITCH_CASE, B_SWITCH_NORMAL
return
@ -9519,6 +9521,8 @@ BattleScript_RedCardActivationNoSwitch::
waitmessage B_WAIT_TIME_LONG
removeitem BS_SCRIPTING
restoretarget
restoreattacker
restoresavedmove
return
BattleScript_RedCardActivates::
@ -9537,22 +9541,17 @@ BattleScript_RedCardEnd:
return
BattleScript_RedCardIngrain:
printstring STRINGID_PKMNANCHOREDITSELF
BattleScript_RedCardIngrainContinue:
waitmessage B_WAIT_TIME_LONG
removeitem BS_SCRIPTING
restoretarget
return
BattleScript_RedCardSuctionCups:
printstring STRINGID_PKMNANCHORSITSELFWITH
waitmessage B_WAIT_TIME_LONG
removeitem BS_SCRIPTING
restoretarget
return
printstring STRINGID_PKMNANCHORSITSELFWITH
goto BattleScript_RedCardIngrainContinue
BattleScript_RedCardDynamaxed:
printstring STRINGID_MOVEBLOCKEDBYDYNAMAX
waitmessage B_WAIT_TIME_LONG
removeitem BS_SCRIPTING
restoretarget
return
goto BattleScript_RedCardIngrainContinue
BattleScript_EjectButtonActivates::
makevisible BS_ATTACKER

View File

@ -836,6 +836,7 @@ struct BattleStruct
struct MessageStatus slideMessageStatus;
u8 trainerSlideSpriteIds[MAX_BATTLERS_COUNT];
u8 embodyAspectBoost[NUM_BATTLE_SIDES];
u16 savedMove; // backup current move for mid-turn switching, e.g. Red Card
};
// The palaceFlags member of struct BattleStruct contains 1 flag per move to indicate which moves the AI should consider,

View File

@ -293,13 +293,13 @@ enum MoveEndEffects
MOVEEND_LIFEORB_SHELLBELL, // Includes shell bell, throat spray, etc
MOVEEND_CHANGED_ITEMS,
MOVEEND_PICKPOCKET,
MOVEEND_DANCER,
MOVEEND_EMERGENCY_EXIT,
MOVEEND_SYMBIOSIS,
MOVEEND_OPPORTUNIST, // Occurs after other stat change items/abilities to try and copy the boosts
MOVEEND_SAME_MOVE_TURNS,
MOVEEND_SET_EVOLUTION_TRACKER,
MOVEEND_CLEAR_BITS,
MOVEEND_DANCER,
MOVEEND_PURSUIT_NEXT_ACTION,
MOVEEND_COUNT,
};

View File

@ -5072,7 +5072,7 @@ static s32 AI_Risky(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
return score;
}
// Adds score bonus to best powered move
// Adds score bonus to OHKOs and 2HKOs
static s32 AI_TryTo2HKO(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
{
if (IS_TARGETING_PARTNER(battlerAtk, battlerDef))

View File

@ -1719,9 +1719,9 @@ static void MoveSelectionDisplayMoveType(u32 battler)
{
if (speciesId == SPECIES_OGERPON_WELLSPRING || speciesId == SPECIES_OGERPON_WELLSPRING_TERA
|| speciesId == SPECIES_OGERPON_HEARTHFLAME || speciesId == SPECIES_OGERPON_HEARTHFLAME_TERA
|| speciesId == SPECIES_OGERPON_CORNERSTONE || speciesId == SPECIES_OGERPON_CORNERSTONE_TERA)
type = gBattleMons[battler].types[1];
|| speciesId == SPECIES_OGERPON_HEARTHFLAME || speciesId == SPECIES_OGERPON_HEARTHFLAME_TERA
|| speciesId == SPECIES_OGERPON_CORNERSTONE || speciesId == SPECIES_OGERPON_CORNERSTONE_TERA)
type = gSpeciesInfo[speciesId].types[1];
}
else if (GetMoveCategory(move) == DAMAGE_CATEGORY_STATUS
&& (GetActiveGimmick(battler) == GIMMICK_DYNAMAX || IsGimmickSelected(battler, GIMMICK_DYNAMAX)))

View File

@ -5668,7 +5668,7 @@ static void FreeResetData_ReturnToOvOrDoEvolutions(void)
{
// To account for Battle Factory and Slateport Battle Tent, enemy parties are zeroed out in the facilitites respective src/xxx.c files
// The ZeroEnemyPartyMons() call happens in SaveXXXChallenge function (eg. SaveFactoryChallenge)
if (!(gBattleTypeFlags & BATTLE_TYPE_FRONTIER))
if (!(gBattleTypeFlags & (BATTLE_TYPE_FRONTIER | BATTLE_TYPE_ROAMER)))
{
ZeroEnemyPartyMons();
}
@ -5741,6 +5741,7 @@ static void ReturnFromBattleToOverworld(void)
if (gBattleTypeFlags & BATTLE_TYPE_ROAMER)
{
UpdateRoamerHPStatus(&gEnemyParty[0]);
ZeroEnemyPartyMons();
#ifndef BUGFIX
if ((gBattleOutcome & B_OUTCOME_WON) || gBattleOutcome == B_OUTCOME_CAUGHT)
@ -5962,19 +5963,19 @@ u32 GetDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler, u8 *ateBoost)
case SPECIES_TAUROS_PALDEA_COMBAT:
case SPECIES_TAUROS_PALDEA_BLAZE:
case SPECIES_TAUROS_PALDEA_AQUA:
return type2;
return gSpeciesInfo[species].types[1];
}
break;
case EFFECT_IVY_CUDGEL:
switch (species)
{
case SPECIES_OGERPON_WELLSPRING:
case SPECIES_OGERPON_HEARTHFLAME:
case SPECIES_OGERPON_CORNERSTONE:
case SPECIES_OGERPON_WELLSPRING_TERA:
case SPECIES_OGERPON_HEARTHFLAME:
case SPECIES_OGERPON_HEARTHFLAME_TERA:
case SPECIES_OGERPON_CORNERSTONE:
case SPECIES_OGERPON_CORNERSTONE_TERA:
return type2;
return gSpeciesInfo[species].types[1];
}
break;
case EFFECT_NATURAL_GIFT:

View File

@ -7075,6 +7075,8 @@ static void Cmd_moveend(void)
{
gLastUsedItem = gBattleMons[battler].item;
SaveBattlerTarget(battler); // save battler with red card
SaveBattlerAttacker(gBattlerAttacker);
gBattleStruct->savedMove = gCurrentMove;
gBattleScripting.battler = battler;
gEffectBattler = gBattlerAttacker;
gBattleStruct->redCardActivates = TRUE;
@ -7141,49 +7143,6 @@ static void Cmd_moveend(void)
}
gBattleScripting.moveendState++;
break;
case MOVEEND_DANCER: // Special case because it's so annoying
if (IsDanceMove(gCurrentMove) && !gBattleStruct->snatchedMoveIsUsed)
{
u32 battler, nextDancer = 0;
bool32 hasDancerTriggered = FALSE;
for (battler = 0; battler < gBattlersCount; battler++)
{
if (gSpecialStatuses[battler].dancerUsedMove)
{
// in case a battler fails to act on a Dancer-called move
hasDancerTriggered = TRUE;
break;
}
}
if (!(gBattleStruct->moveResultFlags[gBattlerTarget] & (MOVE_RESULT_FAILED | MOVE_RESULT_DOESNT_AFFECT_FOE)
|| (gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE && !hasDancerTriggered)
|| (!gSpecialStatuses[gBattlerAttacker].dancerUsedMove && gBattleStruct->bouncedMoveIsUsed)))
{ // Dance move succeeds
// Set target for other Dancer mons; set bit so that mon cannot activate Dancer off of its own move
if (!gSpecialStatuses[gBattlerAttacker].dancerUsedMove)
{
gBattleScripting.savedBattler = gBattlerTarget | 0x4;
gBattleScripting.savedBattler |= (gBattlerAttacker << 4);
gSpecialStatuses[gBattlerAttacker].dancerUsedMove = TRUE;
}
for (battler = 0; battler < gBattlersCount; battler++)
{
if (GetBattlerAbility(battler) == ABILITY_DANCER && !gSpecialStatuses[battler].dancerUsedMove)
{
if (!nextDancer || (gBattleMons[battler].speed < gBattleMons[nextDancer & 0x3].speed))
nextDancer = battler | 0x4;
}
}
if (nextDancer && AbilityBattleEffects(ABILITYEFFECT_MOVE_END_OTHER, nextDancer & 0x3, 0, 0, 0))
effect = TRUE;
ClearDamageCalcResults();
}
}
gBattleScripting.moveendState++;
break;
case MOVEEND_EMERGENCY_EXIT: // Special case, because moves hitting multiple opponents stop after switching out
for (i = 0; i < gBattlersCount; i++)
{
@ -7289,8 +7248,6 @@ static void Cmd_moveend(void)
gBattleStruct->isAtkCancelerForCalledMove = FALSE;
gBattleStruct->swapDamageCategory = FALSE;
gBattleStruct->categoryOverride = FALSE;
gBattleStruct->bouncedMoveIsUsed = FALSE;
gBattleStruct->snatchedMoveIsUsed = FALSE;
gBattleStruct->additionalEffectsCounter = 0;
gBattleStruct->poisonPuppeteerConfusion = FALSE;
gBattleStruct->fickleBeamBoosted = FALSE;
@ -7303,7 +7260,6 @@ static void Cmd_moveend(void)
if (B_CHARGE >= GEN_9 && moveType == TYPE_ELECTRIC && (IsBattlerTurnDamaged(gBattlerTarget) || gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT))
gStatuses3[gBattlerAttacker] &= ~(STATUS3_CHARGED_UP);
memset(gQueuedStatBoosts, 0, sizeof(gQueuedStatBoosts));
ClearDamageCalcResults();
for (i = 0; i < gBattlersCount; i++)
{
@ -7318,6 +7274,47 @@ static void Cmd_moveend(void)
}
}
gBattleScripting.moveendState++;
break;
case MOVEEND_DANCER: // Special case because it's so annoying
if (IsDanceMove(gCurrentMove) && !gBattleStruct->snatchedMoveIsUsed)
{
u32 battler, nextDancer = 0;
bool32 hasDancerTriggered = FALSE;
for (battler = 0; battler < gBattlersCount; battler++)
{
if (gSpecialStatuses[battler].dancerUsedMove)
{
// in case a battler fails to act on a Dancer-called move
hasDancerTriggered = TRUE;
break;
}
}
if (!(gBattleStruct->moveResultFlags[gBattlerTarget] & (MOVE_RESULT_FAILED | MOVE_RESULT_DOESNT_AFFECT_FOE)
|| (gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE && !hasDancerTriggered)
|| (!gSpecialStatuses[gBattlerAttacker].dancerUsedMove && gBattleStruct->bouncedMoveIsUsed)))
{ // Dance move succeeds
// Set target for other Dancer mons; set bit so that mon cannot activate Dancer off of its own move
if (!gSpecialStatuses[gBattlerAttacker].dancerUsedMove)
{
gBattleScripting.savedBattler = gBattlerTarget | 0x4;
gBattleScripting.savedBattler |= (gBattlerAttacker << 4);
gSpecialStatuses[gBattlerAttacker].dancerUsedMove = TRUE;
}
for (battler = 0; battler < gBattlersCount; battler++)
{
if (GetBattlerAbility(battler) == ABILITY_DANCER && !gSpecialStatuses[battler].dancerUsedMove)
{
if (!nextDancer || (gBattleMons[battler].speed < gBattleMons[nextDancer & 0x3].speed))
nextDancer = battler | 0x4;
}
}
if (nextDancer && AbilityBattleEffects(ABILITYEFFECT_MOVE_END_OTHER, nextDancer & 0x3, 0, 0, 0))
effect = TRUE;
}
}
gBattleScripting.moveendState++;
break;
case MOVEEND_PURSUIT_NEXT_ACTION:
@ -8743,6 +8740,7 @@ static void ResetValuesForCalledMove(void)
gBattleScripting.animTargetsHit = 0;
SetTypeBeforeUsingMove(gCurrentMove, gBattlerAttacker);
HandleMoveTargetRedirection();
ClearDamageCalcResults();
}
static void Cmd_jumptocalledmove(void)
@ -18644,3 +18642,16 @@ void BS_SetSteelsurge(void)
gBattlescriptCurrInstr = cmd->nextInstr;
}
}
void BS_RestoreSavedMove(void)
{
NATIVE_ARGS();
if (gBattleStruct->savedMove == MOVE_NONE)
DebugPrintfLevel(MGBA_LOG_WARN, "restoresavedmove was called with no move saved!");
gCurrentMove = gBattleStruct->savedMove;
gBattleStruct->savedMove = MOVE_NONE;
gBattlescriptCurrInstr = cmd->nextInstr;
}

View File

@ -811,6 +811,8 @@ void HandleAction_ActionFinished(void)
gBattleScripting.animTurn = 0;
gBattleScripting.animTargetsHit = 0;
gBattleStruct->dynamicMoveType = 0;
gBattleStruct->bouncedMoveIsUsed = FALSE;
gBattleStruct->snatchedMoveIsUsed = FALSE;
gBattleScripting.moveendState = 0;
gBattleCommunication[3] = 0;
gBattleCommunication[4] = 0;

View File

@ -2174,6 +2174,11 @@ void ObjectEventInteractionGetBerryCountString(void)
u8 berry = GetBerryTypeByBerryTreeId(treeId);
u8 count = GetBerryCountByBerryTreeId(treeId);
// The strings for growing Berries all refer to a singular berry plant.
// This ensures that text about planting a Berry and the growing Berry reads correctly.
if (GetStageByBerryTreeId(treeId) != BERRY_STAGE_BERRIES)
count = 1;
gSpecialVar_0x8006 = BerryTypeToItemId(berry);
CopyItemNameHandlePlural(BerryTypeToItemId(berry), gStringVar1, count);
berry = GetTreeMutationValue(treeId);

View File

@ -7508,7 +7508,7 @@ const struct SpeciesInfo gSpeciesInfoGen7[] =
.natDexNum = NATIONAL_DEX_MELMETAL,
.categoryName = _("Hex Nut"),
.height = 25,
.weight = 800,
.weight = 8000,
.description = COMPOUND_STRING(
"Revered long ago for its capacity to\n"
"create iron from nothing, for some reason\n"

View File

@ -46,7 +46,7 @@ Optional fields for Pokemon:
(Order does not matter)
- EVs (252 HP / 128 Spe / 48 Def, defaults to all 0, is not capped at 512 total)
(Order does not matter)
- Ball (Poke Ball or ITEM_POKE_BALL, defaults to Poke Ball
- Ball (Poke Ball or ITEM_POKE_BALL, defaults to Poke Ball)
- Happiness (Number between 1 and 255)
- Nature (Rash or NATURE_RASH, defaults to Hardy)
- Shiny (Yes/No, defaults to No)

View File

@ -2002,6 +2002,19 @@ u16 MonTryLearningNewMove(struct Pokemon *mon, bool8 firstMove)
}
}
// Handler for if Zacian or Zamazenta should learn Iron Head
// since it transforms in the Behemoth Blade/Bash move in
// battle in the Crowned forms.
if (learnset[sLearningMoveTableID].move == MOVE_IRON_HEAD && (species == SPECIES_ZAMAZENTA_CROWNED || species == SPECIES_ZACIAN_CROWNED))
{
for (u32 accessor = MON_DATA_MOVE1; accessor <= MON_DATA_MOVE4; accessor++)
{
u32 move = GetMonData(mon, accessor);
if (move == MOVE_BEHEMOTH_BLADE || move == MOVE_BEHEMOTH_BASH)
return MOVE_NONE;
}
}
if (learnset[sLearningMoveTableID].level == level)
{
gMoveToLearn = learnset[sLearningMoveTableID].move;

View File

@ -39,7 +39,7 @@ DOUBLE_BATTLE_TEST("Dancer can copy Teeter Dance and confuse both opposing targe
GIVEN {
ASSUME(IsDanceMove(MOVE_TEETER_DANCE));
ASSUME(gItemsInfo[ITEM_LUM_BERRY].holdEffect == HOLD_EFFECT_CURE_STATUS);
PLAYER(SPECIES_WOBBUFFET)
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WYNAUT) { Item(ITEM_LUM_BERRY); }
OPPONENT(SPECIES_ORICORIO) { Ability(ABILITY_DANCER); Item(ITEM_LUM_BERRY); }
OPPONENT(SPECIES_SLOWPOKE) { Ability(ABILITY_OWN_TEMPO); }
@ -58,10 +58,10 @@ DOUBLE_BATTLE_TEST("Dancer triggers from slowest to fastest")
{
GIVEN {
ASSUME(IsDanceMove(MOVE_DRAGON_DANCE));
PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_DANCER); Speed(10); }
PLAYER(SPECIES_ORICORIO) { Ability(ABILITY_DANCER); Speed(10); }
PLAYER(SPECIES_WYNAUT) { Speed(50); }
OPPONENT(SPECIES_ORICORIO) { Ability(ABILITY_DANCER); Speed(20); }
OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_DANCER); Speed(3); }
OPPONENT(SPECIES_ORICORIO) { Ability(ABILITY_DANCER); Speed(3); }
} WHEN {
TURN { MOVE(playerRight, MOVE_DRAGON_DANCE); }
} SCENE {
@ -103,7 +103,7 @@ DOUBLE_BATTLE_TEST("Dancer still triggers if another dancer flinches")
GIVEN {
ASSUME(MoveHasAdditionalEffectWithChance(MOVE_FAKE_OUT, MOVE_EFFECT_FLINCH, 100));
ASSUME(IsDanceMove(MOVE_DRAGON_DANCE));
PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_DANCER); Speed(10); }
PLAYER(SPECIES_ORICORIO) { Ability(ABILITY_DANCER); Speed(10); }
PLAYER(SPECIES_WYNAUT) { Speed(5); }
OPPONENT(SPECIES_ORICORIO) { Ability(ABILITY_DANCER); Speed(20); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(3); }
@ -114,9 +114,9 @@ DOUBLE_BATTLE_TEST("Dancer still triggers if another dancer flinches")
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DANCE, playerRight);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight);
ABILITY_POPUP(playerLeft, ABILITY_DANCER);
MESSAGE("Wobbuffet flinched and couldn't move!");
MESSAGE("Oricorio flinched and couldn't move!");
NONE_OF {
MESSAGE("Wobbuffet used Dragon Dance!");
MESSAGE("Oricorio used Dragon Dance!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DANCE, playerLeft);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft);
}
@ -246,3 +246,91 @@ DOUBLE_BATTLE_TEST("Dancer doesn't call a move that didn't execute due to Powder
}
}
}
DOUBLE_BATTLE_TEST("Dancer still activates after Red Card")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) ;
PLAYER(SPECIES_ORICORIO) { Ability(ABILITY_DANCER); }
PLAYER(SPECIES_CHANSEY);
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_RED_CARD); }
OPPONENT(SPECIES_BULBASAUR);
OPPONENT(SPECIES_SHUCKLE);
} WHEN {
TURN { MOVE(playerLeft, MOVE_FIERY_DANCE, target: opponentLeft); }
} SCENE {
MESSAGE("Wobbuffet used Fiery Dance!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_FIERY_DANCE, playerLeft);
HP_BAR(opponentLeft);
// Red card trigger
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponentLeft);
MESSAGE("The opposing Wobbuffet held up its Red Card against Wobbuffet!");
MESSAGE("Chansey was dragged out!");
// Dancer
ABILITY_POPUP(playerRight, ABILITY_DANCER);
ANIMATION(ANIM_TYPE_MOVE, MOVE_FIERY_DANCE, playerRight);
HP_BAR(opponentLeft);
}
}
DOUBLE_BATTLE_TEST("Dancer still activate after Red Card even if blocked by Suction Cups")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_SUCTION_CUPS); }
PLAYER(SPECIES_ORICORIO) { Ability(ABILITY_DANCER); }
PLAYER(SPECIES_CHANSEY);
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_RED_CARD); }
OPPONENT(SPECIES_BULBASAUR);
OPPONENT(SPECIES_SHUCKLE);
} WHEN {
TURN { MOVE(playerLeft, MOVE_FIERY_DANCE, target: opponentLeft); }
} SCENE {
MESSAGE("Wobbuffet used Fiery Dance!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_FIERY_DANCE, playerLeft);
HP_BAR(opponentLeft);
// red card trigger
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponentLeft);
MESSAGE("The opposing Wobbuffet held up its Red Card against Wobbuffet!");
MESSAGE("Wobbuffet anchors itself with Suction Cups!");
NOT MESSAGE("Chansey was dragged out!");
// Dancer
ABILITY_POPUP(playerRight, ABILITY_DANCER);
ANIMATION(ANIM_TYPE_MOVE, MOVE_FIERY_DANCE, playerRight);
HP_BAR(opponentLeft);
}
}
DOUBLE_BATTLE_TEST("Dancer correctly restores move targets")
{
GIVEN {
ASSUME(IsDanceMove(MOVE_REVELATION_DANCE));
PLAYER(SPECIES_ORICORIO) { Speed(10); }
PLAYER(SPECIES_ORICORIO) { Speed(3); }
OPPONENT(SPECIES_ORICORIO) { Speed(1); }
OPPONENT(SPECIES_ORICORIO) { Speed(5); }
} WHEN {
TURN { MOVE(playerLeft, MOVE_REVELATION_DANCE, target: opponentLeft);
MOVE(opponentRight, MOVE_TACKLE, target: playerRight);
MOVE(playerRight, MOVE_TACKLE, target: opponentRight);
MOVE(opponentLeft, MOVE_TACKLE, target: playerRight); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_REVELATION_DANCE, playerLeft);
HP_BAR(opponentLeft);
ABILITY_POPUP(opponentLeft, ABILITY_DANCER);
ANIMATION(ANIM_TYPE_MOVE, MOVE_REVELATION_DANCE, opponentLeft);
HP_BAR(playerLeft);
ABILITY_POPUP(playerRight, ABILITY_DANCER);
ANIMATION(ANIM_TYPE_MOVE, MOVE_REVELATION_DANCE, playerRight);
HP_BAR(opponentLeft);
ABILITY_POPUP(opponentRight, ABILITY_DANCER);
ANIMATION(ANIM_TYPE_MOVE, MOVE_REVELATION_DANCE, opponentRight);
HP_BAR(playerLeft);
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponentRight);
HP_BAR(playerRight);
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, playerRight);
HP_BAR(opponentRight);
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponentLeft);
HP_BAR(playerRight);
}
}

View File

@ -520,3 +520,4 @@ SINGLE_BATTLE_TEST("Red Card activates before Eject Pack")
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent);
}
}