2017-09-06 17:34:18 +01:00
|
|
|
#include "global.h"
|
|
|
|
#include "pokemon.h"
|
2017-09-11 17:27:54 +01:00
|
|
|
#include "battle.h"
|
|
|
|
#include "event_data.h"
|
|
|
|
#include "rng.h"
|
|
|
|
#include "sprite.h"
|
|
|
|
#include "species.h"
|
|
|
|
#include "text.h"
|
|
|
|
#include "string_util.h"
|
2017-09-06 17:34:18 +01:00
|
|
|
|
2017-09-11 17:27:54 +01:00
|
|
|
struct Unknown_020249B4
|
|
|
|
{
|
|
|
|
u8 unk0[0xC];
|
|
|
|
struct SpriteTemplate* templates;
|
|
|
|
};
|
2017-09-06 17:34:18 +01:00
|
|
|
|
2017-09-11 17:27:54 +01:00
|
|
|
extern u8 gAbsentBankFlags;
|
|
|
|
extern u8 gActiveBank;
|
|
|
|
extern u8 gBankAttacker;
|
|
|
|
extern u8 gBankTarget;
|
|
|
|
extern u16 gTrainerBattleOpponent_A;
|
|
|
|
extern u32 gBattleTypeFlags;
|
|
|
|
extern struct SpriteTemplate gUnknown_0202499C;
|
|
|
|
extern struct Unknown_020249B4* gUnknown_020249B4[2];
|
|
|
|
|
|
|
|
extern const u32 gBitTable[];
|
|
|
|
extern const struct SpriteTemplate gUnknown_08329D98[];
|
|
|
|
extern const struct SpriteTemplate gUnknown_08329DF8[];
|
|
|
|
extern const struct SpriteTemplate gUnknown_08329D98[];
|
|
|
|
extern const union AnimCmd* gUnknown_082FF70C[];
|
|
|
|
extern const union AnimCmd* const * const gUnknown_08309AAC[];
|
|
|
|
extern const union AnimCmd* const * const gUnknown_08305D0C[];
|
|
|
|
extern const union AnimCmd* const * const gUnknown_0830536C[];
|
|
|
|
extern const u8 gBadEggNickname[];
|
|
|
|
extern const u8 gEggNickname[];
|
|
|
|
|
|
|
|
extern u8 GetBankSide(u8 bank);
|
|
|
|
extern u8 GetBankByPlayerAI(u8 bank);
|
|
|
|
extern u8 GetBankIdentity(u8 bank);
|
|
|
|
|
|
|
|
u8 CountAliveMonsInBattle(u8 caseId)
|
|
|
|
{
|
|
|
|
s32 i;
|
|
|
|
u8 retVal = 0;
|
|
|
|
|
|
|
|
switch (caseId)
|
|
|
|
{
|
|
|
|
case BATTLE_ALIVE_EXCEPT_ACTIVE:
|
|
|
|
for (i = 0; i < 4; i++)
|
|
|
|
{
|
|
|
|
if (i != gActiveBank && !(gAbsentBankFlags & gBitTable[i]))
|
|
|
|
retVal++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case BATTLE_ALIVE_ATK_SIDE:
|
|
|
|
for (i = 0; i < 4; i++)
|
|
|
|
{
|
|
|
|
if (GetBankSide(i) == GetBankSide(gBankAttacker) && !(gAbsentBankFlags & gBitTable[i]))
|
|
|
|
retVal++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case BATTLE_ALIVE_DEF_SIDE:
|
|
|
|
for (i = 0; i < 4; i++)
|
|
|
|
{
|
|
|
|
if (GetBankSide(i) == GetBankSide(gBankTarget) && !(gAbsentBankFlags & gBitTable[i]))
|
|
|
|
retVal++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return retVal;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool8 ShouldGetStatBadgeBoost(u16 badgeFlag, u8 bank)
|
|
|
|
{
|
|
|
|
if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_x2000000 | BATTLE_TYPE_FRONTIER))
|
|
|
|
return FALSE;
|
|
|
|
if (GetBankSide(bank) != SIDE_PLAYER)
|
|
|
|
return FALSE;
|
|
|
|
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER && gTrainerBattleOpponent_A == SECRET_BASE_OPPONENT)
|
|
|
|
return FALSE;
|
|
|
|
if (FlagGet(badgeFlag))
|
|
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
u8 sub_8069F34(u8 bank)
|
|
|
|
{
|
|
|
|
u8 status = GetBankIdentity(bank) & 1;
|
|
|
|
|
|
|
|
status ^= 1;
|
|
|
|
if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
|
|
|
|
return GetBankByPlayerAI(status);
|
|
|
|
if (CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_ACTIVE) > 1)
|
|
|
|
{
|
|
|
|
u8 val;
|
|
|
|
|
|
|
|
if ((Random() & 1) == 0)
|
|
|
|
val = status ^ 2;
|
|
|
|
else
|
|
|
|
val = status;
|
|
|
|
return GetBankByPlayerAI(val);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ((gAbsentBankFlags & gBitTable[status]))
|
|
|
|
return GetBankByPlayerAI(status ^ 2);
|
|
|
|
else
|
|
|
|
return GetBankByPlayerAI(status);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
u8 GetMonGender(struct Pokemon *mon)
|
|
|
|
{
|
|
|
|
return GetBoxMonGender(&mon->box);
|
|
|
|
}
|
|
|
|
|
|
|
|
u8 GetBoxMonGender(struct BoxPokemon *boxMon)
|
|
|
|
{
|
|
|
|
u16 species = GetBoxMonData(boxMon, MON_DATA_SPECIES, NULL);
|
|
|
|
u32 personality = GetBoxMonData(boxMon, MON_DATA_PERSONALITY, NULL);
|
|
|
|
|
|
|
|
switch (gBaseStats[species].genderRatio)
|
|
|
|
{
|
|
|
|
case MON_MALE:
|
|
|
|
case MON_FEMALE:
|
|
|
|
case MON_GENDERLESS:
|
|
|
|
return gBaseStats[species].genderRatio;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gBaseStats[species].genderRatio > (personality & 0xFF))
|
|
|
|
return MON_FEMALE;
|
|
|
|
else
|
|
|
|
return MON_MALE;
|
|
|
|
}
|
|
|
|
|
|
|
|
u8 GetGenderFromSpeciesAndPersonality(u16 species, u32 personality)
|
|
|
|
{
|
|
|
|
switch (gBaseStats[species].genderRatio)
|
|
|
|
{
|
|
|
|
case MON_MALE:
|
|
|
|
case MON_FEMALE:
|
|
|
|
case MON_GENDERLESS:
|
|
|
|
return gBaseStats[species].genderRatio;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gBaseStats[species].genderRatio > (personality & 0xFF))
|
|
|
|
return MON_FEMALE;
|
|
|
|
else
|
|
|
|
return MON_MALE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void sub_806A068(u16 species, u8 bankIdentity)
|
|
|
|
{
|
|
|
|
if (gBattleSpritesGfx != NULL)
|
|
|
|
gUnknown_0202499C = gBattleSpritesGfx->templates[bankIdentity];
|
|
|
|
else if (gUnknown_020249B4[0])
|
|
|
|
gUnknown_0202499C = gUnknown_020249B4[0]->templates[bankIdentity];
|
|
|
|
else if (gUnknown_020249B4[1])
|
|
|
|
gUnknown_0202499C = gUnknown_020249B4[1]->templates[bankIdentity];
|
|
|
|
else
|
|
|
|
gUnknown_0202499C = gUnknown_08329D98[bankIdentity];
|
|
|
|
|
|
|
|
gUnknown_0202499C.paletteTag = species;
|
|
|
|
if (bankIdentity == 0 || bankIdentity == 2)
|
|
|
|
gUnknown_0202499C.anims = gUnknown_082FF70C;
|
|
|
|
else if (species > 500)
|
|
|
|
gUnknown_0202499C.anims = gUnknown_08309AAC[species - 500];
|
|
|
|
else
|
|
|
|
gUnknown_0202499C.anims = gUnknown_08309AAC[species];
|
|
|
|
}
|
|
|
|
|
|
|
|
void sub_806A12C(u16 trainerSpriteId, u8 bankIdentity)
|
|
|
|
{
|
|
|
|
gUnknown_0202499C.paletteTag = trainerSpriteId;
|
|
|
|
if (bankIdentity == 0 || bankIdentity == 2)
|
|
|
|
{
|
|
|
|
gUnknown_0202499C = gUnknown_08329DF8[trainerSpriteId];
|
|
|
|
gUnknown_0202499C.anims = gUnknown_08305D0C[trainerSpriteId];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (gBattleSpritesGfx != NULL)
|
|
|
|
gUnknown_0202499C = gBattleSpritesGfx->templates[bankIdentity];
|
|
|
|
else
|
|
|
|
gUnknown_0202499C = gUnknown_08329D98[bankIdentity];
|
|
|
|
gUnknown_0202499C.anims = gUnknown_0830536C[trainerSpriteId];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void sub_806A1C0(u16 arg0, u8 bankIdentity)
|
|
|
|
{
|
|
|
|
if (gBattleSpritesGfx != NULL)
|
|
|
|
gUnknown_0202499C = gBattleSpritesGfx->templates[bankIdentity];
|
|
|
|
else
|
|
|
|
gUnknown_0202499C = gUnknown_08329D98[bankIdentity];
|
|
|
|
gUnknown_0202499C.paletteTag = arg0;
|
|
|
|
gUnknown_0202499C.anims = gUnknown_0830536C[arg0];
|
|
|
|
}
|
|
|
|
|
|
|
|
void EncryptBoxMon(struct BoxPokemon *boxMon)
|
|
|
|
{
|
|
|
|
u32 i;
|
|
|
|
for (i = 0; i < 12; i++)
|
|
|
|
{
|
|
|
|
boxMon->secure.raw[i] ^= boxMon->personality;
|
|
|
|
boxMon->secure.raw[i] ^= boxMon->otId;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DecryptBoxMon(struct BoxPokemon *boxMon)
|
|
|
|
{
|
|
|
|
u32 i;
|
|
|
|
for (i = 0; i < 12; i++)
|
|
|
|
{
|
|
|
|
boxMon->secure.raw[i] ^= boxMon->otId;
|
|
|
|
boxMon->secure.raw[i] ^= boxMon->personality;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#define SUBSTRUCT_CASE(n, v1, v2, v3, v4) \
|
|
|
|
case n: \
|
|
|
|
{ \
|
|
|
|
union PokemonSubstruct *substructs0 = boxMon->secure.substructs; \
|
|
|
|
union PokemonSubstruct *substructs1 = boxMon->secure.substructs; \
|
|
|
|
union PokemonSubstruct *substructs2 = boxMon->secure.substructs; \
|
|
|
|
union PokemonSubstruct *substructs3 = boxMon->secure.substructs; \
|
|
|
|
union PokemonSubstruct *substructs4 = boxMon->secure.substructs; \
|
|
|
|
union PokemonSubstruct *substructs5 = boxMon->secure.substructs; \
|
|
|
|
union PokemonSubstruct *substructs6 = boxMon->secure.substructs; \
|
|
|
|
union PokemonSubstruct *substructs7 = boxMon->secure.substructs; \
|
|
|
|
union PokemonSubstruct *substructs8 = boxMon->secure.substructs; \
|
|
|
|
union PokemonSubstruct *substructs9 = boxMon->secure.substructs; \
|
|
|
|
union PokemonSubstruct *substructs10 = boxMon->secure.substructs; \
|
|
|
|
union PokemonSubstruct *substructs11 = boxMon->secure.substructs; \
|
|
|
|
union PokemonSubstruct *substructs12 = boxMon->secure.substructs; \
|
|
|
|
union PokemonSubstruct *substructs13 = boxMon->secure.substructs; \
|
|
|
|
union PokemonSubstruct *substructs14 = boxMon->secure.substructs; \
|
|
|
|
union PokemonSubstruct *substructs15 = boxMon->secure.substructs; \
|
|
|
|
union PokemonSubstruct *substructs16 = boxMon->secure.substructs; \
|
|
|
|
union PokemonSubstruct *substructs17 = boxMon->secure.substructs; \
|
|
|
|
union PokemonSubstruct *substructs18 = boxMon->secure.substructs; \
|
|
|
|
union PokemonSubstruct *substructs19 = boxMon->secure.substructs; \
|
|
|
|
union PokemonSubstruct *substructs20 = boxMon->secure.substructs; \
|
|
|
|
union PokemonSubstruct *substructs21 = boxMon->secure.substructs; \
|
|
|
|
union PokemonSubstruct *substructs22 = boxMon->secure.substructs; \
|
|
|
|
union PokemonSubstruct *substructs23 = boxMon->secure.substructs; \
|
|
|
|
\
|
|
|
|
switch (substructType) \
|
|
|
|
{ \
|
|
|
|
case 0: \
|
|
|
|
substruct = &substructs ## n [v1]; \
|
|
|
|
break; \
|
|
|
|
case 1: \
|
|
|
|
substruct = &substructs ## n [v2]; \
|
|
|
|
break; \
|
|
|
|
case 2: \
|
|
|
|
substruct = &substructs ## n [v3]; \
|
|
|
|
break; \
|
|
|
|
case 3: \
|
|
|
|
substruct = &substructs ## n [v4]; \
|
|
|
|
break; \
|
|
|
|
} \
|
|
|
|
break; \
|
|
|
|
} \
|
|
|
|
|
|
|
|
|
|
|
|
union PokemonSubstruct *GetSubstruct(struct BoxPokemon *boxMon, u32 personality, u8 substructType)
|
|
|
|
{
|
|
|
|
union PokemonSubstruct *substruct = NULL;
|
|
|
|
|
|
|
|
switch (personality % 24)
|
|
|
|
{
|
|
|
|
SUBSTRUCT_CASE( 0,0,1,2,3)
|
|
|
|
SUBSTRUCT_CASE( 1,0,1,3,2)
|
|
|
|
SUBSTRUCT_CASE( 2,0,2,1,3)
|
|
|
|
SUBSTRUCT_CASE( 3,0,3,1,2)
|
|
|
|
SUBSTRUCT_CASE( 4,0,2,3,1)
|
|
|
|
SUBSTRUCT_CASE( 5,0,3,2,1)
|
|
|
|
SUBSTRUCT_CASE( 6,1,0,2,3)
|
|
|
|
SUBSTRUCT_CASE( 7,1,0,3,2)
|
|
|
|
SUBSTRUCT_CASE( 8,2,0,1,3)
|
|
|
|
SUBSTRUCT_CASE( 9,3,0,1,2)
|
|
|
|
SUBSTRUCT_CASE(10,2,0,3,1)
|
|
|
|
SUBSTRUCT_CASE(11,3,0,2,1)
|
|
|
|
SUBSTRUCT_CASE(12,1,2,0,3)
|
|
|
|
SUBSTRUCT_CASE(13,1,3,0,2)
|
|
|
|
SUBSTRUCT_CASE(14,2,1,0,3)
|
|
|
|
SUBSTRUCT_CASE(15,3,1,0,2)
|
|
|
|
SUBSTRUCT_CASE(16,2,3,0,1)
|
|
|
|
SUBSTRUCT_CASE(17,3,2,0,1)
|
|
|
|
SUBSTRUCT_CASE(18,1,2,3,0)
|
|
|
|
SUBSTRUCT_CASE(19,1,3,2,0)
|
|
|
|
SUBSTRUCT_CASE(20,2,1,3,0)
|
|
|
|
SUBSTRUCT_CASE(21,3,1,2,0)
|
|
|
|
SUBSTRUCT_CASE(22,2,3,1,0)
|
|
|
|
SUBSTRUCT_CASE(23,3,2,1,0)
|
|
|
|
}
|
|
|
|
|
|
|
|
return substruct;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern u16 GetDeoxysStat(struct Pokemon *mon, s32 statId);
|
|
|
|
|
|
|
|
u32 GetMonData(struct Pokemon *mon, s32 field, u8 *data)
|
|
|
|
{
|
2017-09-11 18:42:37 +01:00
|
|
|
u32 ret;
|
2017-09-11 17:27:54 +01:00
|
|
|
switch (field)
|
|
|
|
{
|
|
|
|
case MON_DATA_STATUS:
|
2017-09-11 18:42:37 +01:00
|
|
|
ret = mon->status;
|
|
|
|
break;
|
2017-09-11 17:27:54 +01:00
|
|
|
case MON_DATA_LEVEL:
|
2017-09-11 18:42:37 +01:00
|
|
|
ret = mon->level;
|
|
|
|
break;
|
2017-09-11 17:27:54 +01:00
|
|
|
case MON_DATA_HP:
|
2017-09-11 18:42:37 +01:00
|
|
|
ret = mon->hp;
|
|
|
|
break;
|
2017-09-11 17:27:54 +01:00
|
|
|
case MON_DATA_MAX_HP:
|
2017-09-11 18:42:37 +01:00
|
|
|
ret = mon->maxHP;
|
|
|
|
break;
|
2017-09-11 17:27:54 +01:00
|
|
|
case MON_DATA_ATK:
|
2017-09-11 18:42:37 +01:00
|
|
|
ret = GetDeoxysStat(mon, STAT_ATK);
|
|
|
|
if (!ret)
|
|
|
|
ret = mon->attack;
|
|
|
|
break;
|
2017-09-11 17:27:54 +01:00
|
|
|
case MON_DATA_DEF:
|
2017-09-11 18:42:37 +01:00
|
|
|
ret = GetDeoxysStat(mon, STAT_DEF);
|
|
|
|
if (!ret)
|
|
|
|
ret = mon->defense;
|
|
|
|
break;
|
2017-09-11 17:27:54 +01:00
|
|
|
case MON_DATA_SPD:
|
2017-09-11 18:42:37 +01:00
|
|
|
ret = GetDeoxysStat(mon, STAT_SPD);
|
|
|
|
if (!ret)
|
|
|
|
ret = mon->speed;
|
|
|
|
break;
|
2017-09-11 17:27:54 +01:00
|
|
|
case MON_DATA_SPATK:
|
2017-09-11 18:42:37 +01:00
|
|
|
ret = GetDeoxysStat(mon, STAT_SPATK);
|
|
|
|
if (!ret)
|
|
|
|
ret = mon->spAttack;
|
|
|
|
break;
|
2017-09-11 17:27:54 +01:00
|
|
|
case MON_DATA_SPDEF:
|
2017-09-11 18:42:37 +01:00
|
|
|
ret = GetDeoxysStat(mon, STAT_SPDEF);
|
|
|
|
if (!ret)
|
|
|
|
ret = mon->spDefense;
|
|
|
|
break;
|
2017-09-11 17:27:54 +01:00
|
|
|
case MON_DATA_ATK2:
|
2017-09-11 18:42:37 +01:00
|
|
|
ret = mon->attack;
|
|
|
|
break;
|
2017-09-11 17:27:54 +01:00
|
|
|
case MON_DATA_DEF2:
|
2017-09-11 18:42:37 +01:00
|
|
|
ret = mon->defense;
|
|
|
|
break;
|
2017-09-11 17:27:54 +01:00
|
|
|
case MON_DATA_SPD2:
|
2017-09-11 18:42:37 +01:00
|
|
|
ret = mon->speed;
|
|
|
|
break;
|
2017-09-11 17:27:54 +01:00
|
|
|
case MON_DATA_SPATK2:
|
2017-09-11 18:42:37 +01:00
|
|
|
ret = mon->spAttack;
|
|
|
|
break;
|
2017-09-11 17:27:54 +01:00
|
|
|
case MON_DATA_SPDEF2:
|
2017-09-11 18:42:37 +01:00
|
|
|
ret = mon->spDefense;
|
|
|
|
break;
|
2017-09-11 17:27:54 +01:00
|
|
|
case MON_DATA_MAIL:
|
2017-09-11 18:42:37 +01:00
|
|
|
ret = mon->mail;
|
|
|
|
break;
|
2017-09-11 17:27:54 +01:00
|
|
|
default:
|
2017-09-11 18:42:37 +01:00
|
|
|
ret = GetBoxMonData(&mon->box, field, data);
|
|
|
|
break;
|
2017-09-11 17:27:54 +01:00
|
|
|
}
|
2017-09-11 18:42:37 +01:00
|
|
|
return ret;
|
2017-09-11 17:27:54 +01:00
|
|
|
}
|