diff options
37 files changed, 674 insertions, 546 deletions
diff --git a/.github/calcrom/calcrom.pl b/.github/calcrom/calcrom.pl index 4858babb9..c351c7612 100755 --- a/.github/calcrom/calcrom.pl +++ b/.github/calcrom/calcrom.pl @@ -1,9 +1,15 @@ #!/usr/bin/perl use IPC::Cmd qw[ run ]; +use Getopt::Long; + +my $usage = "Usage: calcrom.pl file.map [--data]\n"; + +my $showData; +GetOptions("data" => \$showData) or die $usage; (@ARGV == 1) - or die "ERROR: no map file specified.\n"; + or die $usage; open(my $file, $ARGV[0]) or die "ERROR: could not open file '$ARGV[0]'.\n"; @@ -149,17 +155,13 @@ else print "$undocumented symbols undocumented ($undocPct%)\n"; } -print "\n"; -my $dataTotal = $srcdata + $data; -my $srcDataPct = sprintf("%.4f", 100 * $srcdata / $dataTotal); -my $dataPct = sprintf("%.4f", 100 * $data / $dataTotal); - -if ($data == 0) -{ - print "Data porting to C is 100% complete\n" -} -else +if ($showData) { + print "\n"; + my $dataTotal = $srcdata + $data; + my $srcDataPct = sprintf("%.4f", 100 * $srcdata / $dataTotal); + my $dataPct = sprintf("%.4f", 100 * $data / $dataTotal); + print "$dataTotal total bytes of data\n"; print "$srcdata bytes of data in src ($srcDataPct%)\n"; print "$data bytes of data in data ($dataPct%)\n"; @@ -28,4 +28,4 @@ Other disassembly and/or decompilation projects: ## Contacts -You can find us on [Discord](https://discord.gg/d5dubZ3) and [IRC](https://kiwiirc.com/client/irc.freenode.net/?#pret). +You can find us on [Discord](https://discord.gg/d5dubZ3) and [IRC](https://web.libera.chat/?#pret). diff --git a/include/battle.h b/include/battle.h index 14ecfbdd3..e32e621cc 100644 --- a/include/battle.h +++ b/include/battle.h @@ -37,8 +37,6 @@ #define B_ACTION_NOTHING_FAINTED 13 // when choosing an action #define B_ACTION_NONE 0xFF -#define MAX_TRAINER_ITEMS 4 - // array entries for battle communication #define MULTIUSE_STATE 0 #define CURSOR_POSITION 1 @@ -594,16 +592,15 @@ struct BattleSpriteData struct MonSpritesGfx { void* firstDecompressed; // ptr to the decompressed sprite of the first pokemon - union - { - void* ptr[4]; - u8* byte[4]; + union { + void* ptr[MAX_BATTLERS_COUNT]; + u8* byte[MAX_BATTLERS_COUNT]; } sprites; - struct SpriteTemplate templates[4]; - struct SpriteFrameImage field_74[4][4]; - u8 field_F4[0x80]; + struct SpriteTemplate templates[MAX_BATTLERS_COUNT]; + struct SpriteFrameImage frameImages[MAX_BATTLERS_COUNT][4]; + u8 unusedArr[0x80]; u8 *barFontGfx; - void *field_178; + void *unusedPtr; u16 *buffer; }; diff --git a/include/battle_util.h b/include/battle_util.h index e4ef99e0b..d4e2a23f8 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -28,6 +28,8 @@ #define ABILITYEFFECT_COUNT_BATTLER_SIDE 0x11 #define ABILITYEFFECT_COUNT_ON_FIELD 0x12 #define ABILITYEFFECT_CHECK_ON_FIELD 0x13 +#define ABILITYEFFECT_MUD_SPORT 0xFD +#define ABILITYEFFECT_WATER_SPORT 0xFE #define ABILITYEFFECT_SWITCH_IN_WEATHER 0xFF #define ABILITY_ON_OPPOSING_FIELD(battlerId, abilityId)(AbilityBattleEffects(ABILITYEFFECT_CHECK_OTHER_SIDE, battlerId, abilityId, 0, 0)) diff --git a/include/constants/map_scripts.h b/include/constants/map_scripts.h index 7a56cc908..c89df3948 100644 --- a/include/constants/map_scripts.h +++ b/include/constants/map_scripts.h @@ -13,14 +13,14 @@ Almost exclusively used to set metatiles on the map before it's first drawn 6. ON_FRAME_TABLE: Run every frame after the map has faded in, before player input is processed. - This is a table of scripts that each run if their condition is satisfied. + This is a table of scripts; only the first script whose condition is satisfied is run. Used to trigger an event, such as the player exiting the cable car or the SS Tidal sailor announcing progress 2. ON_TRANSITION: Run during the transition to the map Used to set map-specific flags/vars, update object positions/movement types, set weather, etc 5. ON_WARP_INTO_MAP_TABLE: Run after the map's objects are loaded. - This is a table of scripts that each run if their condition is satisfied. + This is a table of scripts; only the first script whose condition is satisfied is run. Used to add objects to the scene or update something about the player as they warp in (e.g. their facing dir or visibility) Note that ON_TRANSITION may also handle object visibility, but would do so by modifying a flag or var diff --git a/include/constants/pokemon.h b/include/constants/pokemon.h index 9bafa0a0b..827725fc2 100644 --- a/include/constants/pokemon.h +++ b/include/constants/pokemon.h @@ -339,4 +339,10 @@ #define MON_PIC_SIZE (64 * 64 / 2) +#define BATTLE_ALIVE_EXCEPT_ACTIVE 0 +#define BATTLE_ALIVE_ATK_SIDE 1 +#define BATTLE_ALIVE_DEF_SIDE 2 + +#define SKIP_FRONT_ANIM (1 << 7) + #endif // GUARD_CONSTANTS_POKEMON_H diff --git a/include/constants/trainers.h b/include/constants/trainers.h index 3f22c7cef..31bad25df 100644 --- a/include/constants/trainers.h +++ b/include/constants/trainers.h @@ -110,6 +110,7 @@ #define TRAINER_PIC_RS_BRENDAN 91 #define TRAINER_PIC_RS_MAY 92 +// The player back pics are assumed to alternate according to the gender values (MALE/FEMALE) #define TRAINER_BACK_PIC_BRENDAN 0 #define TRAINER_BACK_PIC_MAY 1 #define TRAINER_BACK_PIC_RED 2 @@ -334,7 +335,7 @@ #define TRAINER_CLASS_SAILOR 0x2f #define TRAINER_CLASS_COOLTRAINER_2 0x30 // Used for only one trainer. #define TRAINER_CLASS_MAGMA_ADMIN 0x31 -#define TRAINER_CLASS_PKMN_TRAINER_3 0x32 +#define TRAINER_CLASS_RIVAL 0x32 #define TRAINER_CLASS_BUG_CATCHER 0x33 #define TRAINER_CLASS_PKMN_RANGER 0x34 #define TRAINER_CLASS_MAGMA_LEADER 0x35 diff --git a/include/data.h b/include/data.h index f94f55a8f..374435cba 100644 --- a/include/data.h +++ b/include/data.h @@ -5,6 +5,8 @@ #define SPECIES_SHINY_TAG 500 +#define MAX_TRAINER_ITEMS 4 + enum { BATTLER_AFFINE_NORMAL, BATTLER_AFFINE_EMERGE, @@ -66,7 +68,7 @@ struct Trainer /*0x02*/ u8 encounterMusic_gender; // last bit is gender /*0x03*/ u8 trainerPic; /*0x04*/ u8 trainerName[12]; - /*0x10*/ u16 items[4]; + /*0x10*/ u16 items[MAX_TRAINER_ITEMS]; /*0x18*/ bool8 doubleBattle; /*0x1C*/ u32 aiFlags; /*0x20*/ u8 partySize; diff --git a/include/pokemon.h b/include/pokemon.h index 3565bd966..229898d71 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -122,20 +122,32 @@ struct Pokemon u16 spDefense; }; -struct Unknown_806F160_Struct +struct MonSpritesGfxManager { - u32 field_0_0:4; - u32 field_0_1:4; - u32 field_1:8; - u16 magic:8; - u32 field_3_0:4; - u32 field_3_1:4; - void *bytes; - u8 **byteArrays; + u32 numSprites:4; + u32 numSprites2:4; // Never read + u32 numFrames:8; + u32 active:8; + u32 dataSize:4; + u32 mode:4; // MON_SPR_GFX_MODE_* + void *spriteBuffer; + u8 **spritePointers; struct SpriteTemplate *templates; struct SpriteFrameImage *frameImages; }; +enum { + MON_SPR_GFX_MODE_NORMAL, + MON_SPR_GFX_MODE_BATTLE, + MON_SPR_GFX_MODE_FULL_PARTY, +}; + +enum { + MON_SPR_GFX_MANAGER_A, + MON_SPR_GFX_MANAGER_B, // Nothing ever sets up this manager. + MON_SPR_GFX_MANAGERS_COUNT +}; + struct BattlePokemon { /*0x00*/ u16 species; @@ -247,6 +259,8 @@ struct Evolution | (((personality) & 0x00000003) >> 0) \ ) % NUM_UNOWN_FORMS) +#define GET_SHINY_VALUE(otId, personality)HIHALF(otId) ^ LOHALF(otId) ^ HIHALF(personality) ^ LOHALF(personality) + extern u8 gPlayerPartyCount; extern struct Pokemon gPlayerParty[PARTY_SIZE]; extern u8 gEnemyPartyCount; @@ -261,8 +275,8 @@ extern const u8 *const gItemEffectTable[]; extern const u32 gExperienceTables[][MAX_LEVEL + 1]; extern const u16 *const gLevelUpLearnsets[]; extern const u8 gPPUpGetMask[]; -extern const u8 gPPUpSetMask[]; -extern const u8 gPPUpAddMask[]; +extern const u8 gPPUpClearMask[]; +extern const u8 gPPUpAddValues[]; extern const u8 gStatStageRatios[MAX_STAT_STAGE + 1][2]; extern const u16 gLinkPlayerFacilityClasses[]; extern const struct SpriteTemplate gBattlerSpriteTemplates[]; @@ -281,7 +295,7 @@ void CreateMonWithIVsPersonality(struct Pokemon *mon, u16 species, u8 level, u32 void CreateMonWithIVsOTID(struct Pokemon *mon, u16 species, u8 level, u8 *ivs, u32 otId); void CreateMonWithEVSpread(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 evSpread); void CreateBattleTowerMon(struct Pokemon *mon, struct BattleTowerPokemon *src); -void CreateBattleTowerMon2(struct Pokemon *mon, struct BattleTowerPokemon *src, bool8 lvl50); +void CreateBattleTowerMon_HandleLevel(struct Pokemon *mon, struct BattleTowerPokemon *src, bool8 lvl50); void CreateApprenticeMon(struct Pokemon *mon, const struct Apprentice *src, u8 monId); void CreateMonWithEVSpreadNatureOTID(struct Pokemon *mon, u16 species, u8 level, u8 nature, u8 fixedIV, u8 evSpread, u32 otId); void ConvertPokemonToBattleTowerPokemon(struct Pokemon *mon, struct BattleTowerPokemon *dest); @@ -305,12 +319,7 @@ u16 MonTryLearningNewMove(struct Pokemon *mon, bool8 firstMove); void DeleteFirstMoveAndGiveMoveToMon(struct Pokemon *mon, u16 move); void DeleteFirstMoveAndGiveMoveToBoxMon(struct BoxPokemon *boxMon, u16 move); s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *defender, u32 move, u16 sideStatus, u16 powerOverride, u8 typeOverride, u8 bankAtk, u8 bankDef); - u8 CountAliveMonsInBattle(u8 caseId); -#define BATTLE_ALIVE_EXCEPT_ACTIVE 0 -#define BATTLE_ALIVE_ATK_SIDE 1 -#define BATTLE_ALIVE_DEF_SIDE 2 - u8 GetDefaultMoveTarget(u8 battlerId); u8 GetMonGender(struct Pokemon *mon); u8 GetBoxMonGender(struct BoxPokemon *boxMon); @@ -330,7 +339,6 @@ void SetMonData(struct Pokemon *mon, s32 field, const void *dataArg); void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg); void CopyMon(void *dest, void *src, size_t size); u8 GiveMonToPlayer(struct Pokemon *mon); -u8 SendMonToPC(struct Pokemon* mon); u8 CalculatePlayerPartyCount(void); u8 CalculateEnemyPartyCount(void); u8 GetMonsStateToDoubles(void); @@ -362,7 +370,6 @@ u16 SpeciesToNationalPokedexNum(u16 species); u16 SpeciesToHoennPokedexNum(u16 species); u16 HoennToNationalOrder(u16 hoennNum); u16 SpeciesToCryId(u16 species); -void sub_806D544(u16 species, u32 personality, u8 *dest); void DrawSpindaSpots(u16 species, u32 personality, u8 *dest, u8 a4); void EvolutionRenameMon(struct Pokemon *mon, u16 oldSpecies, u16 newSpecies); u8 GetPlayerFlankId(void); @@ -413,17 +420,15 @@ void DoMonFrontSpriteAnimation(struct Sprite* sprite, u16 species, bool8 noCry, void PokemonSummaryDoMonAnimation(struct Sprite* sprite, u16 species, bool8 oneFrame); void StopPokemonAnimationDelayTask(void); void BattleAnimateBackSprite(struct Sprite* sprite, u16 species); -u8 sub_806EF08(u8 arg0); -u8 sub_806EF84(u8 arg0, u8 arg1); -u16 sub_806EFF0(u16 arg0); +u8 GetOpposingLinkMultiBattlerId(bool8 rightSide, u8 multiplayerId); u16 FacilityClassToPicIndex(u16 facilityClass); u16 PlayerGenderToFrontTrainerPicId(u8 playerGender); void HandleSetPokedexFlag(u16 nationalNum, u8 caseId, u32 personality); const u8 *GetTrainerClassNameFromId(u16 trainerId); const u8 *GetTrainerNameFromId(u16 trainerId); bool8 HasTwoFramesAnimation(u16 species); -struct Unknown_806F160_Struct *sub_806F2AC(u8 id, u8 arg1); -void sub_806F47C(u8 id); -u8 *sub_806F4F8(u8 id, u8 arg1); +struct MonSpritesGfxManager *CreateMonSpritesGfxManager(u8 managerId, u8 mode); +void DestroyMonSpritesGfxManager(u8 managerId); +u8 *MonSpritesGfxManager_GetSpritePtr(u8 managerId, u8 spriteNum); #endif // GUARD_POKEMON_H diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index 426dc5d15..537005d30 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -2,6 +2,7 @@ #include "battle.h" #include "battle_anim.h" #include "battle_controllers.h" +#include "data.h" #include "pokemon.h" #include "random.h" #include "util.h" diff --git a/src/battle_anim_effects_3.c b/src/battle_anim_effects_3.c index c827aaaa6..2a649dd8b 100755 --- a/src/battle_anim_effects_3.c +++ b/src/battle_anim_effects_3.c @@ -2286,7 +2286,7 @@ void AnimTask_TransformMon(u8 taskId) sub_80A6BFC(&animBg, gBattleAnimAttacker); if (IsContest()) - position = 0; + position = B_POSITION_PLAYER_LEFT; else position = GetBattlerPosition(gBattleAnimAttacker); diff --git a/src/battle_anim_throw.c b/src/battle_anim_throw.c index 0a81a6eca..bf95a319c 100755 --- a/src/battle_anim_throw.c +++ b/src/battle_anim_throw.c @@ -2227,7 +2227,7 @@ void TryShinyAnimation(u8 battler, struct Pokemon *mon) if (IsBattlerSpriteVisible(battler)) { - shinyValue = HIHALF(otId) ^ LOHALF(otId) ^ HIHALF(personality) ^ LOHALF(personality); + shinyValue = GET_SHINY_VALUE(otId, personality); if (shinyValue < SHINY_ODDS) isShiny = TRUE; diff --git a/src/battle_gfx_sfx_util.c b/src/battle_gfx_sfx_util.c index 77755775e..da15c07a0 100644 --- a/src/battle_gfx_sfx_util.c +++ b/src/battle_gfx_sfx_util.c @@ -924,13 +924,13 @@ void HandleSpeciesGfxDataChange(u8 battlerAtk, u8 battlerDef, bool8 notTransform if (IsContest()) { - position = 0; + position = B_POSITION_PLAYER_LEFT; targetSpecies = gContestResources->moveAnim->targetSpecies; personalityValue = gContestResources->moveAnim->personality; otId = gContestResources->moveAnim->otId; HandleLoadSpecialPokePic_DontHandleDeoxys(&gMonBackPicTable[targetSpecies], - gMonSpritesGfxPtr->sprites.ptr[0], + gMonSpritesGfxPtr->sprites.ptr[position], targetSpecies, gContestResources->moveAnim->targetPersonality); } @@ -1001,7 +1001,7 @@ void BattleLoadSubstituteOrMonSpriteGfx(u8 battlerId, bool8 loadMonSprite) if (!loadMonSprite) { if (IsContest()) - position = 0; + position = B_POSITION_PLAYER_LEFT; else position = GetBattlerPosition(battlerId); @@ -1260,11 +1260,11 @@ void AllocateMonSpritesGfx(void) for (j = 0; j < 4; j++) { - gMonSpritesGfxPtr->field_74[i][j].data = gMonSpritesGfxPtr->sprites.ptr[i] + (j * MON_PIC_SIZE); - gMonSpritesGfxPtr->field_74[i][j].size = MON_PIC_SIZE; + gMonSpritesGfxPtr->frameImages[i][j].data = gMonSpritesGfxPtr->sprites.ptr[i] + (j * MON_PIC_SIZE); + gMonSpritesGfxPtr->frameImages[i][j].size = MON_PIC_SIZE; } - gMonSpritesGfxPtr->templates[i].images = gMonSpritesGfxPtr->field_74[i]; + gMonSpritesGfxPtr->templates[i].images = gMonSpritesGfxPtr->frameImages[i]; } gMonSpritesGfxPtr->barFontGfx = AllocZeroed(0x1000); @@ -1275,17 +1275,14 @@ void FreeMonSpritesGfx(void) if (gMonSpritesGfxPtr == NULL) return; - if (gMonSpritesGfxPtr->buffer != NULL) - FREE_AND_SET_NULL(gMonSpritesGfxPtr->buffer); - if (gMonSpritesGfxPtr->field_178 != NULL) - FREE_AND_SET_NULL(gMonSpritesGfxPtr->field_178); - + TRY_FREE_AND_SET_NULL(gMonSpritesGfxPtr->buffer); + TRY_FREE_AND_SET_NULL(gMonSpritesGfxPtr->unusedPtr); FREE_AND_SET_NULL(gMonSpritesGfxPtr->barFontGfx); FREE_AND_SET_NULL(gMonSpritesGfxPtr->firstDecompressed); - gMonSpritesGfxPtr->sprites.ptr[0] = NULL; - gMonSpritesGfxPtr->sprites.ptr[1] = NULL; - gMonSpritesGfxPtr->sprites.ptr[2] = NULL; - gMonSpritesGfxPtr->sprites.ptr[3] = NULL; + gMonSpritesGfxPtr->sprites.ptr[B_POSITION_PLAYER_LEFT] = NULL; + gMonSpritesGfxPtr->sprites.ptr[B_POSITION_OPPONENT_LEFT] = NULL; + gMonSpritesGfxPtr->sprites.ptr[B_POSITION_PLAYER_RIGHT] = NULL; + gMonSpritesGfxPtr->sprites.ptr[B_POSITION_OPPONENT_RIGHT] = NULL; FREE_AND_SET_NULL(gMonSpritesGfxPtr); } diff --git a/src/battle_main.c b/src/battle_main.c index 1400e712a..970473407 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -501,7 +501,7 @@ const struct TrainerMoney gTrainerMoneyTable[] = {TRAINER_CLASS_TWINS, 3}, {TRAINER_CLASS_SAILOR, 8}, {TRAINER_CLASS_COLLECTOR, 15}, - {TRAINER_CLASS_PKMN_TRAINER_3, 15}, + {TRAINER_CLASS_RIVAL, 15}, {TRAINER_CLASS_PKMN_BREEDER, 10}, {TRAINER_CLASS_PKMN_RANGER, 12}, {TRAINER_CLASS_TEAM_MAGMA, 5}, diff --git a/src/battle_pyramid.c b/src/battle_pyramid.c index 50efeecb4..169dc69c5 100644 --- a/src/battle_pyramid.c +++ b/src/battle_pyramid.c @@ -449,7 +449,7 @@ static const struct PyramidTrainerEncounterMusic sTrainerClassEncounterMusic[54] {TRAINER_CLASS_PKMN_BREEDER, TRAINER_ENCOUNTER_MUSIC_FEMALE}, {TRAINER_CLASS_COLLECTOR, TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS}, {TRAINER_CLASS_PKMN_RANGER, TRAINER_ENCOUNTER_MUSIC_COOL}, - {TRAINER_CLASS_PKMN_TRAINER_3, TRAINER_ENCOUNTER_MUSIC_MALE}, + {TRAINER_CLASS_RIVAL, TRAINER_ENCOUNTER_MUSIC_MALE}, {TRAINER_CLASS_YOUNG_COUPLE, TRAINER_ENCOUNTER_MUSIC_GIRL}, {TRAINER_CLASS_PSYCHIC, TRAINER_ENCOUNTER_MUSIC_INTENSE}, {TRAINER_CLASS_SR_AND_JR, TRAINER_ENCOUNTER_MUSIC_TWINS}, diff --git a/src/battle_tower.c b/src/battle_tower.c index 8d914d706..9c85882a4 100644 --- a/src/battle_tower.c +++ b/src/battle_tower.c @@ -1668,7 +1668,7 @@ static void FillTrainerParty(u16 trainerId, u8 firstMonId, u8 monCount) if (gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].party[j].species != 0 && gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].party[j].level <= level) { - CreateBattleTowerMon2(&gEnemyParty[i], &gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].party[j], FALSE); + CreateBattleTowerMon_HandleLevel(&gEnemyParty[i], &gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].party[j], FALSE); } } return; @@ -3042,7 +3042,7 @@ static void FillPartnerParty(u16 trainerId) if (monData.nickname[0] == EXT_CTRL_CODE_BEGIN && monData.nickname[1] == EXT_CTRL_CODE_JPN) trainerName[5] = EOS; } - CreateBattleTowerMon2(&gPlayerParty[MULTI_PARTY_SIZE + i], &monData, TRUE); + CreateBattleTowerMon_HandleLevel(&gPlayerParty[MULTI_PARTY_SIZE + i], &monData, TRUE); SetMonData(&gPlayerParty[MULTI_PARTY_SIZE + i], MON_DATA_OT_NAME, trainerName); j = IsFrontierTrainerFemale(trainerId + TRAINER_RECORD_MIXING_FRIEND); SetMonData(&gPlayerParty[MULTI_PARTY_SIZE + i], MON_DATA_OT_GENDER, &j); diff --git a/src/battle_tv.c b/src/battle_tv.c index ffdadb697..c78f1bff4 100644 --- a/src/battle_tv.c +++ b/src/battle_tv.c @@ -1130,11 +1130,11 @@ void TryPutLinkBattleTvShowOnAir(void) if (gBattleTypeFlags & BATTLE_TYPE_MULTI) { - if ((playerBestMonId < 3 && !GetLinkTrainerFlankId(gBattleScripting.multiplayerId)) - || (playerBestMonId >= 3 && GetLinkTrainerFlankId(gBattleScripting.multiplayerId))) + if ((playerBestMonId < MULTI_PARTY_SIZE && !GetLinkTrainerFlankId(gBattleScripting.multiplayerId)) + || (playerBestMonId >= MULTI_PARTY_SIZE && GetLinkTrainerFlankId(gBattleScripting.multiplayerId))) { - j = (opponentBestMonId < 3) ? 0 : 1; - PutBattleUpdateOnTheAir(sub_806EF84(j, gBattleScripting.multiplayerId), moveId, playerBestSpecies, opponentBestSpecies); + j = (opponentBestMonId < MULTI_PARTY_SIZE) ? FALSE : TRUE; + PutBattleUpdateOnTheAir(GetOpposingLinkMultiBattlerId(j, gBattleScripting.multiplayerId), moveId, playerBestSpecies, opponentBestSpecies); } } else diff --git a/src/battle_util.c b/src/battle_util.c index 8617134dc..7b47bc994 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3095,14 +3095,14 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveA case ABILITYEFFECT_FIELD_SPORT: // 14 switch (gLastUsedAbility) { - case 0xFD: + case ABILITYEFFECT_MUD_SPORT: for (i = 0; i < gBattlersCount; i++) { if (gStatuses3[i] & STATUS3_MUDSPORT) effect = i + 1; } break; - case 0xFE: + case ABILITYEFFECT_WATER_SPORT: for (i = 0; i < gBattlersCount; i++) { if (gStatuses3[i] & STATUS3_WATERSPORT) diff --git a/src/contest.c b/src/contest.c index 68cad859d..a87e8f28b 100644 --- a/src/contest.c +++ b/src/contest.c @@ -3122,12 +3122,12 @@ static u8 CreateContestantSprite(u16 species, u32 otId, u32 personality, u32 ind species = SanitizeSpecies(species); if (index == gContestPlayerMonIndex) - HandleLoadSpecialPokePic_2(&gMonBackPicTable[species], gMonSpritesGfxPtr->sprites.ptr[0], species, personality); + HandleLoadSpecialPokePic_2(&gMonBackPicTable[species], gMonSpritesGfxPtr->sprites.ptr[B_POSITION_PLAYER_LEFT], species, personality); else - HandleLoadSpecialPokePic_DontHandleDeoxys(&gMonBackPicTable[species], gMonSpritesGfxPtr->sprites.ptr[0], species, personality); + HandleLoadSpecialPokePic_DontHandleDeoxys(&gMonBackPicTable[species], gMonSpritesGfxPtr->sprites.ptr[B_POSITION_PLAYER_LEFT], species, personality); LoadCompressedPalette(GetMonSpritePalFromSpeciesAndPersonality(species, otId, personality), 0x120, 0x20); - SetMultiuseSpriteTemplateToPokemon(species, 0); + SetMultiuseSpriteTemplateToPokemon(species, B_POSITION_PLAYER_LEFT); spriteId = CreateSprite(&gMultiuseSpriteTemplate, 0x70, GetBattlerSpriteFinal_Y(2, species, FALSE), 30); gSprites[spriteId].oam.paletteNum = 2; diff --git a/src/contest_painting.c b/src/contest_painting.c index d4bc8ca04..c591fc9ef 100644 --- a/src/contest_painting.c +++ b/src/contest_painting.c @@ -361,27 +361,27 @@ static void VBlankCB_ContestPainting(void) TransferPlttBuffer(); } -static void InitContestMonPixels(u16 species, u8 whichSprite) +static void InitContestMonPixels(u16 species, bool8 backPic) { const void *pal = GetMonSpritePalFromSpeciesAndPersonality(species, gContestPaintingWinner->trainerId, gContestPaintingWinner->personality); LZDecompressVram(pal, gContestPaintingMonPalette); - if (whichSprite == 0) + if (!backPic) { HandleLoadSpecialPokePic_DontHandleDeoxys( &gMonFrontPicTable[species], - gMonSpritesGfxPtr->sprites.ptr[1], + gMonSpritesGfxPtr->sprites.ptr[B_POSITION_OPPONENT_LEFT], species, gContestPaintingWinner->personality); - _InitContestMonPixels(gMonSpritesGfxPtr->sprites.ptr[1], gContestPaintingMonPalette, (void *)gContestMonPixels); + _InitContestMonPixels(gMonSpritesGfxPtr->sprites.ptr[B_POSITION_OPPONENT_LEFT], gContestPaintingMonPalette, (void *)gContestMonPixels); } else { HandleLoadSpecialPokePic_DontHandleDeoxys( &gMonBackPicTable[species], - gMonSpritesGfxPtr->sprites.ptr[0], + gMonSpritesGfxPtr->sprites.ptr[B_POSITION_PLAYER_LEFT], species, gContestPaintingWinner->personality); - _InitContestMonPixels(gMonSpritesGfxPtr->sprites.ptr[0], gContestPaintingMonPalette, (void *)gContestMonPixels); + _InitContestMonPixels(gMonSpritesGfxPtr->sprites.ptr[B_POSITION_PLAYER_LEFT], gContestPaintingMonPalette, (void *)gContestMonPixels); } } @@ -592,7 +592,7 @@ static void DoContestPaintingImageProcessing(u8 imageEffect) static void CreateContestPaintingPicture(u8 contestWinnerId, bool8 isForArtist) { AllocPaintingResources(); - InitContestMonPixels(gContestPaintingWinner->species, 0); + InitContestMonPixels(gContestPaintingWinner->species, FALSE); DoContestPaintingImageProcessing(GetImageEffectForContestWinner(contestWinnerId)); InitPaintingMonOamData(contestWinnerId); LoadContestPaintingFrame(contestWinnerId, isForArtist); diff --git a/src/contest_util.c b/src/contest_util.c index 66a666264..d3e1a600e 100644 --- a/src/contest_util.c +++ b/src/contest_util.c @@ -893,7 +893,7 @@ static void Task_ShowWinnerMonBanner(u8 taskId) { HandleLoadSpecialPokePic_2( &gMonFrontPicTable[species], - gMonSpritesGfxPtr->sprites.ptr[1], + gMonSpritesGfxPtr->sprites.ptr[B_POSITION_OPPONENT_LEFT], species, personality); } @@ -901,7 +901,7 @@ static void Task_ShowWinnerMonBanner(u8 taskId) { HandleLoadSpecialPokePic_DontHandleDeoxys( &gMonFrontPicTable[species], - gMonSpritesGfxPtr->sprites.ptr[1], + gMonSpritesGfxPtr->sprites.ptr[B_POSITION_OPPONENT_LEFT], species, personality); } @@ -2581,13 +2581,13 @@ void ShowContestEntryMonPic(void) gTasks[taskId].data[0] = 0; gTasks[taskId].data[1] = species; if (gSpecialVar_0x8006 == gContestPlayerMonIndex) - HandleLoadSpecialPokePic_2(&gMonFrontPicTable[species], gMonSpritesGfxPtr->sprites.ptr[1], species, personality); + HandleLoadSpecialPokePic_2(&gMonFrontPicTable[species], gMonSpritesGfxPtr->sprites.ptr[B_POSITION_OPPONENT_LEFT], species, personality); else - HandleLoadSpecialPokePic_DontHandleDeoxys(&gMonFrontPicTable[species], gMonSpritesGfxPtr->sprites.ptr[1], species, personality); + HandleLoadSpecialPokePic_DontHandleDeoxys(&gMonFrontPicTable[species], gMonSpritesGfxPtr->sprites.ptr[B_POSITION_OPPONENT_LEFT], species, personality); palette = GetMonSpritePalStructFromOtIdPersonality(species, otId, personality); LoadCompressedSpritePalette(palette); - SetMultiuseSpriteTemplateToPokemon(species, 1); + SetMultiuseSpriteTemplateToPokemon(species, B_POSITION_OPPONENT_LEFT); gMultiuseSpriteTemplate.paletteTag = palette->tag; spriteId = CreateSprite(&gMultiuseSpriteTemplate, (left + 1) * 8 + 32, (top * 8) + 40, 0); diff --git a/src/data/pokemon/trainer_class_lookups.h b/src/data/pokemon/trainer_class_lookups.h index 2edefb274..909d3d7dc 100644 --- a/src/data/pokemon/trainer_class_lookups.h +++ b/src/data/pokemon/trainer_class_lookups.h @@ -145,13 +145,13 @@ const u8 gFacilityClassToTrainerClass[] = [FACILITY_CLASS_SWIMMER_F] = TRAINER_CLASS_SWIMMER_F, [FACILITY_CLASS_TWINS] = TRAINER_CLASS_TWINS, [FACILITY_CLASS_SAILOR] = TRAINER_CLASS_SAILOR, - [FACILITY_CLASS_WALLY] = TRAINER_CLASS_PKMN_TRAINER_3, - [FACILITY_CLASS_BRENDAN] = TRAINER_CLASS_PKMN_TRAINER_3, - [FACILITY_CLASS_BRENDAN_2] = TRAINER_CLASS_PKMN_TRAINER_3, - [FACILITY_CLASS_BRENDAN_3] = TRAINER_CLASS_PKMN_TRAINER_3, - [FACILITY_CLASS_MAY] = TRAINER_CLASS_PKMN_TRAINER_3, - [FACILITY_CLASS_MAY_2] = TRAINER_CLASS_PKMN_TRAINER_3, - [FACILITY_CLASS_MAY_3] = TRAINER_CLASS_PKMN_TRAINER_3, + [FACILITY_CLASS_WALLY] = TRAINER_CLASS_RIVAL, + [FACILITY_CLASS_BRENDAN] = TRAINER_CLASS_RIVAL, + [FACILITY_CLASS_BRENDAN_2] = TRAINER_CLASS_RIVAL, + [FACILITY_CLASS_BRENDAN_3] = TRAINER_CLASS_RIVAL, + [FACILITY_CLASS_MAY] = TRAINER_CLASS_RIVAL, + [FACILITY_CLASS_MAY_2] = TRAINER_CLASS_RIVAL, + [FACILITY_CLASS_MAY_3] = TRAINER_CLASS_RIVAL, [FACILITY_CLASS_PKMN_BREEDER_M] = TRAINER_CLASS_PKMN_BREEDER, [FACILITY_CLASS_BUG_CATCHER] = TRAINER_CLASS_BUG_CATCHER, [FACILITY_CLASS_PKMN_RANGER_M] = TRAINER_CLASS_PKMN_RANGER, @@ -161,11 +161,11 @@ const u8 gFacilityClassToTrainerClass[] = [FACILITY_CLASS_YOUNG_COUPLE] = TRAINER_CLASS_YOUNG_COUPLE, [FACILITY_CLASS_OLD_COUPLE] = TRAINER_CLASS_OLD_COUPLE, [FACILITY_CLASS_SIS_AND_BRO] = TRAINER_CLASS_SIS_AND_BRO, - [FACILITY_CLASS_STEVEN] = TRAINER_CLASS_PKMN_TRAINER_3, + [FACILITY_CLASS_STEVEN] = TRAINER_CLASS_RIVAL, [FACILITY_CLASS_SALON_MAIDEN_ANABEL] = TRAINER_CLASS_SALON_MAIDEN, [FACILITY_CLASS_DOME_ACE_TUCKER] = TRAINER_CLASS_DOME_ACE, - [FACILITY_CLASS_RED] = TRAINER_CLASS_PKMN_TRAINER_3, - [FACILITY_CLASS_LEAF] = TRAINER_CLASS_PKMN_TRAINER_3, + [FACILITY_CLASS_RED] = TRAINER_CLASS_RIVAL, + [FACILITY_CLASS_LEAF] = TRAINER_CLASS_RIVAL, [FACILITY_CLASS_RS_BRENDAN] = TRAINER_CLASS_RS_PROTAG, [FACILITY_CLASS_RS_MAY] = TRAINER_CLASS_RS_PROTAG, }; diff --git a/src/data/text/trainer_class_names.h b/src/data/text/trainer_class_names.h index f012e877b..63cc356b2 100644 --- a/src/data/text/trainer_class_names.h +++ b/src/data/text/trainer_class_names.h @@ -49,7 +49,7 @@ const u8 gTrainerClassNames[][13] = { [TRAINER_CLASS_SAILOR] = _("SAILOR"), [TRAINER_CLASS_COOLTRAINER_2] = _("COOLTRAINER"), [TRAINER_CLASS_MAGMA_ADMIN] = _("MAGMA ADMIN"), - [TRAINER_CLASS_PKMN_TRAINER_3] = _("{PKMN} TRAINER"), + [TRAINER_CLASS_RIVAL] = _("{PKMN} TRAINER"), [TRAINER_CLASS_BUG_CATCHER] = _("BUG CATCHER"), [TRAINER_CLASS_PKMN_RANGER] = _("{PKMN} RANGER"), [TRAINER_CLASS_MAGMA_LEADER] = _("MAGMA LEADER"), diff --git a/src/data/trainers.h b/src/data/trainers.h index 163a8296d..01cf0259a 100644 --- a/src/data/trainers.h +++ b/src/data/trainers.h @@ -7268,7 +7268,7 @@ const struct Trainer gTrainers[] = { [TRAINER_WALLY_VR_1] = { .partyFlags = F_TRAINER_PARTY_CUSTOM_MOVESET, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = TRAINER_ENCOUNTER_MUSIC_MALE, .trainerPic = TRAINER_PIC_WALLY, .trainerName = _("WALLY"), @@ -7282,7 +7282,7 @@ const struct Trainer gTrainers[] = { [TRAINER_BRENDAN_ROUTE_103_MUDKIP] = { .partyFlags = 0, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = TRAINER_ENCOUNTER_MUSIC_MALE, .trainerPic = TRAINER_PIC_BRENDAN, .trainerName = _("BRENDAN"), @@ -7296,7 +7296,7 @@ const struct Trainer gTrainers[] = { [TRAINER_BRENDAN_ROUTE_110_MUDKIP] = { .partyFlags = 0, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = TRAINER_ENCOUNTER_MUSIC_MALE, .trainerPic = TRAINER_PIC_BRENDAN, .trainerName = _("BRENDAN"), @@ -7310,7 +7310,7 @@ const struct Trainer gTrainers[] = { [TRAINER_BRENDAN_ROUTE_119_MUDKIP] = { .partyFlags = 0, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = TRAINER_ENCOUNTER_MUSIC_MALE, .trainerPic = TRAINER_PIC_BRENDAN, .trainerName = _("BRENDAN"), @@ -7324,7 +7324,7 @@ const struct Trainer gTrainers[] = { [TRAINER_BRENDAN_ROUTE_103_TREECKO] = { .partyFlags = 0, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = TRAINER_ENCOUNTER_MUSIC_MALE, .trainerPic = TRAINER_PIC_BRENDAN, .trainerName = _("BRENDAN"), @@ -7338,7 +7338,7 @@ const struct Trainer gTrainers[] = { [TRAINER_BRENDAN_ROUTE_110_TREECKO] = { .partyFlags = 0, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = TRAINER_ENCOUNTER_MUSIC_MALE, .trainerPic = TRAINER_PIC_BRENDAN, .trainerName = _("BRENDAN"), @@ -7352,7 +7352,7 @@ const struct Trainer gTrainers[] = { [TRAINER_BRENDAN_ROUTE_119_TREECKO] = { .partyFlags = 0, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = TRAINER_ENCOUNTER_MUSIC_MALE, .trainerPic = TRAINER_PIC_BRENDAN, .trainerName = _("BRENDAN"), @@ -7366,7 +7366,7 @@ const struct Trainer gTrainers[] = { [TRAINER_BRENDAN_ROUTE_103_TORCHIC] = { .partyFlags = 0, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = TRAINER_ENCOUNTER_MUSIC_MALE, .trainerPic = TRAINER_PIC_BRENDAN, .trainerName = _("BRENDAN"), @@ -7380,7 +7380,7 @@ const struct Trainer gTrainers[] = { [TRAINER_BRENDAN_ROUTE_110_TORCHIC] = { .partyFlags = 0, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = TRAINER_ENCOUNTER_MUSIC_MALE, .trainerPic = TRAINER_PIC_BRENDAN, .trainerName = _("BRENDAN"), @@ -7394,7 +7394,7 @@ const struct Trainer gTrainers[] = { [TRAINER_BRENDAN_ROUTE_119_TORCHIC] = { .partyFlags = 0, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = TRAINER_ENCOUNTER_MUSIC_MALE, .trainerPic = TRAINER_PIC_BRENDAN, .trainerName = _("BRENDAN"), @@ -7408,7 +7408,7 @@ const struct Trainer gTrainers[] = { [TRAINER_MAY_ROUTE_103_MUDKIP] = { .partyFlags = 0, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = F_TRAINER_FEMALE | TRAINER_ENCOUNTER_MUSIC_FEMALE, .trainerPic = TRAINER_PIC_MAY, .trainerName = _("MAY"), @@ -7422,7 +7422,7 @@ const struct Trainer gTrainers[] = { [TRAINER_MAY_ROUTE_110_MUDKIP] = { .partyFlags = 0, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = F_TRAINER_FEMALE | TRAINER_ENCOUNTER_MUSIC_FEMALE, .trainerPic = TRAINER_PIC_MAY, .trainerName = _("MAY"), @@ -7436,7 +7436,7 @@ const struct Trainer gTrainers[] = { [TRAINER_MAY_ROUTE_119_MUDKIP] = { .partyFlags = 0, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = F_TRAINER_FEMALE | TRAINER_ENCOUNTER_MUSIC_FEMALE, .trainerPic = TRAINER_PIC_MAY, .trainerName = _("MAY"), @@ -7450,7 +7450,7 @@ const struct Trainer gTrainers[] = { [TRAINER_MAY_ROUTE_103_TREECKO] = { .partyFlags = 0, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = F_TRAINER_FEMALE | TRAINER_ENCOUNTER_MUSIC_FEMALE, .trainerPic = TRAINER_PIC_MAY, .trainerName = _("MAY"), @@ -7464,7 +7464,7 @@ const struct Trainer gTrainers[] = { [TRAINER_MAY_ROUTE_110_TREECKO] = { .partyFlags = 0, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = F_TRAINER_FEMALE | TRAINER_ENCOUNTER_MUSIC_FEMALE, .trainerPic = TRAINER_PIC_MAY, .trainerName = _("MAY"), @@ -7478,7 +7478,7 @@ const struct Trainer gTrainers[] = { [TRAINER_MAY_ROUTE_119_TREECKO] = { .partyFlags = 0, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = F_TRAINER_FEMALE | TRAINER_ENCOUNTER_MUSIC_FEMALE, .trainerPic = TRAINER_PIC_MAY, .trainerName = _("MAY"), @@ -7492,7 +7492,7 @@ const struct Trainer gTrainers[] = { [TRAINER_MAY_ROUTE_103_TORCHIC] = { .partyFlags = 0, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = F_TRAINER_FEMALE | TRAINER_ENCOUNTER_MUSIC_FEMALE, .trainerPic = TRAINER_PIC_MAY, .trainerName = _("MAY"), @@ -7506,7 +7506,7 @@ const struct Trainer gTrainers[] = { [TRAINER_MAY_ROUTE_110_TORCHIC] = { .partyFlags = 0, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = F_TRAINER_FEMALE | TRAINER_ENCOUNTER_MUSIC_FEMALE, .trainerPic = TRAINER_PIC_MAY, .trainerName = _("MAY"), @@ -7520,7 +7520,7 @@ const struct Trainer gTrainers[] = { [TRAINER_MAY_ROUTE_119_TORCHIC] = { .partyFlags = 0, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = F_TRAINER_FEMALE | TRAINER_ENCOUNTER_MUSIC_FEMALE, .trainerPic = TRAINER_PIC_MAY, .trainerName = _("MAY"), @@ -8290,7 +8290,7 @@ const struct Trainer gTrainers[] = { [TRAINER_BRENDAN_RUSTBORO_TREECKO] = { .partyFlags = 0, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = TRAINER_ENCOUNTER_MUSIC_MALE, .trainerPic = TRAINER_PIC_BRENDAN, .trainerName = _("BRENDAN"), @@ -8304,7 +8304,7 @@ const struct Trainer gTrainers[] = { [TRAINER_BRENDAN_RUSTBORO_MUDKIP] = { .partyFlags = 0, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = TRAINER_ENCOUNTER_MUSIC_MALE, .trainerPic = TRAINER_PIC_BRENDAN, .trainerName = _("BRENDAN"), @@ -8388,7 +8388,7 @@ const struct Trainer gTrainers[] = { [TRAINER_BRENDAN_RUSTBORO_TORCHIC] = { .partyFlags = 0, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = TRAINER_ENCOUNTER_MUSIC_MALE, .trainerPic = TRAINER_PIC_BRENDAN, .trainerName = _("BRENDAN"), @@ -8402,7 +8402,7 @@ const struct Trainer gTrainers[] = { [TRAINER_MAY_RUSTBORO_MUDKIP] = { .partyFlags = 0, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = F_TRAINER_FEMALE | TRAINER_ENCOUNTER_MUSIC_FEMALE, .trainerPic = TRAINER_PIC_MAY, .trainerName = _("MAY"), @@ -9186,7 +9186,7 @@ const struct Trainer gTrainers[] = { [TRAINER_WALLY_MAUVILLE] = { .partyFlags = 0, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = TRAINER_ENCOUNTER_MUSIC_MALE, .trainerPic = TRAINER_PIC_WALLY, .trainerName = _("WALLY"), @@ -9200,7 +9200,7 @@ const struct Trainer gTrainers[] = { [TRAINER_WALLY_VR_2] = { .partyFlags = F_TRAINER_PARTY_CUSTOM_MOVESET, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = TRAINER_ENCOUNTER_MUSIC_MALE, .trainerPic = TRAINER_PIC_WALLY, .trainerName = _("WALLY"), @@ -9214,7 +9214,7 @@ const struct Trainer gTrainers[] = { [TRAINER_WALLY_VR_3] = { .partyFlags = F_TRAINER_PARTY_CUSTOM_MOVESET, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = TRAINER_ENCOUNTER_MUSIC_MALE, .trainerPic = TRAINER_PIC_WALLY, .trainerName = _("WALLY"), @@ -9228,7 +9228,7 @@ const struct Trainer gTrainers[] = { [TRAINER_WALLY_VR_4] = { .partyFlags = F_TRAINER_PARTY_CUSTOM_MOVESET, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = TRAINER_ENCOUNTER_MUSIC_MALE, .trainerPic = TRAINER_PIC_WALLY, .trainerName = _("WALLY"), @@ -9242,7 +9242,7 @@ const struct Trainer gTrainers[] = { [TRAINER_WALLY_VR_5] = { .partyFlags = F_TRAINER_PARTY_CUSTOM_MOVESET, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = TRAINER_ENCOUNTER_MUSIC_MALE, .trainerPic = TRAINER_PIC_WALLY, .trainerName = _("WALLY"), @@ -9256,7 +9256,7 @@ const struct Trainer gTrainers[] = { [TRAINER_BRENDAN_LILYCOVE_MUDKIP] = { .partyFlags = 0, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = TRAINER_ENCOUNTER_MUSIC_MALE, .trainerPic = TRAINER_PIC_BRENDAN, .trainerName = _("BRENDAN"), @@ -9270,7 +9270,7 @@ const struct Trainer gTrainers[] = { [TRAINER_BRENDAN_LILYCOVE_TREECKO] = { .partyFlags = 0, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = TRAINER_ENCOUNTER_MUSIC_MALE, .trainerPic = TRAINER_PIC_BRENDAN, .trainerName = _("BRENDAN"), @@ -9284,7 +9284,7 @@ const struct Trainer gTrainers[] = { [TRAINER_BRENDAN_LILYCOVE_TORCHIC] = { .partyFlags = 0, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = TRAINER_ENCOUNTER_MUSIC_MALE, .trainerPic = TRAINER_PIC_BRENDAN, .trainerName = _("BRENDAN"), @@ -9298,7 +9298,7 @@ const struct Trainer gTrainers[] = { [TRAINER_MAY_LILYCOVE_MUDKIP] = { .partyFlags = 0, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = F_TRAINER_FEMALE | TRAINER_ENCOUNTER_MUSIC_FEMALE, .trainerPic = TRAINER_PIC_MAY, .trainerName = _("MAY"), @@ -9312,7 +9312,7 @@ const struct Trainer gTrainers[] = { [TRAINER_MAY_LILYCOVE_TREECKO] = { .partyFlags = 0, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = F_TRAINER_FEMALE | TRAINER_ENCOUNTER_MUSIC_FEMALE, .trainerPic = TRAINER_PIC_MAY, .trainerName = _("MAY"), @@ -9326,7 +9326,7 @@ const struct Trainer gTrainers[] = { [TRAINER_MAY_LILYCOVE_TORCHIC] = { .partyFlags = 0, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = F_TRAINER_FEMALE | TRAINER_ENCOUNTER_MUSIC_FEMALE, .trainerPic = TRAINER_PIC_MAY, .trainerName = _("MAY"), @@ -10754,7 +10754,7 @@ const struct Trainer gTrainers[] = { [TRAINER_MAY_RUSTBORO_TREECKO] = { .partyFlags = 0, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = F_TRAINER_FEMALE | TRAINER_ENCOUNTER_MUSIC_FEMALE, .trainerPic = TRAINER_PIC_MAY, .trainerName = _("MAY"), @@ -10768,7 +10768,7 @@ const struct Trainer gTrainers[] = { [TRAINER_MAY_RUSTBORO_TORCHIC] = { .partyFlags = 0, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = F_TRAINER_FEMALE | TRAINER_ENCOUNTER_MUSIC_FEMALE, .trainerPic = TRAINER_PIC_MAY, .trainerName = _("MAY"), @@ -11258,7 +11258,7 @@ const struct Trainer gTrainers[] = { [TRAINER_STEVEN] = { .partyFlags = F_TRAINER_PARTY_HELD_ITEM | F_TRAINER_PARTY_CUSTOM_MOVESET, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = TRAINER_ENCOUNTER_MUSIC_MALE, .trainerPic = TRAINER_PIC_STEVEN, .trainerName = _("STEVEN"), @@ -11916,7 +11916,7 @@ const struct Trainer gTrainers[] = { [TRAINER_RED] = { .partyFlags = 0, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = TRAINER_ENCOUNTER_MUSIC_MALE, .trainerPic = TRAINER_PIC_RED, .trainerName = _("RED"), @@ -11930,7 +11930,7 @@ const struct Trainer gTrainers[] = { [TRAINER_LEAF] = { .partyFlags = 0, - .trainerClass = TRAINER_CLASS_PKMN_TRAINER_3, + .trainerClass = TRAINER_CLASS_RIVAL, .encounterMusic_gender = F_TRAINER_FEMALE | TRAINER_ENCOUNTER_MUSIC_MALE, .trainerPic = TRAINER_PIC_LEAF, .trainerName = _("LEAF"), diff --git a/src/dodrio_berry_picking.c b/src/dodrio_berry_picking.c index 2a4314c4d..d7361ce96 100644 --- a/src/dodrio_berry_picking.c +++ b/src/dodrio_berry_picking.c @@ -517,21 +517,21 @@ static const u8 sDodrioNeighborMap[MAX_RFU_PLAYERS][MAX_RFU_PLAYERS][3] = }, }; -#define __ 9 // No player at this column. This may go out of bounds if this is returned +#define x 9 // No player at this column. This may go out of bounds if this is returned // Takes the number of players and a column and returns the player id at that column. // Note that the assignment is somewhat arbitrary as players share neighboring columns. ALIGNED(4) static const u8 sPlayerIdAtColumn[MAX_RFU_PLAYERS][NUM_BERRY_COLUMNS] = { - {__, __, __, __, 1, 1, 1, __, __, __, __}, // 1 player - {__, __, __, 0, 0, 1, 1, 0, __, __, __}, // 2 players - {__, __, 2, 2, 0, 0, 1, 1, 1, __, __}, // 3 players - {__, 3, 3, 0, 0, 1, 1, 2, 2, 3, __}, // 4 players - { 3, 3, 4, 4, 0, 0, 1, 1, 2, 2, 3}, // 5 players + {x, x, x, x, 1, 1, 1, x, x, x, x}, // 1 player + {x, x, x, 0, 0, 1, 1, 0, x, x, x}, // 2 players + {x, x, 2, 2, 0, 0, 1, 1, 1, x, x}, // 3 players + {x, 3, 3, 0, 0, 1, 1, 2, 2, 3, x}, // 4 players + {3, 3, 4, 4, 0, 0, 1, 1, 2, 2, 3}, // 5 players }; -#undef __ +#undef x // Each array contains the columns that belong solely to one player, dependent on the number of players // When determing how difficult the berries in a column should be, the highest diff --git a/src/egg_hatch.c b/src/egg_hatch.c index 4b668881a..b8ab1b91e 100644 --- a/src/egg_hatch.c +++ b/src/egg_hatch.c @@ -411,21 +411,22 @@ bool8 CheckDaycareMonReceivedMail(void) return _CheckDaycareMonReceivedMail(&gSaveBlock1Ptr->daycare, gSpecialVar_0x8004); } -static u8 EggHatchCreateMonSprite(u8 a0, u8 switchID, u8 pokeID, u16* speciesLoc) +static u8 EggHatchCreateMonSprite(u8 useAlt, u8 switchID, u8 pokeID, u16* speciesLoc) { - u8 r5 = 0; + u8 position = 0; u8 spriteID = 0; struct Pokemon* mon = NULL; - if (a0 == 0) + if (useAlt == FALSE) { mon = &gPlayerParty[pokeID]; - r5 = 1; + position = B_POSITION_OPPONENT_LEFT; } - if (a0 == 1) + if (useAlt == TRUE) { + // Alternate sprite allocation position. Never reached. mon = &gPlayerParty[pokeID]; - r5 = 3; + position = B_POSITION_OPPONENT_RIGHT; } switch (switchID) { @@ -434,14 +435,14 @@ static u8 EggHatchCreateMonSprite(u8 a0, u8 switchID, u8 pokeID, u16* speciesLoc u16 species = GetMonData(mon, MON_DATA_SPECIES); u32 pid = GetMonData(mon, MON_DATA_PERSONALITY); HandleLoadSpecialPokePic_DontHandleDeoxys(&gMonFrontPicTable[species], - gMonSpritesGfxPtr->sprites.ptr [(a0 * 2) + 1], + gMonSpritesGfxPtr->sprites.ptr[(useAlt * 2) + B_POSITION_OPPONENT_LEFT], species, pid); LoadCompressedSpritePalette(GetMonSpritePalStruct(mon)); *speciesLoc = species; } break; case 1: - SetMultiuseSpriteTemplateToPokemon(GetMonSpritePalStruct(mon)->tag, r5); + SetMultiuseSpriteTemplateToPokemon(GetMonSpritePalStruct(mon)->tag, position); spriteID = CreateSprite(&gMultiuseSpriteTemplate, 120, 75, 6); gSprites[spriteID].invisible = TRUE; gSprites[spriteID].callback = SpriteCallbackDummy; @@ -535,11 +536,11 @@ static void CB2_EggHatch_0(void) gMain.state++; break; case 5: - EggHatchCreateMonSprite(0, 0, sEggHatchData->eggPartyID, &sEggHatchData->species); + EggHatchCreateMonSprite(FALSE, 0, sEggHatchData->eggPartyID, &sEggHatchData->species); gMain.state++; break; case 6: - sEggHatchData->pokeSpriteID = EggHatchCreateMonSprite(0, 1, sEggHatchData->eggPartyID, &sEggHatchData->species); + sEggHatchData->pokeSpriteID = EggHatchCreateMonSprite(FALSE, 1, sEggHatchData->eggPartyID, &sEggHatchData->species); gMain.state++; break; case 7: diff --git a/src/evolution_scene.c b/src/evolution_scene.c index bd76993dc..91834876f 100644 --- a/src/evolution_scene.c +++ b/src/evolution_scene.c @@ -260,12 +260,12 @@ void EvolutionScene(struct Pokemon* mon, u16 postEvoSpecies, bool8 canStopEvo, u trainerId = GetMonData(mon, MON_DATA_OT_ID); personality = GetMonData(mon, MON_DATA_PERSONALITY); DecompressPicFromTable_2(&gMonFrontPicTable[currSpecies], - gMonSpritesGfxPtr->sprites.ptr[1], + gMonSpritesGfxPtr->sprites.ptr[B_POSITION_OPPONENT_LEFT], currSpecies); pokePal = GetMonSpritePalStructFromOtIdPersonality(currSpecies, trainerId, personality); LoadCompressedPalette(pokePal->data, 0x110, 0x20); - SetMultiuseSpriteTemplateToPokemon(currSpecies, 1); + SetMultiuseSpriteTemplateToPokemon(currSpecies, B_POSITION_OPPONENT_LEFT); gMultiuseSpriteTemplate.affineAnims = gDummySpriteAffineAnimTable; sEvoStructPtr->preEvoSpriteId = ID = CreateSprite(&gMultiuseSpriteTemplate, 120, 64, 30); @@ -275,12 +275,12 @@ void EvolutionScene(struct Pokemon* mon, u16 postEvoSpecies, bool8 canStopEvo, u // postEvo sprite DecompressPicFromTable_2(&gMonFrontPicTable[postEvoSpecies], - gMonSpritesGfxPtr->sprites.ptr[3], + gMonSpritesGfxPtr->sprites.ptr[B_POSITION_OPPONENT_RIGHT], postEvoSpecies); pokePal = GetMonSpritePalStructFromOtIdPersonality(postEvoSpecies, trainerId, personality); LoadCompressedPalette(pokePal->data, 0x120, 0x20); - SetMultiuseSpriteTemplateToPokemon(postEvoSpecies, 3); + SetMultiuseSpriteTemplateToPokemon(postEvoSpecies, B_POSITION_OPPONENT_RIGHT); gMultiuseSpriteTemplate.affineAnims = gDummySpriteAffineAnimTable; sEvoStructPtr->postEvoSpriteId = ID = CreateSprite(&gMultiuseSpriteTemplate, 120, 64, 30); gSprites[ID].callback = SpriteCallbackDummy_2; @@ -352,13 +352,13 @@ static void CB2_EvolutionSceneLoadGraphics(void) gReservedSpritePaletteCount = 4; DecompressPicFromTable_2(&gMonFrontPicTable[postEvoSpecies], - gMonSpritesGfxPtr->sprites.ptr[3], + gMonSpritesGfxPtr->sprites.ptr[B_POSITION_OPPONENT_RIGHT], postEvoSpecies); pokePal = GetMonSpritePalStructFromOtIdPersonality(postEvoSpecies, trainerId, personality); LoadCompressedPalette(pokePal->data, 0x120, 0x20); - SetMultiuseSpriteTemplateToPokemon(postEvoSpecies, 3); + SetMultiuseSpriteTemplateToPokemon(postEvoSpecies, B_POSITION_OPPONENT_RIGHT); gMultiuseSpriteTemplate.affineAnims = gDummySpriteAffineAnimTable; sEvoStructPtr->postEvoSpriteId = ID = CreateSprite(&gMultiuseSpriteTemplate, 120, 64, 30); @@ -424,7 +424,7 @@ static void CB2_TradeEvolutionSceneLoadGraphics(void) u32 trainerId = GetMonData(mon, MON_DATA_OT_ID); u32 personality = GetMonData(mon, MON_DATA_PERSONALITY); DecompressPicFromTable_2(&gMonFrontPicTable[postEvoSpecies], - gMonSpritesGfxPtr->sprites.ptr[3], + gMonSpritesGfxPtr->sprites.ptr[B_POSITION_OPPONENT_RIGHT], postEvoSpecies); pokePal = GetMonSpritePalStructFromOtIdPersonality(postEvoSpecies, trainerId, personality); LoadCompressedPalette(pokePal->data, 0x120, 0x20); @@ -435,7 +435,7 @@ static void CB2_TradeEvolutionSceneLoadGraphics(void) { u8 ID; - SetMultiuseSpriteTemplateToPokemon(postEvoSpecies, 1); + SetMultiuseSpriteTemplateToPokemon(postEvoSpecies, B_POSITION_OPPONENT_LEFT); gMultiuseSpriteTemplate.affineAnims = gDummySpriteAffineAnimTable; sEvoStructPtr->postEvoSpriteId = ID = CreateSprite(&gMultiuseSpriteTemplate, 120, 64, 30); @@ -488,13 +488,13 @@ void TradeEvolutionScene(struct Pokemon* mon, u16 postEvoSpecies, u8 preEvoSprit sEvoStructPtr->preEvoSpriteId = preEvoSpriteId; DecompressPicFromTable_2(&gMonFrontPicTable[postEvoSpecies], - gMonSpritesGfxPtr->sprites.ptr[1], + gMonSpritesGfxPtr->sprites.ptr[B_POSITION_OPPONENT_LEFT], postEvoSpecies); pokePal = GetMonSpritePalStructFromOtIdPersonality(postEvoSpecies, trainerId, personality); LoadCompressedPalette(pokePal->data, 0x120, 0x20); - SetMultiuseSpriteTemplateToPokemon(postEvoSpecies, 1); + SetMultiuseSpriteTemplateToPokemon(postEvoSpecies, B_POSITION_OPPONENT_LEFT); gMultiuseSpriteTemplate.affineAnims = gDummySpriteAffineAnimTable; sEvoStructPtr->postEvoSpriteId = ID = CreateSprite(&gMultiuseSpriteTemplate, 120, 64, 30); diff --git a/src/main_menu.c b/src/main_menu.c index a60cf1a28..f6dff3d44 100644 --- a/src/main_menu.c +++ b/src/main_menu.c @@ -161,10 +161,7 @@ * - Destroys itself when done. */ -// These two defines are used with the sCurrItemAndOptionsMenuCheck, -// to distinguish between its two parts. -#define OPTION_MENU_FLAG 0x8000 -#define CURRENT_ITEM_MASK 0x7FFF +#define OPTION_MENU_FLAG (1 << 15) // Static type declarations @@ -685,7 +682,7 @@ static void Task_MainMenuCheckSaveFile(u8 taskId) break; } } - sCurrItemAndOptionMenuCheck &= CURRENT_ITEM_MASK; // turn off the "returning from options menu" flag + sCurrItemAndOptionMenuCheck &= ~OPTION_MENU_FLAG; // turn off the "returning from options menu" flag tCurrItem = sCurrItemAndOptionMenuCheck; tItemCount = tMenuType + 2; } diff --git a/src/naming_screen.c b/src/naming_screen.c index 19da9da02..f6558921b 100644 --- a/src/naming_screen.c +++ b/src/naming_screen.c @@ -286,19 +286,26 @@ static const struct WindowTemplate sWindowTemplates[WIN_COUNT + 1] = // This handles what characters get inserted when a key is pressed // The keys shown on the keyboard are handled separately by sNamingScreenKeyboardText -static const u8 sKeyboardChars[KBPAGE_COUNT * KBROW_COUNT * KBCOL_COUNT] = __( - "abcdef ." - "ghijkl ," - "mnopqrs " - "tuvwxyz " - "ABCDEF ." - "GHIJKL ," - "MNOPQRS " - "TUVWXYZ " - "01234 " - "56789 " - "!?♂♀/- " - "…“”‘' "); +static const u8 sKeyboardChars[KBPAGE_COUNT][KBROW_COUNT][KBCOL_COUNT] = { + [KEYBOARD_LETTERS_LOWER] = { + __("abcdef ."), + __("ghijkl ,"), + __("mnopqrs "), + __("tuvwxyz "), + }, + [KEYBOARD_LETTERS_UPPER] = { + __("ABCDEF ."), + __("GHIJKL ,"), + __("MNOPQRS "), + __("TUVWXYZ "), + }, + [KEYBOARD_SYMBOLS] = { + __("01234 "), + __("56789 "), + __("!?♂♀/- "), + __("…“”‘' "), + } +}; static const u8 sPageColumnCounts[KBPAGE_COUNT] = { [KEYBOARD_LETTERS_LOWER] = KBCOL_COUNT, @@ -1780,7 +1787,7 @@ static void DrawGenderIcon(void) static u8 GetCharAtKeyboardPos(s16 x, s16 y) { - return sKeyboardChars[x + y * KBCOL_COUNT + CurrentPageToKeyboardId() * KBCOL_COUNT * KBROW_COUNT]; + return sKeyboardChars[CurrentPageToKeyboardId()][y][x]; } diff --git a/src/pokeblock_feed.c b/src/pokeblock_feed.c index b123e6031..4eb60f3d0 100644 --- a/src/pokeblock_feed.c +++ b/src/pokeblock_feed.c @@ -731,7 +731,7 @@ static bool8 LoadMonAndSceneGfx(struct Pokemon *mon) // Load mon gfx species = GetMonData(mon, MON_DATA_SPECIES2); personality = GetMonData(mon, MON_DATA_PERSONALITY); - HandleLoadSpecialPokePic_2(&gMonFrontPicTable[species], gMonSpritesGfxPtr->sprites.ptr[1], species, personality); + HandleLoadSpecialPokePic_2(&gMonFrontPicTable[species], gMonSpritesGfxPtr->sprites.ptr[B_POSITION_OPPONENT_LEFT], species, personality); sPokeblockFeed->loadGfxState++; break; case 1: @@ -742,7 +742,7 @@ static bool8 LoadMonAndSceneGfx(struct Pokemon *mon) palette = GetMonSpritePalStructFromOtIdPersonality(species, trainerId, personality); LoadCompressedSpritePalette(palette); - SetMultiuseSpriteTemplateToPokemon(palette->tag, 1); + SetMultiuseSpriteTemplateToPokemon(palette->tag, B_POSITION_OPPONENT_LEFT); sPokeblockFeed->loadGfxState++; break; case 2: diff --git a/src/pokemon.c b/src/pokemon.c index aca68d53c..62c444121 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -52,7 +52,6 @@ struct SpeciesItem u16 item; }; -// this file's functions static u16 CalculateBoxMonChecksum(struct BoxPokemon *boxMon); static union PokemonSubstruct *GetSubstruct(struct BoxPokemon *boxMon, u32 personality, u8 substructType); static void EncryptBoxMon(struct BoxPokemon *boxMon); @@ -61,17 +60,16 @@ static void Task_PlayMapChosenOrBattleBGM(u8 taskId); static bool8 ShouldGetStatBadgeBoost(u16 flagId, u8 battlerId); static u16 GiveMoveToBoxMon(struct BoxPokemon *boxMon, u16 move); static bool8 ShouldSkipFriendshipChange(void); +static u8 SendMonToPC(struct Pokemon* mon); -// EWRAM vars EWRAM_DATA static u8 sLearningMoveTableID = 0; EWRAM_DATA u8 gPlayerPartyCount = 0; EWRAM_DATA u8 gEnemyPartyCount = 0; EWRAM_DATA struct Pokemon gPlayerParty[PARTY_SIZE] = {0}; EWRAM_DATA struct Pokemon gEnemyParty[PARTY_SIZE] = {0}; EWRAM_DATA struct SpriteTemplate gMultiuseSpriteTemplate = {0}; -EWRAM_DATA struct Unknown_806F160_Struct *gUnknown_020249B4[2] = {NULL}; +EWRAM_DATA static struct MonSpritesGfxManager *sMonSpritesGfxManagers[MON_SPR_GFX_MANAGERS_COUNT] = {NULL}; -// const rom data #include "data/battle_moves.h" // Used in an unreferenced function in RS. @@ -93,7 +91,8 @@ static const struct CombinedMove sCombinedMoves[2] = #define SPECIES_TO_NATIONAL(name) [SPECIES_##name - 1] = NATIONAL_DEX_##name #define HOENN_TO_NATIONAL(name) [HOENN_DEX_##name - 1] = NATIONAL_DEX_##name -const u16 gSpeciesToHoennPokedexNum[] = // Assigns all species to the Hoenn Dex Index (Summary No. for Hoenn Dex) + // Assigns all species to the Hoenn Dex Index (Summary No. for Hoenn Dex) +static const u16 sSpeciesToHoennPokedexNum[NUM_SPECIES - 1] = { SPECIES_TO_HOENN(BULBASAUR), SPECIES_TO_HOENN(IVYSAUR), @@ -508,7 +507,8 @@ const u16 gSpeciesToHoennPokedexNum[] = // Assigns all species to the Hoenn Dex SPECIES_TO_HOENN(CHIMECHO), }; -const u16 gSpeciesToNationalPokedexNum[] = // Assigns all species to the National Dex Index (Summary No. for National Dex) + // Assigns all species to the National Dex Index (Summary No. for National Dex) +static const u16 sSpeciesToNationalPokedexNum[NUM_SPECIES - 1] = { SPECIES_TO_NATIONAL(BULBASAUR), SPECIES_TO_NATIONAL(IVYSAUR), @@ -923,7 +923,8 @@ const u16 gSpeciesToNationalPokedexNum[] = // Assigns all species to the Nationa SPECIES_TO_NATIONAL(CHIMECHO), }; -const u16 gHoennToNationalOrder[] = // Assigns Hoenn Dex Pokémon (Using National Dex Index) + // Assigns all Hoenn Dex Indexes to a National Dex Index +static const u16 sHoennToNationalOrder[NUM_SPECIES - 1] = { HOENN_TO_NATIONAL(TREECKO), HOENN_TO_NATIONAL(GROVYLE), @@ -1389,7 +1390,7 @@ const s8 gNatureStatTable[NUM_NATURES][NUM_NATURE_STATS] = // SPECIES_NONE are ignored in the following two tables, so decrement before accessing these arrays to get the right result -static const u8 sMonFrontAnimIdsTable[] = +static const u8 sMonFrontAnimIdsTable[NUM_SPECIES - 1] = { [SPECIES_BULBASAUR - 1] = ANIM_V_JUMPS_H_JUMPS, [SPECIES_IVYSAUR - 1] = ANIM_V_STRETCH, @@ -1838,9 +1839,19 @@ static const u8 sMonAnimationDelayTable[NUM_SPECIES - 1] = [SPECIES_RAYQUAZA - 1] = 60, }; -const u8 gPPUpGetMask[] = {0x03, 0x0c, 0x30, 0xc0}; // Masks for getting PP Up count, also PP Max values -const u8 gPPUpSetMask[] = {0xfc, 0xf3, 0xcf, 0x3f}; // Masks for setting PP Up count -const u8 gPPUpAddMask[] = {0x01, 0x04, 0x10, 0x40}; // Values added to PP Up count +#define PP_UP_SHIFTS(val) val, (val) << 2, (val) << 4, (val) << 6 +#define PP_UP_SHIFTS_INV(val) (u8)~(val), (u8)~((val) << 2), (u8)~((val) << 4), (u8)~((val) << 6) + +// PP Up bonuses are stored for a Pokémon as a single byte. +// There are 2 bits (a value 0-3) for each move slot that +// represent how many PP Ups have been applied. +// The following arrays take a move slot id and return: +// gPPUpGetMask - A mask to get the number of PP Ups applied to that move slot +// gPPUpClearMask - A mask to clear the number of PP Ups applied to that move slot +// gPPUpAddValues - A value to add to the PP Bonuses byte to apply 1 PP Up to that move slot +const u8 gPPUpGetMask[MAX_MON_MOVES] = {PP_UP_SHIFTS(3)}; +const u8 gPPUpClearMask[MAX_MON_MOVES] = {PP_UP_SHIFTS_INV(3)}; +const u8 gPPUpAddValues[MAX_MON_MOVES] = {PP_UP_SHIFTS(1)}; const u8 gStatStageRatios[MAX_STAT_STAGE + 1][2] = { @@ -2028,10 +2039,23 @@ static const struct SpriteTemplate sTrainerBackSpriteTemplates[] = }, }; -static const u8 sSecretBaseFacilityClasses[2][5] = +#define NUM_SECRET_BASE_CLASSES 5 +static const u8 sSecretBaseFacilityClasses[GENDER_COUNT][NUM_SECRET_BASE_CLASSES] = { - {FACILITY_CLASS_YOUNGSTER, FACILITY_CLASS_BUG_CATCHER, FACILITY_CLASS_RICH_BOY, FACILITY_CLASS_CAMPER, FACILITY_CLASS_COOLTRAINER_M}, - {FACILITY_CLASS_LASS, FACILITY_CLASS_SCHOOL_KID_F, FACILITY_CLASS_LADY, FACILITY_CLASS_PICNICKER, FACILITY_CLASS_COOLTRAINER_F} + [MALE] = { + FACILITY_CLASS_YOUNGSTER, + FACILITY_CLASS_BUG_CATCHER, + FACILITY_CLASS_RICH_BOY, + FACILITY_CLASS_CAMPER, + FACILITY_CLASS_COOLTRAINER_M + }, + [FEMALE] = { + FACILITY_CLASS_LASS, + FACILITY_CLASS_SCHOOL_KID_F, + FACILITY_CLASS_LADY, + FACILITY_CLASS_PICNICKER, + FACILITY_CLASS_COOLTRAINER_F + } }; static const u8 sGetMonDataEVConstants[] = @@ -2084,7 +2108,7 @@ static const struct SpeciesItem sAlteringCaveWildMonHeldItems[] = {SPECIES_SMEARGLE, ITEM_SALAC_BERRY}, }; -static const struct OamData sOamData_8329F20 = +static const struct OamData sOamData_64x64 = { .y = 0, .affineMode = ST_OAM_AFFINE_OFF, @@ -2101,18 +2125,17 @@ static const struct OamData sOamData_8329F20 = .affineParam = 0 }; -static const struct SpriteTemplate gUnknown_08329F28 = +static const struct SpriteTemplate sSpriteTemplate_64x64 = { .tileTag = TAG_NONE, .paletteTag = TAG_NONE, - .oam = &sOamData_8329F20, + .oam = &sOamData_64x64, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCallbackDummy, }; -// code void ZeroBoxMonData(struct BoxPokemon *boxMon) { u8 *raw = (u8 *)boxMon; @@ -2135,7 +2158,7 @@ void ZeroMonData(struct Pokemon *mon) SetMonData(mon, MON_DATA_SPEED, &arg); SetMonData(mon, MON_DATA_SPATK, &arg); SetMonData(mon, MON_DATA_SPDEF, &arg); - arg = 255; + arg = MAIL_NONE; SetMonData(mon, MON_DATA_MAIL, &arg); } @@ -2155,12 +2178,12 @@ void ZeroEnemyPartyMons(void) void CreateMon(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 hasFixedPersonality, u32 fixedPersonality, u8 otIdType, u32 fixedOtId) { - u32 arg; + u32 mail; 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); + mail = MAIL_NONE; + SetMonData(mon, MON_DATA_MAIL, &mail); CalculateMonStats(mon); } @@ -2180,21 +2203,22 @@ void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u8 fixedIV, SetBoxMonData(boxMon, MON_DATA_PERSONALITY, &personality); - //Determine original trainer ID - if (otIdType == OT_ID_RANDOM_NO_SHINY) //Pokemon cannot be shiny + // Determine original trainer ID + if (otIdType == OT_ID_RANDOM_NO_SHINY) { u32 shinyValue; do { + // Choose random OT IDs until one that results in a non-shiny Pokémon value = Random32(); - shinyValue = HIHALF(value) ^ LOHALF(value) ^ HIHALF(personality) ^ LOHALF(personality); + shinyValue = GET_SHINY_VALUE(value, personality); } while (shinyValue < SHINY_ODDS); } - else if (otIdType == OT_ID_PRESET) //Pokemon has a preset OT ID + else if (otIdType == OT_ID_PRESET) { value = fixedOtId; } - else //Player is the OT + else // Player is the OT { value = gSaveBlock2Ptr->playerTrainerId[0] | (gSaveBlock2Ptr->playerTrainerId[1] << 8) @@ -2272,7 +2296,7 @@ void CreateMonWithNature(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, } while (nature != GetNatureFromPersonality(personality)); - CreateMon(mon, species, level, fixedIV, 1, personality, OT_ID_PLAYER_ID, 0); + CreateMon(mon, species, level, fixedIV, TRUE, personality, OT_ID_PLAYER_ID, 0); } void CreateMonWithGenderNatureLetter(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 gender, u8 nature, u8 unownLetter) @@ -2302,7 +2326,7 @@ void CreateMonWithGenderNatureLetter(struct Pokemon *mon, u16 species, u8 level, || gender != GetGenderFromSpeciesAndPersonality(species, personality)); } - CreateMon(mon, species, level, fixedIV, 1, personality, OT_ID_PLAYER_ID, 0); + CreateMon(mon, species, level, fixedIV, TRUE, personality, OT_ID_PLAYER_ID, 0); } // This is only used to create Wally's Ralts. @@ -2317,25 +2341,25 @@ void CreateMaleMon(struct Pokemon *mon, u16 species, u8 level) personality = Random32(); } while (GetGenderFromSpeciesAndPersonality(species, personality) != MON_MALE); - CreateMon(mon, species, level, USE_RANDOM_IVS, 1, personality, OT_ID_PRESET, otId); + CreateMon(mon, species, level, USE_RANDOM_IVS, TRUE, 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); + CreateMon(mon, species, level, 0, TRUE, 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]); - SetMonData(mon, MON_DATA_SPEED_IV, &ivs[3]); - SetMonData(mon, MON_DATA_SPATK_IV, &ivs[4]); - SetMonData(mon, MON_DATA_SPDEF_IV, &ivs[5]); + CreateMon(mon, species, level, 0, FALSE, 0, OT_ID_PRESET, otId); + SetMonData(mon, MON_DATA_HP_IV, &ivs[STAT_HP]); + SetMonData(mon, MON_DATA_ATK_IV, &ivs[STAT_ATK]); + SetMonData(mon, MON_DATA_DEF_IV, &ivs[STAT_DEF]); + SetMonData(mon, MON_DATA_SPEED_IV, &ivs[STAT_SPEED]); + SetMonData(mon, MON_DATA_SPATK_IV, &ivs[STAT_SPATK]); + SetMonData(mon, MON_DATA_SPDEF_IV, &ivs[STAT_SPDEF]); CalculateMonStats(mon); } @@ -2346,7 +2370,7 @@ void CreateMonWithEVSpread(struct Pokemon *mon, u16 species, u8 level, u8 fixedI u16 evAmount; u8 evsBits; - CreateMon(mon, species, level, fixedIV, 0, 0, OT_ID_PLAYER_ID, 0); + CreateMon(mon, species, level, fixedIV, FALSE, 0, OT_ID_PLAYER_ID, 0); evsBits = evSpread; @@ -2378,7 +2402,7 @@ void CreateBattleTowerMon(struct Pokemon *mon, struct BattleTowerPokemon *src) u8 language; u8 value; - CreateMon(mon, src->species, src->level, 0, 1, src->personality, OT_ID_PRESET, src->otId); + CreateMon(mon, src->species, src->level, 0, TRUE, src->personality, OT_ID_PRESET, src->otId); for (i = 0; i < MAX_MON_MOVES; i++) SetMonMoveSlot(mon, src->moves[i], i); @@ -2425,7 +2449,7 @@ void CreateBattleTowerMon(struct Pokemon *mon, struct BattleTowerPokemon *src) CalculateMonStats(mon); } -void CreateBattleTowerMon2(struct Pokemon *mon, struct BattleTowerPokemon *src, bool8 lvl50) +void CreateBattleTowerMon_HandleLevel(struct Pokemon *mon, struct BattleTowerPokemon *src, bool8 lvl50) { s32 i; u8 nickname[30]; @@ -2440,7 +2464,7 @@ void CreateBattleTowerMon2(struct Pokemon *mon, struct BattleTowerPokemon *src, else level = src->level; - CreateMon(mon, src->species, level, 0, 1, src->personality, OT_ID_PRESET, src->otId); + CreateMon(mon, src->species, level, 0, TRUE, src->personality, OT_ID_PRESET, src->otId); for (i = 0; i < MAX_MON_MOVES; i++) SetMonMoveSlot(mon, src->moves[i], i); @@ -2737,7 +2761,7 @@ void CreateEventLegalEnemyMon(void) s32 itemId = gSpecialVar_0x8006; ZeroEnemyPartyMons(); - CreateEventLegalMon(&gEnemyParty[0], species, level, USE_RANDOM_IVS, 0, 0, 0, 0); + CreateEventLegalMon(&gEnemyParty[0], species, level, USE_RANDOM_IVS, FALSE, 0, OT_ID_PLAYER_ID, 0); if (itemId) { u8 heldItem[2]; @@ -2756,16 +2780,16 @@ static u16 CalculateBoxMonChecksum(struct BoxPokemon *boxMon) union PokemonSubstruct *substruct3 = GetSubstruct(boxMon, boxMon->personality, 3); s32 i; - for (i = 0; i < 6; i++) + for (i = 0; i < (s32)ARRAY_COUNT(substruct0->raw); i++) checksum += substruct0->raw[i]; - for (i = 0; i < 6; i++) + for (i = 0; i < (s32)ARRAY_COUNT(substruct1->raw); i++) checksum += substruct1->raw[i]; - for (i = 0; i < 6; i++) + for (i = 0; i < (s32)ARRAY_COUNT(substruct2->raw); i++) checksum += substruct2->raw[i]; - for (i = 0; i < 6; i++) + for (i = 0; i < (s32)ARRAY_COUNT(substruct3->raw); i++) checksum += substruct3->raw[i]; return checksum; @@ -2857,7 +2881,7 @@ void BoxMonToMon(const struct BoxPokemon *src, struct Pokemon *dest) SetMonData(dest, MON_DATA_STATUS, &value); SetMonData(dest, MON_DATA_HP, &value); SetMonData(dest, MON_DATA_MAX_HP, &value); - value = 255; + value = MAIL_NONE; SetMonData(dest, MON_DATA_MAIL, &value); CalculateMonStats(dest); } @@ -2915,7 +2939,7 @@ u16 GiveMoveToBattleMon(struct BattlePokemon *mon, u16 move) for (i = 0; i < MAX_MON_MOVES; i++) { - if (!mon->moves[i]) + if (mon->moves[i] == MOVE_NONE) { mon->moves[i] = move; mon->pp[i] = gBattleMoves[move].pp; @@ -2923,7 +2947,7 @@ u16 GiveMoveToBattleMon(struct BattlePokemon *mon, u16 move) } } - return 0xFFFF; + return MON_HAS_MAX_MOVES; } void SetMonMoveSlot(struct Pokemon *mon, u16 move, u8 slot) @@ -3013,8 +3037,8 @@ void DeleteFirstMoveAndGiveMoveToMon(struct Pokemon *mon, u16 move) ppBonuses = GetMonData(mon, MON_DATA_PP_BONUSES, NULL); ppBonuses >>= 2; - moves[3] = move; - pp[3] = gBattleMoves[move].pp; + moves[MAX_MON_MOVES - 1] = move; + pp[MAX_MON_MOVES - 1] = gBattleMoves[move].pp; for (i = 0; i < MAX_MON_MOVES; i++) { @@ -3040,8 +3064,8 @@ void DeleteFirstMoveAndGiveMoveToBoxMon(struct BoxPokemon *boxMon, u16 move) ppBonuses = GetBoxMonData(boxMon, MON_DATA_PP_BONUSES, NULL); ppBonuses >>= 2; - moves[3] = move; - pp[3] = gBattleMoves[move].pp; + moves[MAX_MON_MOVES - 1] = move; + pp[MAX_MON_MOVES - 1] = gBattleMoves[move].pp; for (i = 0; i < MAX_MON_MOVES; i++) { @@ -3086,6 +3110,7 @@ s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *de spAttack = attacker->spAttack; spDefense = defender->spDefense; + // Get attacker hold item info if (attacker->item == ITEM_ENIGMA_BERRY) { attackerHoldEffect = gEnigmaBerries[battlerIdAtk].holdEffect; @@ -3097,6 +3122,7 @@ s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *de attackerHoldEffectParam = ItemId_GetHoldEffectParam(attacker->item); } + // Get defender hold item info if (defender->item == ITEM_ENIGMA_BERRY) { defenderHoldEffect = gEnigmaBerries[battlerIdDef].holdEffect; @@ -3120,6 +3146,7 @@ s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *de if (ShouldGetStatBadgeBoost(FLAG_BADGE07_GET, battlerIdDef)) spDefense = (110 * spDefense) / 100; + // Apply type-bonus hold item for (i = 0; i < ARRAY_COUNT(sHoldEffectToType); i++) { if (attackerHoldEffect == sHoldEffectToType[i][0] @@ -3133,6 +3160,7 @@ s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *de } } + // Apply boosts from hold items if (attackerHoldEffect == HOLD_EFFECT_CHOICE_BAND) attack = (150 * attack) / 100; if (attackerHoldEffect == HOLD_EFFECT_SOUL_DEW && !(gBattleTypeFlags & (BATTLE_TYPE_FRONTIER)) && (attacker->species == SPECIES_LATIAS || attacker->species == SPECIES_LATIOS)) @@ -3149,6 +3177,8 @@ s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *de defense *= 2; if (attackerHoldEffect == HOLD_EFFECT_THICK_CLUB && (attacker->species == SPECIES_CUBONE || attacker->species == SPECIES_MAROWAK)) attack *= 2; + + // Apply abilities / field sports if (defender->ability == ABILITY_THICK_FAT && (type == TYPE_FIRE || type == TYPE_ICE)) spAttack /= 2; if (attacker->ability == ABILITY_HUSTLE) @@ -3161,9 +3191,9 @@ s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *de attack = (150 * attack) / 100; if (defender->ability == ABILITY_MARVEL_SCALE && defender->status1) defense = (150 * defense) / 100; - if (type == TYPE_ELECTRIC && AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, 0, 0xFD, 0)) + if (type == TYPE_ELECTRIC && AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, 0, ABILITYEFFECT_MUD_SPORT, 0)) gBattleMovePower /= 2; - if (type == TYPE_FIRE && AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, 0, 0xFE, 0)) + if (type == TYPE_FIRE && AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, 0, ABILITYEFFECT_WATER_SPORT, 0)) gBattleMovePower /= 2; if (type == TYPE_GRASS && attacker->ability == ABILITY_OVERGROW && attacker->hp <= (attacker->maxHP / 3)) gBattleMovePower = (150 * gBattleMovePower) / 100; @@ -3173,6 +3203,8 @@ s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *de gBattleMovePower = (150 * gBattleMovePower) / 100; if (type == TYPE_BUG && attacker->ability == ABILITY_SWARM && attacker->hp <= (attacker->maxHP / 3)) gBattleMovePower = (150 * gBattleMovePower) / 100; + + // Self-destruct / Explosion cut defense in half if (gBattleMoves[gCurrentMove].effect == EFFECT_EXPLOSION) defense /= 2; @@ -3180,6 +3212,7 @@ s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *de { if (gCritMultiplier == 2) { + // Critical hit, if attacker has lost attack stat stages then ignore stat drop if (attacker->statStages[STAT_ATK] > DEFAULT_STAT_STAGE) APPLY_STAT_MOD(damage, attacker, attack, STAT_ATK) else @@ -3193,6 +3226,7 @@ s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *de if (gCritMultiplier == 2) { + // Critical hit, if defender has gained defense stat stages then ignore stat increase if (defender->statStages[STAT_DEF] < DEFAULT_STAT_STAGE) APPLY_STAT_MOD(damageHelper, defender, defense, STAT_DEF) else @@ -3204,9 +3238,11 @@ s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *de damage = damage / damageHelper; damage /= 50; + // Burn cuts attack in half if ((attacker->status1 & STATUS1_BURN) && attacker->ability != ABILITY_GUTS) damage /= 2; + // Apply Reflect if ((sideStatus & SIDE_STATUS_REFLECT) && gCritMultiplier == 1) { if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && CountAliveMonsInBattle(BATTLE_ALIVE_DEF_SIDE) == 2) @@ -3215,10 +3251,11 @@ s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *de damage /= 2; } + // Moves hitting both targets do half damage in double battles if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && gBattleMoves[move].target == MOVE_TARGET_BOTH && CountAliveMonsInBattle(BATTLE_ALIVE_DEF_SIDE) == 2) damage /= 2; - // moves always do at least 1 damage. + // Moves always do at least 1 damage. if (damage == 0) damage = 1; } @@ -3230,6 +3267,7 @@ s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *de { if (gCritMultiplier == 2) { + // Critical hit, if attacker has lost sp. attack stat stages then ignore stat drop if (attacker->statStages[STAT_SPATK] > DEFAULT_STAT_STAGE) APPLY_STAT_MOD(damage, attacker, spAttack, STAT_SPATK) else @@ -3243,6 +3281,7 @@ s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *de if (gCritMultiplier == 2) { + // Critical hit, if defender has gained sp. defense stat stages then ignore stat increase if (defender->statStages[STAT_SPDEF] < DEFAULT_STAT_STAGE) APPLY_STAT_MOD(damageHelper, defender, spDefense, STAT_SPDEF) else @@ -3254,6 +3293,7 @@ s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *de damage = (damage / damageHelper); damage /= 50; + // Apply Lightscreen if ((sideStatus & SIDE_STATUS_LIGHTSCREEN) && gCritMultiplier == 1) { if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && CountAliveMonsInBattle(BATTLE_ALIVE_DEF_SIDE) == 2) @@ -3262,12 +3302,14 @@ s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *de damage /= 2; } + // Moves hitting both targets do half damage in double battles if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && gBattleMoves[move].target == MOVE_TARGET_BOTH && CountAliveMonsInBattle(BATTLE_ALIVE_DEF_SIDE) == 2) damage /= 2; - // are effects of weather negated with cloud nine or air lock + // Are effects of weather negated with cloud nine or air lock if (WEATHER_HAS_EFFECT2) { + // Rain weakens Fire, boosts Water if (gBattleWeather & B_WEATHER_RAIN_TEMPORARY) { switch (type) @@ -3281,11 +3323,11 @@ s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *de } } - // any weather except sun weakens solar beam + // Any weather except sun weakens solar beam if ((gBattleWeather & (B_WEATHER_RAIN | B_WEATHER_SANDSTORM | B_WEATHER_HAIL)) && gCurrentMove == MOVE_SOLAR_BEAM) damage /= 2; - // sunny + // Sun boosts Fire, weakens Water if (gBattleWeather & B_WEATHER_SUN) { switch (type) @@ -3300,7 +3342,7 @@ s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *de } } - // flash fire triggered + // Flash fire triggered if ((gBattleResources->flags->flags[battlerIdAtk] & RESOURCE_FLAG_FLASH_FIRE) && type == TYPE_FIRE) damage = (15 * damage) / 10; } @@ -3425,10 +3467,10 @@ void SetMultiuseSpriteTemplateToPokemon(u16 speciesTag, u8 battlerPosition) { if (gMonSpritesGfxPtr != NULL) gMultiuseSpriteTemplate = gMonSpritesGfxPtr->templates[battlerPosition]; - else if (gUnknown_020249B4[0]) - gMultiuseSpriteTemplate = gUnknown_020249B4[0]->templates[battlerPosition]; - else if (gUnknown_020249B4[1]) - gMultiuseSpriteTemplate = gUnknown_020249B4[1]->templates[battlerPosition]; + else if (sMonSpritesGfxManagers[MON_SPR_GFX_MANAGER_A]) + gMultiuseSpriteTemplate = sMonSpritesGfxManagers[MON_SPR_GFX_MANAGER_A]->templates[battlerPosition]; + else if (sMonSpritesGfxManagers[MON_SPR_GFX_MANAGER_B]) + gMultiuseSpriteTemplate = sMonSpritesGfxManagers[MON_SPR_GFX_MANAGER_B]->templates[battlerPosition]; else gMultiuseSpriteTemplate = gBattlerSpriteTemplates[battlerPosition]; @@ -3441,13 +3483,13 @@ void SetMultiuseSpriteTemplateToPokemon(u16 speciesTag, u8 battlerPosition) gMultiuseSpriteTemplate.anims = gMonFrontAnimsPtrTable[speciesTag]; } -void SetMultiuseSpriteTemplateToTrainerBack(u16 trainerSpriteId, u8 battlerPosition) +void SetMultiuseSpriteTemplateToTrainerBack(u16 trainerPicId, u8 battlerPosition) { - gMultiuseSpriteTemplate.paletteTag = trainerSpriteId; + gMultiuseSpriteTemplate.paletteTag = trainerPicId; if (battlerPosition == B_POSITION_PLAYER_LEFT || battlerPosition == B_POSITION_PLAYER_RIGHT) { - gMultiuseSpriteTemplate = sTrainerBackSpriteTemplates[trainerSpriteId]; - gMultiuseSpriteTemplate.anims = gTrainerBackAnimsPtrTable[trainerSpriteId]; + gMultiuseSpriteTemplate = sTrainerBackSpriteTemplates[trainerPicId]; + gMultiuseSpriteTemplate.anims = gTrainerBackAnimsPtrTable[trainerPicId]; } else { @@ -3455,25 +3497,25 @@ void SetMultiuseSpriteTemplateToTrainerBack(u16 trainerSpriteId, u8 battlerPosit gMultiuseSpriteTemplate = gMonSpritesGfxPtr->templates[battlerPosition]; else gMultiuseSpriteTemplate = gBattlerSpriteTemplates[battlerPosition]; - gMultiuseSpriteTemplate.anims = gTrainerFrontAnimsPtrTable[trainerSpriteId]; + gMultiuseSpriteTemplate.anims = gTrainerFrontAnimsPtrTable[trainerPicId]; } } -void SetMultiuseSpriteTemplateToTrainerFront(u16 arg0, u8 battlerPosition) +void SetMultiuseSpriteTemplateToTrainerFront(u16 trainerPicId, u8 battlerPosition) { if (gMonSpritesGfxPtr != NULL) gMultiuseSpriteTemplate = gMonSpritesGfxPtr->templates[battlerPosition]; else gMultiuseSpriteTemplate = gBattlerSpriteTemplates[battlerPosition]; - gMultiuseSpriteTemplate.paletteTag = arg0; - gMultiuseSpriteTemplate.anims = gTrainerFrontAnimsPtrTable[arg0]; + gMultiuseSpriteTemplate.paletteTag = trainerPicId; + gMultiuseSpriteTemplate.anims = gTrainerFrontAnimsPtrTable[trainerPicId]; } static void EncryptBoxMon(struct BoxPokemon *boxMon) { u32 i; - for (i = 0; i < 12; i++) + for (i = 0; i < ARRAY_COUNT(boxMon->secure.raw); i++) { boxMon->secure.raw[i] ^= boxMon->personality; boxMon->secure.raw[i] ^= boxMon->otId; @@ -3483,7 +3525,7 @@ static void EncryptBoxMon(struct BoxPokemon *boxMon) static void DecryptBoxMon(struct BoxPokemon *boxMon) { u32 i; - for (i = 0; i < 12; i++) + for (i = 0; i < ARRAY_COUNT(boxMon->secure.raw); i++) { boxMon->secure.raw[i] ^= boxMon->otId; boxMon->secure.raw[i] ^= boxMon->personality; @@ -3661,9 +3703,9 @@ u32 GetBoxMonData(struct BoxPokemon *boxMon, s32 field, u8 *data) if (CalculateBoxMonChecksum(boxMon) != boxMon->checksum) { - boxMon->isBadEgg = 1; - boxMon->isEgg = 1; - substruct3->isEgg = 1; + boxMon->isBadEgg = TRUE; + boxMon->isEgg = TRUE; + substruct3->isEgg = TRUE; } } @@ -3915,7 +3957,12 @@ u32 GetBoxMonData(struct BoxPokemon *boxMon, s32 field, u8 *data) retVal = SPECIES_EGG; break; case MON_DATA_IVS: - retVal = substruct3->hpIV | (substruct3->attackIV << 5) | (substruct3->defenseIV << 10) | (substruct3->speedIV << 15) | (substruct3->spAttackIV << 20) | (substruct3->spDefenseIV << 25); + retVal = substruct3->hpIV + | (substruct3->attackIV << 5) + | (substruct3->defenseIV << 10) + | (substruct3->speedIV << 15) + | (substruct3->spAttackIV << 20) + | (substruct3->spDefenseIV << 25); break; case MON_DATA_KNOWN_MOVES: if (substruct0->species && !substruct3->isEgg) @@ -4059,9 +4106,9 @@ void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg) if (CalculateBoxMonChecksum(boxMon) != boxMon->checksum) { - boxMon->isBadEgg = 1; - boxMon->isEgg = 1; - substruct3->isEgg = 1; + boxMon->isBadEgg = TRUE; + boxMon->isEgg = TRUE; + substruct3->isEgg = TRUE; EncryptBoxMon(boxMon); return; } @@ -4114,9 +4161,9 @@ void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg) { SET16(substruct0->species); if (substruct0->species) - boxMon->hasSpecies = 1; + boxMon->hasSpecies = TRUE; else - boxMon->hasSpecies = 0; + boxMon->hasSpecies = FALSE; break; } case MON_DATA_HELD_ITEM: @@ -4224,9 +4271,9 @@ void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg) case MON_DATA_IS_EGG: SET8(substruct3->isEgg); if (substruct3->isEgg) - boxMon->isEgg = 1; + boxMon->isEgg = TRUE; else - boxMon->isEgg = 0; + boxMon->isEgg = FALSE; break; case MON_DATA_ABILITY_NUM: SET8(substruct3->abilityNum); @@ -4337,7 +4384,7 @@ u8 GiveMonToPlayer(struct Pokemon *mon) return MON_GIVEN_TO_PARTY; } -u8 SendMonToPC(struct Pokemon* mon) +static u8 SendMonToPC(struct Pokemon* mon) { s32 boxNo, boxPos; @@ -4468,7 +4515,7 @@ void CreateSecretBaseEnemyParty(struct SecretBase *secretBaseRecord) gBattleResources->secretBase->party.species[i], gBattleResources->secretBase->party.levels[i], 15, - 1, + TRUE, gBattleResources->secretBase->party.personality[i], OT_ID_RANDOM_NO_SHINY, 0); @@ -4489,13 +4536,13 @@ void CreateSecretBaseEnemyParty(struct SecretBase *secretBaseRecord) u8 GetSecretBaseTrainerPicIndex(void) { - u8 facilityClass = sSecretBaseFacilityClasses[gBattleResources->secretBase->gender][gBattleResources->secretBase->trainerId[0] % 5]; + u8 facilityClass = sSecretBaseFacilityClasses[gBattleResources->secretBase->gender][gBattleResources->secretBase->trainerId[0] % NUM_SECRET_BASE_CLASSES]; return gFacilityClassToPicIndex[facilityClass]; } u8 GetSecretBaseTrainerClass(void) { - u8 facilityClass = sSecretBaseFacilityClasses[gBattleResources->secretBase->gender][gBattleResources->secretBase->trainerId[0] % 5]; + u8 facilityClass = sSecretBaseFacilityClasses[gBattleResources->secretBase->gender][gBattleResources->secretBase->trainerId[0] % NUM_SECRET_BASE_CLASSES]; return gFacilityClassToTrainerClass[facilityClass]; } @@ -4529,7 +4576,7 @@ void GetSpeciesName(u8 *name, u16 species) for (i = 0; i <= POKEMON_NAME_LENGTH; i++) { if (species > NUM_SPECIES) - name[i] = gSpeciesNames[0][i]; + name[i] = gSpeciesNames[SPECIES_NONE][i]; else name[i] = gSpeciesNames[species][i]; @@ -4549,13 +4596,13 @@ u8 CalculatePPWithBonus(u16 move, u8 ppBonuses, u8 moveIndex) void RemoveMonPPBonus(struct Pokemon *mon, u8 moveIndex) { u8 ppBonuses = GetMonData(mon, MON_DATA_PP_BONUSES, NULL); - ppBonuses &= gPPUpSetMask[moveIndex]; + ppBonuses &= gPPUpClearMask[moveIndex]; SetMonData(mon, MON_DATA_PP_BONUSES, &ppBonuses); } void RemoveBattleMonPPBonus(struct BattlePokemon *mon, u8 moveIndex) { - mon->ppBonuses &= gPPUpSetMask[moveIndex]; + mon->ppBonuses &= gPPUpClearMask[moveIndex]; } void CopyPlayerPartyMonToBattleData(u8 battlerId, u8 partyIndex) @@ -4618,7 +4665,7 @@ bool8 ExecuteTableBasedItemEffect(struct Pokemon *mon, u16 item, u8 partyIndex, return PokemonUseItemEffects(mon, item, partyIndex, moveIndex, FALSE); } -#define UPDATE_FRIENDSHIP_FROM_ITEM \ +#define UPDATE_FRIENDSHIP_FROM_ITEM() \ { \ if ((retVal == 0 || friendshipOnly) && !ShouldSkipFriendshipChange() && friendshipChange == 0) \ { \ @@ -4855,7 +4902,7 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov temp1 = CalculatePPWithBonus(GetMonData(mon, MON_DATA_MOVE1 + moveIndex, NULL), GetMonData(mon, MON_DATA_PP_BONUSES, NULL), moveIndex); if (dataUnsigned <= 2 && temp1 > 4) { - dataUnsigned = GetMonData(mon, MON_DATA_PP_BONUSES, NULL) + gPPUpAddMask[moveIndex]; + dataUnsigned = GetMonData(mon, MON_DATA_PP_BONUSES, NULL) + gPPUpAddValues[moveIndex]; SetMonData(mon, MON_DATA_PP_BONUSES, &dataUnsigned); dataUnsigned = CalculatePPWithBonus(GetMonData(mon, MON_DATA_MOVE1 + moveIndex, NULL), dataUnsigned, moveIndex) - temp1; @@ -5152,11 +5199,13 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov case 4: // ITEM5_PP_MAX dataUnsigned = (GetMonData(mon, MON_DATA_PP_BONUSES, NULL) & gPPUpGetMask[moveIndex]) >> (moveIndex * 2); temp2 = CalculatePPWithBonus(GetMonData(mon, MON_DATA_MOVE1 + moveIndex, NULL), GetMonData(mon, MON_DATA_PP_BONUSES, NULL), moveIndex); - if (dataUnsigned < 3 && temp2 > 4) + + // Check if 3 PP Ups have been applied already, and that the move has a total PP of at least 5 (excludes Sketch) + if (dataUnsigned < 3 && temp2 >= 5) { dataUnsigned = GetMonData(mon, MON_DATA_PP_BONUSES, NULL); - dataUnsigned &= gPPUpSetMask[moveIndex]; - dataUnsigned += gPPUpAddMask[moveIndex] * 3; + dataUnsigned &= gPPUpClearMask[moveIndex]; + dataUnsigned += gPPUpAddValues[moveIndex] * 3; // Apply 3 PP Ups (max) SetMonData(mon, MON_DATA_PP_BONUSES, &dataUnsigned); dataUnsigned = CalculatePPWithBonus(GetMonData(mon, MON_DATA_MOVE1 + moveIndex, NULL), dataUnsigned, moveIndex) - temp2; @@ -5172,25 +5221,19 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov // In general, Pokémon with lower friendship receive more, // and Pokémon with higher friendship receive less. if (GetMonData(mon, MON_DATA_FRIENDSHIP, NULL) < 100) - { - UPDATE_FRIENDSHIP_FROM_ITEM; - } + UPDATE_FRIENDSHIP_FROM_ITEM(); itemEffectParam++; break; case 6: // ITEM5_FRIENDSHIP_MID if (GetMonData(mon, MON_DATA_FRIENDSHIP, NULL) >= 100 && GetMonData(mon, MON_DATA_FRIENDSHIP, NULL) < 200) - { - UPDATE_FRIENDSHIP_FROM_ITEM; - } + UPDATE_FRIENDSHIP_FROM_ITEM(); itemEffectParam++; break; case 7: // ITEM5_FRIENDSHIP_HIGH if (GetMonData(mon, MON_DATA_FRIENDSHIP, NULL) >= 200) - { - UPDATE_FRIENDSHIP_FROM_ITEM; - } + UPDATE_FRIENDSHIP_FROM_ITEM(); itemEffectParam++; break; } @@ -5496,7 +5539,7 @@ u16 GetEvolutionTargetSpecies(struct Pokemon *mon, u8 mode, u16 evolutionItem) case EVO_TRADE_ITEM: if (gEvolutionTable[species][i].param == heldItem) { - heldItem = 0; + heldItem = ITEM_NONE; SetMonData(mon, MON_DATA_HELD_ITEM, &heldItem); targetSpecies = gEvolutionTable[species][i].targetSpecies; } @@ -5530,7 +5573,7 @@ u16 HoennPokedexNumToSpecies(u16 hoennNum) species = 0; - while (species < (NUM_SPECIES - 1) && gSpeciesToHoennPokedexNum[species] != hoennNum) + while (species < (NUM_SPECIES - 1) && sSpeciesToHoennPokedexNum[species] != hoennNum) species++; if (species == NUM_SPECIES - 1) @@ -5548,7 +5591,7 @@ u16 NationalPokedexNumToSpecies(u16 nationalNum) species = 0; - while (species < (NUM_SPECIES - 1) && gSpeciesToNationalPokedexNum[species] != nationalNum) + while (species < (NUM_SPECIES - 1) && sSpeciesToNationalPokedexNum[species] != nationalNum) species++; if (species == NUM_SPECIES - 1) @@ -5566,7 +5609,7 @@ u16 NationalToHoennOrder(u16 nationalNum) hoennNum = 0; - while (hoennNum < (NUM_SPECIES - 1) && gHoennToNationalOrder[hoennNum] != nationalNum) + while (hoennNum < (NUM_SPECIES - 1) && sHoennToNationalOrder[hoennNum] != nationalNum) hoennNum++; if (hoennNum == NUM_SPECIES - 1) @@ -5580,7 +5623,7 @@ u16 SpeciesToNationalPokedexNum(u16 species) if (!species) return 0; - return gSpeciesToNationalPokedexNum[species - 1]; + return sSpeciesToNationalPokedexNum[species - 1]; } u16 SpeciesToHoennPokedexNum(u16 species) @@ -5588,7 +5631,7 @@ u16 SpeciesToHoennPokedexNum(u16 species) if (!species) return 0; - return gSpeciesToHoennPokedexNum[species - 1]; + return sSpeciesToHoennPokedexNum[species - 1]; } u16 HoennToNationalOrder(u16 hoennNum) @@ -5596,7 +5639,7 @@ u16 HoennToNationalOrder(u16 hoennNum) if (!hoennNum) return 0; - return gHoennToNationalOrder[hoennNum - 1]; + return sHoennToNationalOrder[hoennNum - 1]; } u16 SpeciesToCryId(u16 species) @@ -5655,11 +5698,13 @@ u16 SpeciesToCryId(u16 species) } \ } +// Same as DrawSpindaSpots but attempts to discern for itself whether or +// not it's the front pic. static void DrawSpindaSpotsUnused(u16 species, u32 personality, u8 *dest) { if (species == SPECIES_SPINDA - && dest != gMonSpritesGfxPtr->sprites.ptr[0] - && dest != gMonSpritesGfxPtr->sprites.ptr[2]) + && dest != gMonSpritesGfxPtr->sprites.ptr[B_POSITION_PLAYER_LEFT] + && dest != gMonSpritesGfxPtr->sprites.ptr[B_POSITION_PLAYER_RIGHT]) DRAW_SPINDA_SPOTS; } @@ -6276,7 +6321,7 @@ u16 GetBattleBGM(void) return MUS_VS_GYM_LEADER; case TRAINER_CLASS_CHAMPION: return MUS_VS_CHAMPION; - case TRAINER_CLASS_PKMN_TRAINER_3: + case TRAINER_CLASS_RIVAL: if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER) return MUS_VS_RIVAL; if (!StringCompare(gTrainers[gTrainerBattleOpponent_A].trainerName, gText_BattleWallyName)) @@ -6355,9 +6400,9 @@ const u32 *GetMonSpritePalFromSpeciesAndPersonality(u16 species, u32 otId, u32 p u32 shinyValue; if (species > NUM_SPECIES) - return gMonPaletteTable[0].data; + return gMonPaletteTable[SPECIES_NONE].data; - shinyValue = HIHALF(otId) ^ LOHALF(otId) ^ HIHALF(personality) ^ LOHALF(personality); + shinyValue = GET_SHINY_VALUE(otId, personality); if (shinyValue < SHINY_ODDS) return gMonShinyPaletteTable[species].data; else @@ -6376,7 +6421,7 @@ const struct CompressedSpritePalette *GetMonSpritePalStructFromOtIdPersonality(u { u32 shinyValue; - shinyValue = HIHALF(otId) ^ LOHALF(otId) ^ HIHALF(personality) ^ LOHALF(personality); + shinyValue = GET_SHINY_VALUE(otId, personality); if (shinyValue < SHINY_ODDS) return &gMonShinyPaletteTable[species]; else @@ -6424,12 +6469,11 @@ bool8 IsOtherTrainer(u32 otId, u8 *otName) { if (otId == (gSaveBlock2Ptr->playerTrainerId[0] - | (gSaveBlock2Ptr->playerTrainerId[1] << 8) - | (gSaveBlock2Ptr->playerTrainerId[2] << 16) - | (gSaveBlock2Ptr->playerTrainerId[3] << 24))) + | (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; @@ -6494,28 +6538,30 @@ void SetWildMonHeldItem(void) { u16 rnd = Random() % 100; u16 species = GetMonData(&gEnemyParty[0], MON_DATA_SPECIES, 0); - u16 var1 = 45; - u16 var2 = 95; + u16 chanceNoItem = 45; + u16 chanceCommon = 95; if (!GetMonData(&gPlayerParty[0], MON_DATA_SANITY_IS_EGG, 0) && GetMonAbility(&gPlayerParty[0]) == ABILITY_COMPOUND_EYES) { - var1 = 20; - var2 = 80; + chanceNoItem = 20; + chanceCommon = 80; } if (gMapHeader.mapLayoutId == LAYOUT_ALTERING_CAVE) { s32 alteringCaveId = GetWildMonTableIdInAlteringCave(species); if (alteringCaveId != 0) { - if (rnd < var2) + // In active Altering Cave, use special item list + if (rnd < chanceCommon) return; SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &sAlteringCaveWildMonHeldItems[alteringCaveId].item); } else { - if (rnd < var1) + // In inactive Altering Cave, use normal items + if (rnd < chanceNoItem) return; - if (rnd < var2) + if (rnd < chanceCommon) SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gBaseStats[species].item1); else SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gBaseStats[species].item2); @@ -6523,15 +6569,16 @@ void SetWildMonHeldItem(void) } else { - if (gBaseStats[species].item1 == gBaseStats[species].item2 && gBaseStats[species].item1 != 0) + if (gBaseStats[species].item1 == gBaseStats[species].item2 && gBaseStats[species].item1 != ITEM_NONE) { + // Both held items are the same, 100% chance to hold item SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gBaseStats[species].item1); } else { - if (rnd < var1) + if (rnd < chanceNoItem) return; - if (rnd < var2) + if (rnd < chanceCommon) SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gBaseStats[species].item1); else SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gBaseStats[species].item2); @@ -6550,7 +6597,7 @@ bool8 IsMonShiny(struct Pokemon *mon) bool8 IsShinyOtIdPersonality(u32 otId, u32 personality) { bool8 retVal = FALSE; - u32 shinyValue = HIHALF(otId) ^ LOHALF(otId) ^ HIHALF(personality) ^ LOHALF(personality); + u32 shinyValue = GET_SHINY_VALUE(otId, personality); if (shinyValue < SHINY_ODDS) retVal = TRUE; return retVal; @@ -6588,37 +6635,40 @@ const u8 *GetTrainerPartnerName(void) gTasks[taskId].data[dataId + 1] = (u32)(ptr) >> 16; \ } +#define sAnimId data[2] +#define sAnimDelay data[3] + static void Task_AnimateAfterDelay(u8 taskId) { - if (--gTasks[taskId].data[3] == 0) + if (--gTasks[taskId].sAnimDelay == 0) { - LaunchAnimationTaskForFrontSprite(READ_PTR_FROM_TASK(taskId, 0), gTasks[taskId].data[2]); + LaunchAnimationTaskForFrontSprite(READ_PTR_FROM_TASK(taskId, 0), gTasks[taskId].sAnimId); DestroyTask(taskId); } } static void Task_PokemonSummaryAnimateAfterDelay(u8 taskId) { - if (--gTasks[taskId].data[3] == 0) + if (--gTasks[taskId].sAnimDelay == 0) { - StartMonSummaryAnimation(READ_PTR_FROM_TASK(taskId, 0), gTasks[taskId].data[2]); + StartMonSummaryAnimation(READ_PTR_FROM_TASK(taskId, 0), gTasks[taskId].sAnimId); SummaryScreen_SetAnimDelayTaskId(TASK_NONE); DestroyTask(taskId); } } -void BattleAnimateFrontSprite(struct Sprite* sprite, u16 species, bool8 noCry, u8 arg3) +void BattleAnimateFrontSprite(struct Sprite* sprite, u16 species, bool8 noCry, u8 panMode) { if (gHitMarker & HITMARKER_NO_ANIMATIONS && !(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK))) - DoMonFrontSpriteAnimation(sprite, species, noCry, arg3 | 0x80); + DoMonFrontSpriteAnimation(sprite, species, noCry, panMode | SKIP_FRONT_ANIM); else - DoMonFrontSpriteAnimation(sprite, species, noCry, arg3); + DoMonFrontSpriteAnimation(sprite, species, noCry, panMode); } -void DoMonFrontSpriteAnimation(struct Sprite* sprite, u16 species, bool8 noCry, u8 arg3) +void DoMonFrontSpriteAnimation(struct Sprite* sprite, u16 species, bool8 noCry, u8 panModeAnimFlag) { s8 pan; - switch (arg3 & 0x7F) + switch (panModeAnimFlag & (u8)~SKIP_FRONT_ANIM) // Exclude anim flag to get pan mode { case 0: pan = -25; @@ -6630,8 +6680,9 @@ void DoMonFrontSpriteAnimation(struct Sprite* sprite, u16 species, bool8 noCry, pan = 0; break; } - if (arg3 & 0x80) + if (panModeAnimFlag & SKIP_FRONT_ANIM) { + // No animation, only check if cry needs to be played if (!noCry) PlayCry1(species, pan); sprite->callback = SpriteCallbackDummy; @@ -6646,13 +6697,15 @@ void DoMonFrontSpriteAnimation(struct Sprite* sprite, u16 species, bool8 noCry, } if (sMonAnimationDelayTable[species - 1] != 0) { + // Animation has delay, start delay task u8 taskId = CreateTask(Task_AnimateAfterDelay, 0); STORE_PTR_IN_TASK(sprite, taskId, 0); - gTasks[taskId].data[2] = sMonFrontAnimIdsTable[species - 1]; - gTasks[taskId].data[3] = sMonAnimationDelayTable[species - 1]; + gTasks[taskId].sAnimId = sMonFrontAnimIdsTable[species - 1]; + gTasks[taskId].sAnimDelay = sMonAnimationDelayTable[species - 1]; } else { + // No delay, start animation LaunchAnimationTaskForFrontSprite(sprite, sMonFrontAnimIdsTable[species - 1]); } sprite->callback = SpriteCallbackDummy_2; @@ -6665,15 +6718,17 @@ void PokemonSummaryDoMonAnimation(struct Sprite* sprite, u16 species, bool8 oneF StartSpriteAnim(sprite, 1); if (sMonAnimationDelayTable[species - 1] != 0) { + // Animation has delay, start delay task u8 taskId = CreateTask(Task_PokemonSummaryAnimateAfterDelay, 0); STORE_PTR_IN_TASK(sprite, taskId, 0); - gTasks[taskId].data[2] = sMonFrontAnimIdsTable[species - 1]; - gTasks[taskId].data[3] = sMonAnimationDelayTable[species - 1]; + gTasks[taskId].sAnimId = sMonFrontAnimIdsTable[species - 1]; + gTasks[taskId].sAnimDelay = sMonAnimationDelayTable[species - 1]; SummaryScreen_SetAnimDelayTaskId(taskId); SetSpriteCB_MonAnimDummy(sprite); } else { + // No delay, start animation StartMonSummaryAnimation(sprite, sMonFrontAnimIdsTable[species - 1]); } } @@ -6698,48 +6753,50 @@ void BattleAnimateBackSprite(struct Sprite* sprite, u16 species) } } -u8 sub_806EF08(u8 arg0) +// Unused, identical to GetOpposingLinkMultiBattlerId but for the player +// "rightSide" from that team's perspective, i.e. B_POSITION_*_RIGHT +static u8 GetOwnOpposingLinkMultiBattlerId(bool8 rightSide) { s32 i; - s32 var = 0; + s32 battlerId = 0; u8 multiplayerId = GetMultiplayerId(); switch (gLinkPlayers[multiplayerId].id) { case 0: case 2: - var = (arg0 != 0) ? 1 : 3; + battlerId = rightSide ? 1 : 3; break; case 1: case 3: - var = (arg0 != 0) ? 2 : 0; + battlerId = rightSide ? 2 : 0; break; } for (i = 0; i < MAX_LINK_PLAYERS; i++) { - if (gLinkPlayers[i].id == (s16)(var)) + if (gLinkPlayers[i].id == (s16)battlerId) break; } return i; } -u8 sub_806EF84(u8 arg0, u8 arg1) +u8 GetOpposingLinkMultiBattlerId(bool8 rightSide, u8 multiplayerId) { s32 i; - s32 var = 0; - switch (gLinkPlayers[arg1].id) + s32 battlerId = 0; + switch (gLinkPlayers[multiplayerId].id) { case 0: case 2: - var = (arg0 != 0) ? 1 : 3; + battlerId = rightSide ? 1 : 3; break; case 1: case 3: - var = (arg0 != 0) ? 2 : 0; + battlerId = rightSide ? 2 : 0; break; } for (i = 0; i < MAX_LINK_PLAYERS; i++) { - if (gLinkPlayers[i].id == (s16)(var)) + if (gLinkPlayers[i].id == (s16)battlerId) break; } return i; @@ -6788,9 +6845,9 @@ const u8 *GetTrainerNameFromId(u16 trainerId) bool8 HasTwoFramesAnimation(u16 species) { return (species != SPECIES_CASTFORM - && species != SPECIES_DEOXYS - && species != SPECIES_SPINDA - && species != SPECIES_UNOWN); + && species != SPECIES_DEOXYS + && species != SPECIES_SPINDA + && species != SPECIES_UNOWN); } static bool8 ShouldSkipFriendshipChange(void) @@ -6802,174 +6859,186 @@ static bool8 ShouldSkipFriendshipChange(void) return FALSE; } -static void sub_806F160(struct Unknown_806F160_Struct* structPtr) +// The below functions are for the 'MonSpritesGfxManager', a method of allocating +// space for Pokémon sprites. These are only used for the summary screen Pokémon +// sprites (unless gMonSpritesGfxPtr is in use), but were set up for more general use. +// Only the 'default' mode (MON_SPR_GFX_MODE_NORMAL) is used, which is set +// up to allocate 4 sprites using the battler sprite templates (gBattlerSpriteTemplates). +// MON_SPR_GFX_MODE_BATTLE is identical but never used. +// MON_SPR_GFX_MODE_FULL_PARTY is set up to allocate 7 sprites (party + trainer?) +// using a generic 64x64 template, and is also never used. + +// Between the unnecessarily large sizes below, a mistake allocating the spritePointers +// field, and the fact that ultimately only 1 of the 4 sprite positions is used, this +// system wastes a good deal of memory. + +#define ALLOC_FAIL_BUFFER (1 << 0) +#define ALLOC_FAIL_STRUCT (1 << 1) +#define GFX_MANAGER_ACTIVE 0xA3 // Arbitrary value +#define GFX_MANAGER_SPR_SIZE (MON_PIC_SIZE * 4) // * 4 is unnecessary, MON_PIC_SIZE is sufficient +#define GFX_MANAGER_NUM_FRAMES 4 // Only 2 frames are needed + +static void InitMonSpritesGfx_Battle(struct MonSpritesGfxManager* gfx) { u16 i, j; - for (i = 0; i < structPtr->field_0_0; i++) + for (i = 0; i < gfx->numSprites; i++) { - structPtr->templates[i] = gBattlerSpriteTemplates[i]; - for (j = 0; j < structPtr->field_1; j++) - { - structPtr->frameImages[i * structPtr->field_1 + j].data = &structPtr->byteArrays[i][j * 0x800]; - } - structPtr->templates[i].images = &structPtr->frameImages[i * structPtr->field_1]; + gfx->templates[i] = gBattlerSpriteTemplates[i]; + for (j = 0; j < gfx->numFrames; j++) + gfx->frameImages[i * gfx->numFrames + j].data = &gfx->spritePointers[i][j * MON_PIC_SIZE]; + + gfx->templates[i].images = &gfx->frameImages[i * gfx->numFrames]; } } -static void sub_806F1FC(struct Unknown_806F160_Struct* structPtr) +static void InitMonSpritesGfx_FullParty(struct MonSpritesGfxManager* gfx) { u16 i, j; - for (i = 0; i < structPtr->field_0_0; i++) + for (i = 0; i < gfx->numSprites; i++) { - 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 = gAnims_MonPic; - structPtr->templates[i].paletteTag = i; + gfx->templates[i] = sSpriteTemplate_64x64; + for (j = 0; j < gfx->numFrames; j++) + gfx->frameImages[i * gfx->numSprites + j].data = &gfx->spritePointers[i][j * MON_PIC_SIZE]; + + gfx->templates[i].images = &gfx->frameImages[i * gfx->numSprites]; + gfx->templates[i].anims = gAnims_MonPic; + gfx->templates[i].paletteTag = i; } } -struct Unknown_806F160_Struct *sub_806F2AC(u8 id, u8 arg1) +struct MonSpritesGfxManager *CreateMonSpritesGfxManager(u8 managerId, u8 mode) { u8 i; - u8 flags; - struct Unknown_806F160_Struct *structPtr; + u8 failureFlags; + struct MonSpritesGfxManager *gfx; - flags = 0; - id %= 2; - structPtr = AllocZeroed(sizeof(*structPtr)); - if (structPtr == NULL) + failureFlags = 0; + managerId %= MON_SPR_GFX_MANAGERS_COUNT; + gfx = AllocZeroed(sizeof(*gfx)); + if (gfx == NULL) return NULL; - switch (arg1) + switch (mode) { - 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; + case MON_SPR_GFX_MODE_FULL_PARTY: + gfx->numSprites = PARTY_SIZE + 1; + gfx->numSprites2 = PARTY_SIZE + 1; + gfx->numFrames = GFX_MANAGER_NUM_FRAMES; + gfx->dataSize = 1; + gfx->mode = MON_SPR_GFX_MODE_FULL_PARTY; break; - case 0: + // case MON_SPR_GFX_MODE_BATTLE: + case MON_SPR_GFX_MODE_NORMAL: 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; + gfx->numSprites = MAX_BATTLERS_COUNT; + gfx->numSprites2 = MAX_BATTLERS_COUNT; + gfx->numFrames = GFX_MANAGER_NUM_FRAMES; + gfx->dataSize = 1; + gfx->mode = MON_SPR_GFX_MODE_NORMAL; break; } - structPtr->bytes = AllocZeroed(structPtr->field_3_0 * 0x800 * 4 * structPtr->field_0_0); - structPtr->byteArrays = AllocZeroed(structPtr->field_0_0 * 32); - if (structPtr->bytes == NULL || structPtr->byteArrays == NULL) + // Set up sprite / sprite pointer buffers + gfx->spriteBuffer = AllocZeroed(gfx->dataSize * GFX_MANAGER_SPR_SIZE * gfx->numSprites); + gfx->spritePointers = AllocZeroed(gfx->numSprites * 32); // ? Only * 4 is necessary, perhaps they were thinking bits. + if (gfx->spriteBuffer == NULL || gfx->spritePointers == NULL) { - flags |= 1; + failureFlags |= ALLOC_FAIL_BUFFER; } else { - for (i = 0; i < structPtr->field_0_0; i++) - structPtr->byteArrays[i] = structPtr->bytes + (structPtr->field_3_0 * (i << 13)); + for (i = 0; i < gfx->numSprites; i++) + gfx->spritePointers[i] = gfx->spriteBuffer + (gfx->dataSize * GFX_MANAGER_SPR_SIZE * i); } - 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) + // Set up sprite structs + gfx->templates = AllocZeroed(sizeof(struct SpriteTemplate) * gfx->numSprites); + gfx->frameImages = AllocZeroed(sizeof(struct SpriteFrameImage) * gfx->numSprites * gfx->numFrames); + if (gfx->templates == NULL || gfx->frameImages == NULL) { - flags |= 2; + failureFlags |= ALLOC_FAIL_STRUCT; } else { - for (i = 0; i < structPtr->field_1 * structPtr->field_0_0; i++) - structPtr->frameImages[i].size = 0x800; + for (i = 0; i < gfx->numFrames * gfx->numSprites; i++) + gfx->frameImages[i].size = MON_PIC_SIZE; - switch (structPtr->field_3_1) + switch (gfx->mode) { - case 2: - sub_806F1FC(structPtr); + case MON_SPR_GFX_MODE_FULL_PARTY: + InitMonSpritesGfx_FullParty(gfx); break; - case 0: - case 1: + case MON_SPR_GFX_MODE_NORMAL: + case MON_SPR_GFX_MODE_BATTLE: default: - sub_806F160(structPtr); + InitMonSpritesGfx_Battle(gfx); break; } } - if (flags & 2) + // If either of the allocations failed free their respective members + if (failureFlags & ALLOC_FAIL_STRUCT) { - if (structPtr->frameImages != NULL) - FREE_AND_SET_NULL(structPtr->frameImages); - if (structPtr->templates != NULL) - FREE_AND_SET_NULL(structPtr->templates); + TRY_FREE_AND_SET_NULL(gfx->frameImages); + TRY_FREE_AND_SET_NULL(gfx->templates); } - if (flags & 1) + if (failureFlags & ALLOC_FAIL_BUFFER) { - if (structPtr->byteArrays != NULL) - FREE_AND_SET_NULL(structPtr->byteArrays); - if (structPtr->bytes != NULL) - FREE_AND_SET_NULL(structPtr->bytes); + TRY_FREE_AND_SET_NULL(gfx->spritePointers); + TRY_FREE_AND_SET_NULL(gfx->spriteBuffer); } - if (flags) + if (failureFlags) { - memset(structPtr, 0, sizeof(*structPtr)); - Free(structPtr); + // Clear, something failed to allocate + memset(gfx, 0, sizeof(*gfx)); + Free(gfx); } else { - structPtr->magic = 0xA3; - gUnknown_020249B4[id] = structPtr; + gfx->active = GFX_MANAGER_ACTIVE; + sMonSpritesGfxManagers[managerId] = gfx; } - return gUnknown_020249B4[id]; + return sMonSpritesGfxManagers[managerId]; } -void sub_806F47C(u8 id) +void DestroyMonSpritesGfxManager(u8 managerId) { - struct Unknown_806F160_Struct *structPtr; + struct MonSpritesGfxManager *gfx; - id %= 2; - structPtr = gUnknown_020249B4[id]; - if (structPtr == NULL) + managerId %= MON_SPR_GFX_MANAGERS_COUNT; + gfx = sMonSpritesGfxManagers[managerId]; + if (gfx == NULL) return; - if (structPtr->magic != 0xA3) + if (gfx->active != GFX_MANAGER_ACTIVE) { - memset(structPtr, 0, sizeof(struct Unknown_806F160_Struct)); + memset(gfx, 0, sizeof(*gfx)); } else { - - if (structPtr->frameImages != NULL) - FREE_AND_SET_NULL(structPtr->frameImages); - if (structPtr->templates != NULL) - FREE_AND_SET_NULL(structPtr->templates); - if (structPtr->byteArrays != NULL) - FREE_AND_SET_NULL(structPtr->byteArrays); - if (structPtr->bytes != NULL) - FREE_AND_SET_NULL(structPtr->bytes); - - memset(structPtr, 0, sizeof(struct Unknown_806F160_Struct)); - Free(structPtr); + TRY_FREE_AND_SET_NULL(gfx->frameImages); + TRY_FREE_AND_SET_NULL(gfx->templates); + TRY_FREE_AND_SET_NULL(gfx->spritePointers); + TRY_FREE_AND_SET_NULL(gfx->spriteBuffer); + memset(gfx, 0, sizeof(*gfx)); + Free(gfx); } } -u8 *sub_806F4F8(u8 id, u8 arg1) +u8 *MonSpritesGfxManager_GetSpritePtr(u8 managerId, u8 spriteNum) { - struct Unknown_806F160_Struct *structPtr = gUnknown_020249B4[id % 2]; - if (structPtr->magic != 0xA3) + struct MonSpritesGfxManager *gfx = sMonSpritesGfxManagers[managerId % MON_SPR_GFX_MANAGERS_COUNT]; + if (gfx->active != GFX_MANAGER_ACTIVE) { return NULL; } else { - if (arg1 >= structPtr->field_0_0) - arg1 = 0; + if (spriteNum >= gfx->numSprites) + spriteNum = 0; - return structPtr->byteArrays[arg1]; + return gfx->spritePointers[spriteNum]; } } diff --git a/src/pokemon_summary_screen.c b/src/pokemon_summary_screen.c index dc009bbff..5c4b19bc4 100644 --- a/src/pokemon_summary_screen.c +++ b/src/pokemon_summary_screen.c @@ -1111,7 +1111,7 @@ void ShowPokemonSummaryScreen(u8 mode, void *mons, u8 monIndex, u8 maxMonIndex, SummaryScreen_SetAnimDelayTaskId(TASK_NONE); if (gMonSpritesGfxPtr == NULL) - sub_806F2AC(0, 0); + CreateMonSpritesGfxManager(MON_SPR_GFX_MANAGER_A, MON_SPR_GFX_MODE_NORMAL); SetMainCallback2(CB2_InitSummaryScreen); } @@ -1500,7 +1500,7 @@ static void CloseSummaryScreen(u8 taskId) StopCryAndClearCrySongs(); m4aMPlayVolumeControl(&gMPlayInfo_BGM, 0xFFFF, 0x100); if (gMonSpritesGfxPtr == NULL) - sub_806F47C(0); + DestroyMonSpritesGfxManager(MON_SPR_GFX_MANAGER_A); FreeSummaryScreen(); DestroyTask(taskId); } @@ -3873,25 +3873,43 @@ static u8 LoadMonGfxAndSprite(struct Pokemon *mon, s16 *state) if (gMain.inBattle) { if (ShouldIgnoreDeoxysForm(3, sMonSummaryScreen->curMonIndex)) - HandleLoadSpecialPokePic_DontHandleDeoxys(&gMonFrontPicTable[summary->species2], gMonSpritesGfxPtr->sprites.ptr[1], summary->species2, summary->pid); + HandleLoadSpecialPokePic_DontHandleDeoxys(&gMonFrontPicTable[summary->species2], + gMonSpritesGfxPtr->sprites.ptr[B_POSITION_OPPONENT_LEFT], + summary->species2, + summary->pid); else - HandleLoadSpecialPokePic_2(&gMonFrontPicTable[summary->species2], gMonSpritesGfxPtr->sprites.ptr[1], summary->species2, summary->pid); + HandleLoadSpecialPokePic_2(&gMonFrontPicTable[summary->species2], + gMonSpritesGfxPtr->sprites.ptr[B_POSITION_OPPONENT_LEFT], + summary->species2, + summary->pid); } else { if (gMonSpritesGfxPtr != NULL) { if (sMonSummaryScreen->monList.mons == gPlayerParty || sMonSummaryScreen->mode == SUMMARY_MODE_BOX || sMonSummaryScreen->unk40EF == TRUE) - HandleLoadSpecialPokePic_2(&gMonFrontPicTable[summary->species2], gMonSpritesGfxPtr->sprites.ptr[1], summary->species2, summary->pid); + HandleLoadSpecialPokePic_2(&gMonFrontPicTable[summary->species2], + gMonSpritesGfxPtr->sprites.ptr[B_POSITION_OPPONENT_LEFT], + summary->species2, + summary->pid); else - HandleLoadSpecialPokePic_DontHandleDeoxys(&gMonFrontPicTable[summary->species2], gMonSpritesGfxPtr->sprites.ptr[1], summary->species2, summary->pid); + HandleLoadSpecialPokePic_DontHandleDeoxys(&gMonFrontPicTable[summary->species2], + gMonSpritesGfxPtr->sprites.ptr[B_POSITION_OPPONENT_LEFT], + summary->species2, + summary->pid); } else { if (sMonSummaryScreen->monList.mons == gPlayerParty || sMonSummaryScreen->mode == SUMMARY_MODE_BOX || sMonSummaryScreen->unk40EF == TRUE) - HandleLoadSpecialPokePic_2(&gMonFrontPicTable[summary->species2], sub_806F4F8(0, 1), summary->species2, summary->pid); + HandleLoadSpecialPokePic_2(&gMonFrontPicTable[summary->species2], + MonSpritesGfxManager_GetSpritePtr(MON_SPR_GFX_MANAGER_A, B_POSITION_OPPONENT_LEFT), + summary->species2, + summary->pid); else - HandleLoadSpecialPokePic_DontHandleDeoxys(&gMonFrontPicTable[summary->species2], sub_806F4F8(0, 1), summary->species2, summary->pid); + HandleLoadSpecialPokePic_DontHandleDeoxys(&gMonFrontPicTable[summary->species2], + MonSpritesGfxManager_GetSpritePtr(MON_SPR_GFX_MANAGER_A, B_POSITION_OPPONENT_LEFT), + summary->species2, + summary->pid); } } (*state)++; @@ -3899,7 +3917,7 @@ static u8 LoadMonGfxAndSprite(struct Pokemon *mon, s16 *state) case 1: pal = GetMonSpritePalStructFromOtIdPersonality(summary->species2, summary->OTID, summary->pid); LoadCompressedSpritePalette(pal); - SetMultiuseSpriteTemplateToPokemon(pal->tag, 1); + SetMultiuseSpriteTemplateToPokemon(pal->tag, B_POSITION_OPPONENT_LEFT); (*state)++; return 0xFF; } diff --git a/src/roamer.c b/src/roamer.c index d053e5b25..b8d100967 100644 --- a/src/roamer.c +++ b/src/roamer.c @@ -5,51 +5,74 @@ #include "roamer.h" #include "constants/maps.h" +// Despite having a variable to track it, the roamer is +// hard-coded to only ever be in map group 0 +#define ROAMER_MAP_GROUP 0 + enum { - MAP_GRP = 0, // map group - MAP_NUM = 1, // map number + MAP_GRP, // map group + MAP_NUM, // map number }; +#define ROAMER (&gSaveBlock1Ptr->roamer) EWRAM_DATA static u8 sLocationHistory[3][2] = {0}; EWRAM_DATA static u8 sRoamerLocation[2] = {0}; +#define ___ MAP_NUM(UNDEFINED) // For empty spots in the location table + +// Note: There are two potential softlocks that can occur with this table if its maps are +// changed in particular ways. They can be avoided by ensuring the following: +// - There must be at least 2 location sets that start with a different map, +// i.e. every location set cannot start with the same map. This is because of +// the while loop in RoamerMoveToOtherLocationSet. +// - Each location set must have at least 3 unique maps. This is because of +// the while loop in RoamerMove. In this loop the first map in the set is +// ignored, and an additional map is ignored if the roamer was there recently. +// - Additionally, while not a softlock, it's worth noting that if for any +// map in the location table there is not a location set that starts with +// that map then the roamer will be significantly less likely to move away +// from that map when it lands there. static const u8 sRoamerLocations[][6] = { - { MAP_NUM(ROUTE110), MAP_NUM(ROUTE111), MAP_NUM(ROUTE117), MAP_NUM(ROUTE118), MAP_NUM(ROUTE134), 0xFF }, - { MAP_NUM(ROUTE111), MAP_NUM(ROUTE110), MAP_NUM(ROUTE117), MAP_NUM(ROUTE118), 0xFF, 0xFF }, - { MAP_NUM(ROUTE117), MAP_NUM(ROUTE111), MAP_NUM(ROUTE110), MAP_NUM(ROUTE118), 0xFF, 0xFF }, + { MAP_NUM(ROUTE110), MAP_NUM(ROUTE111), MAP_NUM(ROUTE117), MAP_NUM(ROUTE118), MAP_NUM(ROUTE134), ___ }, + { MAP_NUM(ROUTE111), MAP_NUM(ROUTE110), MAP_NUM(ROUTE117), MAP_NUM(ROUTE118), ___, ___ }, + { MAP_NUM(ROUTE117), MAP_NUM(ROUTE111), MAP_NUM(ROUTE110), MAP_NUM(ROUTE118), ___, ___ }, { MAP_NUM(ROUTE118), MAP_NUM(ROUTE117), MAP_NUM(ROUTE110), MAP_NUM(ROUTE111), MAP_NUM(ROUTE119), MAP_NUM(ROUTE123) }, - { MAP_NUM(ROUTE119), MAP_NUM(ROUTE118), MAP_NUM(ROUTE120), 0xFF, 0xFF, 0xFF }, - { MAP_NUM(ROUTE120), MAP_NUM(ROUTE119), MAP_NUM(ROUTE121), 0xFF, 0xFF, 0xFF }, - { MAP_NUM(ROUTE121), MAP_NUM(ROUTE120), MAP_NUM(ROUTE122), MAP_NUM(ROUTE123), 0xFF, 0xFF }, - { MAP_NUM(ROUTE122), MAP_NUM(ROUTE121), MAP_NUM(ROUTE123), 0xFF, 0xFF, 0xFF }, - { MAP_NUM(ROUTE123), MAP_NUM(ROUTE122), MAP_NUM(ROUTE118), 0xFF, 0xFF, 0xFF }, - { MAP_NUM(ROUTE124), MAP_NUM(ROUTE121), MAP_NUM(ROUTE125), MAP_NUM(ROUTE126), 0xFF, 0xFF }, - { MAP_NUM(ROUTE125), MAP_NUM(ROUTE124), MAP_NUM(ROUTE127), 0xFF, 0xFF, 0xFF }, - { MAP_NUM(ROUTE126), MAP_NUM(ROUTE124), MAP_NUM(ROUTE127), 0xFF, 0xFF, 0xFF }, - { MAP_NUM(ROUTE127), MAP_NUM(ROUTE125), MAP_NUM(ROUTE126), MAP_NUM(ROUTE128), 0xFF, 0xFF }, - { MAP_NUM(ROUTE128), MAP_NUM(ROUTE127), MAP_NUM(ROUTE129), 0xFF, 0xFF, 0xFF }, - { MAP_NUM(ROUTE129), MAP_NUM(ROUTE128), MAP_NUM(ROUTE130), 0xFF, 0xFF, 0xFF }, - { MAP_NUM(ROUTE130), MAP_NUM(ROUTE129), MAP_NUM(ROUTE131), 0xFF, 0xFF, 0xFF }, - { MAP_NUM(ROUTE131), MAP_NUM(ROUTE130), MAP_NUM(ROUTE132), 0xFF, 0xFF, 0xFF }, - { MAP_NUM(ROUTE132), MAP_NUM(ROUTE131), MAP_NUM(ROUTE133), 0xFF, 0xFF, 0xFF }, - { MAP_NUM(ROUTE133), MAP_NUM(ROUTE132), MAP_NUM(ROUTE134), 0xFF, 0xFF, 0xFF }, - { MAP_NUM(ROUTE134), MAP_NUM(ROUTE133), MAP_NUM(ROUTE110), 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { MAP_NUM(ROUTE119), MAP_NUM(ROUTE118), MAP_NUM(ROUTE120), ___, ___, ___ }, + { MAP_NUM(ROUTE120), MAP_NUM(ROUTE119), MAP_NUM(ROUTE121), ___, ___, ___ }, + { MAP_NUM(ROUTE121), MAP_NUM(ROUTE120), MAP_NUM(ROUTE122), MAP_NUM(ROUTE123), ___, ___ }, + { MAP_NUM(ROUTE122), MAP_NUM(ROUTE121), MAP_NUM(ROUTE123), ___, ___, ___ }, + { MAP_NUM(ROUTE123), MAP_NUM(ROUTE122), MAP_NUM(ROUTE118), ___, ___, ___ }, + { MAP_NUM(ROUTE124), MAP_NUM(ROUTE121), MAP_NUM(ROUTE125), MAP_NUM(ROUTE126), ___, ___ }, + { MAP_NUM(ROUTE125), MAP_NUM(ROUTE124), MAP_NUM(ROUTE127), ___, ___, ___ }, + { MAP_NUM(ROUTE126), MAP_NUM(ROUTE124), MAP_NUM(ROUTE127), ___, ___, ___ }, + { MAP_NUM(ROUTE127), MAP_NUM(ROUTE125), MAP_NUM(ROUTE126), MAP_NUM(ROUTE128), ___, ___ }, + { MAP_NUM(ROUTE128), MAP_NUM(ROUTE127), MAP_NUM(ROUTE129), ___, ___, ___ }, + { MAP_NUM(ROUTE129), MAP_NUM(ROUTE128), MAP_NUM(ROUTE130), ___, ___, ___ }, + { MAP_NUM(ROUTE130), MAP_NUM(ROUTE129), MAP_NUM(ROUTE131), ___, ___, ___ }, + { MAP_NUM(ROUTE131), MAP_NUM(ROUTE130), MAP_NUM(ROUTE132), ___, ___, ___ }, + { MAP_NUM(ROUTE132), MAP_NUM(ROUTE131), MAP_NUM(ROUTE133), ___, ___, ___ }, + { MAP_NUM(ROUTE133), MAP_NUM(ROUTE132), MAP_NUM(ROUTE134), ___, ___, ___ }, + { MAP_NUM(ROUTE134), MAP_NUM(ROUTE133), MAP_NUM(ROUTE110), ___, ___, ___ }, + { ___, ___, ___, ___, ___, ___ }, }; +#undef ___ +#define NUM_LOCATION_SETS (ARRAY_COUNT(sRoamerLocations) - 1) +#define NUM_LOCATIONS_PER_SET (ARRAY_COUNT(sRoamerLocations[0])) + void ClearRoamerData(void) { - memset(&gSaveBlock1Ptr->roamer, 0, sizeof(struct Roamer)); - (&gSaveBlock1Ptr->roamer)->species = SPECIES_LATIAS; + memset(ROAMER, 0, sizeof(*ROAMER)); + ROAMER->species = SPECIES_LATIAS; } void ClearRoamerLocationData(void) { u8 i; - for (i = 0; i < 3; i++) + for (i = 0; i < ARRAY_COUNT(sLocationHistory); i++) { sLocationHistory[i][MAP_GRP] = 0; sLocationHistory[i][MAP_NUM] = 0; @@ -62,26 +85,27 @@ void ClearRoamerLocationData(void) static void CreateInitialRoamerMon(bool16 createLatios) { if (!createLatios) - (&gSaveBlock1Ptr->roamer)->species = SPECIES_LATIAS; + ROAMER->species = SPECIES_LATIAS; else - (&gSaveBlock1Ptr->roamer)->species = SPECIES_LATIOS; - - CreateMon(&gEnemyParty[0], (&gSaveBlock1Ptr->roamer)->species, 40, 0x20, 0, 0, OT_ID_PLAYER_ID, 0); - (&gSaveBlock1Ptr->roamer)->level = 40; - (&gSaveBlock1Ptr->roamer)->status = 0; - (&gSaveBlock1Ptr->roamer)->active = TRUE; - (&gSaveBlock1Ptr->roamer)->ivs = GetMonData(&gEnemyParty[0], MON_DATA_IVS); - (&gSaveBlock1Ptr->roamer)->personality = GetMonData(&gEnemyParty[0], MON_DATA_PERSONALITY); - (&gSaveBlock1Ptr->roamer)->hp = GetMonData(&gEnemyParty[0], MON_DATA_MAX_HP); - (&gSaveBlock1Ptr->roamer)->cool = GetMonData(&gEnemyParty[0], MON_DATA_COOL); - (&gSaveBlock1Ptr->roamer)->beauty = GetMonData(&gEnemyParty[0], MON_DATA_BEAUTY); - (&gSaveBlock1Ptr->roamer)->cute = GetMonData(&gEnemyParty[0], MON_DATA_CUTE); - (&gSaveBlock1Ptr->roamer)->smart = GetMonData(&gEnemyParty[0], MON_DATA_SMART); - (&gSaveBlock1Ptr->roamer)->tough = GetMonData(&gEnemyParty[0], MON_DATA_TOUGH); - sRoamerLocation[MAP_GRP] = 0; - sRoamerLocation[MAP_NUM] = sRoamerLocations[Random() % (ARRAY_COUNT(sRoamerLocations) - 1)][0]; + ROAMER->species = SPECIES_LATIOS; + + CreateMon(&gEnemyParty[0], ROAMER->species, 40, USE_RANDOM_IVS, FALSE, 0, OT_ID_PLAYER_ID, 0); + ROAMER->level = 40; + ROAMER->status = 0; + ROAMER->active = TRUE; + ROAMER->ivs = GetMonData(&gEnemyParty[0], MON_DATA_IVS); + ROAMER->personality = GetMonData(&gEnemyParty[0], MON_DATA_PERSONALITY); + ROAMER->hp = GetMonData(&gEnemyParty[0], MON_DATA_MAX_HP); + ROAMER->cool = GetMonData(&gEnemyParty[0], MON_DATA_COOL); + ROAMER->beauty = GetMonData(&gEnemyParty[0], MON_DATA_BEAUTY); + ROAMER->cute = GetMonData(&gEnemyParty[0], MON_DATA_CUTE); + ROAMER->smart = GetMonData(&gEnemyParty[0], MON_DATA_SMART); + ROAMER->tough = GetMonData(&gEnemyParty[0], MON_DATA_TOUGH); + sRoamerLocation[MAP_GRP] = ROAMER_MAP_GROUP; + sRoamerLocation[MAP_NUM] = sRoamerLocations[Random() % NUM_LOCATION_SETS][0]; } +// gSpecialVar_0x8004 here corresponds to the options in the multichoice MULTI_TV_LATI (0 for 'Red', 1 for 'Blue') void InitRoamer(void) { ClearRoamerData(); @@ -104,16 +128,17 @@ void UpdateLocationHistoryForRoamer(void) void RoamerMoveToOtherLocationSet(void) { u8 mapNum = 0; - struct Roamer *roamer = &gSaveBlock1Ptr->roamer; - - if (!roamer->active) + + if (!ROAMER->active) return; - sRoamerLocation[MAP_GRP] = 0; + sRoamerLocation[MAP_GRP] = ROAMER_MAP_GROUP; + // Choose a location set that starts with a map + // different from the roamer's current map while (1) { - mapNum = sRoamerLocations[Random() % (ARRAY_COUNT(sRoamerLocations) - 1)][0]; + mapNum = sRoamerLocations[Random() % NUM_LOCATION_SETS][0]; if (sRoamerLocation[MAP_NUM] != mapNum) { sRoamerLocation[MAP_NUM] = mapNum; @@ -132,20 +157,23 @@ void RoamerMove(void) } else { - struct Roamer *roamer = &gSaveBlock1Ptr->roamer; - - if (!roamer->active) + if (!ROAMER->active) return; - while (locSet < (ARRAY_COUNT(sRoamerLocations) - 1)) + while (locSet < NUM_LOCATION_SETS) { + // Find the location set that starts with the roamer's current map if (sRoamerLocation[MAP_NUM] == sRoamerLocations[locSet][0]) { u8 mapNum; while (1) { - mapNum = sRoamerLocations[locSet][(Random() % 5) + 1]; - if (!(sLocationHistory[2][MAP_GRP] == 0 && sLocationHistory[2][MAP_NUM] == mapNum) && mapNum != 0xFF) + // Choose a new map (excluding the first) within this set + // Also exclude a map if the roamer was there 2 moves ago + mapNum = sRoamerLocations[locSet][(Random() % (NUM_LOCATIONS_PER_SET - 1)) + 1]; + if (!(sLocationHistory[2][MAP_GRP] == ROAMER_MAP_GROUP + && sLocationHistory[2][MAP_NUM] == mapNum) + && mapNum != MAP_NUM(UNDEFINED)) break; } sRoamerLocation[MAP_NUM] = mapNum; @@ -158,9 +186,7 @@ void RoamerMove(void) bool8 IsRoamerAt(u8 mapGroup, u8 mapNum) { - struct Roamer *roamer = &gSaveBlock1Ptr->roamer; - - if (roamer->active && mapGroup == sRoamerLocation[MAP_GRP] && mapNum == sRoamerLocation[MAP_NUM]) + if (ROAMER->active && mapGroup == sRoamerLocation[MAP_GRP] && mapNum == sRoamerLocation[MAP_NUM]) return TRUE; else return FALSE; @@ -168,20 +194,16 @@ bool8 IsRoamerAt(u8 mapGroup, u8 mapNum) void CreateRoamerMonInstance(void) { - struct Pokemon *mon; - struct Roamer *roamer; - - mon = &gEnemyParty[0]; + struct Pokemon *mon = &gEnemyParty[0]; ZeroEnemyPartyMons(); - roamer = &gSaveBlock1Ptr->roamer; - CreateMonWithIVsPersonality(mon, roamer->species, roamer->level, roamer->ivs, roamer->personality); - SetMonData(mon, MON_DATA_STATUS, &gSaveBlock1Ptr->roamer.status); - SetMonData(mon, MON_DATA_HP, &gSaveBlock1Ptr->roamer.hp); - SetMonData(mon, MON_DATA_COOL, &gSaveBlock1Ptr->roamer.cool); - SetMonData(mon, MON_DATA_BEAUTY, &gSaveBlock1Ptr->roamer.beauty); - SetMonData(mon, MON_DATA_CUTE, &gSaveBlock1Ptr->roamer.cute); - SetMonData(mon, MON_DATA_SMART, &gSaveBlock1Ptr->roamer.smart); - SetMonData(mon, MON_DATA_TOUGH, &gSaveBlock1Ptr->roamer.tough); + CreateMonWithIVsPersonality(mon, ROAMER->species, ROAMER->level, ROAMER->ivs, ROAMER->personality); + SetMonData(mon, MON_DATA_STATUS, &ROAMER->status); + SetMonData(mon, MON_DATA_HP, &ROAMER->hp); + SetMonData(mon, MON_DATA_COOL, &ROAMER->cool); + SetMonData(mon, MON_DATA_BEAUTY, &ROAMER->beauty); + SetMonData(mon, MON_DATA_CUTE, &ROAMER->cute); + SetMonData(mon, MON_DATA_SMART, &ROAMER->smart); + SetMonData(mon, MON_DATA_TOUGH, &ROAMER->tough); } bool8 TryStartRoamerEncounter(void) @@ -199,16 +221,15 @@ bool8 TryStartRoamerEncounter(void) void UpdateRoamerHPStatus(struct Pokemon *mon) { - (&gSaveBlock1Ptr->roamer)->hp = GetMonData(mon, MON_DATA_HP); - (&gSaveBlock1Ptr->roamer)->status = GetMonData(mon, MON_DATA_STATUS); + ROAMER->hp = GetMonData(mon, MON_DATA_HP); + ROAMER->status = GetMonData(mon, MON_DATA_STATUS); RoamerMoveToOtherLocationSet(); } void SetRoamerInactive(void) { - struct Roamer *roamer = &gSaveBlock1Ptr->roamer; - roamer->active = FALSE; + ROAMER->active = FALSE; } void GetRoamerLocation(u8 *mapGroup, u8 *mapNum) diff --git a/src/save.c b/src/save.c index a803afedf..40fce4e8a 100644 --- a/src/save.c +++ b/src/save.c @@ -43,11 +43,12 @@ static u8 HandleWriteSector(u16 a1, const struct SaveSectionLocation *location); // (u8 *)structure was removed from the first statement of the macro in Emerald. // This is because malloc is used to allocate addresses so storing the raw // addresses should not be done in the offsets information. -#define SAVEBLOCK_CHUNK(structure, chunkNum) \ -{ \ - chunkNum * SECTOR_DATA_SIZE, \ - min(sizeof(structure) - chunkNum * SECTOR_DATA_SIZE, SECTOR_DATA_SIZE) \ -} \ +#define SAVEBLOCK_CHUNK(structure, chunkNum) \ +{ \ + chunkNum * SECTOR_DATA_SIZE, \ + sizeof(structure) >= chunkNum * SECTOR_DATA_SIZE ? \ + min(sizeof(structure) - chunkNum * SECTOR_DATA_SIZE, SECTOR_DATA_SIZE) : 0 \ +} static const struct SaveSectionOffsets sSaveSectionOffsets[] = { diff --git a/src/script_pokemon_util.c b/src/script_pokemon_util.c index 93a747772..07e86656e 100755 --- a/src/script_pokemon_util.c +++ b/src/script_pokemon_util.c @@ -65,17 +65,18 @@ u8 ScriptGiveMon(u16 species, u8 level, u16 item, u32 unused1, u32 unused2, u8 u u8 heldItem[2]; struct Pokemon mon; - CreateMon(&mon, species, level, USE_RANDOM_IVS, 0, 0, OT_ID_PLAYER_ID, 0); + CreateMon(&mon, species, level, USE_RANDOM_IVS, FALSE, 0, OT_ID_PLAYER_ID, 0); heldItem[0] = item; heldItem[1] = item >> 8; SetMonData(&mon, MON_DATA_HELD_ITEM, heldItem); sentToPc = GiveMonToPlayer(&mon); nationalDexNum = SpeciesToNationalPokedexNum(species); + // Don't set Pokédex flag for MON_CANT_GIVE switch(sentToPc) { - case 0: - case 1: + case MON_GIVEN_TO_PARTY: + case MON_GIVEN_TO_PC: GetSetPokedexFlag(nationalDexNum, FLAG_SET_SEEN); GetSetPokedexFlag(nationalDexNum, FLAG_SET_CAUGHT); break; diff --git a/src/trade.c b/src/trade.c index 60d999edd..d1fc14efe 100644 --- a/src/trade.c +++ b/src/trade.c @@ -2742,9 +2742,9 @@ static void LoadTradeMonPic(u8 whichParty, u8 state) personality = GetMonData(mon, MON_DATA_PERSONALITY); if (whichParty == TRADE_PLAYER) - HandleLoadSpecialPokePic_2(&gMonFrontPicTable[species], gMonSpritesGfxPtr->sprites.ptr[1], species, personality); + HandleLoadSpecialPokePic_2(&gMonFrontPicTable[species], gMonSpritesGfxPtr->sprites.ptr[B_POSITION_OPPONENT_LEFT], species, personality); else - HandleLoadSpecialPokePic_DontHandleDeoxys(&gMonFrontPicTable[species], gMonSpritesGfxPtr->sprites.ptr[whichParty * 2 + 1], species, personality); + HandleLoadSpecialPokePic_DontHandleDeoxys(&gMonFrontPicTable[species], gMonSpritesGfxPtr->sprites.ptr[whichParty * 2 + B_POSITION_OPPONENT_LEFT], species, personality); LoadCompressedSpritePalette(GetMonSpritePalStruct(mon)); sTradeData->monSpecies[whichParty] = species; @@ -3739,7 +3739,7 @@ static bool8 AnimateTradeSequenceCable(void) case TS_STATE_POKEBALL_ARRIVE_WAIT: if (gSprites[sTradeData->bouncingPokeballSpriteId].callback == SpriteCallbackDummy) { - HandleLoadSpecialPokePic_2(&gMonFrontPicTable[sTradeData->monSpecies[TRADE_PARTNER]], gMonSpritesGfxPtr->sprites.ptr[3], sTradeData->monSpecies[TRADE_PARTNER], sTradeData->monPersonalities[TRADE_PARTNER]); + HandleLoadSpecialPokePic_2(&gMonFrontPicTable[sTradeData->monSpecies[TRADE_PARTNER]], gMonSpritesGfxPtr->sprites.ptr[B_POSITION_OPPONENT_RIGHT], sTradeData->monSpecies[TRADE_PARTNER], sTradeData->monPersonalities[TRADE_PARTNER]); sTradeData->state++; } break; @@ -4237,7 +4237,7 @@ static bool8 AnimateTradeSequenceWireless(void) if (gSprites[sTradeData->bouncingPokeballSpriteId].callback == SpriteCallbackDummy) { HandleLoadSpecialPokePic_2(&gMonFrontPicTable[sTradeData->monSpecies[TRADE_PARTNER]], - gMonSpritesGfxPtr->sprites.ptr[3], + gMonSpritesGfxPtr->sprites.ptr[B_POSITION_OPPONENT_RIGHT], sTradeData->monSpecies[TRADE_PARTNER], sTradeData->monPersonalities[TRADE_PARTNER]); sTradeData->state++; diff --git a/src/trainer_hill.c b/src/trainer_hill.c index 70c2dd9d5..34fa24f74 100644 --- a/src/trainer_hill.c +++ b/src/trainer_hill.c @@ -126,7 +126,7 @@ struct {TRAINER_CLASS_PKMN_BREEDER, TRAINER_ENCOUNTER_MUSIC_FEMALE}, {TRAINER_CLASS_COLLECTOR, TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS}, {TRAINER_CLASS_PKMN_RANGER, TRAINER_ENCOUNTER_MUSIC_COOL}, - {TRAINER_CLASS_PKMN_TRAINER_3, TRAINER_ENCOUNTER_MUSIC_MALE}, + {TRAINER_CLASS_RIVAL, TRAINER_ENCOUNTER_MUSIC_MALE}, {TRAINER_CLASS_YOUNG_COUPLE, TRAINER_ENCOUNTER_MUSIC_GIRL}, {TRAINER_CLASS_PSYCHIC, TRAINER_ENCOUNTER_MUSIC_INTENSE}, {TRAINER_CLASS_SR_AND_JR, TRAINER_ENCOUNTER_MUSIC_TWINS}, |