diff --git a/.all-contributorsrc b/.all-contributorsrc index 5b6d38e32f..c8b79ba30e 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -321,7 +321,7 @@ "code" ] }, - { + { "login": "lordraindance2", "name": "lordraindance2", "avatar_url": "https://avatars.githubusercontent.com/u/47706100?v=4", @@ -329,6 +329,15 @@ "contributions": [ "code" ] + }, + { + "login": "pablopenna", + "name": "Pablo Pena", + "avatar_url": "https://avatars.githubusercontent.com/u/11214682?v=4", + "profile": "https://github.com/pablopenna", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, diff --git a/CREDITS.md b/CREDITS.md index 128f26df6f..ab5c596248 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -58,6 +58,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Zatsu
Zatsu

💻 poetahto
poetahto

💻 lordraindance2
lordraindance2

💻 + Pablo Pena
Pablo Pena

💻 diff --git a/Makefile b/Makefile index 8d3c5ad9a2..735bd25454 100644 --- a/Makefile +++ b/Makefile @@ -382,6 +382,9 @@ $(C_BUILDDIR)/pokedex_plus_hgss.o: CFLAGS := -mthumb -mthumb-interwork -O2 -mabi # Annoyingly we can't turn this on just for src/data/trainers.h $(C_BUILDDIR)/data.o: CFLAGS += -fno-show-column -fno-diagnostics-show-caret +# Needed for parity with pret +$(C_BUILDDIR)/graphics.o: override CFLAGS += -Wno-missing-braces + $(TEST_BUILDDIR)/%.o: CFLAGS := -mthumb -mthumb-interwork -O2 -mabi=apcs-gnu -mtune=arm7tdmi -march=armv4t -Wno-pointer-to-int-cast -Werror -Wall -Wno-strict-aliasing -Wno-attribute-alias -Woverride-init # Dependency rules (for the *.c & *.s sources to .o files) @@ -395,10 +398,10 @@ ifneq ($(KEEP_TEMPS),1) @echo "$(CC1) -o $@ $<" @$(CPP) $(CPPFLAGS) $< | $(PREPROC) -i $< charmap.txt | $(CC1) $(CFLAGS) -o - - | cat - <(echo -e ".text\n\t.align\t2, 0") | $(AS) $(ASFLAGS) -o $@ - else - @$(CPP) $(CPPFLAGS) $< -o $*.i - @$(PREPROC) $*.i charmap.txt | $(CC1) $(CFLAGS) -o $*.s - @echo -e ".text\n\t.align\t2, 0\n" >> $*.s - $(AS) $(ASFLAGS) -o $@ $*.s + @$(CPP) $(CPPFLAGS) $< -o $(C_BUILDDIR)/$*.i + @$(PREPROC) $(C_BUILDDIR)/$*.i charmap.txt | $(CC1) $(CFLAGS) -o $(C_BUILDDIR)/$*.s + @echo -e ".text\n\t.align\t2, 0\n" >> $(C_BUILDDIR)/$*.s + $(AS) $(ASFLAGS) -o $@ $(C_BUILDDIR)/$*.s endif $(C_BUILDDIR)/%.d: $(C_SUBDIR)/%.c diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 5d4fd7ed34..ea97d5e10e 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -2459,6 +2459,12 @@ 1: .endm + .macro jumpifabilitycantbesuppressed battler:req, jumpInstr:req + callnative BS_JumpIfAbilityCantBeSuppressed + .byte \battler + .4byte \jumpInstr + .endm + .macro setallytonexttarget jumpInstr:req jumpifbyte CMP_GREATER_THAN, gBattlerTarget, 0x1, 1f addbyte gBattlerTarget, 0x2 diff --git a/asm/macros/event.inc b/asm/macros/event.inc index d58f0197c2..3bc6516097 100644 --- a/asm/macros/event.inc +++ b/asm/macros/event.inc @@ -736,11 +736,11 @@ @ When used with an event script, you can also pass in an optional flag to disable music .macro trainerbattle_single trainer:req, intro_text:req, lose_text:req, event_script=FALSE, music=TRUE .if \event_script == FALSE - trainerbattle TRAINER_BATTLE_SINGLE, OBJ_ID_NONE, \trainer, \intro_text, \lose_text, NULL, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE + trainerbattle TRAINER_BATTLE_SINGLE, LOCALID_NONE, \trainer, \intro_text, \lose_text, NULL, LOCALID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE .elseif \music == TRUE - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT, OBJ_ID_NONE, \trainer, \intro_text, \lose_text, \event_script, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE + trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT, LOCALID_NONE, \trainer, \intro_text, \lose_text, \event_script, LOCALID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE .else - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT_NO_MUSIC, OBJ_ID_NONE, \trainer, \intro_text, \lose_text, \event_script, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE + trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT_NO_MUSIC, LOCALID_NONE, \trainer, \intro_text, \lose_text, \event_script, LOCALID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE .endif .endm @@ -748,27 +748,27 @@ @ and an optional event script. When used with an event script you can pass in an optional flag to disable music .macro trainerbattle_double trainer:req, intro_text:req, lose_text:req, not_enough_pkmn_text:req, event_script=FALSE, music=TRUE .if \event_script == FALSE - trainerbattle TRAINER_BATTLE_DOUBLE, OBJ_ID_NONE, \trainer, \intro_text, \lose_text, NULL, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, TRUE, TRUE, FALSE, FALSE + trainerbattle TRAINER_BATTLE_DOUBLE, LOCALID_NONE, \trainer, \intro_text, \lose_text, NULL, LOCALID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, TRUE, TRUE, FALSE, FALSE .elseif \music == TRUE - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE, OBJ_ID_NONE, \trainer, \intro_text, \lose_text, \event_script, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, TRUE, TRUE, FALSE, FALSE + trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE, LOCALID_NONE, \trainer, \intro_text, \lose_text, \event_script, LOCALID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, TRUE, TRUE, FALSE, FALSE .else - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE_NO_MUSIC, OBJ_ID_NONE, \trainer, \intro_text, \lose_text, \event_script, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, TRUE, FALSE, FALSE, FALSE + trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE_NO_MUSIC, LOCALID_NONE, \trainer, \intro_text, \lose_text, \event_script, LOCALID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, TRUE, FALSE, FALSE, FALSE .endif .endm @ Starts a rematch battle. Takes a trainer, intro text and loss text .macro trainerbattle_rematch trainer:req, intro_text:req, lose_text:req - trainerbattle TRAINER_BATTLE_REMATCH, OBJ_ID_NONE, \trainer, \intro_text, \lose_text, NULL, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, TRUE + trainerbattle TRAINER_BATTLE_REMATCH, LOCALID_NONE, \trainer, \intro_text, \lose_text, NULL, LOCALID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, TRUE .endm @ Starts a rematch double battle. Takes a trainer, intro text, loss text, and text for when you have too few pokemon .macro trainerbattle_rematch_double trainer:req, intro_text:req, lose_text:req, not_enough_pkmn_text:req - trainerbattle TRAINER_BATTLE_REMATCH_DOUBLE, OBJ_ID_NONE, \trainer, \intro_text, \lose_text, NULL, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, FALSE, TRUE, FALSE, TRUE + trainerbattle TRAINER_BATTLE_REMATCH_DOUBLE, LOCALID_NONE, \trainer, \intro_text, \lose_text, NULL, LOCALID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, \not_enough_pkmn_text, FALSE, TRUE, FALSE, TRUE .endm @ Starts a trainer battle, skipping intro text. Takes a trainer and loss text .macro trainerbattle_no_intro trainer:req, lose_text:req - trainerbattle TRAINER_BATTLE_SINGLE_NO_INTRO_TEXT, OBJ_ID_NONE, \trainer, NULL, \lose_text, NULL, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE + trainerbattle TRAINER_BATTLE_SINGLE_NO_INTRO_TEXT, LOCALID_NONE, \trainer, NULL, \lose_text, NULL, LOCALID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, TRUE, FALSE, FALSE .endm @ Starts a double battle with the player against two trainers diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 718fc2ee5a..c7acc4b3bc 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -9278,9 +9278,12 @@ BattleScript_NeutralizingGasExits:: setbyte gBattlerAttacker, 0 BattleScript_NeutralizingGasExitsLoop: copyarraywithindex gBattlerTarget, gBattlerByTurnOrder, gBattlerAttacker, 1 + jumpifabilitycantbesuppressed BS_TARGET, BattleScript_NeutralizingGasExitsLoopIncrement + jumpifability BS_TARGET, ABILITY_IMPOSTER, BattleScript_NeutralizingGasExitsLoopIncrement @ Imposter only activates when first entering the field saveattacker switchinabilities BS_TARGET restoreattacker +BattleScript_NeutralizingGasExitsLoopIncrement: addbyte gBattlerAttacker, 1 jumpifbytenotequal gBattlerAttacker, gBattlersCount, BattleScript_NeutralizingGasExitsLoop restoreattacker diff --git a/data/maps/BattleFrontier_BattlePyramidFloor/scripts.inc b/data/maps/BattleFrontier_BattlePyramidFloor/scripts.inc index 2b0ed8b9c4..791f29f6e7 100644 --- a/data/maps/BattleFrontier_BattlePyramidFloor/scripts.inc +++ b/data/maps/BattleFrontier_BattlePyramidFloor/scripts.inc @@ -105,7 +105,7 @@ BattlePyramid_WarpToTop:: @ TRAINER_PHILLIP is used as a placeholder BattlePyramid_TrainerBattle:: - trainerbattle TRAINER_BATTLE_HILL, OBJ_ID_NONE, TRAINER_PHILLIP, BattleFacility_TrainerBattle_PlaceholderText, BattleFacility_TrainerBattle_PlaceholderText, NULL, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, FALSE + trainerbattle TRAINER_BATTLE_HILL, LOCALID_NONE, TRAINER_PHILLIP, BattleFacility_TrainerBattle_PlaceholderText, BattleFacility_TrainerBattle_PlaceholderText, NULL, LOCALID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, FALSE pyramid_showhint waitmessage waitbuttonpress diff --git a/data/scripts/trainer_hill.inc b/data/scripts/trainer_hill.inc index 877b48c3db..ece0b01ee2 100644 --- a/data/scripts/trainer_hill.inc +++ b/data/scripts/trainer_hill.inc @@ -60,7 +60,7 @@ TrainerHill_1F_Movement_SetInvisible:: @ TRAINER_PHILLIP is an actual Trainer on the SS Tidal, but is used as a placeholder here TrainerHill_EventScript_TrainerBattle:: - trainerbattle TRAINER_BATTLE_HILL, OBJ_ID_NONE, TRAINER_PHILLIP, BattleFacility_TrainerBattle_PlaceholderText, BattleFacility_TrainerBattle_PlaceholderText, NULL, OBJ_ID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, FALSE + trainerbattle TRAINER_BATTLE_HILL, LOCALID_NONE, TRAINER_PHILLIP, BattleFacility_TrainerBattle_PlaceholderText, BattleFacility_TrainerBattle_PlaceholderText, NULL, LOCALID_NONE, TRAINER_NONE, NULL, NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, FALSE trainerhill_postbattletext waitmessage waitbuttonpress diff --git a/include/config/overworld.h b/include/config/overworld.h index 50cad2f5fe..fa87da4d83 100644 --- a/include/config/overworld.h +++ b/include/config/overworld.h @@ -99,7 +99,7 @@ #define OW_ENABLE_DNS TRUE // If set to TRUE, the overworld will be tinted depending on time of day. // Object Event Shadows -#define OW_OBJECT_VANILLA_SHADOWS FALSE // In vanilla shadows in the overworld are only shown when jumping. +#define OW_OBJECT_VANILLA_SHADOWS FALSE // When FALSE, every object in the overworld has a shadow. WARNING: This means every object will take up two sprites instead of one. When TRUE, an object's shadow is only shown when jumping. // Overworld flags // To use the following features in scripting, replace the 0s with the flag ID you're assigning it to. diff --git a/include/global.h b/include/global.h index fa185f3332..70598f35b9 100644 --- a/include/global.h +++ b/include/global.h @@ -680,7 +680,8 @@ struct Roamer /*0x12*/ u8 tough; /*0x13*/ bool8 active; /*0x14*/ u8 statusB; // Stores frostbite - /*0x14*/ u8 filler[0x7]; + /*0x15*/ bool8 shiny; + /*0x16*/ u8 filler[0x6]; }; struct RamScriptData diff --git a/include/graphics.h b/include/graphics.h index 58212d67c2..262afd5337 100644 --- a/include/graphics.h +++ b/include/graphics.h @@ -2,8 +2,8 @@ #define GUARD_GRAPHICS_H // overworld -extern const u32 gSignpostWindow_Gfx[]; -extern const u32 gMessageBox_Gfx[]; +extern const u8 gSignpostWindow_Gfx[]; +extern const u8 gMessageBox_Gfx[]; extern const u16 gMessageBox_Pal[]; // pokeballs @@ -285,17 +285,17 @@ extern const u16 gBattleEnvironmentPalette_StadiumWallace[]; extern const u32 gPokedexInterface_Gfx[]; extern const u16 gPokedexBgHoenn_Pal[]; extern const u32 gPokedexMenu_Gfx[]; -extern const u8 gPokedexList_Tilemap[]; -extern const u8 gPokedexListUnderlay_Tilemap[]; -extern const u8 gPokedexStartMenuMain_Tilemap[]; -extern const u8 gPokedexStartMenuSearchResults_Tilemap[]; +extern const u32 gPokedexList_Tilemap[]; +extern const u32 gPokedexListUnderlay_Tilemap[]; +extern const u32 gPokedexStartMenuMain_Tilemap[]; +extern const u32 gPokedexStartMenuSearchResults_Tilemap[]; extern const u16 gPokedexSearchResults_Pal[]; extern const u16 gPokedexBgNational_Pal[]; -extern const u8 gPokedexInfoScreen_Tilemap[]; -extern const u8 gPokedexCryScreen_Tilemap[]; -extern const u8 gPokedexSizeScreen_Tilemap[]; -extern const u8 gPokedexScreenSelectBarMain_Tilemap[]; -extern const u8 gPokedexScreenSelectBarSubmenu_Tilemap[]; +extern const u32 gPokedexInfoScreen_Tilemap[]; +extern const u32 gPokedexCryScreen_Tilemap[]; +extern const u32 gPokedexSizeScreen_Tilemap[]; +extern const u32 gPokedexScreenSelectBarMain_Tilemap[]; +extern const u32 gPokedexScreenSelectBarSubmenu_Tilemap[]; extern const u16 gPokedexCaughtScreen_Pal[]; extern const u32 gPokedexSearchMenu_Gfx[]; extern const u32 gPokedexSearchMenuHoenn_Tilemap[]; @@ -1782,7 +1782,7 @@ extern const u32 gIntroGroudon_Gfx[]; extern const u32 gIntroGroudon_Tilemap[]; extern const u32 gIntroLegendBg_Gfx[]; extern const u32 gIntroGroudonBg_Tilemap[]; -extern const u8 ALIGNED(2) gIntro3Bg_Pal[0x200]; +extern const u16 gIntro3Bg_Pal[16][16]; extern const u32 gIntroKyogre_Gfx[]; extern const u32 gIntroKyogre_Tilemap[]; extern const u32 gIntroKyogreBg_Tilemap[]; @@ -2005,9 +2005,9 @@ extern const u8 gHealthboxElementsGfxTable[][32]; extern const u16 gNamingScreenMenu_Pal[6][16]; extern const u32 gNamingScreenMenu_Gfx[]; extern const u32 gNamingScreenBackground_Tilemap[]; -extern const u8 gNamingScreenKeyboardUpper_Tilemap[]; -extern const u8 gNamingScreenKeyboardLower_Tilemap[]; -extern const u8 gNamingScreenKeyboardSymbols_Tilemap[]; +extern const u32 gNamingScreenKeyboardUpper_Tilemap[]; +extern const u32 gNamingScreenKeyboardLower_Tilemap[]; +extern const u32 gNamingScreenKeyboardSymbols_Tilemap[]; extern const u32 gNamingScreenPageSwapFrame_Gfx[]; extern const u32 gNamingScreenBackButton_Gfx[]; extern const u32 gNamingScreenOKButton_Gfx[]; @@ -3098,7 +3098,7 @@ extern const u32 gContestAudienceTilemap[]; extern const u16 gContestInterfaceAudiencePalette[]; extern const u32 gContestInterfaceTilemap[]; extern const u32 gContestCurtainTilemap[]; -extern const u32 gContestSliderHeart_Gfx[]; +extern const u8 gContestSliderHeart_Gfx[]; extern const u32 gContestNextTurnGfx[]; extern const u16 gContestPal[]; extern const u32 gContestFaces_Gfx[]; @@ -3125,11 +3125,11 @@ extern const u16 gUsePokeblockGraph_Pal[]; extern const u16 gUsePokeblockNatureWin_Pal[]; // Berry blender -extern const u32 gBerryBlenderPlayerArrow_Gfx[]; -extern const u32 gBerryBlenderStart_Gfx[]; -extern const u32 gBerryBlenderScoreSymbols_Gfx[]; -extern const u32 gBerryBlenderParticles_Gfx[]; -extern const u32 gBerryBlenderCountdownNumbers_Gfx[]; +extern const u8 gBerryBlenderPlayerArrow_Gfx[]; +extern const u8 gBerryBlenderStart_Gfx[]; +extern const u8 gBerryBlenderScoreSymbols_Gfx[]; +extern const u8 gBerryBlenderParticles_Gfx[]; +extern const u8 gBerryBlenderCountdownNumbers_Gfx[]; extern const u16 gBerryBlenderMiscPalette[]; extern const u16 gBerryBlenderArrowPalette[]; extern const u32 gBerryBlenderCenter_Gfx[]; @@ -3360,30 +3360,30 @@ extern const u16 gMailPalette_Tropic[]; extern const u16 gMailPalette_Dream[]; extern const u16 gMailPalette_Fab[]; extern const u16 gMailPalette_Retro[]; -extern const u8 gMailTiles_Orange[]; -extern const u8 gMailTilemap_Orange[]; -extern const u8 gMailTiles_Harbor[]; -extern const u8 gMailTilemap_Harbor[]; -extern const u8 gMailTiles_Glitter[]; -extern const u8 gMailTilemap_Glitter[]; -extern const u8 gMailTiles_Mech[]; -extern const u8 gMailTilemap_Mech[]; -extern const u8 gMailTiles_Wood[]; -extern const u8 gMailTilemap_Wood[]; -extern const u8 gMailTiles_Wave[]; -extern const u8 gMailTilemap_Wave[]; -extern const u8 gMailTiles_Bead[]; -extern const u8 gMailTilemap_Bead[]; -extern const u8 gMailTiles_Shadow[]; -extern const u8 gMailTilemap_Shadow[]; -extern const u8 gMailTiles_Tropic[]; -extern const u8 gMailTilemap_Tropic[]; -extern const u8 gMailTiles_Dream[]; -extern const u8 gMailTilemap_Dream[]; -extern const u8 gMailTiles_Fab[]; -extern const u8 gMailTilemap_Fab[]; -extern const u8 gMailTiles_Retro[]; -extern const u8 gMailTilemap_Retro[]; +extern const u32 gMailTiles_Orange[]; +extern const u32 gMailTilemap_Orange[]; +extern const u32 gMailTiles_Harbor[]; +extern const u32 gMailTilemap_Harbor[]; +extern const u32 gMailTiles_Glitter[]; +extern const u32 gMailTilemap_Glitter[]; +extern const u32 gMailTiles_Mech[]; +extern const u32 gMailTilemap_Mech[]; +extern const u32 gMailTiles_Wood[]; +extern const u32 gMailTilemap_Wood[]; +extern const u32 gMailTiles_Wave[]; +extern const u32 gMailTilemap_Wave[]; +extern const u32 gMailTiles_Bead[]; +extern const u32 gMailTilemap_Bead[]; +extern const u32 gMailTiles_Shadow[]; +extern const u32 gMailTilemap_Shadow[]; +extern const u32 gMailTiles_Tropic[]; +extern const u32 gMailTilemap_Tropic[]; +extern const u32 gMailTiles_Dream[]; +extern const u32 gMailTilemap_Dream[]; +extern const u32 gMailTiles_Fab[]; +extern const u32 gMailTilemap_Fab[]; +extern const u32 gMailTiles_Retro[]; +extern const u32 gMailTilemap_Retro[]; extern const u8 gMonMarkingsMenu_Gfx[]; extern const u16 gMonMarkingsMenu_Pal[]; diff --git a/include/trade.h b/include/trade.h index 33191f0ac6..24de69b036 100644 --- a/include/trade.h +++ b/include/trade.h @@ -7,6 +7,7 @@ extern struct Mail gTradeMail[PARTY_SIZE]; extern u8 gSelectedTradeMonPositions[2]; +extern const u16 gTradePlatform_Tilemap[]; extern const struct WindowTemplate gTradeEvolutionSceneYesNoWindowTemplate; s32 GetGameProgressForLinkTrade(void); diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index df3345ed5a..0147875995 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -2241,7 +2241,8 @@ static void PlayerHandleOneReturnValue_Duplicate(u32 battler) static void PlayerHandleIntroTrainerBallThrow(u32 battler) { - const u16 *trainerPal = gTrainerBacksprites[gSaveBlock2Ptr->playerGender].palette.data; + const u32 paletteIndex = PlayerGetTrainerBackPicId(); + const u16 *trainerPal = gTrainerBacksprites[paletteIndex].palette.data; BtlController_HandleIntroTrainerBallThrow(battler, 0xD6F8, trainerPal, 31, Intro_TryShinyAnimShowHealthbox); } diff --git a/src/battle_controllers.c b/src/battle_controllers.c index 4a631e3f71..51f7e75d37 100644 --- a/src/battle_controllers.c +++ b/src/battle_controllers.c @@ -1148,8 +1148,11 @@ void BtlController_EmitChosenMonReturnValue(u32 battler, u32 bufferId, u8 partyI gBattleResources->transferBuffer[0] = CONTROLLER_CHOSENMONRETURNVALUE; gBattleResources->transferBuffer[1] = partyId; - for (i = 0; i < (int)ARRAY_COUNT(gBattlePartyCurrentOrder); i++) - gBattleResources->transferBuffer[2 + i] = battlePartyOrder[i]; + if (battlePartyOrder != NULL) + { + for (i = 0; i < (int)ARRAY_COUNT(gBattlePartyCurrentOrder); i++) + gBattleResources->transferBuffer[2 + i] = battlePartyOrder[i]; + } PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 5); } diff --git a/src/battle_main.c b/src/battle_main.c index 68e0cd049c..6e99411ce8 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -583,6 +583,12 @@ static void CB2_InitBattleInternal(void) TryFormChange(i, B_SIDE_OPPONENT, FORM_CHANGE_BEGIN_BATTLE); } + if (TESTING) + { + gPlayerPartyCount = CalculatePartyCount(gPlayerParty); + gEnemyPartyCount = CalculatePartyCount(gEnemyParty); + } + gBattleCommunication[MULTIUSE_STATE] = 0; } diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 04e41aa2cb..d0784a137e 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -7458,7 +7458,7 @@ static void Cmd_switchindataupdate(void) u32 side = GetBattlerSide(battler); u32 partyIndex = gBattlerPartyIndexes[battler]; if (TestRunner_Battle_GetForcedAbility(side, partyIndex)) - gBattleMons[battler].ability = gDisableStructs[battler].overwrittenAbility = TestRunner_Battle_GetForcedAbility(side, partyIndex); + gBattleMons[battler].ability = TestRunner_Battle_GetForcedAbility(side, partyIndex); } #endif @@ -16431,6 +16431,9 @@ static void Cmd_tryworryseed(void) } else { + if (gBattleMons[gBattlerTarget].ability == ABILITY_NEUTRALIZING_GAS) + gSpecialStatuses[gBattlerTarget].neutralizingGasRemoved = TRUE; + gBattleScripting.abilityPopupOverwrite = gBattleMons[gBattlerTarget].ability; gBattleMons[gBattlerTarget].ability = gDisableStructs[gBattlerTarget].overwrittenAbility = ABILITY_INSOMNIA; gBattlescriptCurrInstr = cmd->nextInstr; @@ -18597,3 +18600,14 @@ void BS_JumpIfNoWhiteOut(void) else gBattlescriptCurrInstr = cmd->nextInstr; } + +void BS_JumpIfAbilityCantBeSuppressed(void) +{ + NATIVE_ARGS(u8 battler, const u8 *jumpInstr); + u32 battler = GetBattlerForBattleScript(cmd->battler); + + if (gAbilitiesInfo[gBattleMons[battler].ability].cantBeSuppressed) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; +} diff --git a/src/battle_util.c b/src/battle_util.c index 5eb0fc0696..0b6510e7a2 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3520,7 +3520,11 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 u32 diagonalBattler = BATTLE_OPPOSITE(battler); if (IsDoubleBattle()) diagonalBattler = BATTLE_PARTNER(diagonalBattler); - if (IsBattlerAlive(diagonalBattler) + + // Imposter only activates when the battler first switches in + if (gDisableStructs[battler].isFirstTurn == 2 + && !gDisableStructs[battler].overwrittenAbility + && IsBattlerAlive(diagonalBattler) && !(gBattleMons[diagonalBattler].status2 & (STATUS2_TRANSFORMED | STATUS2_SUBSTITUTE)) && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) && gBattleStruct->illusion[diagonalBattler].state != ILLUSION_ON @@ -6353,16 +6357,13 @@ static u8 ItemEffectMoveEnd(u32 battler, enum ItemHoldEffect holdEffect) effect = StatRaiseBerry(battler, gLastUsedItem, STAT_SPDEF, ITEMEFFECT_NONE); break; case HOLD_EFFECT_ENIGMA_BERRY: // consume and heal if hit by super effective move - if (B_BERRIES_INSTANT >= GEN_4) - effect = TrySetEnigmaBerry(battler); + effect = TrySetEnigmaBerry(battler); break; case HOLD_EFFECT_KEE_BERRY: // consume and boost defense if used physical move - if (B_BERRIES_INSTANT >= GEN_4) - effect = DamagedStatBoostBerryEffect(battler, STAT_DEF, DAMAGE_CATEGORY_PHYSICAL); + effect = DamagedStatBoostBerryEffect(battler, STAT_DEF, DAMAGE_CATEGORY_PHYSICAL); break; case HOLD_EFFECT_MARANGA_BERRY: // consume and boost sp. defense if used special move - if (B_BERRIES_INSTANT >= GEN_4) - effect = DamagedStatBoostBerryEffect(battler, STAT_SPDEF, DAMAGE_CATEGORY_SPECIAL); + effect = DamagedStatBoostBerryEffect(battler, STAT_SPDEF, DAMAGE_CATEGORY_SPECIAL); break; case HOLD_EFFECT_RANDOM_STAT_UP: if (B_BERRIES_INSTANT >= GEN_4) @@ -9497,8 +9498,13 @@ bool32 IsFutureSightAttackerInParty(u32 battlerAtk, u32 battlerDef, u32 move) return FALSE; struct Pokemon *party = GetBattlerParty(battlerAtk); - return &party[gWishFutureKnock.futureSightPartyIndex[battlerDef]] != &party[gBattlerPartyIndexes[battlerAtk]] - && &party[gWishFutureKnock.futureSightPartyIndex[battlerDef]] != &party[BATTLE_PARTNER(gBattlerPartyIndexes[battlerAtk])]; + if (IsDoubleBattle()) + { + return &party[gWishFutureKnock.futureSightPartyIndex[battlerDef]] != &party[gBattlerPartyIndexes[battlerAtk]] + && &party[gWishFutureKnock.futureSightPartyIndex[battlerDef]] != &party[gBattlerPartyIndexes[BATTLE_PARTNER(battlerAtk)]]; + } + + return &party[gWishFutureKnock.futureSightPartyIndex[battlerDef]] != &party[gBattlerPartyIndexes[battlerAtk]]; } s32 CalculateMoveDamage(struct DamageContext *ctx) diff --git a/src/data/graphics/intro_scene.h b/src/data/graphics/intro_scene.h index 792f6b3d26..2ee5a86a0f 100644 --- a/src/data/graphics/intro_scene.h +++ b/src/data/graphics/intro_scene.h @@ -1,6 +1,6 @@ const u16 gIntroGameFreakTextFade_Pal[] = INCBIN_U16("graphics/intro/scene_1/text.gbapal"); // game freak text blue fade const u16 gIntroPlayer_Pal[] = INCBIN_U16("graphics/intro/scene_2/player.gbapal"); -const u16 gIntro3Bg_Pal[] = INCBIN_U16("graphics/intro/scene_3/bg.gbapal"); +const u16 gIntro3Bg_Pal[16][16] = INCBIN_U16("graphics/intro/scene_3/bg.gbapal"); const u16 gIntroVolbeat_Pal[] = INCBIN_U16("graphics/intro/scene_2/volbeat.gbapal"); const u16 gIntroTorchic_Pal[] = INCBIN_U16("graphics/intro/scene_2/torchic.gbapal"); const u16 gIntroManectric_Pal[] = INCBIN_U16("graphics/intro/scene_2/manectric.gbapal"); diff --git a/src/data/moves_info.h b/src/data/moves_info.h index 59bcab6fac..08daab5a6b 100644 --- a/src/data/moves_info.h +++ b/src/data/moves_info.h @@ -6053,11 +6053,11 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = { .name = COMPOUND_STRING("Rapid Spin"), .description = COMPOUND_STRING( - "Spins attack that removes\n" + "User spins and removes some\n" #if B_SPEED_BUFFING_RAPID_SPIN >= GEN_8 - "some effects and ups speed."), - #else - "certain effects."), + "effects, while upping speed."), + #else + "effects."), #endif .effect = EFFECT_RAPID_SPIN, .power = B_UPDATED_MOVE_DATA >= GEN_8 ? 50 : 20, diff --git a/src/debug.c b/src/debug.c index f1a8de68c1..e5e37e1b14 100644 --- a/src/debug.c +++ b/src/debug.c @@ -2535,6 +2535,7 @@ static void DebugAction_FlagsVars_FlagsSelect(u8 taskId) { if (JOY_NEW(A_BUTTON)) { + PlaySE(SE_SELECT); FlagToggle(gTasks[taskId].tInput); } else if (JOY_NEW(B_BUTTON)) @@ -2544,7 +2545,6 @@ static void DebugAction_FlagsVars_FlagsSelect(u8 taskId) return; } - PlaySE(SE_SELECT); Debug_HandleInput_Numeric(taskId, 1, FLAGS_COUNT - 1, DEBUG_NUMBER_DIGITS_FLAGS); if (JOY_NEW(DPAD_ANY) || JOY_NEW(A_BUTTON)) diff --git a/src/egg_hatch.c b/src/egg_hatch.c index d965c0c742..545b7d75ea 100644 --- a/src/egg_hatch.c +++ b/src/egg_hatch.c @@ -33,6 +33,7 @@ #include "naming_screen.h" #include "pokemon_storage_system.h" #include "field_screen_effect.h" +#include "trade.h" #include "data.h" #include "battle.h" // to get rid of later #include "constants/rgb.h" @@ -63,7 +64,6 @@ struct EggHatchData u8 textColor[3]; }; -extern const u32 gTradePlatform_Tilemap[]; extern const u8 gText_HatchedFromEgg[]; extern const u8 gText_NicknameHatchPrompt[]; diff --git a/src/field_player_avatar.c b/src/field_player_avatar.c index 07f4b74e08..d02ecbd9fc 100644 --- a/src/field_player_avatar.c +++ b/src/field_player_avatar.c @@ -805,9 +805,27 @@ static void PlayerNotOnBikeMoving(u8 direction, u16 heldKeys) } else { - u8 adjustedCollision = collision - COLLISION_STOP_SURFING; - if (adjustedCollision > 3) + // Player collided with something. Certain collisions have special handling that precludes the normal collision effect. + // COLLISION_STOP_SURFING and COLLISION_PUSHED_BOULDER's effects are started by CheckForObjectEventCollision. + // COLLISION_LEDGE_JUMP's effect is handled further up in this function, so it will never reach this point. + // COLLISION_ROTATING_GATE is unusual however, this was probably included by mistake. When the player walks into a + // rotating gate that cannot rotate there is no additional handling, it's just a regular collision. Its exclusion here + // means that the player avatar won't update if they encounter this kind of collision. This has two noticeable effects: + // - Colliding with it head-on stops the player dead, rather than playing the walking animation and playing a bump sound effect + // - Colliding with it by changing direction won't turn the player avatar, their walking animation will just speed up. +#ifdef BUGFIX + if (collision != COLLISION_STOP_SURFING + && collision != COLLISION_LEDGE_JUMP + && collision != COLLISION_PUSHED_BOULDER) +#else + if (collision != COLLISION_STOP_SURFING + && collision != COLLISION_LEDGE_JUMP + && collision != COLLISION_PUSHED_BOULDER + && collision != COLLISION_ROTATING_GATE) +#endif + { PlayerNotOnBikeCollide(direction); + } return; } } diff --git a/src/graphics.c b/src/graphics.c index 9289ac997f..41aad50431 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -1,4 +1,5 @@ #include "global.h" +#include "graphics.h" const u32 gBattleTextboxTiles[] = INCBIN_U32("graphics/battle_interface/textbox.4bpp.smol"); const u16 gBattleTextboxPalette[] = INCBIN_U16("graphics/battle_interface/textbox.gbapal"); @@ -707,7 +708,7 @@ const u16 gBattleInterface_BallStatusBarPal[] = INCBIN_U16("graphics/battle_inte const u16 gBattleInterface_BallDisplayPal[] = INCBIN_U16("graphics/battle_interface/ball_display.gbapal"); -const u8 gHealthboxElementsGfxTable[] = INCBIN_U8("graphics/battle_interface/hpbar.4bpp", +const u8 gHealthboxElementsGfxTable[][32] = INCBIN_U8("graphics/battle_interface/hpbar.4bpp", "graphics/battle_interface/expbar.4bpp", "graphics/battle_interface/status.4bpp", "graphics/battle_interface/misc.4bpp", @@ -1332,7 +1333,7 @@ const u16 gTilesetAnims_BattleDomePals0_3[] = INCBIN_U16("graphics/battle_fronti static const u16 sUnused0[] = {0x13F, 0x119, 0x113, 0x10E}; -const u16 gBattlePyramidFloor_Pal[] = INCBIN_U16("graphics/battle_frontier/pyramid_floor.gbapal"); +const u16 gBattlePyramidFloor_Pal[][16] = INCBIN_U16("graphics/battle_frontier/pyramid_floor.gbapal"); const u32 gMultiBattleIntroBg_Opponent_Tilemap[] = INCBIN_U32("graphics/battle_frontier/multi_battle_intro_bg_opponent.bin.smolTM"); const u32 gMultiBattleIntroBg_Player_Tilemap[] = INCBIN_U32("graphics/battle_frontier/multi_battle_intro_bg_player.bin.smolTM"); @@ -2087,12 +2088,12 @@ const u16 gTitleScreenPressStartPal[] = INCBIN_U16("graphics/title_screen/p const u32 gTitleScreenPressStartGfx[] = INCBIN_U32("graphics/title_screen/press_start.4bpp.smol"); const u32 gTitleScreenPokemonLogoTilemap[] = INCBIN_U32("graphics/title_screen/pokemon_logo.bin.smolTM"); -const u16 gFrontierPassBg_Pal[] = INCBIN_U16("graphics/frontier_pass/bg.gbapal"); // 8 x 16 +const u16 gFrontierPassBg_Pal[][16] = INCBIN_U16("graphics/frontier_pass/bg.gbapal"); // 8 x 16 const u32 gFrontierPassBg_Gfx[] = INCBIN_U32("graphics/frontier_pass/bg.4bpp.smol"); const u32 gFrontierPassMapAndCard_Gfx[] = INCBIN_U32("graphics/frontier_pass/map_and_card.8bpp.smol"); const u32 gFrontierPassBg_Tilemap[] = INCBIN_U32("graphics/frontier_pass/bg.bin.smolTM"); -const u16 gFrontierPassCancelButton_Tilemap[] = INCBIN_U16("graphics/frontier_pass/cancel.bin"); -const u16 gFrontierPassCancelButtonHighlighted_Tilemap[] = INCBIN_U16("graphics/frontier_pass/cancel_highlighted.bin"); +const u32 gFrontierPassCancelButton_Tilemap[] = INCBIN_U32("graphics/frontier_pass/cancel.bin"); +const u32 gFrontierPassCancelButtonHighlighted_Tilemap[] = INCBIN_U32("graphics/frontier_pass/cancel_highlighted.bin"); // Berry Crush const u16 gBerryCrush_Crusher_Pal[] = INCBIN_U16("graphics/berry_crush/crusher.gbapal"); diff --git a/src/intro.c b/src/intro.c index 48b5de9a77..6548fec358 100644 --- a/src/intro.c +++ b/src/intro.c @@ -1875,12 +1875,15 @@ static void Task_Scene3_StartGroudon(u8 taskId) #define tTrigIdx data[6] // Re-used #define tPalIdx data[7] +// Treats gIntro3Bg_Pal as u8* and iterates by 1 +#define INTRO3_RAW_PTR(palId)(((void *) &gIntro3Bg_Pal) + palId) + static void Task_Scene3_Groudon(u8 taskId) { s16 *data = gTasks[taskId].data; tTimer++; - if ((u16)(tState - 1) < 7 && tTimer % 2 == 0) + if ((tState >= 1 && tState <= 7) && tTimer % 2 == 0) tYShake ^= 3; PanFadeAndZoomScreen(tScreenX, tScreenY + tYShake, tZoom, 0); switch (tState) @@ -1899,7 +1902,7 @@ static void Task_Scene3_Groudon(u8 taskId) if (--tDelay == 0) { tDelay = 2; - CpuCopy16(&gIntro3Bg_Pal[tPalIdx], &gPlttBufferFaded[BG_PLTT_ID(1) + 15], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(tPalIdx), &gPlttBufferFaded[BG_PLTT_ID(1) + 15], PLTT_SIZEOF(1)); tPalIdx += 2; if (tPalIdx == 0x1EC) tState++; @@ -1916,7 +1919,7 @@ static void Task_Scene3_Groudon(u8 taskId) if (--tDelay == 0) { tDelay = 2; - CpuCopy16(&gIntro3Bg_Pal[tPalIdx], &gPlttBufferFaded[BG_PLTT_ID(1) + 15], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(tPalIdx), &gPlttBufferFaded[BG_PLTT_ID(1) + 15], PLTT_SIZEOF(1)); tPalIdx -= 2; if (tPalIdx == 0x1E0) { @@ -2158,7 +2161,7 @@ static void Task_Scene3_Kyogre(u8 taskId) if (--tDelay == 0) { tDelay = 4; - CpuCopy16(&gIntro3Bg_Pal[tPalIdx], &gPlttBufferFaded[BG_PLTT_ID(2) + 15], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(tPalIdx), &gPlttBufferFaded[BG_PLTT_ID(2) + 15], PLTT_SIZEOF(1)); tPalIdx -= 2; if (tPalIdx == 0x1E0) tState++; @@ -2176,7 +2179,7 @@ static void Task_Scene3_Kyogre(u8 taskId) if (--tDelay == 0) { tDelay = 4; - CpuCopy16(&gIntro3Bg_Pal[tPalIdx], &gPlttBufferFaded[BG_PLTT_ID(2) + 15], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(tPalIdx), &gPlttBufferFaded[BG_PLTT_ID(2) + 15], PLTT_SIZEOF(1)); tPalIdx += 2; if (tPalIdx == 0x1EE) { @@ -2507,7 +2510,7 @@ static void SpriteCB_Lightning(struct Sprite *sprite) sprite->sPalIdx = 0x1C2; sprite->sState++; case 1: - CpuCopy16(&gIntro3Bg_Pal[sprite->sPalIdx], &gPlttBufferFaded[BG_PLTT_ID(5) + 13], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(sprite->sPalIdx), &gPlttBufferFaded[BG_PLTT_ID(5) + 13], PLTT_SIZEOF(1)); sprite->sPalIdx += 2; if (sprite->sPalIdx != 0x1CE) break; @@ -2518,7 +2521,7 @@ static void SpriteCB_Lightning(struct Sprite *sprite) if (--sprite->sDelay == 0) { sprite->sDelay = 4; - CpuCopy16(&gIntro3Bg_Pal[sprite->sPalIdx], &gPlttBufferFaded[BG_PLTT_ID(5) + 13], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(sprite->sPalIdx), &gPlttBufferFaded[BG_PLTT_ID(5) + 13], PLTT_SIZEOF(1)); sprite->sPalIdx -= 2; if (sprite->sPalIdx == 0x1C0) DestroySprite(sprite); @@ -2621,7 +2624,7 @@ static void Task_RayquazaAttack(u8 taskId) case 0: if ((data[2] & 1) != 0) { - CpuCopy16(&gIntro3Bg_Pal[0x1A2 + data[1] * 2], &gPlttBufferFaded[BG_PLTT_ID(5) + 14], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(0x1A2 + data[1] * 2), &gPlttBufferFaded[BG_PLTT_ID(5) + 14], PLTT_SIZEOF(1)); data[1]++; } if (data[1] == 6) @@ -2636,7 +2639,7 @@ static void Task_RayquazaAttack(u8 taskId) { if ((data[2] & 1) != 0) { - CpuCopy16(&gIntro3Bg_Pal[0x1A2 + data[1] * 2], &gPlttBufferFaded[BG_PLTT_ID(5) + 8], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(0x1A2 + data[1] * 2), &gPlttBufferFaded[BG_PLTT_ID(5) + 8], PLTT_SIZEOF(1)); data[1]++; } if (data[1] == 6) @@ -2655,7 +2658,7 @@ static void Task_RayquazaAttack(u8 taskId) { if ((data[2] & 1) != 0) { - CpuCopy16(&gIntro3Bg_Pal[0x182 + data[1] * 2], &gPlttBufferFaded[BG_PLTT_ID(5) + 12], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(0x182 + data[1] * 2), &gPlttBufferFaded[BG_PLTT_ID(5) + 12], PLTT_SIZEOF(1)); data[1]++; } if (data[1] == 6) @@ -2679,9 +2682,9 @@ static void Task_RayquazaAttack(u8 taskId) if (--data[3] != 0) { BlendPalette(BG_PLTT_ID(5), 16, data[3], RGB(9, 10, 10)); - CpuCopy16(&gIntro3Bg_Pal[428], &gPlttBufferFaded[BG_PLTT_ID(5) + 14], PLTT_SIZEOF(1)); - CpuCopy16(&gIntro3Bg_Pal[428], &gPlttBufferFaded[BG_PLTT_ID(5) + 8], PLTT_SIZEOF(1)); - CpuCopy16(&gIntro3Bg_Pal[396], &gPlttBufferFaded[BG_PLTT_ID(5) + 12], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(428), &gPlttBufferFaded[BG_PLTT_ID(5) + 14], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(428), &gPlttBufferFaded[BG_PLTT_ID(5) + 8], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(396), &gPlttBufferFaded[BG_PLTT_ID(5) + 12], PLTT_SIZEOF(1)); } else { diff --git a/src/mail.c b/src/mail.c index 7cff48c8ed..34d1520ef4 100644 --- a/src/mail.c +++ b/src/mail.c @@ -48,8 +48,8 @@ struct MailLayout struct MailGraphics { const u16 *palette; - const u8 *tiles; - const u8 *tileMap; + const u32 *tiles; + const u32 *tileMap; u32 unused; u16 textColor; u16 textShadow; diff --git a/src/naming_screen.c b/src/naming_screen.c index 79028a0782..157f6868fd 100644 --- a/src/naming_screen.c +++ b/src/naming_screen.c @@ -1982,7 +1982,7 @@ static void PrintKeyboardKeys(u8 window, u8 page) PutWindowTilemap(window); } -static const u8 *const sNextKeyboardPageTilemaps[] = +static const u32 *const sNextKeyboardPageTilemaps[] = { [KBPAGE_SYMBOLS] = gNamingScreenKeyboardUpper_Tilemap, [KBPAGE_LETTERS_UPPER] = gNamingScreenKeyboardLower_Tilemap, // lower diff --git a/src/roamer.c b/src/roamer.c index 9bca6fdc45..0fc86b6711 100644 --- a/src/roamer.c +++ b/src/roamer.c @@ -113,6 +113,7 @@ static void CreateInitialRoamerMon(u8 index, u16 species, u8 level) ROAMER(index)->cute = GetMonData(&gEnemyParty[0], MON_DATA_CUTE); ROAMER(index)->smart = GetMonData(&gEnemyParty[0], MON_DATA_SMART); ROAMER(index)->tough = GetMonData(&gEnemyParty[0], MON_DATA_TOUGH); + ROAMER(index)->shiny = GetMonData(&gEnemyParty[0], MON_DATA_IS_SHINY); ROAMER(index)->active = TRUE; sRoamerLocation[index][MAP_GRP] = ROAMER_MAP_GROUP; sRoamerLocation[index][MAP_NUM] = sRoamerLocations[Random() % NUM_LOCATION_SETS][0]; @@ -243,8 +244,6 @@ void CreateRoamerMonInstance(u32 roamerIndex) struct Pokemon *mon = &gEnemyParty[0]; ZeroEnemyPartyMons(); CreateMonWithIVsPersonality(mon, ROAMER(roamerIndex)->species, ROAMER(roamerIndex)->level, ROAMER(roamerIndex)->ivs, ROAMER(roamerIndex)->personality); - // The roamer's status field is u16, but SetMonData expects status to be u32, so will set the roamer's status - // using the status field and the following 3 bytes (cool, beauty, and cute). SetMonData(mon, MON_DATA_STATUS, &status); SetMonData(mon, MON_DATA_HP, &ROAMER(roamerIndex)->hp); SetMonData(mon, MON_DATA_COOL, &ROAMER(roamerIndex)->cool); @@ -252,6 +251,7 @@ void CreateRoamerMonInstance(u32 roamerIndex) SetMonData(mon, MON_DATA_CUTE, &ROAMER(roamerIndex)->cute); SetMonData(mon, MON_DATA_SMART, &ROAMER(roamerIndex)->smart); SetMonData(mon, MON_DATA_TOUGH, &ROAMER(roamerIndex)->tough); + SetMonData(mon, MON_DATA_IS_SHINY, &ROAMER(roamerIndex)->shiny); } bool8 TryStartRoamerEncounter(void) diff --git a/src/rom_header_gf.c b/src/rom_header_gf.c index 182d879c83..5613fe6152 100644 --- a/src/rom_header_gf.c +++ b/src/rom_header_gf.c @@ -99,7 +99,7 @@ struct GFRomHeader // This seems to need to be in the text section for some reason. // To avoid a changed section attributes warning it's put in a special .text.consts section. __attribute__((section(".text.consts"))) -static const struct GFRomHeader sGFRomHeader = { +USED static const struct GFRomHeader sGFRomHeader = { .version = GAME_VERSION, .language = GAME_LANGUAGE, .gameName = "pokemon emerald version", diff --git a/src/rom_header_rhh.c b/src/rom_header_rhh.c index c323e9eadf..e9310415c3 100644 --- a/src/rom_header_rhh.c +++ b/src/rom_header_rhh.c @@ -28,7 +28,7 @@ struct RHHRomHeader }; __attribute__((section(".text.consts"))) -static const struct RHHRomHeader sRHHRomHeader = +USED static const struct RHHRomHeader sRHHRomHeader = { .rhh_magic = { 'R', 'H', 'H', 'E', 'X', 'P' }, .expansionVersionMajor = EXPANSION_VERSION_MAJOR, diff --git a/test/battle/ability/neutralizing_gas.c b/test/battle/ability/neutralizing_gas.c index 6338bfbeca..f83e928c4a 100644 --- a/test/battle/ability/neutralizing_gas.c +++ b/test/battle/ability/neutralizing_gas.c @@ -256,7 +256,8 @@ SINGLE_BATTLE_TEST("Neutralizing Gas prevents Trace from copying it") SINGLE_BATTLE_TEST("Neutralizing Gas prevents Contrary inverting stat boosts") { GIVEN { - ASSUME(GetMoveEffect(MOVE_REST) == EFFECT_REST); + ASSUME(GetMoveEffect(MOVE_SWORDS_DANCE) == EFFECT_ATTACK_UP_2); + ASSUME(GetMoveEffect(MOVE_LEER) == EFFECT_DEFENSE_DOWN); PLAYER(SPECIES_INKAY) { Ability(ABILITY_CONTRARY); } OPPONENT(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); } } WHEN { @@ -271,3 +272,41 @@ SINGLE_BATTLE_TEST("Neutralizing Gas prevents Contrary inverting stat boosts") EXPECT_LT(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE); } } + +SINGLE_BATTLE_TEST("Neutralizing Gas exiting the field does not activate abilities that were not suppressed by it again") +{ + u32 species, ability; + // These are the only abilities that could immediately activate again + PARAMETRIZE { species = SPECIES_KOMALA; ability = ABILITY_COMATOSE; } + PARAMETRIZE { species = SPECIES_CALYREX_SHADOW; ability = ABILITY_AS_ONE_SHADOW_RIDER; } + PARAMETRIZE { species = SPECIES_CALYREX_ICE; ability = ABILITY_AS_ONE_ICE_RIDER; } + + GIVEN { + ASSUME(gAbilitiesInfo[ability].cantBeSuppressed); + PLAYER(species) { Ability(ability); } + OPPONENT(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { SWITCH(opponent, 1); } + } SCENE { + ABILITY_POPUP(player, ability); + MESSAGE("The effects of the neutralizing gas wore off!"); + NOT ABILITY_POPUP(player, ability); + } +} + +SINGLE_BATTLE_TEST("Neutralizing Gas exiting the field does not activate Imposter even if it did not activate before") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_DITTO) { Ability(ABILITY_IMPOSTER); } + OPPONENT(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { SWITCH(player, 1); SWITCH(opponent, 1); } + } SCENE { + NOT ABILITY_POPUP(player, ABILITY_IMPOSTER); + MESSAGE("The effects of the neutralizing gas wore off!"); + NOT ABILITY_POPUP(player, ABILITY_IMPOSTER); + } +} diff --git a/test/pokemon.c b/test/pokemon.c index 2fbf96f816..00a4a4485b 100644 --- a/test/pokemon.c +++ b/test/pokemon.c @@ -82,10 +82,14 @@ TEST("Shininess independent from PID and OTID") TEST("Hyper Training increases stats without affecting IVs") { - u32 data, hp, atk, def, speed, spatk, spdef; + u32 data, hp, atk, def, speed, spatk, spdef, friendship = 0; struct Pokemon mon; CreateMon(&mon, SPECIES_WOBBUFFET, 100, 3, TRUE, 0, OT_ID_PRESET, 0); + // Consider B_FRIENDSHIP_BOOST. + SetMonData(&mon, MON_DATA_FRIENDSHIP, &friendship); + CalculateMonStats(&mon); + hp = GetMonData(&mon, MON_DATA_HP); atk = GetMonData(&mon, MON_DATA_ATK); def = GetMonData(&mon, MON_DATA_DEF); @@ -142,8 +146,13 @@ TEST("Status1 round-trips through BoxPokemon") TEST("canhypertrain/hypertrain affect MON_DATA_HYPER_TRAINED_* and recalculate stats") { - u32 atk; + u32 atk, friendship = 0; CreateMon(&gPlayerParty[0], SPECIES_WOBBUFFET, 100, 0, FALSE, 0, OT_ID_PRESET, 0); + + // Consider B_FRIENDSHIP_BOOST. + SetMonData(&gPlayerParty[0], MON_DATA_FRIENDSHIP, &friendship); + CalculateMonStats(&gPlayerParty[0]); + atk = GetMonData(&gPlayerParty[0], MON_DATA_ATK); RUN_OVERWORLD_SCRIPT( diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c index 7884993a1c..20271a588d 100644 --- a/test/test_runner_battle.c +++ b/test/test_runner_battle.c @@ -1563,6 +1563,13 @@ void OpenPokemon(u32 sourceLine, u32 side, u32 species) data = MOVE_NONE; for (i = 0; i < MAX_MON_MOVES; i++) SetMonData(DATA.currentMon, MON_DATA_MOVE1 + i, &data); + data = 0; + if (B_FRIENDSHIP_BOOST) + { + // This way, we avoid the boost affecting tests unless explicitly stated. + SetMonData(DATA.currentMon, MON_DATA_FRIENDSHIP, &data); + CalculateMonStats(DATA.currentMon); + } } // (sNaturePersonalities[i] % NUM_NATURES) == i