pokeemerald/src/pokemon_3.c
2017-09-27 23:43:45 +02:00

1752 lines
46 KiB
C

#include "global.h"
#include "pokemon.h"
#include "main.h"
#include "items.h"
#include "string_util.h"
#include "battle_message.h"
#include "rtc.h"
#include "item.h"
#include "battle.h"
#include "species.h"
#include "link.h"
#include "hold_effects.h"
#include "rng.h"
#include "trainer_classes.h"
#include "trainer_ids.h"
#include "songs.h"
#include "sound.h"
#include "m4a.h"
#include "task.h"
#include "sprite.h"
#include "text.h"
#include "abilities.h"
#include "pokemon_animation.h"
#include "pokedex.h"
extern struct BattlePokemon gBattleMons[4];
extern struct BattleEnigmaBerry gEnigmaBerries[4];
extern u8 gActiveBank;
extern u8 gBankInMenu;
extern u8 gBankTarget;
extern u8 gBankAttacker;
extern u8 gStringBank;
extern u16 gTrainerBattleOpponent_A;
extern u32 gBattleTypeFlags;
extern u8 gBattleMonForms[4];
extern u16 gBattlePartyID[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 s8 gPokeblockFlavorCompatibilityTable[];
extern const u8 gMonAnimationDelayTable[];
extern const u8 gMonFrontAnimIdsTable[];
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);
extern void sub_817F578(struct Sprite*, u8 frontAnimId);
extern u8 GetSpeciesBackAnimId(u16 species);
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, (u8 *)&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[gActiveBank].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)
{
gBankTarget = 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];
}
gStringBank = 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
{
gBankAttacker = gBankInMenu;
BattleStringExpandPlaceholdersToDisplayedString(gText_PkmnGettingPumped);
}
}
}
if (itemEffect[3] & 0x80)
{
gBankAttacker = 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].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];
}
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 != gBattleSpritesGfx->sprites[0]
&& dest != gBattleSpritesGfx->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 sub_806D864(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 nature_stat_mod(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 == CLASS_ELITE_FOUR
|| gTrainers[gTrainerBattleOpponent_A].trainerClass == CLASS_LEADER
|| gTrainers[gTrainerBattleOpponent_A].trainerClass == 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 0x1E0;
if (gBattleTypeFlags & BATTLE_TYPE_REGI)
return 0x1DF;
if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000))
return 0x1DC;
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
{
u8 trainerClass;
if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER)
trainerClass = GetFrontierOpponentClass(gTrainerBattleOpponent_A);
else if (gBattleTypeFlags & BATTLE_TYPE_x4000000)
trainerClass = CLASS_EXPERT;
else
trainerClass = gTrainers[gTrainerBattleOpponent_A].trainerClass;
switch (trainerClass)
{
case CLASS_AQUA_LEADER:
case CLASS_MAGMA_LEADER:
return 0x1E3;
case CLASS_TEAM_AQUA:
case CLASS_TEAM_MAGMA:
case CLASS_AQUA_ADMIN:
case CLASS_MAGMA_ADMIN:
return 0x1DB;
case CLASS_LEADER:
return 0x1DD;
case CLASS_CHAMPION:
return 0x1DE;
case CLASS_PKMN_TRAINER_RIVAL:
if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER)
return 0x1E1;
if (!StringCompare(gTrainers[gTrainerBattleOpponent_A].trainerName, gText_BattleWallyName))
return 0x1DC;
return 0x1E1;
case CLASS_ELITE_FOUR:
return 0x1E2;
case CLASS_SALON_MAIDEN:
case CLASS_DOME_ACE:
case CLASS_PALACE_MAVEN:
case CLASS_ARENA_TYCOON:
case CLASS_FACTORY_HEAD:
case CLASS_PIKE_QUEEN:
case CLASS_PYRAMID_KING:
return 0x1D7;
default:
return 0x1DC;
}
}
return 0x1DA;
}
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 *pokemon_get_pal(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 species_and_otid_get_pal(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 *species_and_otid_get_pal(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 sub_806E7CC(species, otId, personality);
}
const struct CompressedSpritePalette *sub_806E7CC(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 GetMonFlavourRelation(struct Pokemon *mon, u8 a2)
{
u8 nature = GetNature(mon);
return gPokeblockFlavorCompatibilityTable[nature * 5 + a2];
}
s8 GetFlavourRelationByPersonality(u32 personality, u8 a2)
{
u8 nature = GetNatureFromPersonality(personality);
return gPokeblockFlavorCompatibilityTable[nature * 5 + a2];
}
bool8 IsTradedMon(struct Pokemon *mon)
{
u8 otName[8];
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 (!GetBankSide(gBattleStruct->field_49))
gBattleTextBuff1[3] = pokemon_order_func(gBattlePartyID[gBattleStruct->field_49]);
else
gBattleTextBuff1[3] = gBattlePartyID[gBattleStruct->field_49];
PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff2, gBankInMenu, pokemon_order_func(gBattlePartyID[gBankInMenu]))
BattleStringExpandPlaceholders(gText_PkmnsXPreventsSwitching, gStringVar4);
}
struct PokeItem
{
u16 species;
u16 item;
};
extern const struct PokeItem gAlteringCaveWildMonHeldItems[9];
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_x100000)))
{
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_ID_STEVEN].trainerName;
else
{
GetFrontierTrainerName(gStringVar1, gPartnerTrainerId);
return gStringVar1;
}
}
else
{
u8 id = GetMultiplayerId();
return gLinkPlayers[sub_806D864(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)
{
sub_817F578(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);
}
bool8 HasTwoFramesAnimation(u16 species);
extern void SpriteCallbackDummy_2(struct Sprite*);
extern void sub_817F60C(struct Sprite*);
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);
sub_817F60C(sprite);
}
else
{
sub_817F578(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, GetSpeciesBackAnimId(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;
}
extern const u8 gUnknown_0831F578[];
u16 sub_806EFF0(u16 arg0)
{
return gUnknown_0831F578[arg0];
}
u16 sub_806F000(u8 playerGender)
{
if (playerGender)
return sub_806EFF0(0x3F);
else
return sub_806EFF0(0x3C);
}
extern const u8 gTrainerClassNames[][13];
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 :/
}
}
} */