diff options
Diffstat (limited to 'src/pokemon_3.c')
-rw-r--r-- | src/pokemon_3.c | 478 |
1 files changed, 478 insertions, 0 deletions
diff --git a/src/pokemon_3.c b/src/pokemon_3.c new file mode 100644 index 000000000..cf172b122 --- /dev/null +++ b/src/pokemon_3.c @@ -0,0 +1,478 @@ +#include "global.h" +#include "asm.h" +#include "text.h" +#include "string_util.h" +#include "pokemon.h" +#include "rng.h" +#include "species.h" +#include "main.h" +#include "sprite.h" +#include "event_data.h" +#include "rtc.h" +#include "item.h" +#include "items.h" + +#define EVO_FRIENDSHIP 0x0001 // Pokémon levels up with friendship ≥ 220 +#define EVO_FRIENDSHIP_DAY 0x0002 // Pokémon levels up during the day with friendship ≥ 220 +#define EVO_FRIENDSHIP_NIGHT 0x0003 // Pokémon levels up at night with friendship ≥ 220 +#define EVO_LEVEL 0x0004 // Pokémon reaches the specified level +#define EVO_TRADE 0x0005 // Pokémon is traded +#define EVO_TRADE_ITEM 0x0006 // Pokémon is traded while it's holding the specified item +#define EVO_ITEM 0x0007 // specified item is used on Pokémon +#define EVO_LEVEL_ATK_GT_DEF 0x0008 // Pokémon reaches the specified level with attack > defense +#define EVO_LEVEL_ATK_EQ_DEF 0x0009 // Pokémon reaches the specified level with attack = defense +#define EVO_LEVEL_ATK_LT_DEF 0x000a // Pokémon reaches the specified level with attack < defense +#define EVO_LEVEL_SILCOON 0x000b // Pokémon reaches the specified level with a Silcoon personality value +#define EVO_LEVEL_CASCOON 0x000c // Pokémon reaches the specified level with a Cascoon personality value +#define EVO_LEVEL_NINJASK 0x000d // Pokémon reaches the specified level (special value for Ninjask) +#define EVO_LEVEL_SHEDINJA 0x000e // Pokémon reaches the specified level (special value for Shedinja) +#define EVO_BEAUTY 0x000f // Pokémon levels up with beauty ≥ specified value + +struct Evolution +{ + u16 method; + u16 param; + u16 targetSpecies; +}; + +struct EvolutionData +{ + struct Evolution evolutions[5]; +}; + +extern void get_battle_strings_(u8 *); + +extern u8 gPlayerPartyCount; +extern struct Pokemon gPlayerParty[6]; +extern u8 gEnemyPartyCount; +extern struct Pokemon gEnemyParty[6]; +extern struct BattlePokemon gBattleMons[4]; +extern u8 * const gItemEffectTable[]; +extern u8 gUnknown_02024A60; +extern struct BattleEnigmaBerry gEnigmaBerries[]; +extern struct EvolutionData gEvolutionTable[]; +extern u16 gSpeciesToHoennPokedexNum[]; +extern u16 gSpeciesToNationalPokedexNum[]; +extern u16 gHoennToNationalOrder[]; +extern u16 gSpeciesIdToCryId[]; +extern u8 gUnknown_030041C0[]; +extern u8 gUnknown_03004290[]; +extern u8 gUnknown_020238CC[]; +extern u8 gUnknown_02024C07; +extern u8 gUnknown_02024C08; +extern u8 gUnknown_02024C0B; +extern u8 gUnknown_02024E6C; + +extern u8 gUnknown_082082F8[]; +extern u8 gUnknown_083FFDB3[]; +extern u8 gUnknown_083FFDD3[]; +extern u8 gUnknown_083FEE5D[]; +extern u8 gUnknown_083FEE92[]; +extern u8 *gUnknown_08400F58[]; + +bool8 HealStatusConditions(struct Pokemon *mon, u32 unused, u32 healMask, u8 battleId) +{ + u32 status = GetMonData(mon, MON_DATA_STATUS, 0); + + if (status & healMask) + { + status &= ~healMask; + SetMonData(mon, MON_DATA_STATUS, (u8 *)&status); + if (gMain.inBattle && battleId != 4) + gBattleMons[battleId].status1 &= ~healMask; + return FALSE; + } + else + { + return TRUE; + } +} + +u8 GetItemEffectParamOffset(u16 itemId, u8 effectByte, u8 effectBit) +{ + u8 *temp; + u8 *itemEffect; + u8 offset; + int i; + u8 j; + u8 val; + + offset = 6; + + temp = gItemEffectTable[itemId - 13]; + + if (!temp && itemId != ITEM_ENIGMA_BERRY) + return 0; + + if (itemId == ITEM_ENIGMA_BERRY) + { + temp = gEnigmaBerries[gUnknown_02024A60].itemEffect; + } + + itemEffect = temp; + + for (i = 0; i < 6; i++) + { + switch (i) + { + case 0: + case 1: + case 2: + case 3: + if (i == effectByte) + return 0; + break; + case 4: + val = itemEffect[4]; + if (val & 0x20) + val &= 0xDF; + j = 0; + while (val) + { + if (val & 1) + { + switch (j) + { + case 2: + if (val & 0x10) + val &= 0xEF; + case 0: + if (i == effectByte && (val & effectBit)) + return offset; + offset++; + break; + case 1: + if (i == effectByte && (val & effectBit)) + return offset; + offset++; + break; + case 3: + if (i == effectByte && (val & effectBit)) + return offset; + offset++; + break; + case 7: + if (i == effectByte) + return 0; + break; + } + } + j++; + val >>= 1; + if (i == effectByte) + effectBit >>= 1; + } + break; + case 5: + val = itemEffect[5]; + j = 0; + while (val) + { + if (val & 1) + { + switch (j) + { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + if (i == effectByte && (val & effectBit)) + return offset; + offset++; + break; + case 7: + if (i == effectByte) + return 0; + break; + } + } + j++; + val >>= 1; + if (i == effectByte) + effectBit >>= 1; + } + break; + } + } + + return offset; +} + +void sub_803F324(int stat) +{ + gUnknown_02024C08 = gUnknown_02024E6C; + StringCopy(gUnknown_030041C0, gUnknown_08400F58[gUnknown_082082F8[stat]]); + StringCopy(gUnknown_03004290, gUnknown_083FFDB3); + get_battle_strings_(gUnknown_083FFDD3); +} + +u8 *sub_803F378(u16 itemId) +{ + int i; + u8 *itemEffect; + + if (itemId == ITEM_ENIGMA_BERRY) + { + if (gMain.inBattle) + { + itemEffect = gEnigmaBerries[gUnknown_02024E6C].itemEffect; + } + else + { + itemEffect = gSaveBlock1.enigmaBerry.itemEffect; + } + } + else + { + itemEffect = gItemEffectTable[itemId - 13]; + } + + gUnknown_02024C0B = gUnknown_02024E6C; + + for (i = 0; i < 3; i++) + { + if (itemEffect[i] & 0xF) + sub_803F324(i * 2); + if (itemEffect[i] & 0xF0) + { + if (i) + { + sub_803F324(i * 2 + 1); + } + else + { + gUnknown_02024C07 = gUnknown_02024E6C; + get_battle_strings_(gUnknown_083FEE92); + } + } + } + + if (itemEffect[3] & 0x80) + { + gUnknown_02024C07 = gUnknown_02024E6C; + get_battle_strings_(gUnknown_083FEE5D); + } + + return gUnknown_020238CC; +} + +u8 GetNature(struct Pokemon *mon) +{ + return GetMonData(mon, MON_DATA_PERSONALITY, 0) % 25; +} + +u8 GetNatureFromPersonality(u32 personality) +{ + return personality % 25; +} + +u16 GetEvolutionTargetSpecies(struct Pokemon *mon, u8 type, u16 evolutionItem) +{ + int i; + u16 targetSpecies = 0; + 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, 0); + u16 upperPersonality = personality >> 16; + u8 holdEffect; + + if (heldItem == ITEM_ENIGMA_BERRY) + holdEffect = gSaveBlock1.enigmaBerry.holdEffect; + else + holdEffect = ItemId_GetHoldEffect(heldItem); + + if (holdEffect == 38 && type != 3) + return 0; + + switch (type) + { + case 0: + level = GetMonData(mon, MON_DATA_LEVEL, 0); + friendship = GetMonData(mon, MON_DATA_FRIENDSHIP, 0); + + for (i = 0; i < 5; i++) + { + switch (gEvolutionTable[species].evolutions[i].method) + { + case EVO_FRIENDSHIP: + if (friendship >= 220) + targetSpecies = gEvolutionTable[species].evolutions[i].targetSpecies; + break; + case EVO_FRIENDSHIP_DAY: + RtcCalcLocalTime(); + if (gLocalTime.hours >= 12 && gLocalTime.hours < 24 && friendship >= 220) + targetSpecies = gEvolutionTable[species].evolutions[i].targetSpecies; + break; + case EVO_FRIENDSHIP_NIGHT: + RtcCalcLocalTime(); + if (gLocalTime.hours >= 0 && gLocalTime.hours < 12 && friendship >= 220) + targetSpecies = gEvolutionTable[species].evolutions[i].targetSpecies; + break; + case EVO_LEVEL: + if (gEvolutionTable[species].evolutions[i].param <= level) + targetSpecies = gEvolutionTable[species].evolutions[i].targetSpecies; + break; + case EVO_LEVEL_ATK_GT_DEF: + if (gEvolutionTable[species].evolutions[i].param <= level) + if (GetMonData(mon, MON_DATA_ATK, 0) > GetMonData(mon, MON_DATA_DEF, 0)) + targetSpecies = gEvolutionTable[species].evolutions[i].targetSpecies; + break; + case EVO_LEVEL_ATK_EQ_DEF: + if (gEvolutionTable[species].evolutions[i].param <= level) + if (GetMonData(mon, MON_DATA_ATK, 0) == GetMonData(mon, MON_DATA_DEF, 0)) + targetSpecies = gEvolutionTable[species].evolutions[i].targetSpecies; + break; + case EVO_LEVEL_ATK_LT_DEF: + if (gEvolutionTable[species].evolutions[i].param <= level) + if (GetMonData(mon, MON_DATA_ATK, 0) < GetMonData(mon, MON_DATA_DEF, 0)) + targetSpecies = gEvolutionTable[species].evolutions[i].targetSpecies; + break; + case EVO_LEVEL_SILCOON: + if (gEvolutionTable[species].evolutions[i].param <= level && (upperPersonality % 10) <= 4) + targetSpecies = gEvolutionTable[species].evolutions[i].targetSpecies; + break; + case EVO_LEVEL_CASCOON: + if (gEvolutionTable[species].evolutions[i].param <= level && (upperPersonality % 10) > 4) + targetSpecies = gEvolutionTable[species].evolutions[i].targetSpecies; + break; + case EVO_LEVEL_NINJASK: + if (gEvolutionTable[species].evolutions[i].param <= level) + targetSpecies = gEvolutionTable[species].evolutions[i].targetSpecies; + break; + case EVO_BEAUTY: + if (gEvolutionTable[species].evolutions[i].param <= beauty) + targetSpecies = gEvolutionTable[species].evolutions[i].targetSpecies; + break; + } + } + break; + case 1: + for (i = 0; i < 5; i++) + { + switch (gEvolutionTable[species].evolutions[i].method) + { + case EVO_TRADE: + targetSpecies = gEvolutionTable[species].evolutions[i].targetSpecies; + break; + case EVO_TRADE_ITEM: + if (gEvolutionTable[species].evolutions[i].param == heldItem) + { + heldItem = 0; + SetMonData(mon, MON_DATA_HELD_ITEM, (u8 *)&heldItem); + targetSpecies = gEvolutionTable[species].evolutions[i].targetSpecies; + } + break; + } + } + break; + case 2: + case 3: + for (i = 0; i < 5; i++) + { + if (gEvolutionTable[species].evolutions[i].method == EVO_ITEM + && gEvolutionTable[species].evolutions[i].param == evolutionItem) + { + targetSpecies = gEvolutionTable[species].evolutions[i].targetSpecies; + break; + } + } + break; + } + + return targetSpecies; +} + +u16 HoennPokedexNumToSpecies(u16 hoennNum) +{ + u16 species; + + if (!hoennNum) + return 0; + + species = 0; + + while (species < 411 && gSpeciesToHoennPokedexNum[species] != hoennNum) + species++; + + if (species == 411) + return 0; + + return species + 1; +} + +u16 NationalPokedexNumToSpecies(u16 nationalNum) +{ + u16 species; + + if (!nationalNum) + return 0; + + species = 0; + + while (species < 411 && gSpeciesToNationalPokedexNum[species] != nationalNum) + species++; + + if (species == 411) + return 0; + + return species + 1; +} + +u16 NationalToHoennOrder(u16 nationalNum) +{ + u16 hoennNum; + + if (!nationalNum) + return 0; + + hoennNum = 0; + + while (hoennNum < 411 && gHoennToNationalOrder[hoennNum] != nationalNum) + hoennNum++; + + if (hoennNum == 411) + return 0; + + return hoennNum + 1; +} + +u16 SpeciesToNationalPokedexNum(u16 species) +{ + if (!species) + return 0; + + return gSpeciesToNationalPokedexNum[species - 1]; +} + +u16 SpeciesToHoennPokedexNum(u16 species) +{ + if (!species) + return 0; + + return gSpeciesToHoennPokedexNum[species - 1]; +} + +u16 HoennToNationalOrder(u16 hoennNum) +{ + if (!hoennNum) + return 0; + + return gHoennToNationalOrder[hoennNum - 1]; +} + +u32 SpeciesToCryId(u16 species) +{ + if (species <= 250) + return species; + + if (species < 276) + return 200; + + return gSpeciesIdToCryId[species - 276]; +} |