From 1e92d725ed23f69fbdbbd1d6a60a9bb1fddcea12 Mon Sep 17 00:00:00 2001 From: cawtds Date: Sat, 27 Apr 2024 15:12:28 +0200 Subject: [PATCH] updated getevolutionspecies getters for species data redundancies removed --- include/battle.h | 1 + include/constants/pokemon.h | 47 ++-- include/pokemon.h | 12 +- src/battle_main.c | 5 + src/battle_message.c | 2 +- src/battle_script_commands.c | 5 + src/data/battle_moves.h | 4 +- src/data/wild_encounters.json | 12 +- src/daycare.c | 2 +- src/party_menu.c | 2 - src/pokemon.c | 514 ++++++++++++++++++++++++++-------- src/pokemon_summary_screen.c | 2 +- src/quest_log_events.c | 6 +- 13 files changed, 458 insertions(+), 156 deletions(-) diff --git a/include/battle.h b/include/battle.h index f5c4ef286..8d11f91b5 100644 --- a/include/battle.h +++ b/include/battle.h @@ -726,6 +726,7 @@ extern u8 gChosenActionByBattler[MAX_BATTLERS_COUNT]; extern u8 gBattleTerrain; extern struct MultiBattlePokemonTx gMultiPartnerParty[3]; extern u16 gRandomTurnNumber; +extern u8 gPartyCriticalHits[PARTY_SIZE]; static inline u32 GetBattlerPosition(u32 battler) { diff --git a/include/constants/pokemon.h b/include/constants/pokemon.h index b12d7cd7a..711b923c2 100644 --- a/include/constants/pokemon.h +++ b/include/constants/pokemon.h @@ -182,23 +182,23 @@ #define BODY_COLOR_PINK 9 // Evolution types -#define EVOLUTIONS_END 0xFFFF // Not an actual evolution, used to mark the end of an evolution array. -#define EVO_NONE 0xFFFE // Not an actual evolution, used to generate offspring that can't evolve into the specified species, like regional forms. -#define EVO_FRIENDSHIP 1 // Pokémon levels up with friendship ≥ 220 -#define EVO_FRIENDSHIP_DAY 2 // Pokémon levels up during the day with friendship ≥ 220 -#define EVO_FRIENDSHIP_NIGHT 3 // Pokémon levels up at night with friendship ≥ 220 -#define EVO_LEVEL 4 // Pokémon reaches the specified level -#define EVO_TRADE 5 // Pokémon is traded -#define EVO_TRADE_ITEM 6 // Pokémon is traded while it's holding the specified item -#define EVO_ITEM 7 // specified item is used on Pokémon -#define EVO_LEVEL_ATK_GT_DEF 8 // Pokémon reaches the specified level with attack > defense -#define EVO_LEVEL_ATK_EQ_DEF 9 // Pokémon reaches the specified level with attack = defense -#define EVO_LEVEL_ATK_LT_DEF 10 // Pokémon reaches the specified level with attack < defense -#define EVO_LEVEL_SILCOON 11 // Pokémon reaches the specified level with a Silcoon personality value -#define EVO_LEVEL_CASCOON 12 // Pokémon reaches the specified level with a Cascoon personality value -#define EVO_LEVEL_NINJASK 13 // Pokémon reaches the specified level (special value for Ninjask) -#define EVO_LEVEL_SHEDINJA 14 // Pokémon reaches the specified level (special value for Shedinja) -#define EVO_BEAUTY 15 // Pokémon levels up with beauty ≥ specified value +#define EVOLUTIONS_END 0xFFFF // Not an actual evolution, used to mark the end of an evolution array. +#define EVO_NONE 0xFFFE // Not an actual evolution, used to generate offspring that can't evolve into the specified species, like regional forms. +#define EVO_FRIENDSHIP 1 // Pokémon levels up with friendship ≥ 220 +#define EVO_FRIENDSHIP_DAY 2 // Pokémon levels up during the day with friendship ≥ 220 +#define EVO_FRIENDSHIP_NIGHT 3 // Pokémon levels up at night with friendship ≥ 220 +#define EVO_LEVEL 4 // Pokémon reaches the specified level +#define EVO_TRADE 5 // Pokémon is traded +#define EVO_TRADE_ITEM 6 // Pokémon is traded while it's holding the specified item +#define EVO_ITEM 7 // specified item is used on Pokémon +#define EVO_LEVEL_ATK_GT_DEF 8 // Pokémon reaches the specified level with attack > defense +#define EVO_LEVEL_ATK_EQ_DEF 9 // Pokémon reaches the specified level with attack = defense +#define EVO_LEVEL_ATK_LT_DEF 10 // Pokémon reaches the specified level with attack < defense +#define EVO_LEVEL_SILCOON 11 // Pokémon reaches the specified level with a Silcoon personality value +#define EVO_LEVEL_CASCOON 12 // Pokémon reaches the specified level with a Cascoon personality value +#define EVO_LEVEL_NINJASK 13 // Pokémon reaches the specified level (special value for Ninjask) +#define EVO_LEVEL_SHEDINJA 14 // Pokémon reaches the specified level (special value for Shedinja) +#define EVO_BEAUTY 15 // Pokémon levels up with beauty ≥ specified value #define EVO_LEVEL_FEMALE 16 // Pokémon reaches the specified level, is female #define EVO_LEVEL_MALE 17 // Pokémon reaches the specified level, is male #define EVO_LEVEL_NIGHT 18 // Pokémon reaches the specified level, is night @@ -230,14 +230,19 @@ #define EVO_MOVE_THREE_SEGMENT 44 // Pokémon levels up, knows specified move, has a personality value with a modulus of 1-99 #define EVO_LEVEL_FAMILY_OF_THREE 45 // Pokémon reaches the specified level with a personality value with a modulus of 0 #define EVO_LEVEL_FAMILY_OF_FOUR 46 // Pokémon reaches the specified level with a personality value with a modulus of 1-99 +#define EVO_LEVEL_MOVE_TWENTY_TIMES 47 // Pokémon levels up after having used a move for at least 20 times +#define EVO_LEVEL_RECOIL_DAMAGE_MALE 48 // Pokémon levels up after having suffered specified amount of non-fainting recoil damage as a male +#define EVO_LEVEL_RECOIL_DAMAGE_FEMALE 49 // Pokémon levels up after having suffered specified amount of non-fainting recoil damage as a female #define EVOS_PER_MON 5 -#define EVO_MODE_NORMAL 0 -#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_NORMAL 0 +#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 EVO_MODE_OVERWORLD_SPECIAL 5 #define MON_PIC_WIDTH 64 #define MON_PIC_HEIGHT 64 diff --git a/include/pokemon.h b/include/pokemon.h index 68b6b10fa..3722a7039 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -592,8 +592,16 @@ u16 GetMonAbility(struct Pokemon *mon); u8 GetSecretBaseTrainerPicIndex(void); u8 GetSecretBaseTrainerNameIndex(void); bool8 IsPlayerPartyAndPokemonStorageFull(void); -const u8 *GetSpeciesName2(u16 species); -void GetSpeciesName(u8 *name, u16 species); +const u8 *GetSpeciesName(u16 species); +const u8 *GetSpeciesCategory(u16 species); +const u8 *GetSpeciesPokedexDescription(u16 species); +u16 GetSpeciesHeight(u16 species); +u16 GetSpeciesWeight(u16 species); +const struct LevelUpMove *GetSpeciesLevelUpLearnset(u16 species); +const u16 *GetSpeciesTeachableLearnset(u16 species); +const struct Evolution *GetSpeciesEvolutions(u16 species); +const u16 *GetSpeciesFormTable(u16 species); +const struct FormChange *GetSpeciesFormChanges(u16 species); u8 CalculatePPWithBonus(u16 move, u8 ppBonuses, u8 moveIndex); void RemoveMonPPBonus(struct Pokemon *mon, u8 moveIndex); void RemoveBattleMonPPBonus(struct BattlePokemon *mon, u8 moveIndex); diff --git a/src/battle_main.c b/src/battle_main.c index c2e723a7b..7b340bc7f 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -220,6 +220,7 @@ EWRAM_DATA struct MonSpritesGfx *gMonSpritesGfxPtr = NULL; EWRAM_DATA u16 gBattleMovePower = 0; EWRAM_DATA u16 gMoveToLearn = 0; EWRAM_DATA u8 gBattleMonForms[MAX_BATTLERS_COUNT] = {0}; +EWRAM_DATA u8 gPartyCriticalHits[PARTY_SIZE] = {0}; void (*gPreBattleCallback1)(void); void (*gBattleMainFunc)(void); @@ -2335,6 +2336,10 @@ static void BattleStartClearSetData(void) gBattleResults.playerMon2Name[i] = 0; gBattleResults.caughtMonNick[i] = 0; } + + for (i = 0; i < PARTY_SIZE; i++) { + gPartyCriticalHits[i] = 0; + } } void SwitchInClearSetData(void) diff --git a/src/battle_message.c b/src/battle_message.c index 6f1c6935f..ed33662c9 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -2293,7 +2293,7 @@ static void ExpandBattleTextBuffPlaceholders(const u8 *src, u8 *dst) srcId += 2; break; case B_BUFF_SPECIES: // species name - GetSpeciesName(dst, T1_READ_16(&src[srcId + 1])); + StringCopy(dst, GetSpeciesName(T1_READ_16(&src[srcId + 1]))); srcId += 3; break; case B_BUFF_MON_NICK: // poke nick without prefix diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 8658f7afa..2c8f649f9 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1241,9 +1241,14 @@ static void Cmd_critcalc(void) && !(Random() % sCriticalHitChance[critChance]) && (!(gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE) || BtlCtrl_OakOldMan_TestState2Flag(1)) && !(gBattleTypeFlags & BATTLE_TYPE_POKEDUDE)) + { gCritMultiplier = 2; + gPartyCriticalHits[gBattlerPartyIndexes[gBattlerAttacker]]++; + } else + { gCritMultiplier = 1; + } gBattlescriptCurrInstr++; } diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 276afba1f..23c22dfcd 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -2656,7 +2656,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = { .effect = EFFECT_ATTACK_DOWN_2, .power = 0, - .type = TYPE_NORMAL, + .type = TYPE_FAIRY, .accuracy = 100, .pp = 20, .secondaryEffectChance = 0, @@ -8096,7 +8096,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = { .effect = EFFECT_HIT, .power = 0, - .type = TYPE_NORMAL, + .type = TYPE_FAIRY, .accuracy = 100, .pp = 30, .secondaryEffectChance = 0, diff --git a/src/data/wild_encounters.json b/src/data/wild_encounters.json index 1f49cf4e4..81f03f955 100644 --- a/src/data/wild_encounters.json +++ b/src/data/wild_encounters.json @@ -8263,32 +8263,32 @@ { "min_level": 3, "max_level": 3, - "species": "SPECIES_MEWTWO" + "species": "SPECIES_EEVEE" }, { "min_level": 3, "max_level": 3, - "species": "SPECIES_MEWTWO" + "species": "SPECIES_EEVEE" }, { "min_level": 3, "max_level": 3, - "species": "SPECIES_MEWTWO" + "species": "SPECIES_EEVEE" }, { "min_level": 3, "max_level": 3, - "species": "SPECIES_MEW" + "species": "SPECIES_EEVEE" }, { "min_level": 2, "max_level": 2, - "species": "SPECIES_MEW" + "species": "SPECIES_EEVEE" }, { "min_level": 2, "max_level": 2, - "species": "SPECIES_MEW" + "species": "SPECIES_EEVEE" }, { "min_level": 3, diff --git a/src/daycare.c b/src/daycare.c index 21a99e050..4abfbf0de 100644 --- a/src/daycare.c +++ b/src/daycare.c @@ -1650,7 +1650,7 @@ static void AddHatchedMonToParty(u8 id) SetMonData(mon, MON_DATA_IS_EGG, &isEgg); pokeNum = GetMonData(mon, MON_DATA_SPECIES); - GetSpeciesName(name, pokeNum); + StringCopy(name, GetSpeciesName(pokeNum)); SetMonData(mon, MON_DATA_NICKNAME, name); pokeNum = SpeciesToNationalPokedexNum(pokeNum); diff --git a/src/party_menu.c b/src/party_menu.c index 24c4bf923..bd871ab47 100644 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -5410,8 +5410,6 @@ static void Task_TryLearningNextMoveAfterText(u8 taskId) Task_TryLearningNextMove(taskId); } -#define SOME_OFFSET 6 - void ItemUseCB_RareCandy(u8 taskId, TaskFunc func) { struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId]; diff --git a/src/pokemon.c b/src/pokemon.c index ceebd319f..dfe7d0727 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -14,6 +14,7 @@ #include "battle_gfx_sfx_util.h" #include "battle_controllers.h" #include "evolution_scene.h" +#include "field_weather.h" #include "battle_message.h" #include "battle_util.h" #include "link.h" @@ -38,11 +39,9 @@ #include "constants/hold_effects.h" #include "constants/battle_move_effects.h" #include "constants/union_room.h" +#include "constants/weather.h" -#define SPECIES_TO_HOENN(name) [SPECIES_##name - 1] = HOENN_DEX_##name -#define SPECIES_TO_NATIONAL(name) [SPECIES_##name - 1] = NATIONAL_DEX_##name -#define HOENN_TO_NATIONAL(name) [HOENN_DEX_##name - 1] = NATIONAL_DEX_##name -#define KANTO_TO_NATIONAL(name) [KANTO_DEX_##name - 1] = NATIONAL_DEX_##name +#define FRIENDSHIP_EVO_THRESHOLD ((P_FRIENDSHIP_EVO_THRESHOLD >= GEN_9) ? 160 : 220) struct MonSpritesGfxManager { @@ -113,6 +112,9 @@ static const struct CombinedMove sCombinedMoves[2] = // removed: //static const u16 sSpeciesToNationalPokedexNum[NUM_SPECIES - 1] = +#define HOENN_TO_NATIONAL(name) [HOENN_DEX_##name - 1] = NATIONAL_DEX_##name +#define KANTO_TO_NATIONAL(name) [KANTO_DEX_##name - 1] = NATIONAL_DEX_##name + static const u16 sKantoToNationalOrder[NUM_SPECIES - 1] = { // Kanto @@ -1165,7 +1167,7 @@ void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u8 fixedIV, SetBoxMonData(boxMon, MON_DATA_CHECKSUM, &checksum); EncryptBoxMon(boxMon); SetBoxMonData(boxMon, MON_DATA_IS_SHINY, &isShiny); - StringCopy(speciesName, GetSpeciesName2(species)); + StringCopy(speciesName, GetSpeciesName(species)); SetBoxMonData(boxMon, MON_DATA_NICKNAME, speciesName); SetBoxMonData(boxMon, MON_DATA_LANGUAGE, &gGameLanguage); SetBoxMonData(boxMon, MON_DATA_OT_NAME, gSaveBlock2Ptr->playerName); @@ -3503,7 +3505,7 @@ static bool8 IsPokemonStorageFull(void) return TRUE; } -const u8 *GetSpeciesName2(u16 species) +const u8 *GetSpeciesName(u16 species) { species = SanitizeSpeciesId(species); if (gSpeciesInfo[species].speciesName[0] == 0) @@ -3511,24 +3513,70 @@ const u8 *GetSpeciesName2(u16 species) return gSpeciesInfo[species].speciesName; } -void GetSpeciesName(u8 *name, u16 species) +const u8 *GetSpeciesCategory(u16 species) { - StringCopy(name, GetSpeciesName2(species)); - // s32 i; + species = SanitizeSpeciesId(species); + if (gSpeciesInfo[species].categoryName[0] == 0) + return gSpeciesInfo[SPECIES_NONE].categoryName; + return gSpeciesInfo[species].categoryName; +} - // // Hmm? FRLG has < while Ruby/Emerald has <= - // for (i = 0; i < POKEMON_NAME_LENGTH; i++) - // { - // if (species > NUM_SPECIES) - // name[i] = gSpeciesInfo[0].speciesName[i]; - // else - // name[i] = gSpeciesInfo[species].speciesName[i]; +const u8 *GetSpeciesPokedexDescription(u16 species) +{ + species = SanitizeSpeciesId(species); + if (gSpeciesInfo[species].description == NULL) + return gSpeciesInfo[SPECIES_NONE].description; + return gSpeciesInfo[species].description; +} - // if (name[i] == EOS) - // break; - // } +u16 GetSpeciesHeight(u16 species) +{ + return gSpeciesInfo[SanitizeSpeciesId(species)].height; +} - // name[i] = EOS; +u16 GetSpeciesWeight(u16 species) +{ + return gSpeciesInfo[SanitizeSpeciesId(species)].weight; +} + +const struct LevelUpMove *GetSpeciesLevelUpLearnset(u16 species) +{ + const struct LevelUpMove *learnset = gSpeciesInfo[SanitizeSpeciesId(species)].levelUpLearnset; + if (learnset == NULL) + return gSpeciesInfo[SPECIES_NONE].levelUpLearnset; + return learnset; +} + +const u16 *GetSpeciesTeachableLearnset(u16 species) +{ + const u16 *learnset = gSpeciesInfo[SanitizeSpeciesId(species)].teachableLearnset; + if (learnset == NULL) + return gSpeciesInfo[SPECIES_NONE].teachableLearnset; + return learnset; +} + +const struct Evolution *GetSpeciesEvolutions(u16 species) +{ + const struct Evolution *evolutions = gSpeciesInfo[SanitizeSpeciesId(species)].evolutions; + if (evolutions == NULL) + return gSpeciesInfo[SPECIES_NONE].evolutions; + return evolutions; +} + +const u16 *GetSpeciesFormTable(u16 species) +{ + const u16 *formTable = gSpeciesInfo[SanitizeSpeciesId(species)].formSpeciesIdTable; + if (formTable == NULL) + return gSpeciesInfo[SPECIES_NONE].formSpeciesIdTable; + return formTable; +} + +const struct FormChange *GetSpeciesFormChanges(u16 species) +{ + const struct FormChange *evolutions = gSpeciesInfo[SanitizeSpeciesId(species)].formChangeTable; + if (evolutions == NULL) + return gSpeciesInfo[SPECIES_NONE].formChangeTable; + return evolutions; } u8 CalculatePPWithBonus(u16 move, u8 ppBonuses, u8 moveIndex) @@ -4247,56 +4295,6 @@ static void BufferStatRoseMessage(int statIdx) BattleStringExpandPlaceholdersToDisplayedString(gText_DefendersStatRose); } -// const u8 *Battle_PrintStatBoosterEffectMessage(u16 itemId) -// { -// int i; -// const u8 *itemEffect; - -// if (itemId == ITEM_ENIGMA_BERRY) -// { -// if (gMain.inBattle) -// { -// itemEffect = gEnigmaBerries[gBattlerInMenuId].itemEffect; -// } -// else -// { -// itemEffect = gSaveBlock1Ptr->enigmaBerry.itemEffect; -// } -// } -// else -// { -// itemEffect = gItemEffectTable[itemId]; -// } - -// gPotentialItemEffectBattler = gBattlerInMenuId; - -// for (i = 0; i < 3; i++) -// { -// if (itemEffect[i] & (ITEM1_X_ATTACK | ITEM1_X_SPEED | ITEM2_X_SPATK)) -// BufferStatRoseMessage(i * 2); -// if (itemEffect[i] & (ITEM0_DIRE_HIT | ITEM1_X_DEFENSE | ITEM2_X_ACCURACY)) -// { -// if (i != 0) // Dire Hit is the only ITEM0 above -// { -// BufferStatRoseMessage(i * 2 + 1); -// } -// else -// { -// gBattlerAttacker = gBattlerInMenuId; -// BattleStringExpandPlaceholdersToDisplayedString(gBattleText_GetPumped); -// } -// } -// } - -// if (itemEffect[3] & ITEM3_GUARD_SPEC) -// { -// gBattlerAttacker = gBattlerInMenuId; -// BattleStringExpandPlaceholdersToDisplayedString(gBattleText_MistShroud); -// } - -// return gDisplayedStringBattle; -// } - u8 GetNature(struct Pokemon *mon) { return GetMonData(mon, MON_DATA_PERSONALITY, NULL) % NUM_NATURES; @@ -4307,88 +4305,149 @@ static u8 GetNatureFromPersonality(u32 personality) return personality % NUM_NATURES; } -const struct Evolution *GetSpeciesEvolutions(u16 species) +static u32 GetGMaxTargetSpecies(u32 species) { - const struct Evolution *evolutions = gSpeciesInfo[SanitizeSpeciesId(species)].evolutions; - if (evolutions == NULL) - return gSpeciesInfo[SPECIES_NONE].evolutions; - return evolutions; + // const struct FormChange *formChanges = GetSpeciesFormChanges(species); + // u32 i; + // for (i = 0; formChanges[i].method != FORM_CHANGE_TERMINATOR; i++) + // { + // if (formChanges[i].method == FORM_CHANGE_BATTLE_GIGANTAMAX) + // return formChanges[i].targetSpecies; + // } + return SPECIES_NONE; } -u16 GetEvolutionTargetSpecies(struct Pokemon *mon, u8 type, u16 evolutionItem, struct Pokemon *tradePartner) +u16 GetEvolutionTargetSpecies(struct Pokemon *mon, u8 mode, u16 evolutionItem, struct Pokemon *tradePartner) { - int i; + int i, j; u16 targetSpecies = SPECIES_NONE; - u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL); - u16 heldItem = GetMonData(mon, MON_DATA_HELD_ITEM, NULL); - u32 personality = GetMonData(mon, MON_DATA_PERSONALITY, NULL); + u16 species = GetMonData(mon, MON_DATA_SPECIES, 0); + u16 heldItem = GetMonData(mon, MON_DATA_HELD_ITEM, 0); + u32 personality = GetMonData(mon, MON_DATA_PERSONALITY, 0); u8 level; u16 friendship; - u8 beauty = GetMonData(mon, MON_DATA_BEAUTY, NULL); + u8 beauty = GetMonData(mon, MON_DATA_BEAUTY, 0); u16 upperPersonality = personality >> 16; - u8 holdEffect; + u32 holdEffect, currentMap, partnerSpecies, partnerHeldItem, partnerHoldEffect; + bool32 consumeItem = FALSE; + u16 evolutionTracker = GetMonData(mon, MON_DATA_EVOLUTION_TRACKER, 0); const struct Evolution *evolutions = GetSpeciesEvolutions(species); if (evolutions == NULL) return SPECIES_NONE; - if (heldItem == ITEM_ENIGMA_BERRY) + if (tradePartner != NULL) + { + partnerSpecies = GetMonData(tradePartner, MON_DATA_SPECIES, 0); + partnerHeldItem = GetMonData(tradePartner, MON_DATA_HELD_ITEM, 0); + + if (partnerHeldItem == ITEM_ENIGMA_BERRY_E_READER) + #if FREE_ENIGMA_BERRY == FALSE + partnerHoldEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect; + #else + partnerHoldEffect = 0; + #endif //FREE_ENIGMA_BERRY + else + partnerHoldEffect = ItemId_GetHoldEffect(partnerHeldItem); + } + else + { + partnerSpecies = SPECIES_NONE; + partnerHeldItem = ITEM_NONE; + partnerHoldEffect = HOLD_EFFECT_NONE; + } + + if (heldItem == ITEM_ENIGMA_BERRY_E_READER) + #if FREE_ENIGMA_BERRY == FALSE holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect; + #else + holdEffect = 0; + #endif //FREE_ENIGMA_BERRY else holdEffect = ItemId_GetHoldEffect(heldItem); // Prevent evolution with Everstone, unless we're just viewing the party menu with an evolution item - if (holdEffect == HOLD_EFFECT_PREVENT_EVOLVE && type != EVO_MODE_ITEM_CHECK) - return 0; + if (holdEffect == HOLD_EFFECT_PREVENT_EVOLVE + && mode != EVO_MODE_ITEM_CHECK + && (P_KADABRA_EVERSTONE < GEN_4 || species != SPECIES_KADABRA)) + return SPECIES_NONE; - switch (type) + switch (mode) { case EVO_MODE_NORMAL: - level = GetMonData(mon, MON_DATA_LEVEL, NULL); - friendship = GetMonData(mon, MON_DATA_FRIENDSHIP, NULL); + level = GetMonData(mon, MON_DATA_LEVEL, 0); + friendship = GetMonData(mon, MON_DATA_FRIENDSHIP, 0); for (i = 0; evolutions[i].method != EVOLUTIONS_END; i++) { if (SanitizeSpeciesId(evolutions[i].targetSpecies) == SPECIES_NONE) continue; + switch (evolutions[i].method) { case EVO_FRIENDSHIP: - if (friendship >= 220) + if (friendship >= FRIENDSHIP_EVO_THRESHOLD) targetSpecies = evolutions[i].targetSpecies; break; - // FR/LG removed the time of day evolutions due to having no RTC. case EVO_FRIENDSHIP_DAY: - /* - RtcCalcLocalTime(); - if (gLocalTime.hours >= 12 && gLocalTime.hours < 24 && friendship >= 220) - targetSpecies = gEvolutionTable[species][i].targetSpecies; - */ + if (/*GetTimeOfDay() != TIME_NIGHT &&*/ friendship >= FRIENDSHIP_EVO_THRESHOLD) + targetSpecies = evolutions[i].targetSpecies; + break; + case EVO_LEVEL_DAY: + if (/* GetTimeOfDay() != TIME_NIGHT && */ evolutions[i].param <= level) + targetSpecies = evolutions[i].targetSpecies; break; case EVO_FRIENDSHIP_NIGHT: - /* - RtcCalcLocalTime(); - if (gLocalTime.hours >= 0 && gLocalTime.hours < 12 && friendship >= 220) - targetSpecies = gEvolutionTable[species][i].targetSpecies; - */ + if (/* GetTimeOfDay() == TIME_NIGHT && */ friendship >= FRIENDSHIP_EVO_THRESHOLD) + targetSpecies = evolutions[i].targetSpecies; + break; + case EVO_LEVEL_NIGHT: + if (/* GetTimeOfDay() == TIME_NIGHT && */ evolutions[i].param <= level) + targetSpecies = evolutions[i].targetSpecies; + break; + case EVO_ITEM_HOLD_NIGHT: + if (/* GetTimeOfDay() == TIME_NIGHT && */ heldItem == evolutions[i].param) + { + targetSpecies = evolutions[i].targetSpecies; + consumeItem = TRUE; + } + break; + case EVO_ITEM_HOLD_DAY: + if (/* GetTimeOfDay() != TIME_NIGHT && */ heldItem == evolutions[i].param) + { + targetSpecies = evolutions[i].targetSpecies; + consumeItem = TRUE; + } + break; + case EVO_LEVEL_DUSK: + if (/* GetTimeOfDay() == TIME_EVENING && */ evolutions[i].param <= level) + targetSpecies = evolutions[i].targetSpecies; break; case EVO_LEVEL: if (evolutions[i].param <= level) targetSpecies = evolutions[i].targetSpecies; break; + case EVO_LEVEL_FEMALE: + if (evolutions[i].param <= level && GetMonGender(mon) == MON_FEMALE) + targetSpecies = evolutions[i].targetSpecies; + break; + case EVO_LEVEL_MALE: + if (evolutions[i].param <= level && GetMonGender(mon) == MON_MALE) + targetSpecies = evolutions[i].targetSpecies; + break; case EVO_LEVEL_ATK_GT_DEF: if (evolutions[i].param <= level) - if (GetMonData(mon, MON_DATA_ATK, NULL) > GetMonData(mon, MON_DATA_DEF, NULL)) + if (GetMonData(mon, MON_DATA_ATK, 0) > GetMonData(mon, MON_DATA_DEF, 0)) targetSpecies = evolutions[i].targetSpecies; break; case EVO_LEVEL_ATK_EQ_DEF: if (evolutions[i].param <= level) - if (GetMonData(mon, MON_DATA_ATK, NULL) == GetMonData(mon, MON_DATA_DEF, NULL)) + if (GetMonData(mon, MON_DATA_ATK, 0) == GetMonData(mon, MON_DATA_DEF, 0)) targetSpecies = evolutions[i].targetSpecies; break; case EVO_LEVEL_ATK_LT_DEF: if (evolutions[i].param <= level) - if (GetMonData(mon, MON_DATA_ATK, NULL) < GetMonData(mon, MON_DATA_DEF, NULL)) + if (GetMonData(mon, MON_DATA_ATK, 0) < GetMonData(mon, MON_DATA_DEF, 0)) targetSpecies = evolutions[i].targetSpecies; break; case EVO_LEVEL_SILCOON: @@ -4403,10 +4462,155 @@ u16 GetEvolutionTargetSpecies(struct Pokemon *mon, u8 type, u16 evolutionItem, s if (evolutions[i].param <= level) targetSpecies = evolutions[i].targetSpecies; break; + case EVO_LEVEL_FAMILY_OF_FOUR: + if (evolutions[i].param <= level && (personality % 100) != 0) + targetSpecies = evolutions[i].targetSpecies; + break; + case EVO_LEVEL_FAMILY_OF_THREE: + if (evolutions[i].param <= level && (personality % 100) == 0) + targetSpecies = evolutions[i].targetSpecies; + break; case EVO_BEAUTY: if (evolutions[i].param <= beauty) targetSpecies = evolutions[i].targetSpecies; break; + case EVO_MOVE: + if (MonKnowsMove(mon, evolutions[i].param)) + targetSpecies = evolutions[i].targetSpecies; + break; + case EVO_MOVE_TWO_SEGMENT: + if (MonKnowsMove(mon, evolutions[i].param) && (personality % 100) != 0) + targetSpecies = evolutions[i].targetSpecies; + break; + case EVO_MOVE_THREE_SEGMENT: + if (MonKnowsMove(mon, evolutions[i].param) && (personality % 100) == 0) + targetSpecies = evolutions[i].targetSpecies; + break; + case EVO_FRIENDSHIP_MOVE_TYPE: + if (friendship >= FRIENDSHIP_EVO_THRESHOLD) + { + for (j = 0; j < MAX_MON_MOVES; j++) + { + if (gBattleMoves[GetMonData(mon, MON_DATA_MOVE1 + j, NULL)].type == evolutions[i].param) + { + targetSpecies = evolutions[i].targetSpecies; + break; + } + } + } + break; + case EVO_SPECIFIC_MON_IN_PARTY: + for (j = 0; j < PARTY_SIZE; j++) + { + if (GetMonData(&gPlayerParty[j], MON_DATA_SPECIES, NULL) == evolutions[i].param) + { + targetSpecies = evolutions[i].targetSpecies; + break; + } + } + break; + case EVO_LEVEL_DARK_TYPE_MON_IN_PARTY: + if (evolutions[i].param <= level) + { + for (j = 0; j < PARTY_SIZE; j++) + { + u16 currSpecies = GetMonData(&gPlayerParty[j], MON_DATA_SPECIES, NULL); + if (gSpeciesInfo[currSpecies].types[0] == TYPE_DARK + || gSpeciesInfo[currSpecies].types[1] == TYPE_DARK) + { + targetSpecies = evolutions[i].targetSpecies; + break; + } + } + } + break; + case EVO_LEVEL_RAIN: + j = GetCurrentWeather(); + if (evolutions[i].param <= level + && (j == WEATHER_RAIN || j == WEATHER_RAIN_THUNDERSTORM || j == WEATHER_DOWNPOUR)) + targetSpecies = evolutions[i].targetSpecies; + break; + case EVO_LEVEL_FOG: + j = GetCurrentWeather(); + if (evolutions[i].param <= level + && (j == WEATHER_FOG_HORIZONTAL || j == WEATHER_FOG_DIAGONAL)) + targetSpecies = evolutions[i].targetSpecies; + break; + case EVO_MAPSEC: + if (gMapHeader.regionMapSectionId == evolutions[i].param) + targetSpecies = evolutions[i].targetSpecies; + break; + case EVO_SPECIFIC_MAP: + currentMap = ((gSaveBlock1Ptr->location.mapGroup) << 8 | gSaveBlock1Ptr->location.mapNum); + if (currentMap == evolutions[i].param) + targetSpecies = evolutions[i].targetSpecies; + break; + case EVO_LEVEL_NATURE_AMPED: + if (evolutions[i].param <= level) + { + u8 nature = GetNature(mon); + switch (nature) + { + case NATURE_HARDY: + case NATURE_BRAVE: + case NATURE_ADAMANT: + case NATURE_NAUGHTY: + case NATURE_DOCILE: + case NATURE_IMPISH: + case NATURE_LAX: + case NATURE_HASTY: + case NATURE_JOLLY: + case NATURE_NAIVE: + case NATURE_RASH: + case NATURE_SASSY: + case NATURE_QUIRKY: + targetSpecies = evolutions[i].targetSpecies; + break; + } + } + break; + case EVO_LEVEL_NATURE_LOW_KEY: + if (evolutions[i].param <= level) + { + u8 nature = GetNature(mon); + switch (nature) + { + case NATURE_LONELY: + case NATURE_BOLD: + case NATURE_RELAXED: + case NATURE_TIMID: + case NATURE_SERIOUS: + case NATURE_MODEST: + case NATURE_MILD: + case NATURE_QUIET: + case NATURE_BASHFUL: + case NATURE_CALM: + case NATURE_GENTLE: + case NATURE_CAREFUL: + targetSpecies = evolutions[i].targetSpecies; + break; + } + } + break; + case EVO_ITEM_HOLD: + if (heldItem == evolutions[i].param) + { + targetSpecies = evolutions[i].targetSpecies; + consumeItem = TRUE; + } + break; + case EVO_LEVEL_MOVE_TWENTY_TIMES: + if (evolutionTracker >= 20) + targetSpecies = evolutions[i].targetSpecies; + break; + case EVO_LEVEL_RECOIL_DAMAGE_MALE: + if (evolutionTracker >= evolutions[i].param && GetMonGender(mon) == MON_MALE) + targetSpecies = evolutions[i].targetSpecies; + break; + case EVO_LEVEL_RECOIL_DAMAGE_FEMALE: + if (evolutionTracker >= evolutions[i].param && GetMonGender(mon) == MON_FEMALE) + targetSpecies = evolutions[i].targetSpecies; + break; } } break; @@ -4425,16 +4629,13 @@ u16 GetEvolutionTargetSpecies(struct Pokemon *mon, u8 type, u16 evolutionItem, s if (evolutions[i].param == heldItem) { targetSpecies = evolutions[i].targetSpecies; - - // Prevent cross-generational evolutions like Scizor and Steelix until the National Pokedex is obtained - if (IsNationalPokedexEnabled() || targetSpecies <= KANTO_SPECIES_END) - { - heldItem = ITEM_NONE; - SetMonData(mon, MON_DATA_HELD_ITEM, &heldItem); - targetSpecies = evolutions[i].targetSpecies; - } + consumeItem = TRUE; } break; + case EVO_TRADE_SPECIFIC_MON: + if (evolutions[i].param == partnerSpecies && partnerHoldEffect != HOLD_EFFECT_PREVENT_EVOLVE) + targetSpecies = evolutions[i].targetSpecies; + break; } } break; @@ -4442,20 +4643,95 @@ u16 GetEvolutionTargetSpecies(struct Pokemon *mon, u8 type, u16 evolutionItem, s case EVO_MODE_ITEM_CHECK: for (i = 0; evolutions[i].method != EVOLUTIONS_END; i++) { - if (SanitizeSpeciesId(evolutions[i].targetSpecies) == SPECIES_NONE) { + if (SanitizeSpeciesId(evolutions[i].targetSpecies) == SPECIES_NONE) continue; - } - switch(evolutions[i].method) + switch (evolutions[i].method) { - case EVO_ITEM: - if (evolutions[i].param == evolutionItem) { - targetSpecies = evolutions[i].targetSpecies; - } - break; + case EVO_ITEM: + if (evolutions[i].param == evolutionItem) + targetSpecies = evolutions[i].targetSpecies; + break; + case EVO_ITEM_FEMALE: + if (GetMonGender(mon) == MON_FEMALE && evolutions[i].param == evolutionItem) + targetSpecies = evolutions[i].targetSpecies; + break; + case EVO_ITEM_MALE: + if (GetMonGender(mon) == MON_MALE && evolutions[i].param == evolutionItem) + targetSpecies = evolutions[i].targetSpecies; + break; + case EVO_ITEM_NIGHT: + if (/* GetTimeOfDay() == TIME_NIGHT && */ evolutions[i].param == evolutionItem) + targetSpecies = evolutions[i].targetSpecies; + break; + case EVO_ITEM_DAY: + if (/* GetTimeOfDay() != TIME_NIGHT && */ evolutions[i].param == evolutionItem) + targetSpecies = evolutions[i].targetSpecies; + break; } } break; + // Battle evolution without leveling; party slot is being passed into the evolutionItem arg. + case EVO_MODE_BATTLE_SPECIAL: + for (i = 0; evolutions[i].method != EVOLUTIONS_END; i++) + { + if (SanitizeSpeciesId(evolutions[i].targetSpecies) == SPECIES_NONE) + continue; + + switch (evolutions[i].method) + { + case EVO_CRITICAL_HITS: + if (gPartyCriticalHits[evolutionItem] >= evolutions[i].param) + targetSpecies = evolutions[i].targetSpecies; + break; + } + } + break; + // Overworld evolution without leveling; evolution method is being passed into the evolutionItem arg. + case EVO_MODE_OVERWORLD_SPECIAL: + for (i = 0; evolutions[i].method != EVOLUTIONS_END; i++) + { + if (SanitizeSpeciesId(evolutions[i].targetSpecies) == SPECIES_NONE) + continue; + + switch (evolutions[i].method) + { + case EVO_SCRIPT_TRIGGER_DMG: + { + u16 currentHp = GetMonData(mon, MON_DATA_HP, NULL); + if (evolutionItem == EVO_SCRIPT_TRIGGER_DMG + && currentHp != 0 + && (GetMonData(mon, MON_DATA_MAX_HP, NULL) - currentHp >= evolutions[i].param)) + targetSpecies = evolutions[i].targetSpecies; + break; + } + case EVO_DARK_SCROLL: + if (evolutionItem == EVO_DARK_SCROLL) + targetSpecies = evolutions[i].targetSpecies; + break; + case EVO_WATER_SCROLL: + if (evolutionItem == EVO_WATER_SCROLL) + targetSpecies = evolutions[i].targetSpecies; + break; + } + } + break; + } + + // Pikachu, Meowth, and Eevee cannot evolve if they have the + // Gigantamax Factor. We assume that is because their evolutions + // do not have a Gigantamax Form. + if (GetMonData(mon, MON_DATA_GIGANTAMAX_FACTOR, NULL) + && GetGMaxTargetSpecies(species) != SPECIES_NONE + && GetGMaxTargetSpecies(targetSpecies) == SPECIES_NONE) + { + return SPECIES_NONE; + } + + if (consumeItem) + { + heldItem = ITEM_NONE; + SetMonData(mon, MON_DATA_HELD_ITEM, &heldItem); } return targetSpecies; diff --git a/src/pokemon_summary_screen.c b/src/pokemon_summary_screen.c index 4213f4e2d..1a5ba96d4 100644 --- a/src/pokemon_summary_screen.c +++ b/src/pokemon_summary_screen.c @@ -2097,7 +2097,7 @@ static void BufferMonInfo(void) if (!sMonSummaryScreen->isEgg) { dexNum = GetMonData(&sMonSummaryScreen->currentMon, MON_DATA_SPECIES); - GetSpeciesName(sMonSummaryScreen->summary.speciesNameStrBuf, dexNum); + StringCopy(sMonSummaryScreen->summary.speciesNameStrBuf, GetSpeciesName(dexNum)); } else { diff --git a/src/quest_log_events.c b/src/quest_log_events.c index 130d64d5b..bd350ed7a 100644 --- a/src/quest_log_events.c +++ b/src/quest_log_events.c @@ -1016,9 +1016,13 @@ static void QuestLog_GetSpeciesName(u16 species, u8 *dest, u8 stringVarId) if (dest != NULL) { if (species != SPECIES_EGG) - GetSpeciesName(dest, species); + { + StringCopy(dest, GetSpeciesName(species)); + } else + { StringCopy(dest, gText_EggNickname); + } } else {