Last Respects effect + Fixed Supreme Overlord (#4151)
* Last Respects effect + Fixed Supreme Overlord * Fixed ability pop-up happening when there's no fainted party members * Fixed Supreme Overlord counting faints during the battle instead of fainted party * Removed invalid test. * Converted GetSupremeOverlordModifier to an inline function * Created inline functions to obtain faint counters * Fixed erroneous implemenation and tests
This commit is contained in:
parent
5496115f92
commit
af95a09961
8 changed files with 187 additions and 28 deletions
|
@ -748,7 +748,6 @@ struct BattleStruct
|
|||
u8 storedHealingWish:4; // Each battler as a bit.
|
||||
u8 storedLunarDance:4; // Each battler as a bit.
|
||||
u8 bonusCritStages[MAX_BATTLERS_COUNT]; // G-Max Chi Strike boosts crit stages of allies.
|
||||
uq4_12_t supremeOverlordModifier[MAX_BATTLERS_COUNT];
|
||||
u8 itemPartyIndex[MAX_BATTLERS_COUNT];
|
||||
u8 itemMoveIndex[MAX_BATTLERS_COUNT];
|
||||
u8 trainerSlideFirstCriticalHitMsgState:2;
|
||||
|
@ -769,6 +768,7 @@ struct BattleStruct
|
|||
u8 transformZeroToHero[NUM_BATTLE_SIDES];
|
||||
u8 stickySyrupdBy[MAX_BATTLERS_COUNT];
|
||||
u8 abilityActivated[NUM_BATTLE_SIDES];
|
||||
u8 supremeOverlordCounter[MAX_BATTLERS_COUNT];
|
||||
};
|
||||
|
||||
// The palaceFlags member of struct BattleStruct contains 1 flag per move to indicate which moves the AI should consider,
|
||||
|
|
|
@ -349,6 +349,7 @@ enum {
|
|||
EFFECT_SHED_TAIL,
|
||||
EFFECT_UPPER_HAND,
|
||||
EFFECT_DRAGON_CHEER,
|
||||
EFFECT_LAST_RESPECTS,
|
||||
NUM_BATTLE_MOVE_EFFECTS,
|
||||
};
|
||||
|
||||
|
|
|
@ -3234,6 +3234,7 @@ const u8* FaintClearSetData(u32 battler)
|
|||
{
|
||||
s32 i;
|
||||
const u8 *result = NULL;
|
||||
u8 battlerSide = GetBattlerSide(battler);
|
||||
|
||||
for (i = 0; i < NUM_BATTLE_STATS; i++)
|
||||
gBattleMons[battler].statStages[i] = DEFAULT_STAT_STAGE;
|
||||
|
@ -3320,7 +3321,7 @@ const u8* FaintClearSetData(u32 battler)
|
|||
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
if (i != battler && GetBattlerSide(i) != GetBattlerSide(battler))
|
||||
if (i != battler && GetBattlerSide(i) != battlerSide)
|
||||
gBattleStruct->lastTakenMove[i] = MOVE_NONE;
|
||||
|
||||
gBattleStruct->lastTakenMoveFrom[i][battler] = 0;
|
||||
|
|
|
@ -60,7 +60,6 @@ static bool32 IsUnnerveAbilityOnOpposingSide(u32 battler);
|
|||
static u32 GetFlingPowerFromItemId(u32 itemId);
|
||||
static void SetRandomMultiHitCounter();
|
||||
static u32 GetBattlerItemHoldEffectParam(u32 battler, u32 item);
|
||||
static uq4_12_t GetSupremeOverlordModifier(u32 battler);
|
||||
static bool32 CanBeInfinitelyConfused(u32 battler);
|
||||
|
||||
extern const u8 *const gBattlescriptsForRunningByItem[];
|
||||
|
@ -3946,25 +3945,20 @@ bool32 ChangeTypeBasedOnTerrain(u32 battler)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
// Supreme Overlord adds a damage boost for each fainted ally.
|
||||
// The first ally adds a x1.2 boost, and subsequent allies add an extra x0.1 boost each.
|
||||
static uq4_12_t GetSupremeOverlordModifier(u32 battler)
|
||||
static inline u8 GetSideFaintCounter(u32 side)
|
||||
{
|
||||
u32 i;
|
||||
struct Pokemon *party = GetBattlerParty(battler);
|
||||
uq4_12_t modifier = UQ_4_12(1.0);
|
||||
bool32 appliedFirstBoost = FALSE;
|
||||
return (side == B_SIDE_PLAYER) ? gBattleResults.playerFaintCounter : gBattleResults.opponentFaintCounter;
|
||||
}
|
||||
|
||||
for (i = 0; i < PARTY_SIZE; i++)
|
||||
{
|
||||
if (GetMonData(&party[i], MON_DATA_SPECIES) != SPECIES_NONE
|
||||
&& !GetMonData(&party[i], MON_DATA_IS_EGG)
|
||||
&& GetMonData(&party[i], MON_DATA_HP) == 0)
|
||||
modifier += (!appliedFirstBoost) ? UQ_4_12(0.2) : UQ_4_12(0.1);
|
||||
appliedFirstBoost = TRUE;
|
||||
}
|
||||
static inline u8 GetBattlerSideFaintCounter(u32 battler)
|
||||
{
|
||||
return GetSideFaintCounter(GetBattlerSide(battler));
|
||||
}
|
||||
|
||||
return modifier;
|
||||
// Supreme Overlord adds a x0.1 damage boost for each fainted ally.
|
||||
static inline uq4_12_t GetSupremeOverlordModifier(u32 battler)
|
||||
{
|
||||
return UQ_4_12(1.0) + (UQ_4_12(0.1) * gBattleStruct->supremeOverlordCounter[battler]);
|
||||
}
|
||||
|
||||
static inline bool32 HadMoreThanHalfHpNowHasLess(u32 battler)
|
||||
|
@ -4599,12 +4593,15 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
|||
}
|
||||
break;
|
||||
case ABILITY_SUPREME_OVERLORD:
|
||||
if (!gSpecialStatuses[battler].switchInAbilityDone && CountUsablePartyMons(battler) < PARTY_SIZE)
|
||||
if (!gSpecialStatuses[battler].switchInAbilityDone)
|
||||
{
|
||||
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||
gBattleStruct->supremeOverlordModifier[battler] = GetSupremeOverlordModifier(battler);
|
||||
BattleScriptPushCursorAndCallback(BattleScript_SupremeOverlordActivates);
|
||||
effect++;
|
||||
gBattleStruct->supremeOverlordCounter[battler] = min(5, GetBattlerSideFaintCounter(battler));
|
||||
if (gBattleStruct->supremeOverlordCounter[battler] > 0)
|
||||
{
|
||||
BattleScriptPushCursorAndCallback(BattleScript_SupremeOverlordActivates);
|
||||
effect++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ABILITY_COSTAR:
|
||||
|
@ -8662,6 +8659,9 @@ static inline u32 CalcMoveBasePower(u32 move, u32 battlerAtk, u32 battlerDef, u3
|
|||
if (RandomPercentage(RNG_FICKLE_BEAM, 30))
|
||||
basePower *= 2;
|
||||
break;
|
||||
case EFFECT_LAST_RESPECTS:
|
||||
basePower += (basePower * min(100, GetBattlerSideFaintCounter(battlerAtk)));
|
||||
break;
|
||||
}
|
||||
|
||||
// Move-specific base power changes
|
||||
|
@ -8888,7 +8888,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(u32 move, u32 battlerAtk, u32
|
|||
modifier = uq4_12_multiply(modifier, UQ_4_12(1.5));
|
||||
break;
|
||||
case ABILITY_SUPREME_OVERLORD:
|
||||
modifier = uq4_12_multiply(modifier, gBattleStruct->supremeOverlordModifier[battlerAtk]);
|
||||
modifier = uq4_12_multiply(modifier, GetSupremeOverlordModifier(battlerAtk));
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -2214,4 +2214,10 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] =
|
|||
.battleTvScore = 1,
|
||||
.encourageEncore = TRUE,
|
||||
},
|
||||
|
||||
[EFFECT_LAST_RESPECTS] =
|
||||
{
|
||||
.battleScript = BattleScript_EffectHit,
|
||||
.battleTvScore = 0, // TODO: Assign points
|
||||
},
|
||||
};
|
||||
|
|
|
@ -18634,7 +18634,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
|
|||
.target = MOVE_TARGET_SELECTED,
|
||||
.priority = 0,
|
||||
.category = DAMAGE_CATEGORY_SPECIAL,
|
||||
.metronomeBanned = TRUE, // Only since it isn't implemented yet
|
||||
.forcePressure = TRUE,
|
||||
},
|
||||
|
||||
|
@ -18686,7 +18685,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
|
|||
.description = COMPOUND_STRING(
|
||||
"This move deals more damage\n"
|
||||
"for each defeated ally."),
|
||||
.effect = EFFECT_PLACEHOLDER, // EFFECT_LAST_RESPECTS
|
||||
.effect = EFFECT_LAST_RESPECTS,
|
||||
.power = 50,
|
||||
.type = TYPE_GHOST,
|
||||
.accuracy = 100,
|
||||
|
@ -18694,7 +18693,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
|
|||
.target = MOVE_TARGET_SELECTED,
|
||||
.priority = 0,
|
||||
.category = DAMAGE_CATEGORY_PHYSICAL,
|
||||
.metronomeBanned = TRUE, // Only since it isn't implemented yet
|
||||
},
|
||||
|
||||
[MOVE_LUMINA_CRASH] =
|
||||
|
@ -18851,7 +18849,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
|
|||
.priority = 0,
|
||||
.category = DAMAGE_CATEGORY_PHYSICAL,
|
||||
.makesContact = TRUE,
|
||||
.metronomeBanned = TRUE, // Only since it isn't implemented yet
|
||||
},
|
||||
|
||||
[MOVE_REVIVAL_BLESSING] =
|
||||
|
|
87
test/battle/ability/supreme_overlord.c
Normal file
87
test/battle/ability/supreme_overlord.c
Normal file
|
@ -0,0 +1,87 @@
|
|||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
DOUBLE_BATTLE_TEST("Supreme Overlord boosts Attack by an additive 10% per fainted mon on the side", s16 damage)
|
||||
{
|
||||
bool32 switchMon = 0;
|
||||
PARAMETRIZE { switchMon = FALSE; }
|
||||
PARAMETRIZE { switchMon = TRUE; }
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_KINGAMBIT) { Ability(ABILITY_SUPREME_OVERLORD); }
|
||||
PLAYER(SPECIES_PAWNIARD);
|
||||
PLAYER(SPECIES_PAWNIARD);
|
||||
PLAYER(SPECIES_PAWNIARD);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
if (switchMon)
|
||||
TURN { SWITCH(playerLeft, 3); }
|
||||
TURN { MOVE(playerRight, MOVE_MEMENTO, target: opponentRight); SEND_OUT(playerRight, 2); }
|
||||
if (switchMon)
|
||||
TURN { SWITCH(playerLeft, 0); }
|
||||
TURN { MOVE(playerLeft, MOVE_TACKLE, target: opponentLeft); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, playerLeft);
|
||||
HP_BAR(opponentLeft, captureDamage: &results[i].damage);
|
||||
} FINALLY {
|
||||
EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.1), results[1].damage);
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Supreme Overlord's boost caps at a 1.5x multipler", s16 damage)
|
||||
{
|
||||
u32 faintCount = 0;
|
||||
PARAMETRIZE { faintCount = 5; }
|
||||
PARAMETRIZE { faintCount = 6; }
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_PAWNIARD);
|
||||
PLAYER(SPECIES_PAWNIARD);
|
||||
PLAYER(SPECIES_PAWNIARD);
|
||||
PLAYER(SPECIES_KINGAMBIT) { Ability(ABILITY_SUPREME_OVERLORD); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(playerLeft, MOVE_MEMENTO, target: opponentRight); SEND_OUT(playerLeft, 2); }
|
||||
TURN { MOVE(playerLeft, MOVE_MEMENTO, target: opponentRight); SEND_OUT(playerLeft, 0); USE_ITEM(playerRight, ITEM_REVIVE, 0); }
|
||||
TURN { MOVE(playerLeft, MOVE_MEMENTO, target: opponentRight); SEND_OUT(playerLeft, 2); USE_ITEM(playerRight, ITEM_REVIVE, 2); }
|
||||
TURN { MOVE(playerLeft, MOVE_MEMENTO, target: opponentRight); SEND_OUT(playerLeft, 0); USE_ITEM(playerRight, ITEM_REVIVE, 0); }
|
||||
TURN { MOVE(playerLeft, MOVE_MEMENTO, target: opponentRight); SEND_OUT(playerLeft, 2); USE_ITEM(playerRight, ITEM_REVIVE, 2); }
|
||||
if (faintCount == 6)
|
||||
TURN { MOVE(playerLeft, MOVE_MEMENTO, target: opponentRight); SEND_OUT(playerLeft, 0); USE_ITEM(playerRight, ITEM_REVIVE, 0); }
|
||||
TURN { SWITCH(playerRight, 3); }
|
||||
TURN { MOVE(playerRight, MOVE_TACKLE, target: opponentLeft); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, playerRight);
|
||||
HP_BAR(opponentLeft, captureDamage: &results[i].damage);
|
||||
} FINALLY {
|
||||
EXPECT_EQ(results[0].damage, results[1].damage);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Supreme Overlord does not boost attack if party members are already fainted at the start of the battle", s16 damage)
|
||||
{
|
||||
u32 fainted = 0;
|
||||
|
||||
PARAMETRIZE { fainted = FALSE; }
|
||||
PARAMETRIZE { fainted = TRUE; }
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_KINGAMBIT) { Ability(ABILITY_SUPREME_OVERLORD); }
|
||||
PLAYER(SPECIES_PAWNIARD) { HP(fainted ? 0 : 1); }
|
||||
PLAYER(SPECIES_PAWNIARD) { HP(fainted ? 0 : 1); }
|
||||
PLAYER(SPECIES_PAWNIARD) { HP(fainted ? 0 : 1); }
|
||||
PLAYER(SPECIES_PAWNIARD) { HP(fainted ? 0 : 1); }
|
||||
PLAYER(SPECIES_PAWNIARD) { HP(fainted ? 0 : 1); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_TACKLE, target: opponent); }
|
||||
} SCENE {
|
||||
NONE_OF {
|
||||
ABILITY_POPUP(player, ABILITY_SUPREME_OVERLORD);
|
||||
MESSAGE("Kingambit gained strength from the fallen!");
|
||||
}
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player);
|
||||
HP_BAR(opponent, captureDamage: &results[i].damage);
|
||||
} FINALLY {
|
||||
EXPECT_EQ(results[0].damage, results[1].damage);
|
||||
}
|
||||
}
|
67
test/battle/move_effect/last_respects.c
Normal file
67
test/battle/move_effect/last_respects.c
Normal file
|
@ -0,0 +1,67 @@
|
|||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(gMovesInfo[MOVE_LAST_RESPECTS].effect == EFFECT_LAST_RESPECTS);
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Last Respects power is multiplied by the amount of fainted mon in the user's side - Player", s16 damage)
|
||||
{
|
||||
u32 j = 0, faintCount = 0;
|
||||
PARAMETRIZE { faintCount = 0; }
|
||||
PARAMETRIZE { faintCount = 1; }
|
||||
PARAMETRIZE { faintCount = 2; }
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_GOLEM); // Not Wobbuffet to omit type effectiveness
|
||||
PLAYER(SPECIES_GEODUDE);
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_LEPPA_BERRY); Moves(MOVE_RECYCLE, MOVE_NONE, MOVE_NONE, MOVE_NONE); }
|
||||
} WHEN {
|
||||
for (j = 0; j < faintCount; j++)
|
||||
{
|
||||
TURN { MOVE(opponent, MOVE_RECYCLE); SWITCH(player, 1); }
|
||||
TURN { MOVE(opponent, MOVE_RECYCLE); MOVE(player, MOVE_MEMENTO); SEND_OUT(player, 0); }
|
||||
TURN { MOVE(opponent, MOVE_RECYCLE); USE_ITEM(player, ITEM_REVIVE, partyIndex: 1); }
|
||||
}
|
||||
TURN {
|
||||
MOVE(opponent, MOVE_RECYCLE);
|
||||
MOVE(player, MOVE_LAST_RESPECTS);
|
||||
}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_LAST_RESPECTS, player);
|
||||
HP_BAR(opponent, captureDamage: &results[j].damage);
|
||||
} THEN {
|
||||
if (faintCount > 0)
|
||||
EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.0 + faintCount), results[faintCount].damage);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Last Respects power is multiplied by the amount of fainted mon in the user's side - Opponent", s16 damage)
|
||||
{
|
||||
u32 j = 0, faintCount = 0;
|
||||
PARAMETRIZE { faintCount = 0; }
|
||||
PARAMETRIZE { faintCount = 1; }
|
||||
PARAMETRIZE { faintCount = 2; }
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_LEPPA_BERRY); Moves(MOVE_RECYCLE, MOVE_NONE, MOVE_NONE, MOVE_NONE); }
|
||||
OPPONENT(SPECIES_GOLEM); // Not Wobbuffet to omit type effectiveness
|
||||
OPPONENT(SPECIES_GEODUDE);
|
||||
} WHEN {
|
||||
for (j = 0; j < faintCount; j++)
|
||||
{
|
||||
TURN { MOVE(player, MOVE_RECYCLE); SWITCH(opponent, 1); }
|
||||
TURN { MOVE(player, MOVE_RECYCLE); MOVE(opponent, MOVE_MEMENTO); SEND_OUT(opponent, 0); }
|
||||
TURN { MOVE(player, MOVE_RECYCLE); USE_ITEM(opponent, ITEM_REVIVE, partyIndex: 1); }
|
||||
}
|
||||
TURN {
|
||||
MOVE(player, MOVE_RECYCLE);
|
||||
MOVE(opponent, MOVE_LAST_RESPECTS);
|
||||
}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_LAST_RESPECTS, opponent);
|
||||
HP_BAR(player, captureDamage: &results[j].damage);
|
||||
} THEN {
|
||||
if (faintCount > 0)
|
||||
EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.0 + faintCount), results[faintCount].damage);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue