Fix Costar not copying partner's critical hit boosts (#8386)
This commit is contained in:
parent
115694675f
commit
d0965814fe
@ -745,7 +745,6 @@ struct BattleStruct
|
||||
u8 pledgeMove:1;
|
||||
u8 effectsBeforeUsingMoveDone:1; // Mega Evo and Focus Punch/Shell Trap effects.
|
||||
u8 spriteIgnore0Hp:1;
|
||||
u8 bonusCritStages[MAX_BATTLERS_COUNT]; // G-Max Chi Strike boosts crit stages of allies.
|
||||
u8 itemPartyIndex[MAX_BATTLERS_COUNT];
|
||||
u8 itemMoveIndex[MAX_BATTLERS_COUNT];
|
||||
s32 aiDelayTimer; // Counts number of frames AI takes to choose an action.
|
||||
|
||||
@ -386,6 +386,7 @@ u32 GetBattlerAffectionHearts(u32 battler);
|
||||
void TryToRevertMimicryAndFlags(void);
|
||||
bool32 BattleArenaTurnEnd(void);
|
||||
u32 CountBattlerStatIncreases(u32 battler, bool32 countEvasionAcc);
|
||||
bool32 BattlerHasCopyableChanges(u32 battler);
|
||||
bool32 ChangeTypeBasedOnTerrain(u32 battler);
|
||||
void RemoveConfusionStatus(u32 battler);
|
||||
u8 GetBattlerGender(u32 battler);
|
||||
|
||||
@ -186,6 +186,7 @@ enum VolatileFlags
|
||||
F(VOLATILE_FORESIGHT, foresight, (u32, 1)) \
|
||||
F(VOLATILE_DRAGON_CHEER, dragonCheer, (u32, 1), V_BATON_PASSABLE) \
|
||||
F(VOLATILE_FOCUS_ENERGY, focusEnergy, (u32, 1), V_BATON_PASSABLE) \
|
||||
F(VOLATILE_BONUS_CRIT_STAGES, bonusCritStages, (u32, 3)) \
|
||||
F(VOLATILE_SEMI_INVULNERABLE, semiInvulnerable, (u32, SEMI_INVULNERABLE_COUNT - 1)) \
|
||||
F(VOLATILE_ELECTRIFIED, electrified, (u32, 1)) \
|
||||
F(VOLATILE_MUD_SPORT, mudSport, (u32, 1), V_BATON_PASSABLE) \
|
||||
|
||||
@ -353,6 +353,7 @@ struct Volatiles
|
||||
// u32 foresight:1;
|
||||
// u32 dragonCheer:1;
|
||||
// u32 focusEnergy:1;
|
||||
// u32 bonusCritStages:3;
|
||||
};
|
||||
|
||||
struct BattlePokemon
|
||||
|
||||
@ -3277,9 +3277,6 @@ void SwitchInClearSetData(u32 battler, struct Volatiles *volatilesCopy)
|
||||
gAiLogicData->ejectButtonSwitch = FALSE;
|
||||
gAiLogicData->ejectPackSwitch = FALSE;
|
||||
|
||||
// Reset G-Max Chi Strike boosts.
|
||||
gBattleStruct->bonusCritStages[battler] = 0;
|
||||
|
||||
// Clear selected party ID so Revival Blessing doesn't get confused.
|
||||
gSelectedMonPartyId = PARTY_SIZE;
|
||||
|
||||
|
||||
@ -1627,7 +1627,7 @@ s32 CalcCritChanceStage(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordA
|
||||
+ GetHoldEffectCritChanceIncrease(battlerAtk, holdEffectAtk)
|
||||
+ ((B_AFFECTION_MECHANICS == TRUE && GetBattlerAffectionHearts(battlerAtk) == AFFECTION_FIVE_HEARTS) ? 2 : 0)
|
||||
+ (abilityAtk == ABILITY_SUPER_LUCK ? 1 : 0)
|
||||
+ gBattleStruct->bonusCritStages[gBattlerAttacker];
|
||||
+ gBattleMons[battlerAtk].volatiles.bonusCritStages;
|
||||
|
||||
if (critChance >= ARRAY_COUNT(sCriticalHitOdds))
|
||||
critChance = ARRAY_COUNT(sCriticalHitOdds) - 1;
|
||||
@ -1658,7 +1658,7 @@ s32 CalcCritChanceStageGen1(u32 battlerAtk, u32 battlerDef, u32 move, bool32 rec
|
||||
{
|
||||
s32 critChance = 0;
|
||||
s32 moveCritStage = GetMoveCriticalHitStage(gCurrentMove);
|
||||
s32 bonusCritStage = gBattleStruct->bonusCritStages[battlerAtk]; // G-Max Chi Strike
|
||||
s32 bonusCritStage = gBattleMons[battlerAtk].volatiles.bonusCritStages; // G-Max Chi Strike
|
||||
u32 holdEffectCritStage = GetHoldEffectCritChanceIncrease(battlerAtk, holdEffectAtk);
|
||||
u16 baseSpeed = GetSpeciesBaseSpeed(gBattleMons[battlerAtk].species);
|
||||
|
||||
@ -4042,9 +4042,11 @@ void SetMoveEffect(u32 battler, u32 effectBattler, enum MoveEffect moveEffect, c
|
||||
gBattlescriptCurrInstr = BattleScript_EffectMeanLookSide;
|
||||
break;
|
||||
case MOVE_EFFECT_CRIT_PLUS_SIDE:
|
||||
gBattleStruct->bonusCritStages[gBattlerAttacker]++;
|
||||
gBattleStruct->bonusCritStages[BATTLE_PARTNER(gBattlerAttacker)]++;
|
||||
BattleScriptPush(battleScript);
|
||||
if (gBattleMons[gBattlerAttacker].volatiles.bonusCritStages < 3)
|
||||
gBattleMons[gBattlerAttacker].volatiles.bonusCritStages++;
|
||||
if (gBattleMons[BATTLE_PARTNER(gBattlerAttacker)].volatiles.bonusCritStages < 3)
|
||||
gBattleMons[BATTLE_PARTNER(gBattlerAttacker)].volatiles.bonusCritStages++;
|
||||
BattleScriptPush(gBattlescriptCurrInstr + 1);
|
||||
gBattlescriptCurrInstr = BattleScript_EffectRaiseCritAlliesAnim;
|
||||
break;
|
||||
case MOVE_EFFECT_HEAL_TEAM:
|
||||
|
||||
@ -4494,15 +4494,20 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
||||
}
|
||||
break;
|
||||
case ABILITY_COSTAR:
|
||||
partner = BATTLE_PARTNER(battler);
|
||||
if (!gSpecialStatuses[battler].switchInAbilityDone
|
||||
&& IsDoubleBattle()
|
||||
&& IsBattlerAlive(BATTLE_PARTNER(battler))
|
||||
&& CountBattlerStatIncreases(BATTLE_PARTNER(battler), FALSE))
|
||||
&& IsBattlerAlive(partner)
|
||||
&& BattlerHasCopyableChanges(partner))
|
||||
{
|
||||
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||
for (i = 0; i < NUM_BATTLE_STATS; i++)
|
||||
gBattleMons[battler].statStages[i] = gBattleMons[BATTLE_PARTNER(battler)].statStages[i];
|
||||
gEffectBattler = BATTLE_PARTNER(battler);
|
||||
gBattleMons[battler].statStages[i] = gBattleMons[partner].statStages[i];
|
||||
// Copy crit boosts (Focus Energy, Dragon Cheer, G-Max Chi Strike)
|
||||
gBattleMons[battler].volatiles.focusEnergy = gBattleMons[partner].volatiles.focusEnergy;
|
||||
gBattleMons[battler].volatiles.dragonCheer = gBattleMons[partner].volatiles.dragonCheer;
|
||||
gBattleMons[battler].volatiles.bonusCritStages = gBattleMons[partner].volatiles.bonusCritStages;
|
||||
gEffectBattler = partner;
|
||||
BattleScriptPushCursorAndCallback(BattleScript_CostarActivates);
|
||||
effect++;
|
||||
}
|
||||
@ -6773,6 +6778,24 @@ u32 CountBattlerStatIncreases(u32 battler, bool32 countEvasionAcc)
|
||||
return count;
|
||||
}
|
||||
|
||||
bool32 BattlerHasCopyableChanges(u32 battler)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < NUM_BATTLE_STATS; i++)
|
||||
{
|
||||
if (gBattleMons[battler].statStages[i] != DEFAULT_STAT_STAGE)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (gBattleMons[battler].volatiles.focusEnergy
|
||||
|| gBattleMons[battler].volatiles.dragonCheer
|
||||
|| gBattleMons[battler].volatiles.bonusCritStages != 0)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
u32 GetMoveTargetCount(struct DamageContext *ctx)
|
||||
{
|
||||
u32 battlerAtk = ctx->battlerAtk;
|
||||
|
||||
@ -25,8 +25,99 @@ DOUBLE_BATTLE_TEST("Costar copies an ally's stat stages upon entering battle")
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Costar copies an ally's Dragon Cheer critical hit boost")
|
||||
{
|
||||
PASSES_RANDOMLY(1, 8, RNG_CRITICAL_HIT);
|
||||
GIVEN {
|
||||
ASSUME(gMovesInfo[MOVE_DRAGON_CHEER].effect == EFFECT_DRAGON_CHEER);
|
||||
ASSUME(gMovesInfo[MOVE_TACKLE].criticalHitStage == 0);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
PLAYER(SPECIES_FLAMIGO) { Ability(ABILITY_COSTAR); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(playerRight, MOVE_DRAGON_CHEER, target: playerLeft); MOVE(playerLeft, MOVE_CELEBRATE); }
|
||||
TURN { SWITCH(playerRight, 2); }
|
||||
TURN { MOVE(playerRight, MOVE_TACKLE, target: opponentLeft); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_CHEER, playerRight);
|
||||
ABILITY_POPUP(playerRight, ABILITY_COSTAR);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, playerRight);
|
||||
MESSAGE("A critical hit!");
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Costar copies an ally's lowered stat stages")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gMovesInfo[MOVE_GROWL].effect == EFFECT_ATTACK_DOWN);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
PLAYER(SPECIES_FLAMIGO) { Ability(ABILITY_COSTAR); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponentLeft, MOVE_GROWL); MOVE(opponentRight, MOVE_CELEBRATE); }
|
||||
TURN { SWITCH(playerRight, 2); MOVE(playerLeft, MOVE_CELEBRATE); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_GROWL, opponentLeft);
|
||||
ABILITY_POPUP(playerRight, ABILITY_COSTAR);
|
||||
} THEN {
|
||||
EXPECT_EQ(playerLeft->statStages[STAT_ATK], DEFAULT_STAT_STAGE - 1);
|
||||
EXPECT_EQ(playerRight->statStages[STAT_ATK], DEFAULT_STAT_STAGE - 1);
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Costar copies an ally's Focus Energy critical hit boost")
|
||||
{
|
||||
PASSES_RANDOMLY(1, 2, RNG_CRITICAL_HIT);
|
||||
GIVEN {
|
||||
ASSUME(gMovesInfo[MOVE_FOCUS_ENERGY].effect == EFFECT_FOCUS_ENERGY);
|
||||
ASSUME(gMovesInfo[MOVE_TACKLE].criticalHitStage == 0);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
PLAYER(SPECIES_FLAMIGO) { Ability(ABILITY_COSTAR); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(playerLeft, MOVE_SWORDS_DANCE); MOVE(playerRight, MOVE_CELEBRATE); }
|
||||
TURN { MOVE(playerLeft, MOVE_FOCUS_ENERGY); MOVE(playerRight, MOVE_CELEBRATE); }
|
||||
TURN { SWITCH(playerRight, 2); }
|
||||
TURN { MOVE(playerRight, MOVE_TACKLE, target: opponentLeft); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, playerLeft);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_FOCUS_ENERGY, playerLeft);
|
||||
ABILITY_POPUP(playerRight, ABILITY_COSTAR);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, playerRight);
|
||||
MESSAGE("A critical hit!");
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Costar copies an ally's Dragon Cheer critical hit boost")
|
||||
{
|
||||
PASSES_RANDOMLY(1, 8, RNG_CRITICAL_HIT);
|
||||
GIVEN {
|
||||
ASSUME(gMovesInfo[MOVE_DRAGON_CHEER].effect == EFFECT_DRAGON_CHEER);
|
||||
ASSUME(gMovesInfo[MOVE_TACKLE].criticalHitStage == 0);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
PLAYER(SPECIES_FLAMIGO) { Ability(ABILITY_COSTAR); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(playerRight, MOVE_DRAGON_CHEER, target: playerLeft); MOVE(playerLeft, MOVE_SWORDS_DANCE); }
|
||||
TURN { SWITCH(playerRight, 2); MOVE(playerLeft, MOVE_CELEBRATE); }
|
||||
TURN { MOVE(playerRight, MOVE_TACKLE, target: opponentLeft); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_CHEER, playerRight);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, playerLeft);
|
||||
ABILITY_POPUP(playerRight, ABILITY_COSTAR);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, playerRight);
|
||||
MESSAGE("A critical hit!");
|
||||
}
|
||||
}
|
||||
|
||||
// Copy from Ruin ability tests
|
||||
TO_DO_BATTLE_TEST("Costar's message displays correctly after all battlers fainted - Player");
|
||||
TO_DO_BATTLE_TEST("Costar's message displays correctly after all battlers fainted - Opponent");
|
||||
|
||||
TO_DO_BATTLE_TEST("Costar can copy an ally's critical hit ratio");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user