diff --git a/include/constants/pokemon.h b/include/constants/pokemon.h index c375bbdd10..a7f0e3e4ed 100644 --- a/include/constants/pokemon.h +++ b/include/constants/pokemon.h @@ -379,6 +379,7 @@ #define EVO_SPECIFIC_MAP 32 // Pokémon levels up on specified map #define EVO_LEVEL_NATURE_AMPED 33 // Pokémon reaches the specified level, it has a Hardy, Brave, Adamant, Naughty, Docile, Impish, Lax, Hasty, Jolly, Naive, Rash, Sassy, or Quirky nature. #define EVO_LEVEL_NATURE_LOW_KEY 34 // Pokémon reaches the specified level, it has a Lonely, Bold, Relaxed, Timid, Serious, Modest, Mild, Quiet, Bashful, Calm, Gentle, or Careful nature. +#define EVO_CRITICAL_HITS 35 // Pokémon performs specified number of critical hits in one battle #define EVOS_PER_MON 10 @@ -387,6 +388,7 @@ #define EVO_MODE_TRADE 1 #define EVO_MODE_ITEM_USE 2 #define EVO_MODE_ITEM_CHECK 3 // If an Everstone is being held, still want to show that the stone *could* be used on that Pokémon to evolve +#define EVO_MODE_BATTLE_SPECIAL 4 #define NUM_MALE_LINK_FACILITY_CLASSES 8 #define NUM_FEMALE_LINK_FACILITY_CLASSES 8 diff --git a/src/battle_main.c b/src/battle_main.c index 479cafae6a..ca59ff86ef 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -115,6 +115,7 @@ static void HandleEndTurn_MonFled(void); static void HandleEndTurn_FinishBattle(void); static void SpriteCB_UnusedBattleInit(struct Sprite* sprite); static void SpriteCB_UnusedBattleInit_Main(struct Sprite *sprite); +static void TrySpecialEvolution(void); EWRAM_DATA u16 gBattle_BG0_X = 0; EWRAM_DATA u16 gBattle_BG0_Y = 0; @@ -237,6 +238,8 @@ EWRAM_DATA bool8 gHasFetchedBall = FALSE; EWRAM_DATA u8 gLastUsedBall = 0; EWRAM_DATA u16 gLastThrownBall = 0; EWRAM_DATA bool8 gSwapDamageCategory = FALSE; // Photon Geyser, Shell Side Arm, Light That Burns the Sky +EWRAM_DATA u8 gPartyCriticalHits[PARTY_SIZE] = {0}; +EWRAM_DATA static u8 sTriedEvolving = 0; void (*gPreBattleCallback1)(void); void (*gBattleMainFunc)(void); @@ -2999,6 +3002,7 @@ static void BattleStartClearSetData(void) gBattleStruct->usedHeldItems[i][0] = 0; gBattleStruct->usedHeldItems[i][1] = 0; gBattleStruct->itemStolen[i].originalItem = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM); + gPartyCriticalHits[i] = 0; } gSwapDamageCategory = FALSE; // Photon Geyser, Shell Side Arm, Light That Burns the Sky @@ -5154,9 +5158,16 @@ static void FreeResetData_ReturnToOvOrDoEvolutions(void) gIsFishingEncounter = FALSE; gIsSurfingEncounter = FALSE; ResetSpriteData(); - if (gLeveledUpInBattle && (gBattleOutcome == B_OUTCOME_WON || gBattleOutcome == B_OUTCOME_CAUGHT)) + if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK + | BATTLE_TYPE_RECORDED_LINK + | BATTLE_TYPE_FIRST_BATTLE + | BATTLE_TYPE_SAFARI + | BATTLE_TYPE_FRONTIER + | BATTLE_TYPE_EREADER_TRAINER + | BATTLE_TYPE_WALLY_TUTORIAL)) + && (gBattleOutcome == B_OUTCOME_WON || gBattleOutcome == B_OUTCOME_CAUGHT)) { - gBattleMainFunc = TryEvolvePokemon; + gBattleMainFunc = TrySpecialEvolution; } else { @@ -5174,6 +5185,26 @@ static void FreeResetData_ReturnToOvOrDoEvolutions(void) } } +static void TrySpecialEvolution(void) // Attempts to perform non-level related battle evolutions (not the script command). +{ + s32 i; + + for (i = 0; i < PARTY_SIZE; i++) + { + u16 species = GetEvolutionTargetSpecies(&gPlayerParty[i], EVO_MODE_BATTLE_SPECIAL, i, SPECIES_NONE); + if (species != SPECIES_NONE && !(sTriedEvolving & gBitTable[i])) + { + sTriedEvolving |= gBitTable[i]; + FreeAllWindowBuffers(); + gBattleMainFunc = WaitForEvoSceneToFinish; + EvolutionScene(&gPlayerParty[i], species, TRUE, i); + return; + } + } + sTriedEvolving = 0; + gBattleMainFunc = TryEvolvePokemon; +} + static void TryEvolvePokemon(void) { s32 i; @@ -5208,7 +5239,7 @@ static void TryEvolvePokemon(void) static void WaitForEvoSceneToFinish(void) { if (gMain.callback2 == BattleMainCB2) - gBattleMainFunc = TryEvolvePokemon; + gBattleMainFunc = TrySpecialEvolution; } static void ReturnFromBattleToOverworld(void) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index d6edb0ab2d..4ae67d1a28 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1914,6 +1914,7 @@ s8 GetInverseCritChance(u8 battlerAtk, u8 battlerDef, u32 move) static void Cmd_critcalc(void) { + u16 partySlot; s32 critChance = CalcCritChanceStage(gBattlerAttacker, gBattlerTarget, gCurrentMove, TRUE); gPotentialItemEffectBattler = gBattlerAttacker; @@ -1928,6 +1929,12 @@ static void Cmd_critcalc(void) else gIsCriticalHit = FALSE; + // Counter for EVO_CRITICAL_HITS. + partySlot = gBattlerPartyIndexes[gBattlerAttacker]; + if (gIsCriticalHit && GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER + && !(gBattleTypeFlags & BATTLE_TYPE_MULTI && GetBattlerPosition(gBattlerAttacker) == B_POSITION_PLAYER_LEFT)) + gPartyCriticalHits[partySlot]++; + gBattlescriptCurrInstr++; } diff --git a/src/pokemon.c b/src/pokemon.c index 71176d2eb6..ff2dcbe510 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -5394,6 +5394,19 @@ u16 GetEvolutionTargetSpecies(struct Pokemon *mon, u8 mode, u16 evolutionItem) } } break; + // Battle evolution without leveling; party slot is being passed into the evolutionItem arg. + case EVO_MODE_BATTLE_SPECIAL: + for (i = 0; i < EVOS_PER_MON; i++) + { + switch (gEvolutionTable[species][i].method) + { + case EVO_CRITICAL_HITS: + if (gPartyCriticalHits[evolutionItem] >= gEvolutionTable[species][i].param) + targetSpecies = gEvolutionTable[species][i].targetSpecies; + break; + } + } + break; } return targetSpecies;