diff --git a/.all-contributorsrc b/.all-contributorsrc
index aa13a3864d..a54e1caefd 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -441,6 +441,15 @@
"contributions": [
"code"
]
+ },
+ {
+ "login": "MandL27",
+ "name": "MandL27",
+ "avatar_url": "https://avatars.githubusercontent.com/u/10366615?v=4",
+ "profile": "https://github.com/MandL27",
+ "contributions": [
+ "code"
+ ]
}
],
"contributorsPerLine": 7,
diff --git a/CREDITS.md b/CREDITS.md
index d3d46d0361..547b5bd52d 100644
--- a/CREDITS.md
+++ b/CREDITS.md
@@ -74,6 +74,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
 ghostyboyy97 💻 |
 Marky 💻 |
+  MandL27 💻 |
diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s
index 01b25762cd..cecd0c0be8 100644
--- a/data/battle_scripts_1.s
+++ b/data/battle_scripts_1.s
@@ -2536,6 +2536,7 @@ BattleScript_CantMakeAsleep::
BattleScript_EffectAbsorbLiquidOoze::
call BattleScript_AbilityPopUpTarget
+ jumpifability BS_ATTACKER, ABILITY_MAGIC_GUARD, BattleScript_EffectAbsorbRet
goto BattleScript_EffectAbsorb
BattleScript_EffectAbsorb::
@@ -2544,6 +2545,7 @@ BattleScript_EffectAbsorb::
printfromtable gAbsorbDrainStringIds
waitmessage B_WAIT_TIME_LONG
tryfaintmon BS_ATTACKER
+BattleScript_EffectAbsorbRet:
return
BattleScript_EffectExplosion::
@@ -4945,10 +4947,12 @@ BattleScript_LeechSeedTurnDrainLiquidOoze::
copybyte gBattlerAbility, gBattlerAttacker
call BattleScript_AbilityPopUp
copybyte gBattlerAttacker, gBattlerTarget @ needed to get liquid ooze message correct
+ jumpifability BS_TARGET, ABILITY_MAGIC_GUARD, BattleScript_LeechSeedTurnDrainHealBlockEnd2
goto BattleScript_LeechSeedTurnDrainGainHp
BattleScript_LeechSeedTurnDrainHealBlock::
call BattleScript_LeechSeedTurnDrain
+BattleScript_LeechSeedTurnDrainHealBlockEnd2:
end2
BattleScript_LeechSeedTurnDrainRecovery::
diff --git a/graphics/pokemon/kingler/overworld.png b/graphics/pokemon/kingler/overworld.png
index 135f79b326..c67ce3a53a 100644
Binary files a/graphics/pokemon/kingler/overworld.png and b/graphics/pokemon/kingler/overworld.png differ
diff --git a/graphics/pokemon/krabby/overworld.png b/graphics/pokemon/krabby/overworld.png
index abe66ceb6f..f712b6f6ff 100644
Binary files a/graphics/pokemon/krabby/overworld.png and b/graphics/pokemon/krabby/overworld.png differ
diff --git a/include/battle_gimmick.h b/include/battle_gimmick.h
index 42b8c7255a..84b1d6b26a 100644
--- a/include/battle_gimmick.h
+++ b/include/battle_gimmick.h
@@ -35,6 +35,7 @@ void SetGimmickAsActivated(u32 battler, enum Gimmick gimmick);
void ChangeGimmickTriggerSprite(u32 spriteId, u32 animId);
void CreateGimmickTriggerSprite(u32 battler);
bool32 IsGimmickTriggerSpriteActive(void);
+bool32 IsGimmickTriggerSpriteMatchingBattler(u32 battler);
void HideGimmickTriggerSprite(void);
void DestroyGimmickTriggerSprite(void);
diff --git a/include/battle_util.h b/include/battle_util.h
index cc65a79bd5..f6d92b6b11 100644
--- a/include/battle_util.h
+++ b/include/battle_util.h
@@ -423,6 +423,7 @@ bool32 CanMoveSkipAccuracyCalc(u32 battlerAtk, u32 battlerDef, enum Ability abil
u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, enum Ability atkAbility, enum Ability defAbility, enum HoldEffect atkHoldEffect, enum HoldEffect defHoldEffect);
bool32 IsSemiInvulnerable(u32 battler, enum SemiInvulnerableExclusion excludeCommander);
bool32 BreaksThroughSemiInvulnerablity(u32 battler, u32 move);
+bool32 HasPartnerTrainer(u32 battler);
u32 GetNaturePowerMove(u32 battler);
u32 GetNaturePowerMove(u32 battler);
void RemoveAbilityFlags(u32 battler);
diff --git a/include/config/summary_screen.h b/include/config/summary_screen.h
index 4b5f434cb3..07bae63533 100644
--- a/include/config/summary_screen.h
+++ b/include/config/summary_screen.h
@@ -8,6 +8,7 @@
#define P_SUMMARY_SCREEN_RENAME TRUE // If TRUE, an option to change Pokémon nicknames replaces the cancel prompt on the summary screen info page.
#define P_SUMMARY_SCREEN_IV_EV_INFO FALSE // If TRUE, will allow player to cycle through the Stats, IVs, and EVs in the summary screen skills page.
#define P_SUMMARY_SCREEN_IV_EV_BOX_ONLY FALSE // If TRUE, will allow player to cycle through the Stats, IVs, and EVs in the summary screen skills page, but only in the PC storage box.
+#define P_SUMMARY_SCREEN_IV_HYPERTRAIN TRUE // If TRUE, stats that have been hyper trained will show as 31/S when viewing them in the summary screen
#define P_SUMMARY_SCREEN_IV_EV_TILESET FALSE // If TRUE, loads an alternate tileset to allow changing the "STATS" label in the summary screen skills page. Note: if it's still loading the alternate tileset after changing this and recompiling, you may need a `make clean` before compilation.
#define P_SUMMARY_SCREEN_IV_EV_VALUES FALSE // If TRUE, will show the actual IV value instead of the letter grade.
/*
diff --git a/include/constants/battle.h b/include/constants/battle.h
index 12f34a396b..380903acdb 100644
--- a/include/constants/battle.h
+++ b/include/constants/battle.h
@@ -103,6 +103,7 @@ enum BattleSide
#define BATTLE_TWO_VS_ONE_OPPONENT ((gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && TRAINER_BATTLE_PARAM.opponentB == 0xFFFF))
#define BATTLE_TYPE_HAS_AI (BATTLE_TYPE_TRAINER | BATTLE_TYPE_FIRST_BATTLE | BATTLE_TYPE_SAFARI | BATTLE_TYPE_ROAMER | BATTLE_TYPE_INGAME_PARTNER)
#define BATTLE_TYPE_MORE_THAN_TWO_BATTLERS (BATTLE_TYPE_DOUBLE | BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER | BATTLE_TYPE_TWO_OPPONENTS)
+#define BATTLE_TYPE_PLAYER_HAS_PARTNER (BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER | BATTLE_TYPE_TOWER_LINK_MULTI)
// Multibattle test composite flags
#define BATTLE_MULTI_TEST (BATTLE_TYPE_IS_MASTER | BATTLE_TYPE_TRAINER | BATTLE_TYPE_INGAME_PARTNER | BATTLE_TYPE_MULTI | BATTLE_TYPE_TWO_OPPONENTS)
diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c
index e30ba186af..0b9c9ed3e1 100644
--- a/src/battle_ai_switch_items.c
+++ b/src/battle_ai_switch_items.c
@@ -1119,7 +1119,7 @@ bool32 ShouldSwitch(u32 battler)
if (IsDoubleBattle())
{
- u32 partner = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerAtPosition(battler)));
+ u32 partner = BATTLE_PARTNER(battler);
battlerIn1 = battler;
if (gAbsentBattlerFlags & (1u << partner))
battlerIn2 = battler;
@@ -1270,7 +1270,7 @@ void ModifySwitchAfterMoveScoring(u32 battler)
if (IsDoubleBattle())
{
- u32 partner = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerAtPosition(battler)));
+ u32 partner = BATTLE_PARTNER(battler);
battlerIn1 = battler;
if (gAbsentBattlerFlags & (1u << partner))
battlerIn2 = battler;
@@ -1318,7 +1318,7 @@ bool32 IsSwitchinValid(u32 battler)
// Edge case: See if partner already chose to switch into the same mon
if (IsDoubleBattle())
{
- u32 partner = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerAtPosition(battler)));
+ u32 partner = BATTLE_PARTNER(battler);
if (gBattleStruct->AI_monToSwitchIntoId[battler] == PARTY_SIZE) // Generic switch
{
if ((gAiLogicData->shouldSwitch & (1u << partner)) && gAiLogicData->monToSwitchInId[partner] == gAiLogicData->mostSuitableMonId[battler])
diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c
index 202e9fd041..008bef4812 100644
--- a/src/battle_ai_util.c
+++ b/src/battle_ai_util.c
@@ -891,7 +891,7 @@ static inline bool32 ShouldCalcCritDamage(u32 battlerAtk, u32 battlerDef, u32 mo
struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, uq4_12_t *typeEffectiveness, enum AIConsiderGimmick considerGimmickAtk, enum AIConsiderGimmick considerGimmickDef, u32 weather)
{
- struct SimulatedDamage simDamage;
+ struct SimulatedDamage simDamage = {0};
enum BattleMoveEffects moveEffect = GetMoveEffect(move);
bool32 isDamageMoveUnusable = FALSE;
bool32 toggledGimmickAtk = FALSE;
@@ -924,7 +924,7 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u
gBattleStruct->magnitudeBasePower = 70;
gBattleStruct->presentBasePower = 80;
- struct DamageContext ctx;
+ struct DamageContext ctx = {0};
ctx.battlerAtk = battlerAtk;
ctx.battlerDef = battlerDef;
ctx.move = move;
diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c
index 1d63466ef8..d3076417f4 100644
--- a/src/battle_controller_player.c
+++ b/src/battle_controller_player.c
@@ -455,6 +455,12 @@ void HandleInputChooseTarget(u32 battler)
PlaySE(SE_SELECT);
gSprites[gBattlerSpriteIds[gMultiUsePlayerCursor]].callback = SpriteCB_HideAsMoveTarget;
gBattlerControllerFuncs[battler] = HandleInputChooseMove;
+ if (gBattleStruct->gimmick.playerSelect == 1 && gBattleStruct->gimmick.usableGimmick[battler] == GIMMICK_Z_MOVE)
+ {
+ gBattleStruct->gimmick.playerSelect = 0;
+ gBattleStruct->zmove.viewing = TRUE;
+ ReloadMoveNames(battler);
+ }
DoBounceEffect(battler, BOUNCE_HEALTHBOX, 7, 1);
DoBounceEffect(battler, BOUNCE_MON, 7, 1);
EndBounceEffect(gMultiUsePlayerCursor, BOUNCE_HEALTHBOX);
@@ -2100,6 +2106,8 @@ void PlayerHandleChooseMove(u32 battler)
if (!IsGimmickTriggerSpriteActive())
gBattleStruct->gimmick.triggerSpriteId = 0xFF;
+ else if (!IsGimmickTriggerSpriteMatchingBattler(battler))
+ DestroyGimmickTriggerSprite();
if (!(gBattleStruct->gimmick.usableGimmick[battler] == GIMMICK_Z_MOVE && !gBattleStruct->zmove.viable))
CreateGimmickTriggerSprite(battler);
diff --git a/src/battle_end_turn.c b/src/battle_end_turn.c
index 50072c2313..2aafa6624d 100644
--- a/src/battle_end_turn.c
+++ b/src/battle_end_turn.c
@@ -298,13 +298,12 @@ static bool32 HandleEndTurnEmergencyExit(u32 battler)
&& IsBattlerAlive(battler)
&& (CanBattlerSwitch(battler) || !(gBattleTypeFlags & BATTLE_TYPE_TRAINER))
&& !(gBattleTypeFlags & BATTLE_TYPE_ARENA)
- && CountUsablePartyMons(battler) > 0
&& gBattleMons[battler].volatiles.semiInvulnerable != STATE_SKY_DROP) // Not currently held by Sky Drop
{
gBattlerAbility = battler;
gLastUsedAbility = ability;
- if (gBattleTypeFlags & BATTLE_TYPE_TRAINER || IsOnPlayerSide(battler))
+ if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
BattleScriptExecute(BattleScript_EmergencyExitEnd2);
else
BattleScriptExecute(BattleScript_EmergencyExitWildEnd2);
diff --git a/src/battle_gimmick.c b/src/battle_gimmick.c
index 76ea80a4f6..38d60d4365 100644
--- a/src/battle_gimmick.c
+++ b/src/battle_gimmick.c
@@ -178,6 +178,13 @@ bool32 IsGimmickTriggerSpriteActive(void)
return FALSE;
}
+bool32 IsGimmickTriggerSpriteMatchingBattler(u32 battler)
+{
+ if (battler == gSprites[gBattleStruct->gimmick.triggerSpriteId].tBattler)
+ return TRUE;
+ return FALSE;
+}
+
void HideGimmickTriggerSprite(void)
{
if (gBattleStruct->gimmick.triggerSpriteId != 0xFF)
diff --git a/src/battle_main.c b/src/battle_main.c
index 685b1a9f15..a57155753d 100644
--- a/src/battle_main.c
+++ b/src/battle_main.c
@@ -3237,6 +3237,9 @@ void SwitchInClearSetData(u32 battler, struct Volatiles *volatilesCopy)
gBattleStruct->battlerState[battler].stompingTantrumTimer = 0;
gBattleStruct->palaceFlags &= ~(1u << battler);
gBattleStruct->battlerState[battler].canPickupItem = FALSE;
+ gBattleStruct->hazardsCounter = 0;
+ gDisableStructs[battler].hazardsDone = FALSE;
+ gSpecialStatuses[battler].switchInItemDone = FALSE;
ClearPursuitValuesIfSet(battler);
diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c
index 3052b45a53..3ec480f9a2 100644
--- a/src/battle_script_commands.c
+++ b/src/battle_script_commands.c
@@ -1098,7 +1098,6 @@ bool32 EmergencyExitCanBeTriggered(u32 battler)
&& HadMoreThanHalfHpNowDoesnt(battler)
&& (CanBattlerSwitch(battler) || !(gBattleTypeFlags & BATTLE_TYPE_TRAINER))
&& !(gBattleTypeFlags & BATTLE_TYPE_ARENA)
- && CountUsablePartyMons(battler) > 0
&& gBattleMons[battler].volatiles.semiInvulnerable != STATE_SKY_DROP)
return TRUE;
@@ -6696,7 +6695,7 @@ static void Cmd_moveend(void)
effect = TRUE;
gBattleScripting.battler = battler;
- if (gBattleTypeFlags & BATTLE_TYPE_TRAINER || IsOnPlayerSide(battler))
+ if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
BattleScriptCall(BattleScript_EmergencyExit);
else
BattleScriptCall(BattleScript_EmergencyExitWild);
@@ -15386,9 +15385,7 @@ void BS_TryAllySwitch(void)
{
NATIVE_ARGS(const u8 *failInstr);
- if (!IsBattlerAlive(BATTLE_PARTNER(gBattlerAttacker))
- || (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER && gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
- || (GetBattlerSide(gBattlerAttacker) == B_SIDE_OPPONENT && gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS))
+ if (!IsBattlerAlive(BATTLE_PARTNER(gBattlerAttacker)) || HasPartnerTrainer(gBattlerAttacker))
{
gBattlescriptCurrInstr = cmd->failInstr;
}
@@ -16831,11 +16828,14 @@ void BS_ArenaJudgmentWindow(void)
gBattlescriptCurrInstr = cmd->nextInstr;
}
-static void SetArenMonLostValues(u32 battler)
+static void SetArenMonLostValues(u32 battler, u32 side)
{
gBattleMons[battler].hp = 0;
gHitMarker |= HITMARKER_FAINTED(battler);
- gBattleStruct->arenaLostOpponentMons |= 1u << gBattlerPartyIndexes[battler];
+ if (side == B_SIDE_PLAYER)
+ gBattleStruct->arenaLostPlayerMons |= 1u << gBattlerPartyIndexes[battler];
+ else
+ gBattleStruct->arenaLostOpponentMons |= 1u << gBattlerPartyIndexes[battler];
gDisableStructs[battler].truantSwitchInHack = TRUE;
}
@@ -16844,22 +16844,22 @@ static void SetArenMonLostValues(u32 battler)
void BS_ArenaOpponentMonLost(void)
{
NATIVE_ARGS();
- SetArenMonLostValues(opponentMon);
+ SetArenMonLostValues(opponentMon, B_SIDE_OPPONENT);
gBattlescriptCurrInstr = cmd->nextInstr;
}
void BS_ArenaPlayerMonLost(void)
{
NATIVE_ARGS();
- SetArenMonLostValues(playerMon);
+ SetArenMonLostValues(playerMon, B_SIDE_PLAYER);
gBattlescriptCurrInstr = cmd->nextInstr;
}
void BS_ArenaBothMonsLost(void)
{
NATIVE_ARGS();
- SetArenMonLostValues(playerMon);
- SetArenMonLostValues(opponentMon);
+ SetArenMonLostValues(playerMon, B_SIDE_PLAYER);
+ SetArenMonLostValues(opponentMon, B_SIDE_OPPONENT);
gBattlescriptCurrInstr = cmd->nextInstr;
}
#undef playerMon
diff --git a/src/battle_tower.c b/src/battle_tower.c
index 0f31106142..d589cb757a 100644
--- a/src/battle_tower.c
+++ b/src/battle_tower.c
@@ -1990,7 +1990,7 @@ void DoSpecialTrainerBattle(void)
gBattleTypeFlags |= BATTLE_TYPE_DOUBLE | BATTLE_TYPE_INGAME_PARTNER | BATTLE_TYPE_MULTI | BATTLE_TYPE_TWO_OPPONENTS;
break;
case FRONTIER_MODE_LINK_MULTIS:
- gBattleTypeFlags |= BATTLE_TYPE_DOUBLE | BATTLE_TYPE_LINK | BATTLE_TYPE_MULTI | BATTLE_TYPE_TOWER_LINK_MULTI;
+ gBattleTypeFlags |= BATTLE_TYPE_DOUBLE | BATTLE_TYPE_LINK | BATTLE_TYPE_MULTI | BATTLE_TYPE_TOWER_LINK_MULTI | BATTLE_TYPE_TWO_OPPONENTS;
FillFrontierTrainersParties(FRONTIER_MULTI_PARTY_SIZE);
break;
}
diff --git a/src/battle_util.c b/src/battle_util.c
index 187ce52955..648f6a9e76 100644
--- a/src/battle_util.c
+++ b/src/battle_util.c
@@ -10771,6 +10771,15 @@ bool32 BreaksThroughSemiInvulnerablity(u32 battler, u32 move)
return FALSE;
}
+bool32 HasPartnerTrainer(u32 battler)
+{
+ if ((GetBattlerSide(battler) == B_SIDE_PLAYER && gBattleTypeFlags & BATTLE_TYPE_PLAYER_HAS_PARTNER)
+ || (GetBattlerSide(battler) == B_SIDE_OPPONENT && gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS))
+ return TRUE;
+ else
+ return FALSE;
+}
+
static u32 GetMirrorMoveMove(void)
{
s32 i, validMovesCount;
diff --git a/src/data/pokemon/species_info/gen_1_families.h b/src/data/pokemon/species_info/gen_1_families.h
index a661147349..f42bf0f445 100644
--- a/src/data/pokemon/species_info/gen_1_families.h
+++ b/src/data/pokemon/species_info/gen_1_families.h
@@ -12522,7 +12522,7 @@ const struct SpeciesInfo gSpeciesInfoGen1[] =
SIZE_32x32,
SHADOW_SIZE_M,
TRACKS_FOOT,
- sAnimTable_Following,
+ sAnimTable_Following_Asym,
gOverworldPalette_Krabby,
gShinyOverworldPalette_Krabby
)
@@ -12592,7 +12592,7 @@ const struct SpeciesInfo gSpeciesInfoGen1[] =
SIZE_32x32,
SHADOW_SIZE_M,
TRACKS_FOOT,
- sAnimTable_Following,
+ sAnimTable_Following_Asym,
gOverworldPalette_Kingler,
gShinyOverworldPalette_Kingler
)
diff --git a/src/field_specials.c b/src/field_specials.c
index 183abbd35c..dde236c911 100644
--- a/src/field_specials.c
+++ b/src/field_specials.c
@@ -22,12 +22,13 @@
#include "item.h"
#include "item_icon.h"
#include "link.h"
-#include "load_save.h"
#include "list_menu.h"
+#include "load_save.h"
#include "main.h"
-#include "mystery_gift.h"
#include "match_call.h"
#include "menu.h"
+#include "metatile_behavior.h"
+#include "mystery_gift.h"
#include "overworld.h"
#include "party_menu.h"
#include "pokeblock.h"
@@ -985,7 +986,7 @@ void FieldShowRegionMap(void)
static bool32 IsBuildingPCTile(u32 tileId)
{
- return gMapHeader.mapLayout->primaryTileset == &gTileset_Building && (tileId == METATILE_Building_PC_On || tileId == METATILE_Building_PC_Off);
+ return (MetatileBehavior_IsPC(UNPACK_BEHAVIOR(GetMetatileAttributesById(tileId))));
}
static bool32 IsPlayerHousePCTile(u32 tileId)
diff --git a/src/pokemon_summary_screen.c b/src/pokemon_summary_screen.c
index f5b61f9cc7..5223c1d35c 100644
--- a/src/pokemon_summary_screen.c
+++ b/src/pokemon_summary_screen.c
@@ -333,6 +333,7 @@ static const u8 *GetLetterGrade(u32 stat);
static u8 AddWindowFromTemplateList(const struct WindowTemplate *template, u8 templateId);
static u8 IncrementSkillsStatsMode(u8 mode);
static void ClearStatLabel(u32 length, u32 statsCoordX, u32 statsCoordY);
+u32 GetAdjustedIvData(struct Pokemon *mon, u32 stat);
static const struct BgTemplate sBgTemplates[] =
{
@@ -1172,6 +1173,13 @@ static void DestroyCategoryIcon(void)
sMonSummaryScreen->categoryIconSpriteId = 0xFF;
}
+u32 GetAdjustedIvData(struct Pokemon *mon, u32 stat)
+{
+ if (P_SUMMARY_SCREEN_IV_HYPERTRAIN && GetMonData(mon, MON_DATA_HYPER_TRAINED_HP + stat))
+ return MAX_PER_STAT_IVS;
+ return GetMonData(mon, MON_DATA_HP_IV + stat);
+}
+
void ShowPokemonSummaryScreen(u8 mode, void *mons, u8 monIndex, u8 maxMonIndex, void (*callback)(void))
{
sMonSummaryScreen = AllocZeroed(sizeof(*sMonSummaryScreen));
@@ -1863,12 +1871,12 @@ void ExtractMonSkillStatsData(struct Pokemon *mon, struct PokeSummary *sum)
void ExtractMonSkillIvData(struct Pokemon *mon, struct PokeSummary *sum)
{
- sum->currentHP = GetMonData(mon, MON_DATA_HP_IV);
- sum->atk = GetMonData(mon, MON_DATA_ATK_IV);
- sum->def = GetMonData(mon, MON_DATA_DEF_IV);
- sum->spatk = GetMonData(mon, MON_DATA_SPATK_IV);
- sum->spdef = GetMonData(mon, MON_DATA_SPDEF_IV);
- sum->speed = GetMonData(mon, MON_DATA_SPEED_IV);
+ sum->currentHP = GetAdjustedIvData(mon, STAT_HP);
+ sum->atk = GetAdjustedIvData(mon, STAT_ATK);
+ sum->def = GetAdjustedIvData(mon, STAT_DEF);
+ sum->spatk = GetAdjustedIvData(mon, STAT_SPATK);
+ sum->spdef = GetAdjustedIvData(mon, STAT_SPDEF);
+ sum->speed = GetAdjustedIvData(mon, STAT_SPEED);
}
void ExtractMonSkillEvData(struct Pokemon *mon, struct PokeSummary *sum)
diff --git a/test/battle/ability/emergency_exit.c b/test/battle/ability/emergency_exit.c
index 5027d929ec..1dcd0be21b 100644
--- a/test/battle/ability/emergency_exit.c
+++ b/test/battle/ability/emergency_exit.c
@@ -108,3 +108,69 @@ SINGLE_BATTLE_TEST("Emergency Exit activates when taking residual damage and fal
ABILITY_POPUP(opponent, ABILITY_EMERGENCY_EXIT);
}
}
+
+WILD_BATTLE_TEST("Emergency Exit makes the pokemon flee during wild battle")
+{
+ GIVEN {
+ PLAYER(SPECIES_WOBBUFFET);
+ PLAYER(SPECIES_WYNAUT);
+ OPPONENT(SPECIES_GOLISOPOD) { Ability(ABILITY_EMERGENCY_EXIT); MaxHP(263); HP(262); };
+ } WHEN {
+ TURN { MOVE(player, MOVE_SUPER_FANG);}
+ } SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_SUPER_FANG, player);
+ HP_BAR(opponent);
+ ABILITY_POPUP(opponent, ABILITY_EMERGENCY_EXIT);
+ } THEN {
+ EXPECT_EQ(gBattleOutcome, B_OUTCOME_MON_TELEPORTED);
+ }
+}
+
+WILD_BATTLE_TEST("Emergency Exit activates when taking residual damage and falling under 50% max-hp (wild battle)")
+{
+ GIVEN {
+ PLAYER(SPECIES_WOBBUFFET);
+ PLAYER(SPECIES_WYNAUT);
+ OPPONENT(SPECIES_GOLISOPOD) { Ability(ABILITY_EMERGENCY_EXIT); MaxHP(263); HP(134); Status1(STATUS1_BURN); };
+ } WHEN {
+ TURN { }
+ } SCENE {
+ HP_BAR(opponent);
+ ABILITY_POPUP(opponent, ABILITY_EMERGENCY_EXIT);
+ } THEN {
+ EXPECT_EQ(gBattleOutcome, B_OUTCOME_MON_TELEPORTED);
+ }
+}
+
+WILD_BATTLE_TEST("Emergency Exit makes the player ran during wild battle")
+{
+ GIVEN {
+ PLAYER(SPECIES_GOLISOPOD) { Ability(ABILITY_EMERGENCY_EXIT); MaxHP(263); HP(262); };
+ PLAYER(SPECIES_WYNAUT);
+ OPPONENT(SPECIES_WOBBUFFET);
+ } WHEN {
+ TURN { MOVE(opponent, MOVE_SUPER_FANG);}
+ } SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_SUPER_FANG, opponent);
+ HP_BAR(player);
+ ABILITY_POPUP(player, ABILITY_EMERGENCY_EXIT);
+ } THEN {
+ EXPECT_EQ(gBattleOutcome, B_OUTCOME_PLAYER_TELEPORTED);
+ }
+}
+
+WILD_BATTLE_TEST("Emergency Exit activates when taking residual damage and falling under 50% max-hp (wild battle player side)")
+{
+ GIVEN {
+ PLAYER(SPECIES_GOLISOPOD) { Ability(ABILITY_EMERGENCY_EXIT); MaxHP(263); HP(134); };
+ PLAYER(SPECIES_WYNAUT);
+ OPPONENT(SPECIES_WOBBUFFET);
+ } WHEN {
+ TURN { MOVE(opponent, MOVE_SANDSTORM);}
+ } SCENE {
+ HP_BAR(player);
+ ABILITY_POPUP(player, ABILITY_EMERGENCY_EXIT);
+ } THEN {
+ EXPECT_EQ(gBattleOutcome, B_OUTCOME_PLAYER_TELEPORTED);
+ }
+}
diff --git a/test/battle/ability/liquid_ooze.c b/test/battle/ability/liquid_ooze.c
index 3af8cc102f..a9e5fb4b90 100644
--- a/test/battle/ability/liquid_ooze.c
+++ b/test/battle/ability/liquid_ooze.c
@@ -187,3 +187,34 @@ SINGLE_BATTLE_TEST("Liquid Ooze does not cause Dream Eater users to lose HP inst
EXPECT_LT(damage, 0); // Negative damage = Heal
}
}
+
+SINGLE_BATTLE_TEST("Liquid Ooze HP loss from Absorb is blocked by Magic Guard")
+{
+ GIVEN {
+ PLAYER(SPECIES_CLEFFA) { Ability(ABILITY_MAGIC_GUARD); }
+ OPPONENT(SPECIES_TENTACOOL) { Ability(ABILITY_LIQUID_OOZE); }
+ } WHEN {
+ TURN { MOVE(player, MOVE_ABSORB); }
+ } SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_ABSORB, player);
+ HP_BAR(opponent);
+ NONE_OF {
+ HP_BAR(player);
+ MESSAGE("Wobbuffet sucked up the liquid ooze!");
+ }
+ }
+}
+
+SINGLE_BATTLE_TEST("Liquid Ooze HP loss from Leech Seed is blocked by Magic Guard")
+{
+ GIVEN {
+ PLAYER(SPECIES_CLEFFA) { Ability(ABILITY_MAGIC_GUARD); }
+ OPPONENT(SPECIES_TENTACOOL) { Ability(ABILITY_LIQUID_OOZE); }
+ } WHEN {
+ TURN { MOVE(player, MOVE_LEECH_SEED); }
+ } SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_LEECH_SEED, player);
+ HP_BAR(opponent);
+ NOT HP_BAR(player);
+ }
+}
diff --git a/test/battle/hazards.c b/test/battle/hazards.c
index 9c974bb7b1..17ecb41f5c 100644
--- a/test/battle/hazards.c
+++ b/test/battle/hazards.c
@@ -38,3 +38,26 @@ SINGLE_BATTLE_TEST("Hazards are applied based on order of set up")
EXPECT_EQ(gBattleStruct->hazardsQueue[0][5], HAZARDS_NONE);
}
}
+
+SINGLE_BATTLE_TEST("Hazards are applied correctly after a battler faints")
+{
+ GIVEN {
+ ASSUME(GetMoveEffect(MOVE_FINAL_GAMBIT) == EFFECT_FINAL_GAMBIT);
+ PLAYER(SPECIES_WYNAUT);
+ PLAYER(SPECIES_WOBBUFFET) { HP(1); }
+ PLAYER(SPECIES_WYNAUT);
+ OPPONENT(SPECIES_WOBBUFFET);
+ } WHEN {
+ TURN { MOVE(opponent, MOVE_STEALTH_ROCK);
+ MOVE(player, MOVE_FINAL_GAMBIT);
+ SEND_OUT(player, 1);
+ SEND_OUT(player, 2); }
+ } SCENE {
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_STEALTH_ROCK, opponent);
+ ANIMATION(ANIM_TYPE_MOVE, MOVE_FINAL_GAMBIT, player);
+ MESSAGE("Wynaut fainted!");
+ MESSAGE("Pointed stones dug into Wobbuffet!");
+ MESSAGE("Wobbuffet fainted!");
+ MESSAGE("Pointed stones dug into Wynaut!");
+ }
+}