Fix stats defined in tests being overwritteng by stat change (#8018)
Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com>
This commit is contained in:
parent
1343ddf7c3
commit
5b4403ddfe
@ -789,6 +789,7 @@ u32 GetSpeciesBaseDefense(u16 species);
|
||||
u32 GetSpeciesBaseSpAttack(u16 species);
|
||||
u32 GetSpeciesBaseSpDefense(u16 species);
|
||||
u32 GetSpeciesBaseSpeed(u16 species);
|
||||
u32 GetSpeciesBaseStat(u16 species, u32 statIndex);
|
||||
const struct LevelUpMove *GetSpeciesLevelUpLearnset(u16 species);
|
||||
const u16 *GetSpeciesTeachableLearnset(u16 species);
|
||||
const u16 *GetSpeciesEggMoves(u16 species);
|
||||
|
||||
@ -1691,32 +1691,10 @@ static u16 CalculateBoxMonChecksumReencrypt(struct BoxPokemon *boxMon)
|
||||
return checksum;
|
||||
}
|
||||
|
||||
#define CALC_STAT(base, iv, ev, statIndex, field) \
|
||||
{ \
|
||||
u8 baseStat = gSpeciesInfo[species].base; \
|
||||
s32 n = (((2 * baseStat + iv + ev / 4) * level) / 100) + 5; \
|
||||
n = ModifyStatByNature(nature, n, statIndex); \
|
||||
if (B_FRIENDSHIP_BOOST == TRUE) \
|
||||
n = n + ((n * 10 * friendship) / (MAX_FRIENDSHIP * 100));\
|
||||
SetMonData(mon, field, &n); \
|
||||
}
|
||||
|
||||
void CalculateMonStats(struct Pokemon *mon)
|
||||
{
|
||||
s32 oldMaxHP = GetMonData(mon, MON_DATA_MAX_HP, NULL);
|
||||
s32 currentHP = GetMonData(mon, MON_DATA_HP, NULL);
|
||||
s32 hpIV = GetMonData(mon, MON_DATA_HYPER_TRAINED_HP) ? MAX_PER_STAT_IVS : GetMonData(mon, MON_DATA_HP_IV, NULL);
|
||||
s32 hpEV = GetMonData(mon, MON_DATA_HP_EV, NULL);
|
||||
s32 attackIV = GetMonData(mon, MON_DATA_HYPER_TRAINED_ATK) ? MAX_PER_STAT_IVS : GetMonData(mon, MON_DATA_ATK_IV, NULL);
|
||||
s32 attackEV = GetMonData(mon, MON_DATA_ATK_EV, NULL);
|
||||
s32 defenseIV = GetMonData(mon, MON_DATA_HYPER_TRAINED_DEF) ? MAX_PER_STAT_IVS : GetMonData(mon, MON_DATA_DEF_IV, NULL);
|
||||
s32 defenseEV = GetMonData(mon, MON_DATA_DEF_EV, NULL);
|
||||
s32 speedIV = GetMonData(mon, MON_DATA_HYPER_TRAINED_SPEED) ? MAX_PER_STAT_IVS : GetMonData(mon, MON_DATA_SPEED_IV, NULL);
|
||||
s32 speedEV = GetMonData(mon, MON_DATA_SPEED_EV, NULL);
|
||||
s32 spAttackIV = GetMonData(mon, MON_DATA_HYPER_TRAINED_SPATK) ? MAX_PER_STAT_IVS : GetMonData(mon, MON_DATA_SPATK_IV, NULL);
|
||||
s32 spAttackEV = GetMonData(mon, MON_DATA_SPATK_EV, NULL);
|
||||
s32 spDefenseIV = GetMonData(mon, MON_DATA_HYPER_TRAINED_SPDEF) ? MAX_PER_STAT_IVS : GetMonData(mon, MON_DATA_SPDEF_IV, NULL);
|
||||
s32 spDefenseEV = GetMonData(mon, MON_DATA_SPDEF_EV, NULL);
|
||||
u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL);
|
||||
u8 friendship = GetMonData(mon, MON_DATA_FRIENDSHIP, NULL);
|
||||
s32 level = GetLevelFromMonExp(mon);
|
||||
@ -1726,28 +1704,55 @@ void CalculateMonStats(struct Pokemon *mon)
|
||||
|
||||
SetMonData(mon, MON_DATA_LEVEL, &level);
|
||||
|
||||
bool32 hyperTrained[NUM_STATS]; //In a battle test, hyper training flag indicates a fixed stat
|
||||
s32 iv[NUM_STATS];
|
||||
s32 ev[NUM_STATS];
|
||||
for (u32 i = 0; i < NUM_STATS; i++)
|
||||
{
|
||||
hyperTrained[i] = GetMonData(mon, MON_DATA_HYPER_TRAINED_HP + i);
|
||||
iv[i] = GetMonData(mon, MON_DATA_HP_IV + i);
|
||||
ev[i] = GetMonData(mon, MON_DATA_HP_EV + i);
|
||||
|
||||
if (hyperTrained[i])
|
||||
{
|
||||
#if TESTING
|
||||
if (gMain.inBattle)
|
||||
continue;
|
||||
#endif
|
||||
iv[i] = MAX_PER_STAT_IVS;
|
||||
}
|
||||
|
||||
if (i == STAT_HP)
|
||||
continue;
|
||||
|
||||
u8 baseStat = GetSpeciesBaseStat(species, i);
|
||||
s32 n = (((2 * baseStat + iv[i] + ev[i] / 4) * level) / 100) + 5;
|
||||
n = ModifyStatByNature(nature, n, i);
|
||||
if (B_FRIENDSHIP_BOOST == TRUE)
|
||||
n = n + ((n * 10 * friendship) / (MAX_FRIENDSHIP * 100));
|
||||
SetMonData(mon, MON_DATA_MAX_HP + i, &n);
|
||||
}
|
||||
|
||||
#if TESTING
|
||||
if (hyperTrained[STAT_HP] && gMain.inBattle)
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (species == SPECIES_SHEDINJA)
|
||||
{
|
||||
newMaxHP = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
s32 n = 2 * GetSpeciesBaseHP(species) + hpIV;
|
||||
newMaxHP = (((n + hpEV / 4) * level) / 100) + level + 10;
|
||||
s32 n = 2 * GetSpeciesBaseHP(species) + iv[STAT_HP];
|
||||
newMaxHP = (((n + ev[STAT_HP] / 4) * level) / 100) + level + 10;
|
||||
}
|
||||
|
||||
gBattleScripting.levelUpHP = newMaxHP - oldMaxHP;
|
||||
if (gBattleScripting.levelUpHP == 0)
|
||||
gBattleScripting.levelUpHP = 1;
|
||||
|
||||
SetMonData(mon, MON_DATA_MAX_HP, &newMaxHP);
|
||||
|
||||
CALC_STAT(baseAttack, attackIV, attackEV, STAT_ATK, MON_DATA_ATK)
|
||||
CALC_STAT(baseDefense, defenseIV, defenseEV, STAT_DEF, MON_DATA_DEF)
|
||||
CALC_STAT(baseSpeed, speedIV, speedEV, STAT_SPEED, MON_DATA_SPEED)
|
||||
CALC_STAT(baseSpAttack, spAttackIV, spAttackEV, STAT_SPATK, MON_DATA_SPATK)
|
||||
CALC_STAT(baseSpDefense, spDefenseIV, spDefenseEV, STAT_SPDEF, MON_DATA_SPDEF)
|
||||
|
||||
// Since a pokemon's maxHP data could either not have
|
||||
// been initialized at this point or this pokemon is
|
||||
// just fainted, the check for oldMaxHP is important.
|
||||
@ -3567,6 +3572,26 @@ u32 GetSpeciesBaseSpeed(u16 species)
|
||||
return gSpeciesInfo[SanitizeSpeciesId(species)].baseSpeed;
|
||||
}
|
||||
|
||||
u32 GetSpeciesBaseStat(u16 species, u32 statIndex)
|
||||
{
|
||||
switch (statIndex)
|
||||
{
|
||||
case STAT_HP:
|
||||
return GetSpeciesBaseHP(species);
|
||||
case STAT_ATK:
|
||||
return GetSpeciesBaseAttack(species);
|
||||
case STAT_DEF:
|
||||
return GetSpeciesBaseDefense(species);
|
||||
case STAT_SPEED:
|
||||
return GetSpeciesBaseSpeed(species);
|
||||
case STAT_SPATK:
|
||||
return GetSpeciesBaseSpAttack(species);
|
||||
case STAT_SPDEF:
|
||||
return GetSpeciesBaseSpDefense(species);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct LevelUpMove *GetSpeciesLevelUpLearnset(u16 species)
|
||||
{
|
||||
const struct LevelUpMove *learnset = gSpeciesInfo[SanitizeSpeciesId(species)].levelUpLearnset;
|
||||
|
||||
@ -75,10 +75,10 @@ SINGLE_BATTLE_TEST("Mega Evolution doesn't affect turn order (Gen6)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(GEN_CONFIG_MEGA_EVO_TURN_ORDER, GEN_6);
|
||||
PLAYER(SPECIES_GARDEVOIR) { Item(ITEM_GARDEVOIRITE); Speed(105); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(106); }
|
||||
PLAYER(SPECIES_GARDEVOIR) { Item(ITEM_GARDEVOIRITE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) {}
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_CELEBRATE, gimmick: GIMMICK_MEGA); }
|
||||
TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_CELEBRATE, gimmick: GIMMICK_MEGA); }
|
||||
} SCENE {
|
||||
MESSAGE("The opposing Wobbuffet used Celebrate!");
|
||||
MESSAGE("Gardevoir used Celebrate!");
|
||||
@ -91,10 +91,10 @@ SINGLE_BATTLE_TEST("Mega Evolution affects turn order (Gen7+)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(GEN_CONFIG_MEGA_EVO_TURN_ORDER, GEN_7);
|
||||
PLAYER(SPECIES_GARDEVOIR) { Item(ITEM_GARDEVOIRITE); Speed(105); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(106); }
|
||||
PLAYER(SPECIES_GARDEVOIR) { Item(ITEM_GARDEVOIRITE);}
|
||||
OPPONENT(SPECIES_WOBBUFFET) {}
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_CELEBRATE, gimmick: GIMMICK_MEGA); }
|
||||
TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_CELEBRATE, gimmick: GIMMICK_MEGA); }
|
||||
} SCENE {
|
||||
MESSAGE("Gardevoir used Celebrate!");
|
||||
MESSAGE("The opposing Wobbuffet used Celebrate!");
|
||||
@ -117,7 +117,7 @@ SINGLE_BATTLE_TEST("Abilities replaced by Mega Evolution do not affect turn orde
|
||||
MESSAGE("Sableye used Celebrate!");
|
||||
MESSAGE("The opposing Wobbuffet used Celebrate!");
|
||||
} THEN {
|
||||
ASSUME(player->speed == 45);
|
||||
ASSUME(player->speed == 105);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -59,10 +59,10 @@ SINGLE_BATTLE_TEST("Ultra Burst affects turn order")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(GEN_CONFIG_MEGA_EVO_TURN_ORDER, GEN_7);
|
||||
PLAYER(SPECIES_NECROZMA_DUSK_MANE) { Item(ITEM_ULTRANECROZIUM_Z); Speed(105); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(106); }
|
||||
PLAYER(SPECIES_NECROZMA_DUSK_MANE) { Item(ITEM_ULTRANECROZIUM_Z);}
|
||||
OPPONENT(SPECIES_WOBBUFFET) {}
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_CELEBRATE, gimmick: GIMMICK_ULTRA_BURST); }
|
||||
TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_CELEBRATE, gimmick: GIMMICK_ULTRA_BURST); }
|
||||
} SCENE {
|
||||
MESSAGE("Necrozma used Celebrate!");
|
||||
MESSAGE("The opposing Wobbuffet used Celebrate!");
|
||||
|
||||
@ -25,3 +25,58 @@ SINGLE_BATTLE_TEST("Forced abilities activate on switch-in")
|
||||
MESSAGE("Kadabra's Sp. Atk was heightened!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Setting level doesn't overwrite set stats")
|
||||
{
|
||||
u32 level = 0;
|
||||
|
||||
PARAMETRIZE{level = 1;}
|
||||
PARAMETRIZE{level = 10;}
|
||||
PARAMETRIZE{level = 50;}
|
||||
PARAMETRIZE{level = 99;}
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) {HP(5); MaxHP(10); Attack(10); Defense(10); Speed(10); SpAttack(10); SpDefense(10); Level(level); };
|
||||
OPPONENT(SPECIES_WOBBUFFET) {Speed(1);}
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE);}
|
||||
} THEN {
|
||||
EXPECT_EQ(player->hp, 5);
|
||||
EXPECT_EQ(player->maxHP, 10);
|
||||
EXPECT_EQ(player->attack, 10);
|
||||
EXPECT_EQ(player->defense, 10);
|
||||
EXPECT_EQ(player->speed, 10);
|
||||
EXPECT_EQ(player->spAttack, 10);
|
||||
EXPECT_EQ(player->spDefense, 10);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Changing forms doesn't overwrite set stats (not HP)")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_DIANCIE) {Attack(10); Defense(10); Speed(10); SpAttack(10); SpDefense(10); Item(ITEM_DIANCITE);}
|
||||
OPPONENT(SPECIES_WOBBUFFET) {Speed(1);}
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_CELEBRATE, gimmick: GIMMICK_MEGA); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_MEGA_EVOLUTION, player);
|
||||
} THEN {
|
||||
EXPECT_EQ(player->attack, 10);
|
||||
EXPECT_EQ(player->defense, 10);
|
||||
EXPECT_EQ(player->speed, 10);
|
||||
EXPECT_EQ(player->spAttack, 10);
|
||||
EXPECT_EQ(player->spDefense, 10);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Changing forms doesn't overwrite set stats (HP)")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_TERAPAGOS) {HP(5); MaxHP(10); TeraType(TYPE_STELLAR);}
|
||||
OPPONENT(SPECIES_WOBBUFFET) {}
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_CELEBRATE, gimmick: GIMMICK_TERA); MOVE(opponent, MOVE_CELEBRATE);}
|
||||
} THEN {
|
||||
EXPECT_EQ(player->hp, 5);
|
||||
EXPECT_EQ(player->maxHP, 10);
|
||||
}
|
||||
}
|
||||
|
||||
@ -477,6 +477,24 @@ TEST("Optimised SetMonData")
|
||||
EXPECT_FASTER(optimised, vanilla);
|
||||
}
|
||||
|
||||
//Sanity check for a CalculateMonStats refactor (could be deleted or improved)
|
||||
TEST("CalculateMonStats")
|
||||
{
|
||||
ZeroPlayerPartyMons();
|
||||
|
||||
RUN_OVERWORLD_SCRIPT(
|
||||
givemon SPECIES_WOBBUFFET, 100, item=ITEM_LEFTOVERS, ball=ITEM_MASTER_BALL, nature=NATURE_BOLD, abilityNum=2, gender=MON_MALE, hpEv=1, atkEv=2, defEv=3, speedEv=4, spAtkEv=5, spDefEv=6, hpIv=7, atkIv=8, defIv=9, speedIv=10, spAtkIv=11, spDefIv=12, move1=MOVE_SCRATCH, move2=MOVE_SPLASH, move3=MOVE_CELEBRATE, move4=MOVE_EXPLOSION, shinyMode=SHINY_MODE_ALWAYS, gmaxFactor=TRUE, teraType=TYPE_FIRE, dmaxLevel=7;
|
||||
);
|
||||
|
||||
EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_MAX_HP), 497);
|
||||
EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_ATK), 71);
|
||||
EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_DEF), 143);
|
||||
EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_SPEED), 82);
|
||||
EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_SPATK), 83);
|
||||
EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_SPDEF), 134);
|
||||
|
||||
}
|
||||
|
||||
TEST("BoxPokemon encryption works")
|
||||
{
|
||||
u32 raw[20] =
|
||||
|
||||
@ -1681,7 +1681,9 @@ void Level_(u32 sourceLine, u32 level)
|
||||
INVALID_IF(level == 0 || level > MAX_LEVEL, "Illegal level: %d", level);
|
||||
SetMonData(DATA.currentMon, MON_DATA_LEVEL, &level);
|
||||
SetMonData(DATA.currentMon, MON_DATA_EXP, &gExperienceTables[gSpeciesInfo[species].growthRate][level]);
|
||||
gMain.inBattle = TRUE;
|
||||
CalculateMonStats(DATA.currentMon);
|
||||
gMain.inBattle = FALSE;
|
||||
}
|
||||
|
||||
void MaxHP_(u32 sourceLine, u32 maxHP)
|
||||
@ -1689,6 +1691,8 @@ void MaxHP_(u32 sourceLine, u32 maxHP)
|
||||
INVALID_IF(!DATA.currentMon, "MaxHP outside of PLAYER/OPPONENT");
|
||||
INVALID_IF(maxHP == 0, "Illegal max HP: %d", maxHP);
|
||||
SetMonData(DATA.currentMon, MON_DATA_MAX_HP, &maxHP);
|
||||
bool32 hyperTrainingFlag = TRUE;
|
||||
SetMonData(DATA.currentMon, MON_DATA_HYPER_TRAINED_HP, &hyperTrainingFlag);
|
||||
}
|
||||
|
||||
void HP_(u32 sourceLine, u32 hp)
|
||||
@ -1704,6 +1708,8 @@ void Attack_(u32 sourceLine, u32 attack)
|
||||
INVALID_IF(!DATA.currentMon, "Attack outside of PLAYER/OPPONENT");
|
||||
INVALID_IF(attack == 0, "Illegal attack: %d", attack);
|
||||
SetMonData(DATA.currentMon, MON_DATA_ATK, &attack);
|
||||
bool32 hyperTrainingFlag = TRUE;
|
||||
SetMonData(DATA.currentMon, MON_DATA_HYPER_TRAINED_ATK, &hyperTrainingFlag);
|
||||
}
|
||||
|
||||
void Defense_(u32 sourceLine, u32 defense)
|
||||
@ -1711,6 +1717,8 @@ void Defense_(u32 sourceLine, u32 defense)
|
||||
INVALID_IF(!DATA.currentMon, "Defense outside of PLAYER/OPPONENT");
|
||||
INVALID_IF(defense == 0, "Illegal defense: %d", defense);
|
||||
SetMonData(DATA.currentMon, MON_DATA_DEF, &defense);
|
||||
bool32 hyperTrainingFlag = TRUE;
|
||||
SetMonData(DATA.currentMon, MON_DATA_HYPER_TRAINED_DEF, &hyperTrainingFlag);
|
||||
}
|
||||
|
||||
void SpAttack_(u32 sourceLine, u32 spAttack)
|
||||
@ -1718,6 +1726,8 @@ void SpAttack_(u32 sourceLine, u32 spAttack)
|
||||
INVALID_IF(!DATA.currentMon, "SpAttack outside of PLAYER/OPPONENT");
|
||||
INVALID_IF(spAttack == 0, "Illegal special attack: %d", spAttack);
|
||||
SetMonData(DATA.currentMon, MON_DATA_SPATK, &spAttack);
|
||||
bool32 hyperTrainingFlag = TRUE;
|
||||
SetMonData(DATA.currentMon, MON_DATA_HYPER_TRAINED_SPATK, &hyperTrainingFlag);
|
||||
}
|
||||
|
||||
void SpDefense_(u32 sourceLine, u32 spDefense)
|
||||
@ -1725,6 +1735,8 @@ void SpDefense_(u32 sourceLine, u32 spDefense)
|
||||
INVALID_IF(!DATA.currentMon, "SpDefense outside of PLAYER/OPPONENT");
|
||||
INVALID_IF(spDefense == 0, "Illegal special defense: %d", spDefense);
|
||||
SetMonData(DATA.currentMon, MON_DATA_SPDEF, &spDefense);
|
||||
bool32 hyperTrainingFlag = TRUE;
|
||||
SetMonData(DATA.currentMon, MON_DATA_HYPER_TRAINED_SPDEF, &hyperTrainingFlag);
|
||||
}
|
||||
|
||||
void Speed_(u32 sourceLine, u32 speed)
|
||||
@ -1732,6 +1744,8 @@ void Speed_(u32 sourceLine, u32 speed)
|
||||
INVALID_IF(!DATA.currentMon, "Speed outside of PLAYER/OPPONENT");
|
||||
INVALID_IF(speed == 0, "Illegal speed: %d", speed);
|
||||
SetMonData(DATA.currentMon, MON_DATA_SPEED, &speed);
|
||||
bool32 hyperTrainingFlag = TRUE;
|
||||
SetMonData(DATA.currentMon, MON_DATA_HYPER_TRAINED_SPEED, &hyperTrainingFlag);
|
||||
DATA.hasExplicitSpeeds = TRUE;
|
||||
DATA.explicitSpeeds[DATA.currentSide] |= 1 << DATA.currentPartyIndex;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user