2017-09-06 17:19:08 +02:00
|
|
|
#include "global.h"
|
|
|
|
#include "pokemon.h"
|
|
|
|
#include "rng.h"
|
|
|
|
#include "main.h"
|
|
|
|
#include "items.h"
|
|
|
|
#include "string_util.h"
|
|
|
|
#include "text.h"
|
|
|
|
|
|
|
|
//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)
|
|
|
|
|
|
|
|
extern u8 sav1_map_get_name(void);
|
|
|
|
|
|
|
|
void ZeroBoxMonData(struct BoxPokemon *boxMon)
|
|
|
|
{
|
|
|
|
u8 *raw = (u8 *)boxMon;
|
|
|
|
u32 i;
|
|
|
|
for (i = 0; i < sizeof(struct BoxPokemon); i++)
|
|
|
|
raw[i] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ZeroMonData(struct Pokemon *mon)
|
|
|
|
{
|
|
|
|
u32 arg;
|
|
|
|
ZeroBoxMonData(&mon->box);
|
|
|
|
arg = 0;
|
|
|
|
SetMonData(mon, MON_DATA_STATUS, &arg);
|
|
|
|
SetMonData(mon, MON_DATA_LEVEL, &arg);
|
|
|
|
SetMonData(mon, MON_DATA_HP, &arg);
|
|
|
|
SetMonData(mon, MON_DATA_MAX_HP, &arg);
|
|
|
|
SetMonData(mon, MON_DATA_ATK, &arg);
|
|
|
|
SetMonData(mon, MON_DATA_DEF, &arg);
|
2017-10-24 03:43:26 +02:00
|
|
|
SetMonData(mon, MON_DATA_SPEED, &arg);
|
2017-09-06 17:19:08 +02:00
|
|
|
SetMonData(mon, MON_DATA_SPATK, &arg);
|
|
|
|
SetMonData(mon, MON_DATA_SPDEF, &arg);
|
|
|
|
arg = 255;
|
|
|
|
SetMonData(mon, MON_DATA_MAIL, &arg);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ZeroPlayerPartyMons(void)
|
|
|
|
{
|
|
|
|
s32 i;
|
|
|
|
for (i = 0; i < 6; i++)
|
|
|
|
ZeroMonData(&gPlayerParty[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ZeroEnemyPartyMons(void)
|
|
|
|
{
|
|
|
|
s32 i;
|
|
|
|
for (i = 0; i < 6; i++)
|
|
|
|
ZeroMonData(&gEnemyParty[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CreateMon(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 hasFixedPersonality, u32 fixedPersonality, u8 otIdType, u32 fixedOtId)
|
|
|
|
{
|
|
|
|
u32 arg;
|
|
|
|
ZeroMonData(mon);
|
|
|
|
CreateBoxMon(&mon->box, species, level, fixedIV, hasFixedPersonality, fixedPersonality, otIdType, fixedOtId);
|
|
|
|
SetMonData(mon, MON_DATA_LEVEL, &level);
|
|
|
|
arg = 255;
|
|
|
|
SetMonData(mon, MON_DATA_MAIL, &arg);
|
|
|
|
CalculateMonStats(mon);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u8 fixedIV, u8 hasFixedPersonality, u32 fixedPersonality, u8 otIdType, u32 fixedOtId)
|
|
|
|
{
|
|
|
|
u8 speciesName[POKEMON_NAME_LENGTH + 1];
|
|
|
|
u32 personality;
|
|
|
|
u32 value;
|
|
|
|
u16 checksum;
|
|
|
|
|
|
|
|
ZeroBoxMonData(boxMon);
|
|
|
|
|
|
|
|
if (hasFixedPersonality)
|
|
|
|
personality = fixedPersonality;
|
|
|
|
else
|
|
|
|
personality = Random32();
|
|
|
|
|
|
|
|
SetBoxMonData(boxMon, MON_DATA_PERSONALITY, &personality);
|
|
|
|
|
|
|
|
//Determine original trainer ID
|
|
|
|
if (otIdType == OT_ID_RANDOM_NO_SHINY) //Pokemon cannot be shiny
|
|
|
|
{
|
|
|
|
u32 shinyValue;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
value = Random32();
|
|
|
|
shinyValue = HIHALF(value) ^ LOHALF(value) ^ HIHALF(personality) ^ LOHALF(personality);
|
|
|
|
} while (shinyValue < 8);
|
|
|
|
}
|
|
|
|
else if (otIdType == OT_ID_PRESET) //Pokemon has a preset OT ID
|
|
|
|
{
|
|
|
|
value = fixedOtId;
|
|
|
|
}
|
|
|
|
else //Player is the OT
|
|
|
|
{
|
|
|
|
value = gSaveBlock2Ptr->playerTrainerId[0]
|
|
|
|
| (gSaveBlock2Ptr->playerTrainerId[1] << 8)
|
|
|
|
| (gSaveBlock2Ptr->playerTrainerId[2] << 16)
|
|
|
|
| (gSaveBlock2Ptr->playerTrainerId[3] << 24);
|
|
|
|
}
|
|
|
|
|
|
|
|
SetBoxMonData(boxMon, MON_DATA_OT_ID, &value);
|
|
|
|
|
|
|
|
checksum = CalculateBoxMonChecksum(boxMon);
|
|
|
|
SetBoxMonData(boxMon, MON_DATA_CHECKSUM, &checksum);
|
|
|
|
EncryptBoxMon(boxMon);
|
|
|
|
GetSpeciesName(speciesName, species);
|
|
|
|
SetBoxMonData(boxMon, MON_DATA_NICKNAME, speciesName);
|
|
|
|
SetBoxMonData(boxMon, MON_DATA_LANGUAGE, &gGameLanguage);
|
|
|
|
SetBoxMonData(boxMon, MON_DATA_OT_NAME, gSaveBlock2Ptr->playerName);
|
|
|
|
SetBoxMonData(boxMon, MON_DATA_SPECIES, &species);
|
|
|
|
SetBoxMonData(boxMon, MON_DATA_EXP, &gExperienceTables[gBaseStats[species].growthRate][level]);
|
|
|
|
SetBoxMonData(boxMon, MON_DATA_FRIENDSHIP, &gBaseStats[species].friendship);
|
|
|
|
value = sav1_map_get_name();
|
|
|
|
SetBoxMonData(boxMon, MON_DATA_MET_LOCATION, &value);
|
|
|
|
SetBoxMonData(boxMon, MON_DATA_MET_LEVEL, &level);
|
|
|
|
SetBoxMonData(boxMon, MON_DATA_MET_GAME, &gGameVersion);
|
|
|
|
value = ITEM_POKE_BALL;
|
|
|
|
SetBoxMonData(boxMon, MON_DATA_POKEBALL, &value);
|
|
|
|
SetBoxMonData(boxMon, MON_DATA_OT_GENDER, &gSaveBlock2Ptr->playerGender);
|
|
|
|
|
|
|
|
if (fixedIV < 32)
|
|
|
|
{
|
|
|
|
SetBoxMonData(boxMon, MON_DATA_HP_IV, &fixedIV);
|
|
|
|
SetBoxMonData(boxMon, MON_DATA_ATK_IV, &fixedIV);
|
|
|
|
SetBoxMonData(boxMon, MON_DATA_DEF_IV, &fixedIV);
|
2017-10-24 03:43:26 +02:00
|
|
|
SetBoxMonData(boxMon, MON_DATA_SPEED_IV, &fixedIV);
|
2017-09-06 17:19:08 +02:00
|
|
|
SetBoxMonData(boxMon, MON_DATA_SPATK_IV, &fixedIV);
|
|
|
|
SetBoxMonData(boxMon, MON_DATA_SPDEF_IV, &fixedIV);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
u32 iv;
|
|
|
|
value = Random();
|
|
|
|
|
|
|
|
iv = value & 0x1F;
|
|
|
|
SetBoxMonData(boxMon, MON_DATA_HP_IV, &iv);
|
|
|
|
iv = (value & 0x3E0) >> 5;
|
|
|
|
SetBoxMonData(boxMon, MON_DATA_ATK_IV, &iv);
|
|
|
|
iv = (value & 0x7C00) >> 10;
|
|
|
|
SetBoxMonData(boxMon, MON_DATA_DEF_IV, &iv);
|
|
|
|
|
|
|
|
value = Random();
|
|
|
|
|
|
|
|
iv = value & 0x1F;
|
2017-10-24 03:43:26 +02:00
|
|
|
SetBoxMonData(boxMon, MON_DATA_SPEED_IV, &iv);
|
2017-09-06 17:19:08 +02:00
|
|
|
iv = (value & 0x3E0) >> 5;
|
|
|
|
SetBoxMonData(boxMon, MON_DATA_SPATK_IV, &iv);
|
|
|
|
iv = (value & 0x7C00) >> 10;
|
|
|
|
SetBoxMonData(boxMon, MON_DATA_SPDEF_IV, &iv);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gBaseStats[species].ability2)
|
|
|
|
{
|
|
|
|
value = personality & 1;
|
|
|
|
SetBoxMonData(boxMon, MON_DATA_ALT_ABILITY, &value);
|
|
|
|
}
|
|
|
|
|
|
|
|
GiveBoxMonInitialMoveset(boxMon);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CreateMonWithNature(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 nature)
|
|
|
|
{
|
|
|
|
u32 personality;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
personality = Random32();
|
|
|
|
}
|
|
|
|
while (nature != GetNatureFromPersonality(personality));
|
|
|
|
|
|
|
|
CreateMon(mon, species, level, fixedIV, 1, personality, OT_ID_PLAYER_ID, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CreateMonWithGenderNatureLetter(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 gender, u8 nature, u8 unownLetter)
|
|
|
|
{
|
|
|
|
u32 personality;
|
|
|
|
|
|
|
|
if ((u8)(unownLetter - 1) < 28)
|
|
|
|
{
|
|
|
|
u16 actualLetter;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
personality = Random32();
|
|
|
|
actualLetter = ((((personality & 0x3000000) >> 18) | ((personality & 0x30000) >> 12) | ((personality & 0x300) >> 6) | (personality & 0x3)) % 28);
|
|
|
|
}
|
|
|
|
while (nature != GetNatureFromPersonality(personality)
|
|
|
|
|| gender != GetGenderFromSpeciesAndPersonality(species, personality)
|
|
|
|
|| actualLetter != unownLetter - 1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
|
|
|
personality = Random32();
|
|
|
|
}
|
|
|
|
while (nature != GetNatureFromPersonality(personality)
|
|
|
|
|| gender != GetGenderFromSpeciesAndPersonality(species, personality));
|
|
|
|
}
|
|
|
|
|
|
|
|
CreateMon(mon, species, level, fixedIV, 1, personality, OT_ID_PLAYER_ID, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// This is only used to create Wally's Ralts.
|
|
|
|
void CreateMaleMon(struct Pokemon *mon, u16 species, u8 level)
|
|
|
|
{
|
|
|
|
u32 personality;
|
|
|
|
u32 otId;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
otId = Random32();
|
|
|
|
personality = Random32();
|
|
|
|
}
|
|
|
|
while (GetGenderFromSpeciesAndPersonality(species, personality) != MON_MALE);
|
|
|
|
CreateMon(mon, species, level, 32, 1, personality, OT_ID_PRESET, otId);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CreateMonWithIVsPersonality(struct Pokemon *mon, u16 species, u8 level, u32 ivs, u32 personality)
|
|
|
|
{
|
|
|
|
CreateMon(mon, species, level, 0, 1, personality, OT_ID_PLAYER_ID, 0);
|
|
|
|
SetMonData(mon, MON_DATA_IVS, &ivs);
|
|
|
|
CalculateMonStats(mon);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CreateMonWithIVsOTID(struct Pokemon *mon, u16 species, u8 level, u8 *ivs, u32 otId)
|
|
|
|
{
|
|
|
|
CreateMon(mon, species, level, 0, 0, 0, OT_ID_PRESET, otId);
|
|
|
|
SetMonData(mon, MON_DATA_HP_IV, &ivs[0]);
|
|
|
|
SetMonData(mon, MON_DATA_ATK_IV, &ivs[1]);
|
|
|
|
SetMonData(mon, MON_DATA_DEF_IV, &ivs[2]);
|
2017-10-24 03:43:26 +02:00
|
|
|
SetMonData(mon, MON_DATA_SPEED_IV, &ivs[3]);
|
2017-09-06 17:19:08 +02:00
|
|
|
SetMonData(mon, MON_DATA_SPATK_IV, &ivs[4]);
|
|
|
|
SetMonData(mon, MON_DATA_SPDEF_IV, &ivs[5]);
|
|
|
|
CalculateMonStats(mon);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CreateMonWithEVSpread(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 evSpread)
|
|
|
|
{
|
|
|
|
s32 i;
|
|
|
|
s32 statCount = 0;
|
|
|
|
u16 evAmount;
|
|
|
|
u8 temp;
|
|
|
|
|
|
|
|
CreateMon(mon, species, level, fixedIV, 0, 0, 0, 0);
|
|
|
|
|
|
|
|
temp = evSpread;
|
|
|
|
|
|
|
|
for (i = 0; i < 6; i++)
|
|
|
|
{
|
|
|
|
if (temp & 1)
|
|
|
|
statCount++;
|
|
|
|
temp >>= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
evAmount = 510 / statCount;
|
|
|
|
|
|
|
|
temp = 1;
|
|
|
|
|
|
|
|
for (i = 0; i < 6; i++)
|
|
|
|
{
|
|
|
|
if (evSpread & temp)
|
|
|
|
SetMonData(mon, MON_DATA_HP_EV + i, &evAmount);
|
|
|
|
temp <<= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
CalculateMonStats(mon);
|
|
|
|
}
|
|
|
|
|
|
|
|
void sub_806819C(struct Pokemon *mon, struct UnknownPokemonStruct *src)
|
|
|
|
{
|
|
|
|
s32 i;
|
|
|
|
u8 nickname[30];
|
|
|
|
u8 language;
|
|
|
|
u8 value;
|
|
|
|
|
|
|
|
CreateMon(mon, src->species, src->level, 0, 1, src->personality, 1, src->otId);
|
|
|
|
|
|
|
|
for (i = 0; i < 4; i++)
|
|
|
|
SetMonMoveSlot(mon, src->moves[i], i);
|
|
|
|
|
|
|
|
SetMonData(mon, MON_DATA_PP_BONUSES, &src->ppBonuses);
|
|
|
|
SetMonData(mon, MON_DATA_HELD_ITEM, &src->heldItem);
|
|
|
|
SetMonData(mon, MON_DATA_FRIENDSHIP, &src->friendship);
|
|
|
|
|
|
|
|
StringCopy(nickname, src->nickname);
|
|
|
|
|
|
|
|
if (nickname[0] == EXT_CTRL_CODE_BEGIN && nickname[1] == EXT_CTRL_CODE_JPN)
|
|
|
|
{
|
|
|
|
language = LANGUAGE_JAPANESE;
|
|
|
|
StripExtCtrlCodes(nickname);
|
|
|
|
}
|
|
|
|
else
|
2017-09-12 15:36:04 +02:00
|
|
|
{
|
2017-09-06 17:19:08 +02:00
|
|
|
language = GAME_LANGUAGE;
|
2017-09-12 15:36:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
SetMonData(mon, MON_DATA_LANGUAGE, &language);
|
|
|
|
SetMonData(mon, MON_DATA_NICKNAME, nickname);
|
|
|
|
SetMonData(mon, MON_DATA_HP_EV, &src->hpEV);
|
|
|
|
SetMonData(mon, MON_DATA_ATK_EV, &src->attackEV);
|
|
|
|
SetMonData(mon, MON_DATA_DEF_EV, &src->defenseEV);
|
2017-10-26 20:47:14 +02:00
|
|
|
SetMonData(mon, MON_DATA_SPEED_EV, &src->speedEV);
|
2017-09-12 15:36:04 +02:00
|
|
|
SetMonData(mon, MON_DATA_SPATK_EV, &src->spAttackEV);
|
|
|
|
SetMonData(mon, MON_DATA_SPDEF_EV, &src->spDefenseEV);
|
|
|
|
value = src->altAbility;
|
|
|
|
SetMonData(mon, MON_DATA_ALT_ABILITY, &value);
|
|
|
|
value = src->hpIV;
|
|
|
|
SetMonData(mon, MON_DATA_HP_IV, &value);
|
|
|
|
value = src->attackIV;
|
|
|
|
SetMonData(mon, MON_DATA_ATK_IV, &value);
|
|
|
|
value = src->defenseIV;
|
|
|
|
SetMonData(mon, MON_DATA_DEF_IV, &value);
|
|
|
|
value = src->speedIV;
|
2017-10-24 03:43:26 +02:00
|
|
|
SetMonData(mon, MON_DATA_SPEED_IV, &value);
|
2017-09-12 15:36:04 +02:00
|
|
|
value = src->spAttackIV;
|
|
|
|
SetMonData(mon, MON_DATA_SPATK_IV, &value);
|
|
|
|
value = src->spDefenseIV;
|
|
|
|
SetMonData(mon, MON_DATA_SPDEF_IV, &value);
|
|
|
|
MonRestorePP(mon);
|
|
|
|
CalculateMonStats(mon);
|
|
|
|
}
|
|
|
|
|
|
|
|
u8 BattleFrontierGetOpponentLvl(u8);
|
|
|
|
|
|
|
|
void sub_8068338(struct Pokemon *mon, struct UnknownPokemonStruct *src, bool8 lvl50)
|
|
|
|
{
|
|
|
|
s32 i;
|
|
|
|
u8 nickname[30];
|
|
|
|
u8 level;
|
|
|
|
u8 language;
|
|
|
|
u8 value;
|
|
|
|
|
|
|
|
if (gSaveBlock2Ptr->frontierChosenLvl != 0)
|
|
|
|
level = BattleFrontierGetOpponentLvl(gSaveBlock2Ptr->frontierChosenLvl);
|
|
|
|
else if (lvl50)
|
|
|
|
level = 50;
|
|
|
|
else
|
|
|
|
level = src->level;
|
|
|
|
|
|
|
|
CreateMon(mon, src->species, level, 0, 1, src->personality, 1, src->otId);
|
|
|
|
|
|
|
|
for (i = 0; i < 4; i++)
|
|
|
|
SetMonMoveSlot(mon, src->moves[i], i);
|
|
|
|
|
|
|
|
SetMonData(mon, MON_DATA_PP_BONUSES, &src->ppBonuses);
|
|
|
|
SetMonData(mon, MON_DATA_HELD_ITEM, &src->heldItem);
|
|
|
|
SetMonData(mon, MON_DATA_FRIENDSHIP, &src->friendship);
|
|
|
|
|
|
|
|
StringCopy(nickname, src->nickname);
|
|
|
|
|
|
|
|
if (nickname[0] == EXT_CTRL_CODE_BEGIN && nickname[1] == EXT_CTRL_CODE_JPN)
|
|
|
|
{
|
|
|
|
language = LANGUAGE_JAPANESE;
|
|
|
|
StripExtCtrlCodes(nickname);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
language = GAME_LANGUAGE;
|
|
|
|
}
|
2017-09-06 17:19:08 +02:00
|
|
|
|
|
|
|
SetMonData(mon, MON_DATA_LANGUAGE, &language);
|
|
|
|
SetMonData(mon, MON_DATA_NICKNAME, nickname);
|
|
|
|
SetMonData(mon, MON_DATA_HP_EV, &src->hpEV);
|
|
|
|
SetMonData(mon, MON_DATA_ATK_EV, &src->attackEV);
|
|
|
|
SetMonData(mon, MON_DATA_DEF_EV, &src->defenseEV);
|
2017-10-26 20:47:14 +02:00
|
|
|
SetMonData(mon, MON_DATA_SPEED_EV, &src->speedEV);
|
2017-09-06 17:19:08 +02:00
|
|
|
SetMonData(mon, MON_DATA_SPATK_EV, &src->spAttackEV);
|
|
|
|
SetMonData(mon, MON_DATA_SPDEF_EV, &src->spDefenseEV);
|
|
|
|
value = src->altAbility;
|
|
|
|
SetMonData(mon, MON_DATA_ALT_ABILITY, &value);
|
|
|
|
value = src->hpIV;
|
|
|
|
SetMonData(mon, MON_DATA_HP_IV, &value);
|
|
|
|
value = src->attackIV;
|
|
|
|
SetMonData(mon, MON_DATA_ATK_IV, &value);
|
|
|
|
value = src->defenseIV;
|
|
|
|
SetMonData(mon, MON_DATA_DEF_IV, &value);
|
|
|
|
value = src->speedIV;
|
2017-10-24 03:43:26 +02:00
|
|
|
SetMonData(mon, MON_DATA_SPEED_IV, &value);
|
2017-09-06 17:19:08 +02:00
|
|
|
value = src->spAttackIV;
|
|
|
|
SetMonData(mon, MON_DATA_SPATK_IV, &value);
|
|
|
|
value = src->spDefenseIV;
|
|
|
|
SetMonData(mon, MON_DATA_SPDEF_IV, &value);
|
2017-09-06 21:48:30 +02:00
|
|
|
MonRestorePP(mon);
|
2017-09-06 17:19:08 +02:00
|
|
|
CalculateMonStats(mon);
|
|
|
|
}
|