summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/pokemon_1.c1838
-rw-r--r--src/pokemon_3.c1746
2 files changed, 1834 insertions, 1750 deletions
diff --git a/src/pokemon_1.c b/src/pokemon_1.c
index 90071b8a4..b7c703f30 100644
--- a/src/pokemon_1.c
+++ b/src/pokemon_1.c
@@ -16,7 +16,17 @@
#include "event_data.h"
#include "item.h"
#include "battle_controllers.h"
+#include "battle_message.h"
#include "evolution_scene.h"
+#include "pokemon_animation.h"
+#include "pokedex.h"
+#include "pokeblock.h"
+#include "constants/songs.h"
+#include "sound.h"
+#include "task.h"
+#include "rtc.h"
+#include "m4a.h"
+#include "malloc.h"
//Extracts the upper 16 bits of a 32-bit number
#define HIHALF(n) (((n) & 0xFFFF0000) >> 16)
@@ -24,12 +34,27 @@
//Extracts the lower 16 bits of a 32-bit number
#define LOHALF(n) ((n) & 0xFFFF)
-struct Unknown_020249B4
+struct Unknown_806F160_Struct
{
- u8 unk0[0xC];
- struct SpriteTemplate* templates;
+ u8 field_0_0 : 4;
+ u8 field_0_1 : 4;
+ u8 field_1;
+ u8 field_2;
+ u8 field_3_0 : 4;
+ u8 field_3_1 : 4;
+ void *bytes;
+ u8 **byteArrays;
+ struct SpriteTemplate *templates;
+ struct SpriteFrameImage *frameImages;
};
+struct PokeItem
+{
+ u16 species;
+ u16 item;
+};
+extern const struct PokeItem gAlteringCaveWildMonHeldItems[9];
+
extern u8 gAbsentBattlerFlags;
extern u8 gActiveBattler;
extern u8 gBattlersCount;
@@ -41,7 +66,7 @@ extern u8 gLastUsedAbility;
extern u16 gTrainerBattleOpponent_A;
extern u32 gBattleTypeFlags;
extern struct SpriteTemplate gUnknown_0202499C;
-extern struct Unknown_020249B4* gUnknown_020249B4[2];
+extern struct Unknown_806F160_Struct *gUnknown_020249B4[2];
extern struct BattlePokemon gBattleMons[4];
extern u32 gBattleTypeFlags;
extern struct BattlePokemon gBattleMons[4];
@@ -56,6 +81,20 @@ extern s32 gBattleMoveDamage;
extern u8 gUnknown_0203C7B4;
extern u16 gMoveToLearn;
extern u8 gStringBattler;
+extern struct BattlePokemon gBattleMons[4];
+extern struct BattleEnigmaBerry gEnigmaBerries[4];
+extern u8 gActiveBattler;
+extern u8 gBankInMenu;
+extern u8 gBattlerTarget;
+extern u8 gBattlerAttacker;
+extern u8 gStringBattler;
+extern u16 gTrainerBattleOpponent_A;
+extern u32 gBattleTypeFlags;
+extern u8 gBattleMonForms[4];
+extern u16 gBattlerPartyIndexes[4];
+extern u8 gLastUsedAbility;
+extern u16 gPartnerTrainerId;
+extern u32 gHitMarker;
extern const u32 gBitTable[];
extern const struct SpriteTemplate gUnknown_08329D98[];
@@ -83,6 +122,31 @@ extern const u8 gUnknown_08329D22[];
extern const u8 gUnknown_08329D26[];
extern const u8 gUnknown_08329D2A[];
extern const u8 gUnknown_08329EC2[];
+extern const u16 gSpeciesToHoennPokedexNum[];
+extern const u16 gSpeciesToNationalPokedexNum[];
+extern const u16 gHoennToNationalOrder[];
+extern const u16 gSpeciesIdToCryId[];
+extern const struct SpindaSpot gSpindaSpotGraphics[];
+extern const u8* const gStatNamesTable[];
+extern const u8 gSpeciesNames[][11];
+extern const u8 gUnknown_08329EC8[];
+extern const u8 gText_StatRose[];
+extern const u8 gText_PkmnsStatChanged2[];
+extern const u8 gText_PkmnGettingPumped[];
+extern const u8 gText_PkmnShroudedInMist[];
+extern const s8 gNatureStatTable[][5];
+extern const s8 gUnknown_08329ECE[][3];
+extern const u32 gBitTable[];
+extern const u32 gTMHMLearnsets[][2];
+extern const u8 gText_BattleWallyName[];
+extern const u8 gText_PkmnsXPreventsSwitching[];
+extern const struct CompressedSpritePalette gMonPaletteTable[];
+extern const struct CompressedSpritePalette gMonShinyPaletteTable[];
+extern const u16 gHMMoves[];
+extern const u8 gMonAnimationDelayTable[];
+extern const u8 gMonFrontAnimIdsTable[];
+extern const u8 gFacilityClassToPicIndex[];
+extern const u8 gTrainerClassNames[][13];
extern bool8 ShouldGetStatBadgeBoost(u16 flagId, u8 bank);
extern u8 pokemon_order_func(u8);
@@ -104,9 +168,23 @@ extern u16 sub_806EFF0(u16);
extern bool8 HealStatusConditions(struct Pokemon *mon, u32 unused, u32 healMask, u8 battleId);
extern bool8 sub_806F104(void);
extern bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 moveIndex, u8 e);
+extern void SpriteCallbackDummy_2(struct Sprite*);
+extern bool8 InBattlePyramid(void);
+extern bool8 InBattlePike(void);
+extern bool8 sub_81D5C18(void);
+extern bool8 sub_806F104(void);
+extern bool32 IsNationalPokedexEnabled(void);
+extern u8 GetTrainerEncounterMusicIdInBattlePyramind(u16 trainerOpponentId);
+extern u8 sub_81D63C8(u16 trainerOpponentId);
+extern u8 sav1_map_get_name(void);
+extern u8 GetFrontierOpponentClass(u16 trainerId);
+extern u8 pokemon_order_func(u8 bankPartyId);
+extern void GetFrontierTrainerName(u8* dest, u16 trainerId);
+extern void sub_81C488C(u8);
// this file's functions
union PokemonSubstruct *GetSubstruct(struct BoxPokemon *boxMon, u32 personality, u8 substructType);
+void sub_806E6CC(u8 taskId);
// EWRAM vars
EWRAM_DATA u8 sLearningMoveTableID = 0;
@@ -3212,4 +3290,1756 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov
return retVal;
}
+bool8 HealStatusConditions(struct Pokemon *mon, u32 battlePartyId, u32 healMask, u8 battleBank)
+{
+ u32 status = GetMonData(mon, MON_DATA_STATUS, 0);
+
+ if (status & healMask)
+ {
+ status &= ~healMask;
+ SetMonData(mon, MON_DATA_STATUS, &status);
+ if (gMain.inBattle && battleBank != 4)
+ gBattleMons[battleBank].status1 &= ~healMask;
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+}
+
+u8 GetItemEffectParamOffset(u16 itemId, u8 effectByte, u8 effectBit)
+{
+ const u8 *temp;
+ const 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[gActiveBattler].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_806CF24(s32 stat)
+{
+ gBattlerTarget = gBankInMenu;
+ StringCopy(gBattleTextBuff1, gStatNamesTable[gUnknown_08329EC8[stat]]);
+ StringCopy(gBattleTextBuff2, gText_StatRose);
+ BattleStringExpandPlaceholdersToDisplayedString(gText_PkmnsStatChanged2);
+}
+
+u8 *sub_806CF78(u16 itemId)
+{
+ int i;
+ const u8 *itemEffect;
+
+ if (itemId == ITEM_ENIGMA_BERRY)
+ {
+ if (gMain.inBattle)
+ itemEffect = gEnigmaBerries[gBankInMenu].itemEffect;
+ else
+ itemEffect = gSaveBlock1Ptr->enigmaBerry.itemEffect;
+ }
+ else
+ {
+ itemEffect = gItemEffectTable[itemId - 13];
+ }
+
+ gStringBattler = gBankInMenu;
+
+ for (i = 0; i < 3; i++)
+ {
+ if (itemEffect[i] & 0xF)
+ sub_806CF24(i * 2);
+ if (itemEffect[i] & 0xF0)
+ {
+ if (i)
+ {
+ sub_806CF24(i * 2 + 1);
+ }
+ else
+ {
+ gBattlerAttacker = gBankInMenu;
+ BattleStringExpandPlaceholdersToDisplayedString(gText_PkmnGettingPumped);
+ }
+ }
+ }
+
+ if (itemEffect[3] & 0x80)
+ {
+ gBattlerAttacker = gBankInMenu;
+ BattleStringExpandPlaceholdersToDisplayedString(gText_PkmnShroudedInMist);
+ }
+
+ return gDisplayedStringBattle;
+}
+
+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 = gSaveBlock1Ptr->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][i].method)
+ {
+ case EVO_FRIENDSHIP:
+ if (friendship >= 220)
+ targetSpecies = gEvolutionTable[species][i].targetSpecies;
+ break;
+ case EVO_FRIENDSHIP_DAY:
+ RtcCalcLocalTime();
+ if (gLocalTime.hours >= 12 && gLocalTime.hours < 24 && friendship >= 220)
+ targetSpecies = gEvolutionTable[species][i].targetSpecies;
+ break;
+ case EVO_FRIENDSHIP_NIGHT:
+ RtcCalcLocalTime();
+ if (gLocalTime.hours >= 0 && gLocalTime.hours < 12 && friendship >= 220)
+ targetSpecies = gEvolutionTable[species][i].targetSpecies;
+ break;
+ case EVO_LEVEL:
+ if (gEvolutionTable[species][i].param <= level)
+ targetSpecies = gEvolutionTable[species][i].targetSpecies;
+ break;
+ case EVO_LEVEL_ATK_GT_DEF:
+ if (gEvolutionTable[species][i].param <= level)
+ if (GetMonData(mon, MON_DATA_ATK, 0) > GetMonData(mon, MON_DATA_DEF, 0))
+ targetSpecies = gEvolutionTable[species][i].targetSpecies;
+ break;
+ case EVO_LEVEL_ATK_EQ_DEF:
+ if (gEvolutionTable[species][i].param <= level)
+ if (GetMonData(mon, MON_DATA_ATK, 0) == GetMonData(mon, MON_DATA_DEF, 0))
+ targetSpecies = gEvolutionTable[species][i].targetSpecies;
+ break;
+ case EVO_LEVEL_ATK_LT_DEF:
+ if (gEvolutionTable[species][i].param <= level)
+ if (GetMonData(mon, MON_DATA_ATK, 0) < GetMonData(mon, MON_DATA_DEF, 0))
+ targetSpecies = gEvolutionTable[species][i].targetSpecies;
+ break;
+ case EVO_LEVEL_SILCOON:
+ if (gEvolutionTable[species][i].param <= level && (upperPersonality % 10) <= 4)
+ targetSpecies = gEvolutionTable[species][i].targetSpecies;
+ break;
+ case EVO_LEVEL_CASCOON:
+ if (gEvolutionTable[species][i].param <= level && (upperPersonality % 10) > 4)
+ targetSpecies = gEvolutionTable[species][i].targetSpecies;
+ break;
+ case EVO_LEVEL_NINJASK:
+ if (gEvolutionTable[species][i].param <= level)
+ targetSpecies = gEvolutionTable[species][i].targetSpecies;
+ break;
+ case EVO_BEAUTY:
+ if (gEvolutionTable[species][i].param <= beauty)
+ targetSpecies = gEvolutionTable[species][i].targetSpecies;
+ break;
+ }
+ }
+ break;
+ case 1:
+ for (i = 0; i < 5; i++)
+ {
+ switch (gEvolutionTable[species][i].method)
+ {
+ case EVO_TRADE:
+ targetSpecies = gEvolutionTable[species][i].targetSpecies;
+ break;
+ case EVO_TRADE_ITEM:
+ if (gEvolutionTable[species][i].param == heldItem)
+ {
+ heldItem = 0;
+ SetMonData(mon, MON_DATA_HELD_ITEM, (u8 *)&heldItem);
+ targetSpecies = gEvolutionTable[species][i].targetSpecies;
+ }
+ break;
+ }
+ }
+ break;
+ case 2:
+ case 3:
+ for (i = 0; i < 5; i++)
+ {
+ if (gEvolutionTable[species][i].method == EVO_ITEM
+ && gEvolutionTable[species][i].param == evolutionItem)
+ {
+ targetSpecies = gEvolutionTable[species][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];
+}
+
+u16 SpeciesToCryId(u16 species)
+{
+ if (species <= 250)
+ return species;
+
+ if (species < 276)
+ return 200;
+
+ return gSpeciesIdToCryId[species - 276];
+}
+
+void sub_806D544(u16 species, u32 personality, u8 *dest)
+{
+ if (species == SPECIES_SPINDA
+ && dest != gMonSpritesGfxPtr->sprites[0]
+ && dest != gMonSpritesGfxPtr->sprites[2])
+ {
+ int i;
+ for (i = 0; i < 4; i++)
+ {
+ int j;
+ u8 x = gSpindaSpotGraphics[i].x + ((personality & 0x0F) - 8);
+ u8 y = gSpindaSpotGraphics[i].y + (((personality & 0xF0) >> 4) - 8);
+
+ for (j = 0; j < 16; j++)
+ {
+ int k;
+ s32 row = gSpindaSpotGraphics[i].image[j];
+
+ for (k = x; k < x + 16; k++)
+ {
+ u8 *val = dest + ((k / 8) * 32) + ((k % 8) / 2) + ((y >> 3) << 8) + ((y & 7) << 2);
+
+ if (row & 1)
+ {
+ if (k & 1)
+ {
+ if ((u8)((*val & 0xF0) - 0x10) <= 0x20)
+ *val += 0x40;
+ }
+ else
+ {
+ if ((u8)((*val & 0xF) - 0x01) <= 0x02)
+ *val += 0x04;
+ }
+ }
+
+ row >>= 1;
+ }
+
+ y++;
+ }
+
+ personality >>= 8;
+ }
+ }
+}
+
+void DrawSpindaSpots(u16 species, u32 personality, u8 *dest, u8 a4)
+{
+ if (species == SPECIES_SPINDA && a4)
+ {
+ int i;
+ for (i = 0; i < 4; i++)
+ {
+ int j;
+ u8 x = gSpindaSpotGraphics[i].x + ((personality & 0x0F) - 8);
+ u8 y = gSpindaSpotGraphics[i].y + (((personality & 0xF0) >> 4) - 8);
+
+ for (j = 0; j < 16; j++)
+ {
+ int k;
+ s32 row = gSpindaSpotGraphics[i].image[j];
+
+ for (k = x; k < x + 16; k++)
+ {
+ u8 *val = dest + ((k / 8) * 32) + ((k % 8) / 2) + ((y >> 3) << 8) + ((y & 7) << 2);
+
+ if (row & 1)
+ {
+ if (k & 1)
+ {
+ if ((u8)((*val & 0xF0) - 0x10) <= 0x20)
+ *val += 0x40;
+ }
+ else
+ {
+ if ((u8)((*val & 0xF) - 0x01) <= 0x02)
+ *val += 0x04;
+ }
+ }
+
+ row >>= 1;
+ }
+
+ y++;
+ }
+
+ personality >>= 8;
+ }
+ }
+}
+
+void EvolutionRenameMon(struct Pokemon *mon, u16 oldSpecies, u16 newSpecies)
+{
+ u8 language;
+ GetMonData(mon, MON_DATA_NICKNAME, gStringVar1);
+ language = GetMonData(mon, MON_DATA_LANGUAGE, &language);
+ if (language == GAME_LANGUAGE && !StringCompare(gSpeciesNames[oldSpecies], gStringVar1))
+ SetMonData(mon, MON_DATA_NICKNAME, gSpeciesNames[newSpecies]);
+}
+
+bool8 sub_806D7EC(void)
+{
+ bool8 retVal = FALSE;
+ switch (gLinkPlayers[GetMultiplayerId()].lp_field_18)
+ {
+ case 0:
+ case 3:
+ retVal = FALSE;
+ break;
+ case 1:
+ case 2:
+ retVal = TRUE;
+ break;
+ }
+ return retVal;
+}
+
+bool16 sub_806D82C(u8 id)
+{
+ bool16 retVal = FALSE;
+ switch (gLinkPlayers[id].lp_field_18)
+ {
+ case 0:
+ case 3:
+ retVal = FALSE;
+ break;
+ case 1:
+ case 2:
+ retVal = TRUE;
+ break;
+ }
+ return retVal;
+}
+
+s32 GetBattlerMultiplayerId(u16 a1)
+{
+ s32 id;
+ for (id = 0; id < MAX_LINK_PLAYERS; id++)
+ if (gLinkPlayers[id].lp_field_18 == a1)
+ break;
+ return id;
+}
+
+u8 GetTrainerEncounterMusicId(u16 trainerOpponentId)
+{
+ if (InBattlePyramid())
+ return GetTrainerEncounterMusicIdInBattlePyramind(trainerOpponentId);
+ if (sub_81D5C18())
+ return sub_81D63C8(trainerOpponentId);
+ return TRAINER_ENCOUNTER_MUSIC(trainerOpponentId);
+}
+
+u16 ModifyStatByNature(u8 nature, u16 n, u8 statIndex)
+{
+ if (statIndex < 1 || statIndex > 5)
+ {
+ // should just be "return n", but it wouldn't match without this
+ u16 retVal = n;
+ retVal++;
+ retVal--;
+ return retVal;
+ }
+
+ switch (gNatureStatTable[nature][statIndex - 1])
+ {
+ case 1:
+ return (u16)(n * 110) / 100;
+ case -1:
+ return (u16)(n * 90) / 100;
+ }
+
+ return n;
+}
+
+void AdjustFriendship(struct Pokemon *mon, u8 event)
+{
+ u16 species, heldItem;
+ u8 holdEffect;
+
+ if (sub_806F104())
+ return;
+
+ species = GetMonData(mon, MON_DATA_SPECIES2, 0);
+ heldItem = GetMonData(mon, MON_DATA_HELD_ITEM, 0);
+
+ if (heldItem == ITEM_ENIGMA_BERRY)
+ {
+ if (gMain.inBattle)
+ holdEffect = gEnigmaBerries[0].holdEffect;
+ else
+ holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect;
+ }
+ else
+ {
+ holdEffect = ItemId_GetHoldEffect(heldItem);
+ }
+
+ if (species && species != SPECIES_EGG)
+ {
+ u8 friendshipLevel = 0;
+ s16 friendship = GetMonData(mon, MON_DATA_FRIENDSHIP, 0);
+ if (friendship > 99)
+ friendshipLevel++;
+ if (friendship > 199)
+ friendshipLevel++;
+ if ((event != 5 || !(Random() & 1))
+ && (event != 3
+ || ((gBattleTypeFlags & BATTLE_TYPE_TRAINER)
+ && (gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_ELITE_FOUR
+ || gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_LEADER
+ || gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_CHAMPION))))
+ {
+ s8 mod = gUnknown_08329ECE[event][friendshipLevel];
+ if (mod > 0 && holdEffect == HOLD_EFFECT_HAPPINESS_UP)
+ mod = (150 * mod) / 100;
+ friendship += mod;
+ if (mod > 0)
+ {
+ if (GetMonData(mon, MON_DATA_POKEBALL, 0) == ITEM_LUXURY_BALL)
+ friendship++;
+ if (GetMonData(mon, MON_DATA_MET_LOCATION, 0) == sav1_map_get_name())
+ friendship++;
+ }
+ if (friendship < 0)
+ friendship = 0;
+ if (friendship > 255)
+ friendship = 255;
+ SetMonData(mon, MON_DATA_FRIENDSHIP, &friendship);
+ }
+ }
+}
+
+void MonGainEVs(struct Pokemon *mon, u16 defeatedSpecies)
+{
+ u8 evs[NUM_STATS];
+ u16 evIncrease = 0;
+ u16 totalEVs = 0;
+ u16 heldItem;
+ u8 holdEffect;
+ int i;
+
+ for (i = 0; i < NUM_STATS; i++)
+ {
+ evs[i] = GetMonData(mon, MON_DATA_HP_EV + i, 0);
+ totalEVs += evs[i];
+ }
+
+ for (i = 0; i < NUM_STATS; i++)
+ {
+ u8 hasHadPokerus;
+ int multiplier;
+
+ if (totalEVs >= MAX_TOTAL_EVS)
+ break;
+
+ hasHadPokerus = CheckPartyHasHadPokerus(mon, 0);
+
+ if (hasHadPokerus)
+ multiplier = 2;
+ else
+ multiplier = 1;
+
+ switch (i)
+ {
+ case 0:
+ evIncrease = gBaseStats[defeatedSpecies].evYield_HP * multiplier;
+ break;
+ case 1:
+ evIncrease = gBaseStats[defeatedSpecies].evYield_Attack * multiplier;
+ break;
+ case 2:
+ evIncrease = gBaseStats[defeatedSpecies].evYield_Defense * multiplier;
+ break;
+ case 3:
+ evIncrease = gBaseStats[defeatedSpecies].evYield_Speed * multiplier;
+ break;
+ case 4:
+ evIncrease = gBaseStats[defeatedSpecies].evYield_SpAttack * multiplier;
+ break;
+ case 5:
+ evIncrease = gBaseStats[defeatedSpecies].evYield_SpDefense * multiplier;
+ break;
+ }
+
+ heldItem = GetMonData(mon, MON_DATA_HELD_ITEM, 0);
+
+ if (heldItem == ITEM_ENIGMA_BERRY)
+ {
+ if (gMain.inBattle)
+ holdEffect = gEnigmaBerries[0].holdEffect;
+ else
+ holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect;
+ }
+ else
+ {
+ holdEffect = ItemId_GetHoldEffect(heldItem);
+ }
+
+ if (holdEffect == HOLD_EFFECT_MACHO_BRACE)
+ evIncrease *= 2;
+
+ if (totalEVs + (s16)evIncrease > MAX_TOTAL_EVS)
+ evIncrease = ((s16)evIncrease + MAX_TOTAL_EVS) - (totalEVs + evIncrease);
+
+ if (evs[i] + (s16)evIncrease > 255)
+ {
+ int val1 = (s16)evIncrease + 255;
+ int val2 = evs[i] + evIncrease;
+ evIncrease = val1 - val2;
+ }
+
+ evs[i] += evIncrease;
+ totalEVs += evIncrease;
+ SetMonData(mon, MON_DATA_HP_EV + i, &evs[i]);
+ }
+}
+
+u16 GetMonEVCount(struct Pokemon *mon)
+{
+ int i;
+ u16 count = 0;
+
+ for (i = 0; i < NUM_STATS; i++)
+ count += GetMonData(mon, MON_DATA_HP_EV + i, 0);
+
+ return count;
+}
+
+void RandomlyGivePartyPokerus(struct Pokemon *party)
+{
+ u16 rnd = Random();
+ if (rnd == 0x4000 || rnd == 0x8000 || rnd == 0xC000)
+ {
+ struct Pokemon *mon;
+
+ do
+ {
+ do
+ {
+ rnd = Random() % PARTY_SIZE;
+ mon = &party[rnd];
+ }
+ while (!GetMonData(mon, MON_DATA_SPECIES, 0));
+ }
+ while (GetMonData(mon, MON_DATA_IS_EGG, 0));
+
+ if (!(CheckPartyHasHadPokerus(party, gBitTable[rnd])))
+ {
+ u8 rnd2;
+
+ do
+ {
+ rnd2 = Random();
+ }
+ while ((rnd2 & 0x7) == 0);
+
+ if (rnd2 & 0xF0)
+ rnd2 &= 0x7;
+
+ rnd2 |= (rnd2 << 4);
+ rnd2 &= 0xF3;
+ rnd2++;
+
+ SetMonData(&party[rnd], MON_DATA_POKERUS, &rnd2);
+ }
+ }
+}
+
+u8 CheckPartyPokerus(struct Pokemon *party, u8 selection)
+{
+ u8 retVal;
+
+ int partyIndex = 0;
+ unsigned curBit = 1;
+ retVal = 0;
+
+ if (selection)
+ {
+ do
+ {
+ if ((selection & 1) && (GetMonData(&party[partyIndex], MON_DATA_POKERUS, 0) & 0xF))
+ retVal |= curBit;
+ partyIndex++;
+ curBit <<= 1;
+ selection >>= 1;
+ }
+ while (selection);
+ }
+ else if (GetMonData(&party[0], MON_DATA_POKERUS, 0) & 0xF)
+ {
+ retVal = 1;
+ }
+
+ return retVal;
+}
+
+u8 CheckPartyHasHadPokerus(struct Pokemon *party, u8 selection)
+{
+ u8 retVal;
+
+ int partyIndex = 0;
+ unsigned curBit = 1;
+ retVal = 0;
+
+ if (selection)
+ {
+ do
+ {
+ if ((selection & 1) && GetMonData(&party[partyIndex], MON_DATA_POKERUS, 0))
+ retVal |= curBit;
+ partyIndex++;
+ curBit <<= 1;
+ selection >>= 1;
+ }
+ while (selection);
+ }
+ else if (GetMonData(&party[0], MON_DATA_POKERUS, 0))
+ {
+ retVal = 1;
+ }
+
+ return retVal;
+}
+
+void UpdatePartyPokerusTime(u16 days)
+{
+ int i;
+ for (i = 0; i < PARTY_SIZE; i++)
+ {
+ if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES, 0))
+ {
+ u8 pokerus = GetMonData(&gPlayerParty[i], MON_DATA_POKERUS, 0);
+ if (pokerus & 0xF)
+ {
+ if ((pokerus & 0xF) < days || days > 4)
+ pokerus &= 0xF0;
+ else
+ pokerus -= days;
+
+ if (pokerus == 0)
+ pokerus = 0x10;
+
+ SetMonData(&gPlayerParty[i], MON_DATA_POKERUS, &pokerus);
+ }
+ }
+ }
+}
+
+void PartySpreadPokerus(struct Pokemon *party)
+{
+ if ((Random() % 3) == 0)
+ {
+ int i;
+ for (i = 0; i < PARTY_SIZE; i++)
+ {
+ if (GetMonData(&party[i], MON_DATA_SPECIES, 0))
+ {
+ u8 pokerus = GetMonData(&party[i], MON_DATA_POKERUS, 0);
+ u8 curPokerus = pokerus;
+ if (pokerus)
+ {
+ if (pokerus & 0xF)
+ {
+ // spread to adjacent party members
+ if (i != 0 && !(GetMonData(&party[i - 1], MON_DATA_POKERUS, 0) & 0xF0))
+ SetMonData(&party[i - 1], MON_DATA_POKERUS, &curPokerus);
+ if (i != (PARTY_SIZE - 1) && !(GetMonData(&party[i + 1], MON_DATA_POKERUS, 0) & 0xF0))
+ {
+ SetMonData(&party[i + 1], MON_DATA_POKERUS, &curPokerus);
+ i++;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+bool8 TryIncrementMonLevel(struct Pokemon *mon)
+{
+ u16 species = GetMonData(mon, MON_DATA_SPECIES, 0);
+ u8 nextLevel = GetMonData(mon, MON_DATA_LEVEL, 0) + 1;
+ u32 expPoints = GetMonData(mon, MON_DATA_EXP, 0);
+ if (expPoints > gExperienceTables[gBaseStats[species].growthRate][MAX_MON_LEVEL])
+ {
+ expPoints = gExperienceTables[gBaseStats[species].growthRate][MAX_MON_LEVEL];
+ SetMonData(mon, MON_DATA_EXP, &expPoints);
+ }
+ if (nextLevel > MAX_MON_LEVEL || expPoints < gExperienceTables[gBaseStats[species].growthRate][nextLevel])
+ {
+ return FALSE;
+ }
+ else
+ {
+ SetMonData(mon, MON_DATA_LEVEL, &nextLevel);
+ return TRUE;
+ }
+}
+
+u32 CanMonLearnTMHM(struct Pokemon *mon, u8 tm)
+{
+ u16 species = GetMonData(mon, MON_DATA_SPECIES2, 0);
+ if (species == SPECIES_EGG)
+ {
+ return 0;
+ }
+ else if (tm < 32)
+ {
+ u32 mask = 1 << tm;
+ return gTMHMLearnsets[species][0] & mask;
+ }
+ else
+ {
+ u32 mask = 1 << (tm - 32);
+ return gTMHMLearnsets[species][1] & mask;
+ }
+}
+
+u32 CanSpeciesLearnTMHM(u16 species, u8 tm)
+{
+ if (species == SPECIES_EGG)
+ {
+ return 0;
+ }
+ else if (tm < 32)
+ {
+ u32 mask = 1 << tm;
+ return gTMHMLearnsets[species][0] & mask;
+ }
+ else
+ {
+ u32 mask = 1 << (tm - 32);
+ return gTMHMLearnsets[species][1] & mask;
+ }
+}
+
+u8 GetMoveRelearnerMoves(struct Pokemon *mon, u16 *moves)
+{
+ u16 learnedMoves[4];
+ u8 numMoves = 0;
+ u16 species = GetMonData(mon, MON_DATA_SPECIES, 0);
+ u8 level = GetMonData(mon, MON_DATA_LEVEL, 0);
+ int i, j, k;
+
+ for (i = 0; i < 4; i++)
+ learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0);
+
+ for (i = 0; i < 20; i++)
+ {
+ u16 moveLevel;
+
+ if (gLevelUpLearnsets[species][i] == 0xFFFF)
+ break;
+
+ moveLevel = gLevelUpLearnsets[species][i] & 0xFE00;
+
+ if (moveLevel <= (level << 9))
+ {
+ for (j = 0; j < 4 && learnedMoves[j] != (gLevelUpLearnsets[species][i] & 0x1FF); j++)
+ ;
+
+ if (j == 4)
+ {
+ for (k = 0; k < numMoves && moves[k] != (gLevelUpLearnsets[species][i] & 0x1FF); k++)
+ ;
+
+ if (k == numMoves)
+ moves[numMoves++] = gLevelUpLearnsets[species][i] & 0x1FF;
+ }
+ }
+ }
+
+ return numMoves;
+}
+
+u8 GetLevelUpMovesBySpecies(u16 species, u16 *moves)
+{
+ u8 numMoves = 0;
+ int i;
+
+ for (i = 0; i < 20 && gLevelUpLearnsets[species][i] != 0xFFFF; i++)
+ moves[numMoves++] = gLevelUpLearnsets[species][i] & 0x1FF;
+
+ return numMoves;
+}
+
+u8 GetNumberOfRelearnableMoves(struct Pokemon *mon)
+{
+ u16 learnedMoves[4];
+ u16 moves[20];
+ u8 numMoves = 0;
+ u16 species = GetMonData(mon, MON_DATA_SPECIES2, 0);
+ u8 level = GetMonData(mon, MON_DATA_LEVEL, 0);
+ int i, j, k;
+
+ if (species == SPECIES_EGG)
+ return 0;
+
+ for (i = 0; i < 4; i++)
+ learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0);
+
+ for (i = 0; i < 20; i++)
+ {
+ u16 moveLevel;
+
+ if (gLevelUpLearnsets[species][i] == 0xFFFF)
+ break;
+
+ moveLevel = gLevelUpLearnsets[species][i] & 0xFE00;
+
+ if (moveLevel <= (level << 9))
+ {
+ for (j = 0; j < 4 && learnedMoves[j] != (gLevelUpLearnsets[species][i] & 0x1FF); j++)
+ ;
+
+ if (j == 4)
+ {
+ for (k = 0; k < numMoves && moves[k] != (gLevelUpLearnsets[species][i] & 0x1FF); k++)
+ ;
+
+ if (k == numMoves)
+ moves[numMoves++] = gLevelUpLearnsets[species][i] & 0x1FF;
+ }
+ }
+ }
+
+ return numMoves;
+}
+
+u16 SpeciesToPokedexNum(u16 species)
+{
+ if (IsNationalPokedexEnabled())
+ {
+ return SpeciesToNationalPokedexNum(species);
+ }
+ else
+ {
+ species = SpeciesToHoennPokedexNum(species);
+ if (species <= 202)
+ return species;
+ return 0xFFFF;
+ }
+}
+
+bool32 sub_806E3F8(u16 species)
+{
+ if (SpeciesToHoennPokedexNum(species) > 202)
+ return FALSE;
+ else
+ return TRUE;
+}
+
+void ClearBattleMonForms(void)
+{
+ int i;
+ for (i = 0; i < 4; i++)
+ gBattleMonForms[i] = 0;
+}
+
+u16 GetBattleBGM(void)
+{
+ if (gBattleTypeFlags & BATTLE_TYPE_KYOGRE_GROUDON)
+ return MUS_BATTLE34;
+ if (gBattleTypeFlags & BATTLE_TYPE_REGI)
+ return MUS_BATTLE36;
+ if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000))
+ return MUS_BATTLE20;
+ if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
+ {
+ u8 trainerClass;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER)
+ trainerClass = GetFrontierOpponentClass(gTrainerBattleOpponent_A);
+ else if (gBattleTypeFlags & BATTLE_TYPE_x4000000)
+ trainerClass = TRAINER_CLASS_EXPERT;
+ else
+ trainerClass = gTrainers[gTrainerBattleOpponent_A].trainerClass;
+
+ switch (trainerClass)
+ {
+ case TRAINER_CLASS_AQUA_LEADER:
+ case TRAINER_CLASS_MAGMA_LEADER:
+ return MUS_BATTLE30;
+ case TRAINER_CLASS_TEAM_AQUA:
+ case TRAINER_CLASS_TEAM_MAGMA:
+ case TRAINER_CLASS_AQUA_ADMIN:
+ case TRAINER_CLASS_MAGMA_ADMIN:
+ return MUS_BATTLE31;
+ case TRAINER_CLASS_LEADER:
+ return MUS_BATTLE32;
+ case TRAINER_CLASS_CHAMPION:
+ return MUS_BATTLE33;
+ case TRAINER_CLASS_PKMN_TRAINER_3:
+ if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER)
+ return MUS_BATTLE35;
+ if (!StringCompare(gTrainers[gTrainerBattleOpponent_A].trainerName, gText_BattleWallyName))
+ return MUS_BATTLE20;
+ return MUS_BATTLE35;
+ case TRAINER_CLASS_ELITE_FOUR:
+ return MUS_BATTLE38;
+ case TRAINER_CLASS_SALON_MAIDEN:
+ case TRAINER_CLASS_DOME_ACE:
+ case TRAINER_CLASS_PALACE_MAVEN:
+ case TRAINER_CLASS_ARENA_TYCOON:
+ case TRAINER_CLASS_FACTORY_HEAD:
+ case TRAINER_CLASS_PIKE_QUEEN:
+ case TRAINER_CLASS_PYRAMID_KING:
+ return MUS_VS_FRONT;
+ default:
+ return MUS_BATTLE20;
+ }
+ }
+ return MUS_BATTLE27;
+}
+
+void PlayBattleBGM(void)
+{
+ ResetMapMusic();
+ m4aMPlayAllStop();
+ PlayBGM(GetBattleBGM());
+}
+
+void PlayMapChosenOrBattleBGM(u16 songId)
+{
+ ResetMapMusic();
+ m4aMPlayAllStop();
+ if (songId)
+ PlayNewMapMusic(songId);
+ else
+ PlayNewMapMusic(GetBattleBGM());
+}
+
+void sub_806E694(u16 songId)
+{
+ u8 taskId;
+
+ ResetMapMusic();
+ m4aMPlayAllStop();
+
+ taskId = CreateTask(sub_806E6CC, 0);
+ gTasks[taskId].data[0] = songId;
+}
+
+void sub_806E6CC(u8 taskId)
+{
+ if (gTasks[taskId].data[0])
+ PlayNewMapMusic(gTasks[taskId].data[0]);
+ else
+ PlayNewMapMusic(GetBattleBGM());
+ DestroyTask(taskId);
+}
+
+const u8 *GetMonFrontSpritePal(struct Pokemon *mon)
+{
+ u16 species = GetMonData(mon, MON_DATA_SPECIES2, 0);
+ u32 otId = GetMonData(mon, MON_DATA_OT_ID, 0);
+ u32 personality = GetMonData(mon, MON_DATA_PERSONALITY, 0);
+ return GetFrontSpritePalFromSpeciesAndPersonality(species, otId, personality);
+}
+
+// Extracts the upper 16 bits of a 32-bit number
+#define HIHALF(n) (((n) & 0xFFFF0000) >> 16)
+
+// Extracts the lower 16 bits of a 32-bit number
+#define LOHALF(n) ((n) & 0xFFFF)
+
+const u8 *GetFrontSpritePalFromSpeciesAndPersonality(u16 species, u32 otId, u32 personality)
+{
+ u32 shinyValue;
+
+ if (species > SPECIES_EGG)
+ return gMonPaletteTable[0].data;
+
+ shinyValue = HIHALF(otId) ^ LOHALF(otId) ^ HIHALF(personality) ^ LOHALF(personality);
+ if (shinyValue < 8)
+ return gMonShinyPaletteTable[species].data;
+ else
+ return gMonPaletteTable[species].data;
+}
+
+const struct CompressedSpritePalette *sub_806E794(struct Pokemon *mon)
+{
+ u16 species = GetMonData(mon, MON_DATA_SPECIES2, 0);
+ u32 otId = GetMonData(mon, MON_DATA_OT_ID, 0);
+ u32 personality = GetMonData(mon, MON_DATA_PERSONALITY, 0);
+ return GetMonSpritePalStructFromOtIdPersonality(species, otId, personality);
+}
+
+const struct CompressedSpritePalette *GetMonSpritePalStructFromOtIdPersonality(u16 species, u32 otId , u32 personality)
+{
+ u32 shinyValue;
+
+ shinyValue = HIHALF(otId) ^ LOHALF(otId) ^ HIHALF(personality) ^ LOHALF(personality);
+ if (shinyValue < 8)
+ return &gMonShinyPaletteTable[species];
+ else
+ return &gMonPaletteTable[species];
+}
+
+bool32 IsHMMove2(u16 move)
+{
+ int i = 0;
+ while (gHMMoves[i] != 0xFFFF)
+ {
+ if (gHMMoves[i++] == move)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 IsPokeSpriteNotFlipped(u16 species)
+{
+ return gBaseStats[species].noFlip;
+}
+
+s8 GetMonFlavorRelation(struct Pokemon *mon, u8 flavor)
+{
+ u8 nature = GetNature(mon);
+ return gPokeblockFlavorCompatibilityTable[nature * 5 + flavor];
+}
+
+s8 GetFlavorRelationByPersonality(u32 personality, u8 flavor)
+{
+ u8 nature = GetNatureFromPersonality(personality);
+ return gPokeblockFlavorCompatibilityTable[nature * 5 + flavor];
+}
+
+bool8 IsTradedMon(struct Pokemon *mon)
+{
+ u8 otName[OT_NAME_LENGTH + 1];
+ u32 otId;
+ GetMonData(mon, MON_DATA_OT_NAME, otName);
+ otId = GetMonData(mon, MON_DATA_OT_ID, 0);
+ return IsOtherTrainer(otId, otName);
+}
+
+bool8 IsOtherTrainer(u32 otId, u8 *otName)
+{
+ if (otId ==
+ (gSaveBlock2Ptr->playerTrainerId[0]
+ | (gSaveBlock2Ptr->playerTrainerId[1] << 8)
+ | (gSaveBlock2Ptr->playerTrainerId[2] << 16)
+ | (gSaveBlock2Ptr->playerTrainerId[3] << 24)))
+ {
+ int i;
+
+ for (i = 0; otName[i] != EOS; i++)
+ if (otName[i] != gSaveBlock2Ptr->playerName[i])
+ return TRUE;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void MonRestorePP(struct Pokemon *mon)
+{
+ BoxMonRestorePP(&mon->box);
+}
+
+void BoxMonRestorePP(struct BoxPokemon *boxMon)
+{
+ int i;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (GetBoxMonData(boxMon, MON_DATA_MOVE1 + i, 0))
+ {
+ u16 move = GetBoxMonData(boxMon, MON_DATA_MOVE1 + i, 0);
+ u16 bonus = GetBoxMonData(boxMon, MON_DATA_PP_BONUSES, 0);
+ u8 pp = CalculatePPWithBonus(move, bonus, i);
+ SetBoxMonData(boxMon, MON_DATA_PP1 + i, &pp);
+ }
+ }
+}
+
+void sub_806E994(void)
+{
+ gLastUsedAbility = gBattleStruct->field_B0;
+
+ gBattleTextBuff1[0] = B_BUFF_PLACEHOLDER_BEGIN;
+ gBattleTextBuff1[1] = B_BUFF_MON_NICK_WITH_PREFIX;
+ gBattleTextBuff1[2] = gBattleStruct->field_49;
+ gBattleTextBuff1[4] = B_BUFF_EOS;
+
+ if (!GetBattlerSide(gBattleStruct->field_49))
+ gBattleTextBuff1[3] = pokemon_order_func(gBattlerPartyIndexes[gBattleStruct->field_49]);
+ else
+ gBattleTextBuff1[3] = gBattlerPartyIndexes[gBattleStruct->field_49];
+
+ PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff2, gBankInMenu, pokemon_order_func(gBattlerPartyIndexes[gBankInMenu]))
+
+ BattleStringExpandPlaceholders(gText_PkmnsXPreventsSwitching, gStringVar4);
+}
+
+static s32 GetWildMonTableIdInAlteringCave(u16 species)
+{
+ s32 i;
+ for (i = 0; i < (s32) ARRAY_COUNT(gAlteringCaveWildMonHeldItems); i++)
+ if (gAlteringCaveWildMonHeldItems[i].species == species)
+ return i;
+ return 0;
+}
+
+void SetWildMonHeldItem(void)
+{
+ if (!(gBattleTypeFlags & (BATTLE_TYPE_LEGENDARY | BATTLE_TYPE_TRAINER | BATTLE_TYPE_PYRAMID | BATTLE_TYPE_PIKE)))
+ {
+ u16 rnd = Random() % 100;
+ u16 species = GetMonData(&gEnemyParty[0], MON_DATA_SPECIES, 0);
+ u16 var1 = 45;
+ u16 var2 = 95;
+ if (!GetMonData(&gPlayerParty[0], MON_DATA_SANITY_BIT3, 0)
+ && GetMonAbility(&gPlayerParty[0]) == ABILITY_COMPOUND_EYES)
+ {
+ var1 = 20;
+ var2 = 80;
+ }
+ if (gMapHeader.mapDataId == 0x1A4)
+ {
+ s32 alteringCaveId = GetWildMonTableIdInAlteringCave(species);
+ if (alteringCaveId != 0)
+ {
+ if (rnd < var2)
+ return;
+ SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gAlteringCaveWildMonHeldItems[alteringCaveId].item);
+ }
+ else
+ {
+ if (rnd < var1)
+ return;
+ if (rnd < var2)
+ SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gBaseStats[species].item1);
+ else
+ SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gBaseStats[species].item2);
+ }
+ }
+ else
+ {
+ if (gBaseStats[species].item1 == gBaseStats[species].item2 && gBaseStats[species].item1 != 0)
+ {
+ SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gBaseStats[species].item1);
+ }
+ else
+ {
+ if (rnd < var1)
+ return;
+ if (rnd < var2)
+ SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gBaseStats[species].item1);
+ else
+ SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gBaseStats[species].item2);
+ }
+ }
+ }
+}
+
+bool8 IsMonShiny(struct Pokemon *mon)
+{
+ u32 otId = GetMonData(mon, MON_DATA_OT_ID, 0);
+ u32 personality = GetMonData(mon, MON_DATA_PERSONALITY, 0);
+ return IsShinyOtIdPersonality(otId, personality);
+}
+
+bool8 IsShinyOtIdPersonality(u32 otId, u32 personality)
+{
+ bool8 retVal = FALSE;
+ u32 shinyValue = HIHALF(otId) ^ LOHALF(otId) ^ HIHALF(personality) ^ LOHALF(personality);
+ if (shinyValue < 8)
+ retVal = TRUE;
+ return retVal;
+}
+
+const u8 *GetTrainerPartnerName(void)
+{
+ if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
+ {
+ if (gPartnerTrainerId == STEVEN_PARTNER_ID)
+ {
+ return gTrainers[TRAINER_STEVEN].trainerName;
+ }
+ else
+ {
+ GetFrontierTrainerName(gStringVar1, gPartnerTrainerId);
+ return gStringVar1;
+ }
+ }
+ else
+ {
+ u8 id = GetMultiplayerId();
+ return gLinkPlayers[GetBattlerMultiplayerId(gLinkPlayers[id].lp_field_18 ^ 2)].name;
+ }
+}
+
+#define READ_PTR_FROM_TASK(taskId, dataId) \
+ (void*)( \
+ ((u16)(gTasks[taskId].data[dataId]) | \
+ ((u16)(gTasks[taskId].data[dataId + 1]) << 0x10)))
+
+#define STORE_PTR_IN_TASK(ptr, taskId, dataId) \
+{ \
+ gTasks[taskId].data[dataId] = (u32)(ptr); \
+ gTasks[taskId].data[dataId + 1] = (u32)(ptr) >> 0x10; \
+}
+
+static void Task_AnimateAfterDelay(u8 taskId)
+{
+ if (--gTasks[taskId].data[3] == 0)
+ {
+ LaunchAnimationTaskForFrontSprite(READ_PTR_FROM_TASK(taskId, 0), gTasks[taskId].data[2]);
+ DestroyTask(taskId);
+ }
+}
+
+static void Task_PokemonSummaryAnimateAfterDelay(u8 taskId)
+{
+ if (--gTasks[taskId].data[3] == 0)
+ {
+ StartMonSummaryAnimation(READ_PTR_FROM_TASK(taskId, 0), gTasks[taskId].data[2]);
+ sub_81C488C(0xFF);
+ DestroyTask(taskId);
+ }
+}
+
+void BattleAnimateFrontSprite(struct Sprite* sprite, u16 species, bool8 noCry, u8 arg3)
+{
+ if (gHitMarker & HITMARKER_NO_ANIMATIONS && !(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000)))
+ DoMonFrontSpriteAnimation(sprite, species, noCry, arg3 | 0x80);
+ else
+ DoMonFrontSpriteAnimation(sprite, species, noCry, arg3);
+}
+
+void DoMonFrontSpriteAnimation(struct Sprite* sprite, u16 species, bool8 noCry, u8 arg3)
+{
+ s8 pan;
+ switch (arg3 & 0x7F)
+ {
+ case 0:
+ pan = -25;
+ break;
+ case 1:
+ pan = 25;
+ break;
+ default:
+ pan = 0;
+ break;
+ }
+ if (arg3 & 0x80)
+ {
+ if (!noCry)
+ PlayCry1(species, pan);
+ sprite->callback = SpriteCallbackDummy;
+ }
+ else
+ {
+ if (!noCry)
+ {
+ PlayCry1(species, pan);
+ if (HasTwoFramesAnimation(species))
+ StartSpriteAnim(sprite, 1);
+ }
+ if (gMonAnimationDelayTable[species - 1] != 0)
+ {
+ u8 taskId = CreateTask(Task_AnimateAfterDelay, 0);
+ STORE_PTR_IN_TASK(sprite, taskId, 0);
+ gTasks[taskId].data[2] = gMonFrontAnimIdsTable[species - 1];
+ gTasks[taskId].data[3] = gMonAnimationDelayTable[species - 1];
+ }
+ else
+ {
+ LaunchAnimationTaskForFrontSprite(sprite, gMonFrontAnimIdsTable[species - 1]);
+ }
+ sprite->callback = SpriteCallbackDummy_2;
+ }
+}
+
+void PokemonSummaryDoMonAnimation(struct Sprite* sprite, u16 species, bool8 oneFrame)
+{
+ if (!oneFrame && HasTwoFramesAnimation(species))
+ StartSpriteAnim(sprite, 1);
+ if (gMonAnimationDelayTable[species - 1] != 0)
+ {
+ u8 taskId = CreateTask(Task_PokemonSummaryAnimateAfterDelay, 0);
+ STORE_PTR_IN_TASK(sprite, taskId, 0);
+ gTasks[taskId].data[2] = gMonFrontAnimIdsTable[species - 1];
+ gTasks[taskId].data[3] = gMonAnimationDelayTable[species - 1];
+ sub_81C488C(taskId);
+ SetSpriteCB_MonAnimDummy(sprite);
+ }
+ else
+ {
+ StartMonSummaryAnimation(sprite, gMonFrontAnimIdsTable[species - 1]);
+ }
+}
+
+void sub_806EE98(void)
+{
+ u8 delayTaskId = FindTaskIdByFunc(Task_PokemonSummaryAnimateAfterDelay);
+ if (delayTaskId != 0xFF)
+ DestroyTask(delayTaskId);
+}
+
+void BattleAnimateBackSprite(struct Sprite* sprite, u16 species)
+{
+ if (gHitMarker & HITMARKER_NO_ANIMATIONS && !(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000)))
+ {
+ sprite->callback = SpriteCallbackDummy;
+ }
+ else
+ {
+ LaunchAnimationTaskForBackSprite(sprite, GetSpeciesBackAnimSet(species));
+ sprite->callback = SpriteCallbackDummy_2;
+ }
+}
+u8 sub_806EF08(u8 arg0)
+{
+ s32 i;
+ s32 var = 0;
+ u8 multiplayerId = GetMultiplayerId();
+ switch (gLinkPlayers[multiplayerId].lp_field_18)
+ {
+ case 0:
+ case 2:
+ var = (arg0 != 0) ? 1 : 3;
+ break;
+ case 1:
+ case 3:
+ var = (arg0 != 0) ? 2 : 0;
+ break;
+ }
+ for (i = 0; i < 4; i++)
+ {
+ if (gLinkPlayers[i].lp_field_18 == (s16)(var))
+ break;
+ }
+ return i;
+}
+
+u8 sub_806EF84(u8 arg0, u8 arg1)
+{
+ s32 i;
+ s32 var = 0;
+ switch (gLinkPlayers[arg1].lp_field_18)
+ {
+ case 0:
+ case 2:
+ var = (arg0 != 0) ? 1 : 3;
+ break;
+ case 1:
+ case 3:
+ var = (arg0 != 0) ? 2 : 0;
+ break;
+ }
+ for (i = 0; i < 4; i++)
+ {
+ if (gLinkPlayers[i].lp_field_18 == (s16)(var))
+ break;
+ }
+ return i;
+}
+
+u16 sub_806EFF0(u16 arg0)
+{
+ return gFacilityClassToPicIndex[arg0];
+}
+
+u16 PlayerGenderToFrontTrainerPicId(u8 playerGender)
+{
+ if (playerGender)
+ return sub_806EFF0(0x3F);
+ else
+ return sub_806EFF0(0x3C);
+}
+
+void HandleSetPokedexFlag(u16 nationalNum, u8 caseId, u32 personality)
+{
+ u8 getFlagCaseId = (caseId == FLAG_SET_SEEN) ? FLAG_GET_SEEN : FLAG_GET_CAUGHT;
+ if (!GetSetPokedexFlag(nationalNum, getFlagCaseId)) // don't set if it's already set
+ {
+ GetSetPokedexFlag(nationalNum, caseId);
+ if (NationalPokedexNumToSpecies(nationalNum) == SPECIES_UNOWN)
+ gSaveBlock2Ptr->pokedex.unownPersonality = personality;
+ if (NationalPokedexNumToSpecies(nationalNum) == SPECIES_SPINDA)
+ gSaveBlock2Ptr->pokedex.spindaPersonality = personality;
+ }
+}
+
+const u8 *GetTrainerClassNameFromId(u16 trainerId)
+{
+ if (trainerId > NO_OF_TRAINERS)
+ trainerId = 0;
+ return gTrainerClassNames[gTrainers[trainerId].trainerClass];
+}
+
+const u8 *GetTrainerNameFromId(u16 trainerId)
+{
+ if (trainerId > NO_OF_TRAINERS)
+ trainerId = 0;
+ return gTrainers[trainerId].trainerName;
+}
+
+bool8 HasTwoFramesAnimation(u16 species)
+{
+ return (species != SPECIES_CASTFORM
+ && species != SPECIES_DEOXYS
+ && species != SPECIES_SPINDA
+ && species != SPECIES_UNOWN);
+}
+
+bool8 sub_806F104(void)
+{
+ if (gMain.inBattle && gBattleTypeFlags & (BATTLE_TYPE_FRONTIER))
+ return TRUE;
+ if (!gMain.inBattle && (InBattlePike() || InBattlePyramid()))
+ return TRUE;
+ return FALSE;
+}
+
+extern const struct SpriteTemplate gUnknown_08329D98[];
+extern const struct SpriteTemplate gUnknown_08329F28;
+
+void sub_806F160(struct Unknown_806F160_Struct* structPtr)
+{
+ s32 i;
+ u16 j;
+ for (i = 0; i < structPtr->field_0_0; i = (u16)(i + 1))
+ {
+ structPtr->templates[i] = gUnknown_08329D98[i];
+ for (j = 0; j < structPtr->field_1; j++)
+ {
+ asm("");
+ structPtr->frameImages[i * structPtr->field_1 + j].data = &structPtr->byteArrays[i][j * 0x800];
+ }
+ structPtr->templates[i].images = &structPtr->frameImages[i * structPtr->field_1];
+ }
+}
+
+void sub_806F1FC(struct Unknown_806F160_Struct* structPtr)
+{
+ s32 i;
+ u16 j;
+ for (i = 0; i < structPtr->field_0_0; i = (u16)(i + 1))
+ {
+ structPtr->templates[i] = gUnknown_08329F28;
+ for (j = 0; j < structPtr->field_1; j++)
+ {
+ structPtr->frameImages[i * structPtr->field_0_0 + j].data = &structPtr->byteArrays[i][j * 0x800];
+ }
+ structPtr->templates[i].images = &structPtr->frameImages[i * structPtr->field_0_0];
+ structPtr->templates[i].anims = gUnknown_082FF70C;
+ structPtr->templates[i].paletteTag = i;
+ }
+}
+
+struct Unknown_806F160_Struct *sub_806F2AC(u8 arg0, u8 arg1)
+{
+ u8 i;
+ u8 flags;
+ struct Unknown_806F160_Struct *structPtr;
+
+ flags = 0;
+ arg0 %= 2;
+ structPtr = AllocZeroed(sizeof(*structPtr));
+ if (structPtr == NULL)
+ return NULL;
+
+ switch (arg1)
+ {
+ case 2:
+ structPtr->field_0_0 = 7;
+ structPtr->field_0_1 = 7;
+ structPtr->field_1 = 4;
+ structPtr->field_3_0 = 1;
+ structPtr->field_3_1 = 2;
+ break;
+ case 0:
+ default:
+ structPtr->field_0_0 = 4;
+ structPtr->field_0_1 = 4;
+ structPtr->field_1 = 4;
+ structPtr->field_3_0 = 1;
+ structPtr->field_3_1 = 0;
+ break;
+ }
+
+ structPtr->bytes = AllocZeroed(structPtr->field_3_0 * structPtr->field_0_0);
+ structPtr->byteArrays = AllocZeroed(structPtr->field_0_0 * 32);
+ if (structPtr->bytes == NULL || structPtr->byteArrays == NULL)
+ {
+ flags |= 1;
+ }
+ else
+ {
+ for (i = 0; i < structPtr->field_0_0; i++)
+ structPtr->byteArrays[i] = structPtr->bytes + (structPtr->field_3_0 * (i << 0xD));
+ }
+
+ structPtr->templates = AllocZeroed(sizeof(struct SpriteTemplate) * structPtr->field_0_0);
+ structPtr->frameImages = AllocZeroed(sizeof(struct SpriteFrameImage) * structPtr->field_0_0 * structPtr->field_1);
+ if (structPtr->templates == NULL || structPtr->frameImages == NULL)
+ {
+ flags |= 2;
+ }
+ else
+ {
+ for (i = 0; i < structPtr->field_1 * structPtr->field_0_0; i++)
+ structPtr->frameImages[i].size = 0x800;
+
+ switch (structPtr->field_3_1)
+ {
+ case 2:
+ sub_806F1FC(structPtr);
+ break;
+ case 0:
+ case 1:
+ default:
+ sub_806F160(structPtr);
+ break;
+ }
+ }
+
+ if (flags & 2)
+ {
+ if (structPtr->frameImages != NULL)
+ FREE_AND_SET_NULL(structPtr->frameImages);
+ if (structPtr->templates != NULL)
+ FREE_AND_SET_NULL(structPtr->templates);
+ }
+ if (flags & 1)
+ {
+ if (structPtr->byteArrays != NULL)
+ FREE_AND_SET_NULL(structPtr->byteArrays);
+ if (structPtr->bytes != NULL)
+ FREE_AND_SET_NULL(structPtr->bytes);
+ }
+
+ if (flags)
+ {
+ memset(structPtr, 0, sizeof(*structPtr));
+ Free(structPtr);
+ }
+ else
+ {
+ structPtr->field_2 = 0xA3;
+ gUnknown_020249B4[arg0] = structPtr;
+ }
+
+ return gUnknown_020249B4[arg0];
+}
diff --git a/src/pokemon_3.c b/src/pokemon_3.c
deleted file mode 100644
index 95d08d0c5..000000000
--- a/src/pokemon_3.c
+++ /dev/null
@@ -1,1746 +0,0 @@
-#include "global.h"
-#include "pokemon.h"
-#include "main.h"
-#include "constants/items.h"
-#include "string_util.h"
-#include "battle_message.h"
-#include "rtc.h"
-#include "item.h"
-#include "battle.h"
-#include "constants/species.h"
-#include "link.h"
-#include "constants/hold_effects.h"
-#include "random.h"
-#include "constants/trainers.h"
-#include "constants/songs.h"
-#include "sound.h"
-#include "m4a.h"
-#include "task.h"
-#include "sprite.h"
-#include "text.h"
-#include "constants/abilities.h"
-#include "pokemon_animation.h"
-#include "pokedex.h"
-#include "pokeblock.h"
-
-extern struct BattlePokemon gBattleMons[4];
-extern struct BattleEnigmaBerry gEnigmaBerries[4];
-extern u8 gActiveBattler;
-extern u8 gBankInMenu;
-extern u8 gBattlerTarget;
-extern u8 gBattlerAttacker;
-extern u8 gStringBattler;
-extern u16 gTrainerBattleOpponent_A;
-extern u32 gBattleTypeFlags;
-extern u8 gBattleMonForms[4];
-extern u16 gBattlerPartyIndexes[4];
-extern u8 gLastUsedAbility;
-extern u16 gPartnerTrainerId;
-extern u32 gHitMarker;
-
-extern const u16 gSpeciesToHoennPokedexNum[];
-extern const u16 gSpeciesToNationalPokedexNum[];
-extern const u16 gHoennToNationalOrder[];
-extern const u16 gSpeciesIdToCryId[];
-extern const struct SpindaSpot gSpindaSpotGraphics[];
-extern const u8* const gStatNamesTable[];
-extern const u8 gSpeciesNames[][11];
-extern const u8 gUnknown_08329EC8[];
-extern const u8 gText_StatRose[];
-extern const u8 gText_PkmnsStatChanged2[];
-extern const u8 gText_PkmnGettingPumped[];
-extern const u8 gText_PkmnShroudedInMist[];
-extern const s8 gNatureStatTable[][5];
-extern const s8 gUnknown_08329ECE[][3];
-extern const u32 gBitTable[];
-extern const u32 gTMHMLearnsets[][2];
-extern const u8 gText_BattleWallyName[];
-extern const u8 gText_PkmnsXPreventsSwitching[];
-extern const struct CompressedSpritePalette gMonPaletteTable[];
-extern const struct CompressedSpritePalette gMonShinyPaletteTable[];
-extern const u16 gHMMoves[];
-extern const u8 gMonAnimationDelayTable[];
-extern const u8 gMonFrontAnimIdsTable[];
-extern const u8 gFacilityClassToPicIndex[];
-extern const u8 gTrainerClassNames[][13];
-
-struct PokeItem
-{
- u16 species;
- u16 item;
-};
-
-extern const struct PokeItem gAlteringCaveWildMonHeldItems[9];
-
-extern void SpriteCallbackDummy_2(struct Sprite*);
-extern bool8 InBattlePyramid(void);
-extern bool8 InBattlePike(void);
-extern bool8 sub_81D5C18(void);
-extern bool8 sub_806F104(void);
-extern bool32 IsNationalPokedexEnabled(void);
-extern u8 GetTrainerEncounterMusicIdInBattlePyramind(u16 trainerOpponentId);
-extern u8 sub_81D63C8(u16 trainerOpponentId);
-extern u8 sav1_map_get_name(void);
-extern u8 GetFrontierOpponentClass(u16 trainerId);
-extern u8 pokemon_order_func(u8 bankPartyId);
-extern void GetFrontierTrainerName(u8* dest, u16 trainerId);
-extern void sub_81C488C(u8);
-
-static void sub_806E6CC(u8 taskId);
-
-bool8 HealStatusConditions(struct Pokemon *mon, u32 battlePartyId, u32 healMask, u8 battleBank)
-{
- u32 status = GetMonData(mon, MON_DATA_STATUS, 0);
-
- if (status & healMask)
- {
- status &= ~healMask;
- SetMonData(mon, MON_DATA_STATUS, &status);
- if (gMain.inBattle && battleBank != 4)
- gBattleMons[battleBank].status1 &= ~healMask;
- return FALSE;
- }
- else
- {
- return TRUE;
- }
-}
-
-u8 GetItemEffectParamOffset(u16 itemId, u8 effectByte, u8 effectBit)
-{
- const u8 *temp;
- const 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[gActiveBattler].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_806CF24(s32 stat)
-{
- gBattlerTarget = gBankInMenu;
- StringCopy(gBattleTextBuff1, gStatNamesTable[gUnknown_08329EC8[stat]]);
- StringCopy(gBattleTextBuff2, gText_StatRose);
- BattleStringExpandPlaceholdersToDisplayedString(gText_PkmnsStatChanged2);
-}
-
-u8 *sub_806CF78(u16 itemId)
-{
- int i;
- const u8 *itemEffect;
-
- if (itemId == ITEM_ENIGMA_BERRY)
- {
- if (gMain.inBattle)
- itemEffect = gEnigmaBerries[gBankInMenu].itemEffect;
- else
- itemEffect = gSaveBlock1Ptr->enigmaBerry.itemEffect;
- }
- else
- {
- itemEffect = gItemEffectTable[itemId - 13];
- }
-
- gStringBattler = gBankInMenu;
-
- for (i = 0; i < 3; i++)
- {
- if (itemEffect[i] & 0xF)
- sub_806CF24(i * 2);
- if (itemEffect[i] & 0xF0)
- {
- if (i)
- {
- sub_806CF24(i * 2 + 1);
- }
- else
- {
- gBattlerAttacker = gBankInMenu;
- BattleStringExpandPlaceholdersToDisplayedString(gText_PkmnGettingPumped);
- }
- }
- }
-
- if (itemEffect[3] & 0x80)
- {
- gBattlerAttacker = gBankInMenu;
- BattleStringExpandPlaceholdersToDisplayedString(gText_PkmnShroudedInMist);
- }
-
- return gDisplayedStringBattle;
-}
-
-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 = gSaveBlock1Ptr->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][i].method)
- {
- case EVO_FRIENDSHIP:
- if (friendship >= 220)
- targetSpecies = gEvolutionTable[species][i].targetSpecies;
- break;
- case EVO_FRIENDSHIP_DAY:
- RtcCalcLocalTime();
- if (gLocalTime.hours >= 12 && gLocalTime.hours < 24 && friendship >= 220)
- targetSpecies = gEvolutionTable[species][i].targetSpecies;
- break;
- case EVO_FRIENDSHIP_NIGHT:
- RtcCalcLocalTime();
- if (gLocalTime.hours >= 0 && gLocalTime.hours < 12 && friendship >= 220)
- targetSpecies = gEvolutionTable[species][i].targetSpecies;
- break;
- case EVO_LEVEL:
- if (gEvolutionTable[species][i].param <= level)
- targetSpecies = gEvolutionTable[species][i].targetSpecies;
- break;
- case EVO_LEVEL_ATK_GT_DEF:
- if (gEvolutionTable[species][i].param <= level)
- if (GetMonData(mon, MON_DATA_ATK, 0) > GetMonData(mon, MON_DATA_DEF, 0))
- targetSpecies = gEvolutionTable[species][i].targetSpecies;
- break;
- case EVO_LEVEL_ATK_EQ_DEF:
- if (gEvolutionTable[species][i].param <= level)
- if (GetMonData(mon, MON_DATA_ATK, 0) == GetMonData(mon, MON_DATA_DEF, 0))
- targetSpecies = gEvolutionTable[species][i].targetSpecies;
- break;
- case EVO_LEVEL_ATK_LT_DEF:
- if (gEvolutionTable[species][i].param <= level)
- if (GetMonData(mon, MON_DATA_ATK, 0) < GetMonData(mon, MON_DATA_DEF, 0))
- targetSpecies = gEvolutionTable[species][i].targetSpecies;
- break;
- case EVO_LEVEL_SILCOON:
- if (gEvolutionTable[species][i].param <= level && (upperPersonality % 10) <= 4)
- targetSpecies = gEvolutionTable[species][i].targetSpecies;
- break;
- case EVO_LEVEL_CASCOON:
- if (gEvolutionTable[species][i].param <= level && (upperPersonality % 10) > 4)
- targetSpecies = gEvolutionTable[species][i].targetSpecies;
- break;
- case EVO_LEVEL_NINJASK:
- if (gEvolutionTable[species][i].param <= level)
- targetSpecies = gEvolutionTable[species][i].targetSpecies;
- break;
- case EVO_BEAUTY:
- if (gEvolutionTable[species][i].param <= beauty)
- targetSpecies = gEvolutionTable[species][i].targetSpecies;
- break;
- }
- }
- break;
- case 1:
- for (i = 0; i < 5; i++)
- {
- switch (gEvolutionTable[species][i].method)
- {
- case EVO_TRADE:
- targetSpecies = gEvolutionTable[species][i].targetSpecies;
- break;
- case EVO_TRADE_ITEM:
- if (gEvolutionTable[species][i].param == heldItem)
- {
- heldItem = 0;
- SetMonData(mon, MON_DATA_HELD_ITEM, (u8 *)&heldItem);
- targetSpecies = gEvolutionTable[species][i].targetSpecies;
- }
- break;
- }
- }
- break;
- case 2:
- case 3:
- for (i = 0; i < 5; i++)
- {
- if (gEvolutionTable[species][i].method == EVO_ITEM
- && gEvolutionTable[species][i].param == evolutionItem)
- {
- targetSpecies = gEvolutionTable[species][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];
-}
-
-u16 SpeciesToCryId(u16 species)
-{
- if (species <= 250)
- return species;
-
- if (species < 276)
- return 200;
-
- return gSpeciesIdToCryId[species - 276];
-}
-
-void sub_806D544(u16 species, u32 personality, u8 *dest)
-{
- if (species == SPECIES_SPINDA
- && dest != gMonSpritesGfxPtr->sprites[0]
- && dest != gMonSpritesGfxPtr->sprites[2])
- {
- int i;
- for (i = 0; i < 4; i++)
- {
- int j;
- u8 x = gSpindaSpotGraphics[i].x + ((personality & 0x0F) - 8);
- u8 y = gSpindaSpotGraphics[i].y + (((personality & 0xF0) >> 4) - 8);
-
- for (j = 0; j < 16; j++)
- {
- int k;
- s32 row = gSpindaSpotGraphics[i].image[j];
-
- for (k = x; k < x + 16; k++)
- {
- u8 *val = dest + ((k / 8) * 32) + ((k % 8) / 2) + ((y >> 3) << 8) + ((y & 7) << 2);
-
- if (row & 1)
- {
- if (k & 1)
- {
- if ((u8)((*val & 0xF0) - 0x10) <= 0x20)
- *val += 0x40;
- }
- else
- {
- if ((u8)((*val & 0xF) - 0x01) <= 0x02)
- *val += 0x04;
- }
- }
-
- row >>= 1;
- }
-
- y++;
- }
-
- personality >>= 8;
- }
- }
-}
-
-void DrawSpindaSpots(u16 species, u32 personality, u8 *dest, u8 a4)
-{
- if (species == SPECIES_SPINDA && a4)
- {
- int i;
- for (i = 0; i < 4; i++)
- {
- int j;
- u8 x = gSpindaSpotGraphics[i].x + ((personality & 0x0F) - 8);
- u8 y = gSpindaSpotGraphics[i].y + (((personality & 0xF0) >> 4) - 8);
-
- for (j = 0; j < 16; j++)
- {
- int k;
- s32 row = gSpindaSpotGraphics[i].image[j];
-
- for (k = x; k < x + 16; k++)
- {
- u8 *val = dest + ((k / 8) * 32) + ((k % 8) / 2) + ((y >> 3) << 8) + ((y & 7) << 2);
-
- if (row & 1)
- {
- if (k & 1)
- {
- if ((u8)((*val & 0xF0) - 0x10) <= 0x20)
- *val += 0x40;
- }
- else
- {
- if ((u8)((*val & 0xF) - 0x01) <= 0x02)
- *val += 0x04;
- }
- }
-
- row >>= 1;
- }
-
- y++;
- }
-
- personality >>= 8;
- }
- }
-}
-
-void EvolutionRenameMon(struct Pokemon *mon, u16 oldSpecies, u16 newSpecies)
-{
- u8 language;
- GetMonData(mon, MON_DATA_NICKNAME, gStringVar1);
- language = GetMonData(mon, MON_DATA_LANGUAGE, &language);
- if (language == GAME_LANGUAGE && !StringCompare(gSpeciesNames[oldSpecies], gStringVar1))
- SetMonData(mon, MON_DATA_NICKNAME, gSpeciesNames[newSpecies]);
-}
-
-bool8 sub_806D7EC(void)
-{
- bool8 retVal = FALSE;
- switch (gLinkPlayers[GetMultiplayerId()].lp_field_18)
- {
- case 0:
- case 3:
- retVal = FALSE;
- break;
- case 1:
- case 2:
- retVal = TRUE;
- break;
- }
- return retVal;
-}
-
-bool16 sub_806D82C(u8 id)
-{
- bool16 retVal = FALSE;
- switch (gLinkPlayers[id].lp_field_18)
- {
- case 0:
- case 3:
- retVal = FALSE;
- break;
- case 1:
- case 2:
- retVal = TRUE;
- break;
- }
- return retVal;
-}
-
-s32 GetBattlerMultiplayerId(u16 a1)
-{
- s32 id;
- for (id = 0; id < MAX_LINK_PLAYERS; id++)
- if (gLinkPlayers[id].lp_field_18 == a1)
- break;
- return id;
-}
-
-u8 GetTrainerEncounterMusicId(u16 trainerOpponentId)
-{
- if (InBattlePyramid())
- return GetTrainerEncounterMusicIdInBattlePyramind(trainerOpponentId);
- if (sub_81D5C18())
- return sub_81D63C8(trainerOpponentId);
- return TRAINER_ENCOUNTER_MUSIC(trainerOpponentId);
-}
-
-u16 ModifyStatByNature(u8 nature, u16 n, u8 statIndex)
-{
- if (statIndex < 1 || statIndex > 5)
- {
- // should just be "return n", but it wouldn't match without this
- u16 retVal = n;
- retVal++;
- retVal--;
- return retVal;
- }
-
- switch (gNatureStatTable[nature][statIndex - 1])
- {
- case 1:
- return (u16)(n * 110) / 100;
- case -1:
- return (u16)(n * 90) / 100;
- }
-
- return n;
-}
-
-void AdjustFriendship(struct Pokemon *mon, u8 event)
-{
- u16 species, heldItem;
- u8 holdEffect;
-
- if (sub_806F104())
- return;
-
- species = GetMonData(mon, MON_DATA_SPECIES2, 0);
- heldItem = GetMonData(mon, MON_DATA_HELD_ITEM, 0);
-
- if (heldItem == ITEM_ENIGMA_BERRY)
- {
- if (gMain.inBattle)
- holdEffect = gEnigmaBerries[0].holdEffect;
- else
- holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect;
- }
- else
- {
- holdEffect = ItemId_GetHoldEffect(heldItem);
- }
-
- if (species && species != SPECIES_EGG)
- {
- u8 friendshipLevel = 0;
- s16 friendship = GetMonData(mon, MON_DATA_FRIENDSHIP, 0);
- if (friendship > 99)
- friendshipLevel++;
- if (friendship > 199)
- friendshipLevel++;
- if ((event != 5 || !(Random() & 1))
- && (event != 3
- || ((gBattleTypeFlags & BATTLE_TYPE_TRAINER)
- && (gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_ELITE_FOUR
- || gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_LEADER
- || gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_CHAMPION))))
- {
- s8 mod = gUnknown_08329ECE[event][friendshipLevel];
- if (mod > 0 && holdEffect == HOLD_EFFECT_HAPPINESS_UP)
- mod = (150 * mod) / 100;
- friendship += mod;
- if (mod > 0)
- {
- if (GetMonData(mon, MON_DATA_POKEBALL, 0) == ITEM_LUXURY_BALL)
- friendship++;
- if (GetMonData(mon, MON_DATA_MET_LOCATION, 0) == sav1_map_get_name())
- friendship++;
- }
- if (friendship < 0)
- friendship = 0;
- if (friendship > 255)
- friendship = 255;
- SetMonData(mon, MON_DATA_FRIENDSHIP, &friendship);
- }
- }
-}
-
-void MonGainEVs(struct Pokemon *mon, u16 defeatedSpecies)
-{
- u8 evs[NUM_STATS];
- u16 evIncrease = 0;
- u16 totalEVs = 0;
- u16 heldItem;
- u8 holdEffect;
- int i;
-
- for (i = 0; i < NUM_STATS; i++)
- {
- evs[i] = GetMonData(mon, MON_DATA_HP_EV + i, 0);
- totalEVs += evs[i];
- }
-
- for (i = 0; i < NUM_STATS; i++)
- {
- u8 hasHadPokerus;
- int multiplier;
-
- if (totalEVs >= MAX_TOTAL_EVS)
- break;
-
- hasHadPokerus = CheckPartyHasHadPokerus(mon, 0);
-
- if (hasHadPokerus)
- multiplier = 2;
- else
- multiplier = 1;
-
- switch (i)
- {
- case 0:
- evIncrease = gBaseStats[defeatedSpecies].evYield_HP * multiplier;
- break;
- case 1:
- evIncrease = gBaseStats[defeatedSpecies].evYield_Attack * multiplier;
- break;
- case 2:
- evIncrease = gBaseStats[defeatedSpecies].evYield_Defense * multiplier;
- break;
- case 3:
- evIncrease = gBaseStats[defeatedSpecies].evYield_Speed * multiplier;
- break;
- case 4:
- evIncrease = gBaseStats[defeatedSpecies].evYield_SpAttack * multiplier;
- break;
- case 5:
- evIncrease = gBaseStats[defeatedSpecies].evYield_SpDefense * multiplier;
- break;
- }
-
- heldItem = GetMonData(mon, MON_DATA_HELD_ITEM, 0);
-
- if (heldItem == ITEM_ENIGMA_BERRY)
- {
- if (gMain.inBattle)
- holdEffect = gEnigmaBerries[0].holdEffect;
- else
- holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect;
- }
- else
- {
- holdEffect = ItemId_GetHoldEffect(heldItem);
- }
-
- if (holdEffect == HOLD_EFFECT_MACHO_BRACE)
- evIncrease *= 2;
-
- if (totalEVs + (s16)evIncrease > MAX_TOTAL_EVS)
- evIncrease = ((s16)evIncrease + MAX_TOTAL_EVS) - (totalEVs + evIncrease);
-
- if (evs[i] + (s16)evIncrease > 255)
- {
- int val1 = (s16)evIncrease + 255;
- int val2 = evs[i] + evIncrease;
- evIncrease = val1 - val2;
- }
-
- evs[i] += evIncrease;
- totalEVs += evIncrease;
- SetMonData(mon, MON_DATA_HP_EV + i, &evs[i]);
- }
-}
-
-u16 GetMonEVCount(struct Pokemon *mon)
-{
- int i;
- u16 count = 0;
-
- for (i = 0; i < NUM_STATS; i++)
- count += GetMonData(mon, MON_DATA_HP_EV + i, 0);
-
- return count;
-}
-
-void RandomlyGivePartyPokerus(struct Pokemon *party)
-{
- u16 rnd = Random();
- if (rnd == 0x4000 || rnd == 0x8000 || rnd == 0xC000)
- {
- struct Pokemon *mon;
-
- do
- {
- do
- {
- rnd = Random() % PARTY_SIZE;
- mon = &party[rnd];
- }
- while (!GetMonData(mon, MON_DATA_SPECIES, 0));
- }
- while (GetMonData(mon, MON_DATA_IS_EGG, 0));
-
- if (!(CheckPartyHasHadPokerus(party, gBitTable[rnd])))
- {
- u8 rnd2;
-
- do
- {
- rnd2 = Random();
- }
- while ((rnd2 & 0x7) == 0);
-
- if (rnd2 & 0xF0)
- rnd2 &= 0x7;
-
- rnd2 |= (rnd2 << 4);
- rnd2 &= 0xF3;
- rnd2++;
-
- SetMonData(&party[rnd], MON_DATA_POKERUS, &rnd2);
- }
- }
-}
-
-u8 CheckPartyPokerus(struct Pokemon *party, u8 selection)
-{
- u8 retVal;
-
- int partyIndex = 0;
- unsigned curBit = 1;
- retVal = 0;
-
- if (selection)
- {
- do
- {
- if ((selection & 1) && (GetMonData(&party[partyIndex], MON_DATA_POKERUS, 0) & 0xF))
- retVal |= curBit;
- partyIndex++;
- curBit <<= 1;
- selection >>= 1;
- }
- while (selection);
- }
- else if (GetMonData(&party[0], MON_DATA_POKERUS, 0) & 0xF)
- {
- retVal = 1;
- }
-
- return retVal;
-}
-
-u8 CheckPartyHasHadPokerus(struct Pokemon *party, u8 selection)
-{
- u8 retVal;
-
- int partyIndex = 0;
- unsigned curBit = 1;
- retVal = 0;
-
- if (selection)
- {
- do
- {
- if ((selection & 1) && GetMonData(&party[partyIndex], MON_DATA_POKERUS, 0))
- retVal |= curBit;
- partyIndex++;
- curBit <<= 1;
- selection >>= 1;
- }
- while (selection);
- }
- else if (GetMonData(&party[0], MON_DATA_POKERUS, 0))
- {
- retVal = 1;
- }
-
- return retVal;
-}
-
-void UpdatePartyPokerusTime(u16 days)
-{
- int i;
- for (i = 0; i < PARTY_SIZE; i++)
- {
- if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES, 0))
- {
- u8 pokerus = GetMonData(&gPlayerParty[i], MON_DATA_POKERUS, 0);
- if (pokerus & 0xF)
- {
- if ((pokerus & 0xF) < days || days > 4)
- pokerus &= 0xF0;
- else
- pokerus -= days;
-
- if (pokerus == 0)
- pokerus = 0x10;
-
- SetMonData(&gPlayerParty[i], MON_DATA_POKERUS, &pokerus);
- }
- }
- }
-}
-
-void PartySpreadPokerus(struct Pokemon *party)
-{
- if ((Random() % 3) == 0)
- {
- int i;
- for (i = 0; i < PARTY_SIZE; i++)
- {
- if (GetMonData(&party[i], MON_DATA_SPECIES, 0))
- {
- u8 pokerus = GetMonData(&party[i], MON_DATA_POKERUS, 0);
- u8 curPokerus = pokerus;
- if (pokerus)
- {
- if (pokerus & 0xF)
- {
- // spread to adjacent party members
- if (i != 0 && !(GetMonData(&party[i - 1], MON_DATA_POKERUS, 0) & 0xF0))
- SetMonData(&party[i - 1], MON_DATA_POKERUS, &curPokerus);
- if (i != (PARTY_SIZE - 1) && !(GetMonData(&party[i + 1], MON_DATA_POKERUS, 0) & 0xF0))
- {
- SetMonData(&party[i + 1], MON_DATA_POKERUS, &curPokerus);
- i++;
- }
- }
- }
- }
- }
- }
-}
-
-bool8 TryIncrementMonLevel(struct Pokemon *mon)
-{
- u16 species = GetMonData(mon, MON_DATA_SPECIES, 0);
- u8 nextLevel = GetMonData(mon, MON_DATA_LEVEL, 0) + 1;
- u32 expPoints = GetMonData(mon, MON_DATA_EXP, 0);
- if (expPoints > gExperienceTables[gBaseStats[species].growthRate][MAX_MON_LEVEL])
- {
- expPoints = gExperienceTables[gBaseStats[species].growthRate][MAX_MON_LEVEL];
- SetMonData(mon, MON_DATA_EXP, &expPoints);
- }
- if (nextLevel > MAX_MON_LEVEL || expPoints < gExperienceTables[gBaseStats[species].growthRate][nextLevel])
- {
- return FALSE;
- }
- else
- {
- SetMonData(mon, MON_DATA_LEVEL, &nextLevel);
- return TRUE;
- }
-}
-
-u32 CanMonLearnTMHM(struct Pokemon *mon, u8 tm)
-{
- u16 species = GetMonData(mon, MON_DATA_SPECIES2, 0);
- if (species == SPECIES_EGG)
- {
- return 0;
- }
- else if (tm < 32)
- {
- u32 mask = 1 << tm;
- return gTMHMLearnsets[species][0] & mask;
- }
- else
- {
- u32 mask = 1 << (tm - 32);
- return gTMHMLearnsets[species][1] & mask;
- }
-}
-
-u32 CanSpeciesLearnTMHM(u16 species, u8 tm)
-{
- if (species == SPECIES_EGG)
- {
- return 0;
- }
- else if (tm < 32)
- {
- u32 mask = 1 << tm;
- return gTMHMLearnsets[species][0] & mask;
- }
- else
- {
- u32 mask = 1 << (tm - 32);
- return gTMHMLearnsets[species][1] & mask;
- }
-}
-
-u8 GetMoveRelearnerMoves(struct Pokemon *mon, u16 *moves)
-{
- u16 learnedMoves[4];
- u8 numMoves = 0;
- u16 species = GetMonData(mon, MON_DATA_SPECIES, 0);
- u8 level = GetMonData(mon, MON_DATA_LEVEL, 0);
- int i, j, k;
-
- for (i = 0; i < 4; i++)
- learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0);
-
- for (i = 0; i < 20; i++)
- {
- u16 moveLevel;
-
- if (gLevelUpLearnsets[species][i] == 0xFFFF)
- break;
-
- moveLevel = gLevelUpLearnsets[species][i] & 0xFE00;
-
- if (moveLevel <= (level << 9))
- {
- for (j = 0; j < 4 && learnedMoves[j] != (gLevelUpLearnsets[species][i] & 0x1FF); j++)
- ;
-
- if (j == 4)
- {
- for (k = 0; k < numMoves && moves[k] != (gLevelUpLearnsets[species][i] & 0x1FF); k++)
- ;
-
- if (k == numMoves)
- moves[numMoves++] = gLevelUpLearnsets[species][i] & 0x1FF;
- }
- }
- }
-
- return numMoves;
-}
-
-u8 GetLevelUpMovesBySpecies(u16 species, u16 *moves)
-{
- u8 numMoves = 0;
- int i;
-
- for (i = 0; i < 20 && gLevelUpLearnsets[species][i] != 0xFFFF; i++)
- moves[numMoves++] = gLevelUpLearnsets[species][i] & 0x1FF;
-
- return numMoves;
-}
-
-u8 GetNumberOfRelearnableMoves(struct Pokemon *mon)
-{
- u16 learnedMoves[4];
- u16 moves[20];
- u8 numMoves = 0;
- u16 species = GetMonData(mon, MON_DATA_SPECIES2, 0);
- u8 level = GetMonData(mon, MON_DATA_LEVEL, 0);
- int i, j, k;
-
- if (species == SPECIES_EGG)
- return 0;
-
- for (i = 0; i < 4; i++)
- learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0);
-
- for (i = 0; i < 20; i++)
- {
- u16 moveLevel;
-
- if (gLevelUpLearnsets[species][i] == 0xFFFF)
- break;
-
- moveLevel = gLevelUpLearnsets[species][i] & 0xFE00;
-
- if (moveLevel <= (level << 9))
- {
- for (j = 0; j < 4 && learnedMoves[j] != (gLevelUpLearnsets[species][i] & 0x1FF); j++)
- ;
-
- if (j == 4)
- {
- for (k = 0; k < numMoves && moves[k] != (gLevelUpLearnsets[species][i] & 0x1FF); k++)
- ;
-
- if (k == numMoves)
- moves[numMoves++] = gLevelUpLearnsets[species][i] & 0x1FF;
- }
- }
- }
-
- return numMoves;
-}
-
-u16 SpeciesToPokedexNum(u16 species)
-{
- if (IsNationalPokedexEnabled())
- {
- return SpeciesToNationalPokedexNum(species);
- }
- else
- {
- species = SpeciesToHoennPokedexNum(species);
- if (species <= 202)
- return species;
- return 0xFFFF;
- }
-}
-
-bool32 sub_806E3F8(u16 species)
-{
- if (SpeciesToHoennPokedexNum(species) > 202)
- return FALSE;
- else
- return TRUE;
-}
-
-void ClearBattleMonForms(void)
-{
- int i;
- for (i = 0; i < 4; i++)
- gBattleMonForms[i] = 0;
-}
-
-u16 GetBattleBGM(void)
-{
- if (gBattleTypeFlags & BATTLE_TYPE_KYOGRE_GROUDON)
- return MUS_BATTLE34;
- if (gBattleTypeFlags & BATTLE_TYPE_REGI)
- return MUS_BATTLE36;
- if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000))
- return MUS_BATTLE20;
- if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
- {
- u8 trainerClass;
-
- if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER)
- trainerClass = GetFrontierOpponentClass(gTrainerBattleOpponent_A);
- else if (gBattleTypeFlags & BATTLE_TYPE_x4000000)
- trainerClass = TRAINER_CLASS_EXPERT;
- else
- trainerClass = gTrainers[gTrainerBattleOpponent_A].trainerClass;
-
- switch (trainerClass)
- {
- case TRAINER_CLASS_AQUA_LEADER:
- case TRAINER_CLASS_MAGMA_LEADER:
- return MUS_BATTLE30;
- case TRAINER_CLASS_TEAM_AQUA:
- case TRAINER_CLASS_TEAM_MAGMA:
- case TRAINER_CLASS_AQUA_ADMIN:
- case TRAINER_CLASS_MAGMA_ADMIN:
- return MUS_BATTLE31;
- case TRAINER_CLASS_LEADER:
- return MUS_BATTLE32;
- case TRAINER_CLASS_CHAMPION:
- return MUS_BATTLE33;
- case TRAINER_CLASS_PKMN_TRAINER_3:
- if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER)
- return MUS_BATTLE35;
- if (!StringCompare(gTrainers[gTrainerBattleOpponent_A].trainerName, gText_BattleWallyName))
- return MUS_BATTLE20;
- return MUS_BATTLE35;
- case TRAINER_CLASS_ELITE_FOUR:
- return MUS_BATTLE38;
- case TRAINER_CLASS_SALON_MAIDEN:
- case TRAINER_CLASS_DOME_ACE:
- case TRAINER_CLASS_PALACE_MAVEN:
- case TRAINER_CLASS_ARENA_TYCOON:
- case TRAINER_CLASS_FACTORY_HEAD:
- case TRAINER_CLASS_PIKE_QUEEN:
- case TRAINER_CLASS_PYRAMID_KING:
- return MUS_VS_FRONT;
- default:
- return MUS_BATTLE20;
- }
- }
- return MUS_BATTLE27;
-}
-
-void PlayBattleBGM(void)
-{
- ResetMapMusic();
- m4aMPlayAllStop();
- PlayBGM(GetBattleBGM());
-}
-
-void PlayMapChosenOrBattleBGM(u16 songId)
-{
- ResetMapMusic();
- m4aMPlayAllStop();
- if (songId)
- PlayNewMapMusic(songId);
- else
- PlayNewMapMusic(GetBattleBGM());
-}
-
-void sub_806E694(u16 songId)
-{
- u8 taskId;
-
- ResetMapMusic();
- m4aMPlayAllStop();
-
- taskId = CreateTask(sub_806E6CC, 0);
- gTasks[taskId].data[0] = songId;
-}
-
-static void sub_806E6CC(u8 taskId)
-{
- if (gTasks[taskId].data[0])
- PlayNewMapMusic(gTasks[taskId].data[0]);
- else
- PlayNewMapMusic(GetBattleBGM());
- DestroyTask(taskId);
-}
-
-const u8 *GetMonFrontSpritePal(struct Pokemon *mon)
-{
- u16 species = GetMonData(mon, MON_DATA_SPECIES2, 0);
- u32 otId = GetMonData(mon, MON_DATA_OT_ID, 0);
- u32 personality = GetMonData(mon, MON_DATA_PERSONALITY, 0);
- return GetFrontSpritePalFromSpeciesAndPersonality(species, otId, personality);
-}
-
-// Extracts the upper 16 bits of a 32-bit number
-#define HIHALF(n) (((n) & 0xFFFF0000) >> 16)
-
-// Extracts the lower 16 bits of a 32-bit number
-#define LOHALF(n) ((n) & 0xFFFF)
-
-const u8 *GetFrontSpritePalFromSpeciesAndPersonality(u16 species, u32 otId, u32 personality)
-{
- u32 shinyValue;
-
- if (species > SPECIES_EGG)
- return gMonPaletteTable[0].data;
-
- shinyValue = HIHALF(otId) ^ LOHALF(otId) ^ HIHALF(personality) ^ LOHALF(personality);
- if (shinyValue < 8)
- return gMonShinyPaletteTable[species].data;
- else
- return gMonPaletteTable[species].data;
-}
-
-const struct CompressedSpritePalette *sub_806E794(struct Pokemon *mon)
-{
- u16 species = GetMonData(mon, MON_DATA_SPECIES2, 0);
- u32 otId = GetMonData(mon, MON_DATA_OT_ID, 0);
- u32 personality = GetMonData(mon, MON_DATA_PERSONALITY, 0);
- return GetMonSpritePalStructFromOtIdPersonality(species, otId, personality);
-}
-
-const struct CompressedSpritePalette *GetMonSpritePalStructFromOtIdPersonality(u16 species, u32 otId , u32 personality)
-{
- u32 shinyValue;
-
- shinyValue = HIHALF(otId) ^ LOHALF(otId) ^ HIHALF(personality) ^ LOHALF(personality);
- if (shinyValue < 8)
- return &gMonShinyPaletteTable[species];
- else
- return &gMonPaletteTable[species];
-}
-
-bool32 IsHMMove2(u16 move)
-{
- int i = 0;
- while (gHMMoves[i] != 0xFFFF)
- {
- if (gHMMoves[i++] == move)
- return TRUE;
- }
- return FALSE;
-}
-
-bool8 IsPokeSpriteNotFlipped(u16 species)
-{
- return gBaseStats[species].noFlip;
-}
-
-s8 GetMonFlavorRelation(struct Pokemon *mon, u8 flavor)
-{
- u8 nature = GetNature(mon);
- return gPokeblockFlavorCompatibilityTable[nature * 5 + flavor];
-}
-
-s8 GetFlavorRelationByPersonality(u32 personality, u8 flavor)
-{
- u8 nature = GetNatureFromPersonality(personality);
- return gPokeblockFlavorCompatibilityTable[nature * 5 + flavor];
-}
-
-bool8 IsTradedMon(struct Pokemon *mon)
-{
- u8 otName[OT_NAME_LENGTH + 1];
- u32 otId;
- GetMonData(mon, MON_DATA_OT_NAME, otName);
- otId = GetMonData(mon, MON_DATA_OT_ID, 0);
- return IsOtherTrainer(otId, otName);
-}
-
-bool8 IsOtherTrainer(u32 otId, u8 *otName)
-{
- if (otId ==
- (gSaveBlock2Ptr->playerTrainerId[0]
- | (gSaveBlock2Ptr->playerTrainerId[1] << 8)
- | (gSaveBlock2Ptr->playerTrainerId[2] << 16)
- | (gSaveBlock2Ptr->playerTrainerId[3] << 24)))
- {
- int i;
-
- for (i = 0; otName[i] != EOS; i++)
- if (otName[i] != gSaveBlock2Ptr->playerName[i])
- return TRUE;
- return FALSE;
- }
-
- return TRUE;
-}
-
-void MonRestorePP(struct Pokemon *mon)
-{
- BoxMonRestorePP(&mon->box);
-}
-
-void BoxMonRestorePP(struct BoxPokemon *boxMon)
-{
- int i;
-
- for (i = 0; i < 4; i++)
- {
- if (GetBoxMonData(boxMon, MON_DATA_MOVE1 + i, 0))
- {
- u16 move = GetBoxMonData(boxMon, MON_DATA_MOVE1 + i, 0);
- u16 bonus = GetBoxMonData(boxMon, MON_DATA_PP_BONUSES, 0);
- u8 pp = CalculatePPWithBonus(move, bonus, i);
- SetBoxMonData(boxMon, MON_DATA_PP1 + i, &pp);
- }
- }
-}
-
-void sub_806E994(void)
-{
- gLastUsedAbility = gBattleStruct->field_B0;
-
- gBattleTextBuff1[0] = B_BUFF_PLACEHOLDER_BEGIN;
- gBattleTextBuff1[1] = B_BUFF_MON_NICK_WITH_PREFIX;
- gBattleTextBuff1[2] = gBattleStruct->field_49;
- gBattleTextBuff1[4] = B_BUFF_EOS;
-
- if (!GetBattlerSide(gBattleStruct->field_49))
- gBattleTextBuff1[3] = pokemon_order_func(gBattlerPartyIndexes[gBattleStruct->field_49]);
- else
- gBattleTextBuff1[3] = gBattlerPartyIndexes[gBattleStruct->field_49];
-
- PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff2, gBankInMenu, pokemon_order_func(gBattlerPartyIndexes[gBankInMenu]))
-
- BattleStringExpandPlaceholders(gText_PkmnsXPreventsSwitching, gStringVar4);
-}
-
-static s32 GetWildMonTableIdInAlteringCave(u16 species)
-{
- s32 i;
- for (i = 0; i < (s32) ARRAY_COUNT(gAlteringCaveWildMonHeldItems); i++)
- if (gAlteringCaveWildMonHeldItems[i].species == species)
- return i;
- return 0;
-}
-
-void SetWildMonHeldItem(void)
-{
- if (!(gBattleTypeFlags & (BATTLE_TYPE_LEGENDARY | BATTLE_TYPE_TRAINER | BATTLE_TYPE_PYRAMID | BATTLE_TYPE_PIKE)))
- {
- u16 rnd = Random() % 100;
- u16 species = GetMonData(&gEnemyParty[0], MON_DATA_SPECIES, 0);
- u16 var1 = 45;
- u16 var2 = 95;
- if (!GetMonData(&gPlayerParty[0], MON_DATA_SANITY_BIT3, 0)
- && GetMonAbility(&gPlayerParty[0]) == ABILITY_COMPOUND_EYES)
- {
- var1 = 20;
- var2 = 80;
- }
- if (gMapHeader.mapDataId == 0x1A4)
- {
- s32 alteringCaveId = GetWildMonTableIdInAlteringCave(species);
- if (alteringCaveId != 0)
- {
- if (rnd < var2)
- return;
- SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gAlteringCaveWildMonHeldItems[alteringCaveId].item);
- }
- else
- {
- if (rnd < var1)
- return;
- if (rnd < var2)
- SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gBaseStats[species].item1);
- else
- SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gBaseStats[species].item2);
- }
- }
- else
- {
- if (gBaseStats[species].item1 == gBaseStats[species].item2 && gBaseStats[species].item1 != 0)
- {
- SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gBaseStats[species].item1);
- }
- else
- {
- if (rnd < var1)
- return;
- if (rnd < var2)
- SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gBaseStats[species].item1);
- else
- SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gBaseStats[species].item2);
- }
- }
- }
-}
-
-bool8 IsMonShiny(struct Pokemon *mon)
-{
- u32 otId = GetMonData(mon, MON_DATA_OT_ID, 0);
- u32 personality = GetMonData(mon, MON_DATA_PERSONALITY, 0);
- return IsShinyOtIdPersonality(otId, personality);
-}
-
-bool8 IsShinyOtIdPersonality(u32 otId, u32 personality)
-{
- bool8 retVal = FALSE;
- u32 shinyValue = HIHALF(otId) ^ LOHALF(otId) ^ HIHALF(personality) ^ LOHALF(personality);
- if (shinyValue < 8)
- retVal = TRUE;
- return retVal;
-}
-
-const u8 *GetTrainerPartnerName(void)
-{
- if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
- {
- if (gPartnerTrainerId == STEVEN_PARTNER_ID)
- {
- return gTrainers[TRAINER_STEVEN].trainerName;
- }
- else
- {
- GetFrontierTrainerName(gStringVar1, gPartnerTrainerId);
- return gStringVar1;
- }
- }
- else
- {
- u8 id = GetMultiplayerId();
- return gLinkPlayers[GetBattlerMultiplayerId(gLinkPlayers[id].lp_field_18 ^ 2)].name;
- }
-}
-
-#define READ_PTR_FROM_TASK(taskId, dataId) \
- (void*)( \
- ((u16)(gTasks[taskId].data[dataId]) | \
- ((u16)(gTasks[taskId].data[dataId + 1]) << 0x10)))
-
-#define STORE_PTR_IN_TASK(ptr, taskId, dataId) \
-{ \
- gTasks[taskId].data[dataId] = (u32)(ptr); \
- gTasks[taskId].data[dataId + 1] = (u32)(ptr) >> 0x10; \
-}
-
-static void Task_AnimateAfterDelay(u8 taskId)
-{
- if (--gTasks[taskId].data[3] == 0)
- {
- LaunchAnimationTaskForFrontSprite(READ_PTR_FROM_TASK(taskId, 0), gTasks[taskId].data[2]);
- DestroyTask(taskId);
- }
-}
-
-static void Task_PokemonSummaryAnimateAfterDelay(u8 taskId)
-{
- if (--gTasks[taskId].data[3] == 0)
- {
- StartMonSummaryAnimation(READ_PTR_FROM_TASK(taskId, 0), gTasks[taskId].data[2]);
- sub_81C488C(0xFF);
- DestroyTask(taskId);
- }
-}
-
-void BattleAnimateFrontSprite(struct Sprite* sprite, u16 species, bool8 noCry, u8 arg3)
-{
- if (gHitMarker & HITMARKER_NO_ANIMATIONS && !(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000)))
- DoMonFrontSpriteAnimation(sprite, species, noCry, arg3 | 0x80);
- else
- DoMonFrontSpriteAnimation(sprite, species, noCry, arg3);
-}
-
-void DoMonFrontSpriteAnimation(struct Sprite* sprite, u16 species, bool8 noCry, u8 arg3)
-{
- s8 pan;
- switch (arg3 & 0x7F)
- {
- case 0:
- pan = -25;
- break;
- case 1:
- pan = 25;
- break;
- default:
- pan = 0;
- break;
- }
- if (arg3 & 0x80)
- {
- if (!noCry)
- PlayCry1(species, pan);
- sprite->callback = SpriteCallbackDummy;
- }
- else
- {
- if (!noCry)
- {
- PlayCry1(species, pan);
- if (HasTwoFramesAnimation(species))
- StartSpriteAnim(sprite, 1);
- }
- if (gMonAnimationDelayTable[species - 1] != 0)
- {
- u8 taskId = CreateTask(Task_AnimateAfterDelay, 0);
- STORE_PTR_IN_TASK(sprite, taskId, 0);
- gTasks[taskId].data[2] = gMonFrontAnimIdsTable[species - 1];
- gTasks[taskId].data[3] = gMonAnimationDelayTable[species - 1];
- }
- else
- {
- LaunchAnimationTaskForFrontSprite(sprite, gMonFrontAnimIdsTable[species - 1]);
- }
- sprite->callback = SpriteCallbackDummy_2;
- }
-}
-
-void PokemonSummaryDoMonAnimation(struct Sprite* sprite, u16 species, bool8 oneFrame)
-{
- if (!oneFrame && HasTwoFramesAnimation(species))
- StartSpriteAnim(sprite, 1);
- if (gMonAnimationDelayTable[species - 1] != 0)
- {
- u8 taskId = CreateTask(Task_PokemonSummaryAnimateAfterDelay, 0);
- STORE_PTR_IN_TASK(sprite, taskId, 0);
- gTasks[taskId].data[2] = gMonFrontAnimIdsTable[species - 1];
- gTasks[taskId].data[3] = gMonAnimationDelayTable[species - 1];
- sub_81C488C(taskId);
- SetSpriteCB_MonAnimDummy(sprite);
- }
- else
- {
- StartMonSummaryAnimation(sprite, gMonFrontAnimIdsTable[species - 1]);
- }
-}
-
-void sub_806EE98(void)
-{
- u8 delayTaskId = FindTaskIdByFunc(Task_PokemonSummaryAnimateAfterDelay);
- if (delayTaskId != 0xFF)
- DestroyTask(delayTaskId);
-}
-
-void BattleAnimateBackSprite(struct Sprite* sprite, u16 species)
-{
- if (gHitMarker & HITMARKER_NO_ANIMATIONS && !(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000)))
- {
- sprite->callback = SpriteCallbackDummy;
- }
- else
- {
- LaunchAnimationTaskForBackSprite(sprite, GetSpeciesBackAnimSet(species));
- sprite->callback = SpriteCallbackDummy_2;
- }
-}
-
-u8 sub_806EF08(u8 arg0)
-{
- s32 i;
- s32 var = 0;
- u8 multiplayerId = GetMultiplayerId();
- switch (gLinkPlayers[multiplayerId].lp_field_18)
- {
- case 0:
- case 2:
- var = (arg0 != 0) ? 1 : 3;
- break;
- case 1:
- case 3:
- var = (arg0 != 0) ? 2 : 0;
- break;
- }
- for (i = 0; i < 4; i++)
- {
- if (gLinkPlayers[i].lp_field_18 == (s16)(var))
- break;
- }
- return i;
-}
-
-u8 sub_806EF84(u8 arg0, u8 arg1)
-{
- s32 i;
- s32 var = 0;
- switch (gLinkPlayers[arg1].lp_field_18)
- {
- case 0:
- case 2:
- var = (arg0 != 0) ? 1 : 3;
- break;
- case 1:
- case 3:
- var = (arg0 != 0) ? 2 : 0;
- break;
- }
- for (i = 0; i < 4; i++)
- {
- if (gLinkPlayers[i].lp_field_18 == (s16)(var))
- break;
- }
- return i;
-}
-
-u16 sub_806EFF0(u16 arg0)
-{
- return gFacilityClassToPicIndex[arg0];
-}
-
-u16 PlayerGenderToFrontTrainerPicId(u8 playerGender)
-{
- if (playerGender)
- return sub_806EFF0(0x3F);
- else
- return sub_806EFF0(0x3C);
-}
-
-void HandleSetPokedexFlag(u16 nationalNum, u8 caseId, u32 personality)
-{
- u8 getFlagCaseId = (caseId == FLAG_SET_SEEN) ? FLAG_GET_SEEN : FLAG_GET_CAUGHT;
- if (!GetSetPokedexFlag(nationalNum, getFlagCaseId)) // don't set if it's already set
- {
- GetSetPokedexFlag(nationalNum, caseId);
- if (NationalPokedexNumToSpecies(nationalNum) == SPECIES_UNOWN)
- gSaveBlock2Ptr->pokedex.unownPersonality = personality;
- if (NationalPokedexNumToSpecies(nationalNum) == SPECIES_SPINDA)
- gSaveBlock2Ptr->pokedex.spindaPersonality = personality;
- }
-}
-
-const u8 *GetTrainerClassNameFromId(u16 trainerId)
-{
- if (trainerId > NO_OF_TRAINERS)
- trainerId = 0;
- return gTrainerClassNames[gTrainers[trainerId].trainerClass];
-}
-
-const u8 *GetTrainerNameFromId(u16 trainerId)
-{
- if (trainerId > NO_OF_TRAINERS)
- trainerId = 0;
- return gTrainers[trainerId].trainerName;
-}
-
-bool8 HasTwoFramesAnimation(u16 species)
-{
- return (species != SPECIES_CASTFORM
- && species != SPECIES_DEOXYS
- && species != SPECIES_SPINDA
- && species != SPECIES_UNOWN);
-}
-
-bool8 sub_806F104(void)
-{
- if (gMain.inBattle && gBattleTypeFlags & (BATTLE_TYPE_FRONTIER))
- return TRUE;
- if (!gMain.inBattle && (InBattlePike() || InBattlePyramid()))
- return TRUE;
- return FALSE;
-}
-
-/*
-
-extern const struct SpriteTemplate gUnknown_08329D98[];
-
-struct Unknown_806F160_Struct
-{
- u8 field_0;
- u8 field_1;
- u8 field_2;
- u8 field_3;
- u8 field_4;
- u8 field_5;
- u8 field_6;
- u8 field_7;
- u8 field_8;
- u8 field_9;
- u8 field_A;
- u8 field_B;
- struct SpriteTemplate* templates;
-};
-
-void sub_806F160(struct Unknown_806F160_Struct* structPtr)
-{
- u16 i, j;
- for (i = 0; i < structPtr->field_0; i++)
- {
- structPtr->templates[i] = gUnknown_08329D98[i];
- for (j = 0; j < structPtr->field_1)
- {
- // no clue what the pointer in the struct point to :/
- }
- }
-} */
-