Merge branch 'upcoming' of https://github.com/rh-hideout/pokeemerald-expansion into trainerSlideMsgUpdate

This commit is contained in:
LOuroboros 2023-02-27 07:43:19 -03:00
commit a54a8d9b2a
11 changed files with 205 additions and 78 deletions

View File

@ -10338,3 +10338,8 @@ BattleScript_PokemonCantUseTheMove::
printstring STRINGID_BUTPOKEMONCANTUSETHEMOVE
waitmessage B_WAIT_TIME_LONG
goto BattleScript_MoveEnd
BattleScript_CouldntFullyProtect::
printstring STRINGID_COULDNTFULLYPROTECT
waitmessage B_WAIT_TIME_LONG
return

View File

@ -192,16 +192,30 @@ BattleScript_ActionWallyThrow:
waitmessage B_WAIT_TIME_LONG
end2
BattleScript_TrainerSlideMsgRet::
BattleScript_TrainerASlideMsgRet::
handletrainerslidemsg BS_SCRIPTING, 0
trainerslidein 1
trainerslidein B_POSITION_OPPONENT_LEFT
handletrainerslidemsg BS_SCRIPTING, 1
waitstate
trainerslideout 1
handletrainerslidemsg BS_SCRIPTING, 2
trainerslideout B_POSITION_OPPONENT_LEFT
waitstate
handletrainerslidemsg BS_SCRIPTING, 2
return
BattleScript_TrainerSlideMsgEnd2::
call BattleScript_TrainerSlideMsgRet
BattleScript_TrainerASlideMsgEnd2::
call BattleScript_TrainerASlideMsgRet
end2
BattleScript_TrainerBSlideMsgRet::
handletrainerslidemsg BS_SCRIPTING, 0
trainerslidein B_POSITION_OPPONENT_RIGHT
handletrainerslidemsg BS_SCRIPTING, 1
waitstate
trainerslideout B_POSITION_OPPONENT_RIGHT
waitstate
handletrainerslidemsg BS_SCRIPTING, 2
return
BattleScript_TrainerBSlideMsgEnd2::
call BattleScript_TrainerBSlideMsgRet
end2

View File

@ -252,6 +252,7 @@ struct AI_SavedBattleMon
u16 moves[MAX_MON_MOVES];
u16 heldItem;
u16 species;
u8 types[3];
};
struct AiPartyMon

View File

@ -244,7 +244,7 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst);
void BattlePutTextOnWindow(const u8 *text, u8 windowId);
void SetPpNumbersPaletteInMoveSelection(void);
u8 GetCurrentPpToMaxPpState(u8 currentPp, u8 maxPp);
bool32 ShouldDoTrainerSlide(u32 battlerId, u32 trainerId, u32 which);
u32 ShouldDoTrainerSlide(u32 battlerId, u32 which); // return 1 for TrainerA, 2 forTrainerB
void ExpandBattleTextBuffPlaceholders(const u8 *src, u8 *dst);
extern struct BattleMsgData *gBattleMsgDataPtr;

View File

@ -295,8 +295,10 @@ extern const u8 BattleScript_MoveEffectClearSmog[];
extern const u8 BattleScript_SideStatusWoreOffReturn[];
extern const u8 BattleScript_MoveEffectSmackDown[];
extern const u8 BattleScript_MoveEffectFlameBurst[];
extern const u8 BattleScript_TrainerSlideMsgRet[];
extern const u8 BattleScript_TrainerSlideMsgEnd2[];
extern const u8 BattleScript_TrainerASlideMsgRet[];
extern const u8 BattleScript_TrainerASlideMsgEnd2[];
extern const u8 BattleScript_TrainerBSlideMsgRet[];
extern const u8 BattleScript_TrainerBSlideMsgEnd2[];
extern const u8 BattleScript_MoveEffectFeint[];
extern const u8 BattleScript_ProteanActivates[];
extern const u8 BattleScript_DazzlingProtected[];
@ -453,6 +455,7 @@ extern const u8 BattleScript_DampPreventsAftermath[];
extern const u8 BattleScript_HealingWishActivates[];
extern const u8 BattleScript_LunarDanceActivates[];
extern const u8 BattleScript_ShellTrapSetUp[];
extern const u8 BattleScript_CouldntFullyProtect[];
// zmoves
extern const u8 BattleScript_ZMoveActivateDamaging[];

View File

@ -641,8 +641,9 @@
#define STRINGID_PKMNSABILITYPREVENTSABILITY 639
#define STRINGID_PREPARESHELLTRAP 640
#define STRINGID_SHELLTRAPDIDNTWORK 641
#define STRINGID_COULDNTFULLYPROTECT 642
#define BATTLESTRINGS_COUNT 642
#define BATTLESTRINGS_COUNT 643
// This is the string id that gBattleStringsTable starts with.
// String ids before this (e.g. STRINGID_INTROMSG) are not in the table,

View File

@ -538,23 +538,73 @@ void SaveBattlerData(u8 battlerId)
AI_THINKING_STRUCT->saved[battlerId].species = gBattleMons[battlerId].species;
for (i = 0; i < 4; i++)
AI_THINKING_STRUCT->saved[battlerId].moves[i] = gBattleMons[battlerId].moves[i];
AI_THINKING_STRUCT->saved[battlerId].types[0] = gBattleMons[battlerId].type1;
AI_THINKING_STRUCT->saved[battlerId].types[1] = gBattleMons[battlerId].type2;
}
}
static bool32 ShouldFailForIllusion(u16 illusionSpecies, u32 battlerId)
{
u32 i, j;
if (BATTLE_HISTORY->abilities[battlerId] == ABILITY_ILLUSION)
return FALSE;
// Don't fall for Illusion if the mon used a move it cannot know.
for (i = 0; i < MAX_MON_MOVES; i++)
{
u16 move = BATTLE_HISTORY->usedMoves[battlerId][i];
if (move == MOVE_NONE)
continue;
for (j = 0; gLevelUpLearnsets[illusionSpecies][j].move != MOVE_UNAVAILABLE; j++)
{
if (gLevelUpLearnsets[illusionSpecies][j].move == move)
break;
}
// The used move is in the learnsets of the fake species.
if (gLevelUpLearnsets[illusionSpecies][j].move != MOVE_UNAVAILABLE)
continue;
// The used move can be learned from Tm/Hm or Move Tutors.
if (CanLearnTeachableMove(illusionSpecies, move))
continue;
// 'Illegal move', AI won't fail for the illusion.
return FALSE;
}
return TRUE;
}
void SetBattlerData(u8 battlerId)
{
if (!IsBattlerAIControlled(battlerId))
{
struct Pokemon *illusionMon;
u32 i;
u32 i, species, illusionSpecies;
// Simulate Illusion
species = gBattleMons[battlerId].species;
illusionSpecies = GetIllusionMonSpecies(battlerId);
if (illusionSpecies != SPECIES_NONE && ShouldFailForIllusion(illusionSpecies, battlerId))
{
// If the battler's type has not been changed, AI assumes the types of the illusion mon.
if (gBattleMons[battlerId].type1 == gSpeciesInfo[species].types[0]
&& gBattleMons[battlerId].type2 == gSpeciesInfo[species].types[1])
{
gBattleMons[battlerId].type1 = gSpeciesInfo[illusionSpecies].types[0];
gBattleMons[battlerId].type2 = gSpeciesInfo[illusionSpecies].types[1];
}
species = illusionSpecies;
}
// Use the known battler's ability.
if (BATTLE_HISTORY->abilities[battlerId] != ABILITY_NONE)
gBattleMons[battlerId].ability = BATTLE_HISTORY->abilities[battlerId];
// Check if mon can only have one ability.
else if (gSpeciesInfo[gBattleMons[battlerId].species].abilities[1] == ABILITY_NONE
|| gSpeciesInfo[gBattleMons[battlerId].species].abilities[1] == gSpeciesInfo[gBattleMons[battlerId].species].abilities[0])
gBattleMons[battlerId].ability = gSpeciesInfo[gBattleMons[battlerId].species].abilities[0];
else if (gSpeciesInfo[species].abilities[1] == ABILITY_NONE
|| gSpeciesInfo[species].abilities[1] == gSpeciesInfo[species].abilities[0])
gBattleMons[battlerId].ability = gSpeciesInfo[species].abilities[0];
// The ability is unknown.
else
gBattleMons[battlerId].ability = ABILITY_NONE;
@ -567,10 +617,6 @@ void SetBattlerData(u8 battlerId)
if (BATTLE_HISTORY->usedMoves[battlerId][i] == 0)
gBattleMons[battlerId].moves[i] = 0;
}
// Simulate Illusion
if ((illusionMon = GetIllusionMonPtr(battlerId)) != NULL)
gBattleMons[battlerId].species = GetMonData(illusionMon, MON_DATA_SPECIES2);
}
}
@ -585,6 +631,8 @@ void RestoreBattlerData(u8 battlerId)
gBattleMons[battlerId].species = AI_THINKING_STRUCT->saved[battlerId].species;
for (i = 0; i < 4; i++)
gBattleMons[battlerId].moves[i] = AI_THINKING_STRUCT->saved[battlerId].moves[i];
gBattleMons[battlerId].type1 = AI_THINKING_STRUCT->saved[battlerId].types[0];
gBattleMons[battlerId].type2 = AI_THINKING_STRUCT->saved[battlerId].types[1];
}
}

View File

@ -3866,18 +3866,18 @@ void BattleTurnPassed(void)
BattleScriptExecute(BattleScript_PalacePrintFlavorText);
else if (gBattleTypeFlags & BATTLE_TYPE_ARENA && gBattleStruct->arenaTurnCounter == 0)
BattleScriptExecute(BattleScript_ArenaTurnBeginning);
else if (ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), gTrainerBattleOpponent_A, TRAINER_SLIDE_LAST_LOW_HP))
BattleScriptExecute(BattleScript_TrainerSlideMsgEnd2);
else if (ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), gTrainerBattleOpponent_A, TRAINER_SLIDE_LAST_HALF_HP))
BattleScriptExecute(BattleScript_TrainerSlideMsgEnd2);
else if (ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), gTrainerBattleOpponent_A, TRAINER_SLIDE_FIRST_CRITICAL_HIT))
BattleScriptExecute(BattleScript_TrainerSlideMsgEnd2);
else if (ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), gTrainerBattleOpponent_A, TRAINER_SLIDE_FIRST_SUPER_EFFECTIVE_HIT))
BattleScriptExecute(BattleScript_TrainerSlideMsgEnd2);
else if (ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), gTrainerBattleOpponent_A, TRAINER_SLIDE_FIRST_STAB_MOVE))
BattleScriptExecute(BattleScript_TrainerSlideMsgEnd2);
else if (ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), gTrainerBattleOpponent_A, TRAINER_SLIDE_PLAYER_MON_UNAFFECTED))
BattleScriptExecute(BattleScript_TrainerSlideMsgEnd2);
else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_LAST_LOW_HP)))
BattleScriptExecute(i == 1 ? BattleScript_TrainerASlideMsgEnd2 : BattleScript_TrainerBSlideMsgEnd2);
else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_LAST_HALF_HP))
BattleScriptExecute(i == 1 ? BattleScript_TrainerASlideMsgEnd2 : BattleScript_TrainerBSlideMsgEnd2);
else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_FIRST_CRITICAL_HIT))
BattleScriptExecute(i == 1 ? BattleScript_TrainerASlideMsgEnd2 : BattleScript_TrainerBSlideMsgEnd2);
else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_FIRST_SUPER_EFFECTIVE_HIT))
BattleScriptExecute(i == 1 ? BattleScript_TrainerASlideMsgEnd2 : BattleScript_TrainerBSlideMsgEnd2);
else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_FIRST_STAB_MOVE))
BattleScriptExecute(i == 1 ? BattleScript_TrainerASlideMsgEnd2 : BattleScript_TrainerBSlideMsgEnd2);
else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_PLAYER_MON_UNAFFECTED))
BattleScriptExecute(i == 1 ? BattleScript_TrainerASlideMsgEnd2 : BattleScript_TrainerBSlideMsgEnd2);
}
u8 IsRunningFromBattleImpossible(void)

View File

@ -776,9 +776,11 @@ static const u8 sText_AbilityWeakenedSurroundingMonsStat[] = _("{B_ATK_NAME_WITH
static const u8 sText_AttackerGainedStrengthFromTheFallen[] = _("{B_ATK_NAME_WITH_PREFIX} gained strength\nfrom the fallen!");
static const u8 sText_PrepareShellTrap[] = _("{B_ATK_NAME_WITH_PREFIX} set a shell trap!");
static const u8 sText_ShellTrapDidntWork[] = _("{B_ATK_NAME_WITH_PREFIX}'s shell trap didn't work!");
static const u8 sText_CouldntFullyProtect[] = _("{B_DEF_NAME_WITH_PREFIX} couldn't fully protect\nitself and got hurt!");
const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
{
[STRINGID_COULDNTFULLYPROTECT - BATTLESTRINGS_TABLE_START] = sText_CouldntFullyProtect,
[STRINGID_ATTACKERGAINEDSTRENGTHFROMTHEFALLEN - BATTLESTRINGS_TABLE_START] = sText_AttackerGainedStrengthFromTheFallen,
[STRINGID_ABILITYWEAKENEDFSURROUNDINGMONSSTAT - BATTLESTRINGS_TABLE_START] = sText_AbilityWeakenedSurroundingMonsStat,
[STRINGID_ELECTRICTERRAINACTIVATEDABILITY - BATTLESTRINGS_TABLE_START] = sText_ElectricTerrainActivatedAbility,
@ -3901,40 +3903,49 @@ static const struct TrainerSlide sTrainerSlides[] =
*/
};
static u32 GetAliveEnemyMonCount(void)
static u32 GetEnemyMonCount(u32 firstId, u32 lastId, bool32 onlyAlive)
{
u32 i, count = 0;
for (i = 0; i < PARTY_SIZE; i++)
for (i = firstId; i < lastId; i++)
{
u32 species = GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2, NULL);
if (species != SPECIES_NONE && species != SPECIES_EGG && GetMonData(&gEnemyParty[i], MON_DATA_HP, NULL))
if (species != SPECIES_NONE
&& species != SPECIES_EGG
&& (!onlyAlive || GetMonData(&gEnemyParty[i], MON_DATA_HP, NULL)))
count++;
}
return count;
}
static u32 GetTotalEnemyMonCount(void)
u32 ShouldDoTrainerSlide(u32 battlerId, u32 which)
{
u32 i, count = 0;
for (i = 0; i < PARTY_SIZE; i++)
{
u32 species = GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2, NULL);
if (species != SPECIES_NONE && species != SPECIES_EGG)
count++;
}
return count;
}
bool32 ShouldDoTrainerSlide(u32 battlerId, u32 trainerId, u32 which)
{
s32 i;
u32 i, firstId, lastId, trainerId, retValue = 1;
if (!(gBattleTypeFlags & BATTLE_TYPE_TRAINER) || GetBattlerSide(battlerId) != B_SIDE_OPPONENT)
return FALSE;
return 0;
// Two opponents support.
if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)
{
if (gBattlerPartyIndexes[battlerId] >= 3)
{
firstId = 3, lastId = PARTY_SIZE;
trainerId = gTrainerBattleOpponent_B;
retValue = 2;
}
else
{
firstId = 0, lastId = 3;
trainerId = gTrainerBattleOpponent_A;
}
}
else
{
firstId = 0, lastId = PARTY_SIZE;
trainerId = gTrainerBattleOpponent_A;
}
for (i = 0; i < ARRAY_COUNT(sTrainerSlides); i++)
{
@ -3944,33 +3955,33 @@ bool32 ShouldDoTrainerSlide(u32 battlerId, u32 trainerId, u32 which)
switch (which)
{
case TRAINER_SLIDE_LAST_SWITCHIN:
if (sTrainerSlides[i].msgLastSwitchIn != NULL && GetAliveEnemyMonCount() == 1)
if (sTrainerSlides[i].msgLastSwitchIn != NULL && !CanBattlerSwitch(battlerId))
{
gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgLastSwitchIn;
return TRUE;
return retValue;
}
break;
case TRAINER_SLIDE_LAST_LOW_HP:
if (sTrainerSlides[i].msgLastLowHp != NULL
&& GetAliveEnemyMonCount() == 1
&& gBattleMons[battlerId].hp <= (gBattleMons[battlerId].maxHP / 4)
&& !gBattleStruct->trainerSlideLowHpMsgDone)
&& GetEnemyMonCount(firstId, lastId, TRUE) == 1
&& IsBattlerHpLow(battlerId)
&& !gBattleStruct->trainerSlideLowHpMsgDone)
{
gBattleStruct->trainerSlideLowHpMsgDone = TRUE;
gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgLastLowHp;
return TRUE;
return retValue;
}
break;
case TRAINER_SLIDE_FIRST_DOWN:
if (sTrainerSlides[i].msgFirstDown != NULL && GetAliveEnemyMonCount() == GetTotalEnemyMonCount() - 1)
if (sTrainerSlides[i].msgFirstDown != NULL && GetEnemyMonCount(firstId, lastId, TRUE) == GetEnemyMonCount(firstId, lastId, FALSE) - 1)
{
gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgFirstDown;
return TRUE;
return retValue;
}
break;
case TRAINER_SLIDE_LAST_HALF_HP:
if (sTrainerSlides[i].msgLastHalfHp != NULL
&& GetAliveEnemyMonCount() == 1
&& GetEnemyMonCount(firstId, lastId, TRUE) == GetEnemyMonCount(firstId, lastId, FALSE) - 1
&& (gBattleMons[battlerId].hp <= (gBattleMons[battlerId].maxHP / 2) && gBattleMons[battlerId].hp > (gBattleMons[battlerId].maxHP / 4))
&& !gBattleStruct->trainerSlideHalfHpMsgDone)
{
@ -4000,7 +4011,7 @@ bool32 ShouldDoTrainerSlide(u32 battlerId, u32 trainerId, u32 which)
case TRAINER_SLIDE_FIRST_STAB_MOVE:
if (sTrainerSlides[i].msgFirstSTABMove != NULL
&& gBattleStruct->trainerSlideFirstSTABMoveMsgState == 1
&& GetAliveEnemyMonCount() == GetTotalEnemyMonCount())
&& GetEnemyMonCount(firstId, lastId, TRUE) == GetEnemyMonCount(firstId, lastId, FALSE))
{
gBattleStruct->trainerSlideFirstSTABMoveMsgState = 2;
gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgFirstSTABMove;
@ -4010,7 +4021,7 @@ bool32 ShouldDoTrainerSlide(u32 battlerId, u32 trainerId, u32 which)
case TRAINER_SLIDE_PLAYER_MON_UNAFFECTED:
if (sTrainerSlides[i].msgPlayerMonUnaffected != NULL
&& gBattleStruct->trainerSlidePlayerMonUnaffectedMsgState == 1
&& GetAliveEnemyMonCount() == GetTotalEnemyMonCount())
&& GetEnemyMonCount(firstId, lastId, TRUE) == GetEnemyMonCount(firstId, lastId, FALSE))
{
gBattleStruct->trainerSlidePlayerMonUnaffectedMsgState = 2;
gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgPlayerMonUnaffected;
@ -4038,5 +4049,5 @@ bool32 ShouldDoTrainerSlide(u32 battlerId, u32 trainerId, u32 which)
}
}
return FALSE;
return 0;
}

View File

@ -1591,6 +1591,14 @@ static void Cmd_attackcanceler(void)
return;
}
// Z-moves and Max Moves bypass protection, but deal reduced damage (factored in CalcFinalDmg)
if (gBattleStruct->zmove.active && IS_BATTLER_PROTECTED(gBattlerTarget))
{
BattleScriptPush(cmd->nextInstr);
gBattlescriptCurrInstr = BattleScript_CouldntFullyProtect;
return;
}
for (i = 0; i < gBattlersCount; i++)
{
if ((gProtectStructs[gBattlerByTurnOrder[i]].stealMove) && gBattleMoves[gCurrentMove].flags & FLAG_SNATCH_AFFECTED)
@ -10120,7 +10128,8 @@ static void Cmd_various(void)
VARIOUS_ARGS(u8 case_);
if (cmd->case_ == 0)
{
gBattleScripting.savedDmg = gBattlerSpriteIds[gActiveBattler];
// Save sprite IDs, because trainer slide in will overwrite gBattlerSpriteIds variable.
gBattleScripting.savedDmg = (gBattlerSpriteIds[gActiveBattler] & 0xFF) | (gBattlerSpriteIds[BATTLE_PARTNER(gActiveBattler)] << 8);
HideBattlerShadowSprite(gActiveBattler);
}
else if (cmd->case_ == 1)
@ -10130,12 +10139,19 @@ static void Cmd_various(void)
}
else
{
gBattlerSpriteIds[gActiveBattler] = gBattleScripting.savedDmg;
if (gBattleMons[gActiveBattler].hp != 0)
gBattlerSpriteIds[BATTLE_PARTNER(gActiveBattler)] = gBattleScripting.savedDmg >> 8;
gBattlerSpriteIds[gActiveBattler] = gBattleScripting.savedDmg & 0xFF;
if (IsBattlerAlive(gActiveBattler))
{
SetBattlerShadowSpriteCallback(gActiveBattler, gBattleMons[gActiveBattler].species);
BattleLoadOpponentMonSpriteGfx(&gEnemyParty[gBattlerPartyIndexes[gActiveBattler]], gActiveBattler);
}
i = BATTLE_PARTNER(gActiveBattler);
if (IsBattlerAlive(i))
{
SetBattlerShadowSpriteCallback(i, gBattleMons[i].species);
BattleLoadOpponentMonSpriteGfx(&gEnemyParty[gBattlerPartyIndexes[i]], i);
}
}
gBattlescriptCurrInstr = cmd->nextInstr;
return;
@ -10143,11 +10159,11 @@ static void Cmd_various(void)
case VARIOUS_TRY_TRAINER_SLIDE_MSG_FIRST_OFF:
{
VARIOUS_ARGS();
if (ShouldDoTrainerSlide(gActiveBattler, gTrainerBattleOpponent_A, TRAINER_SLIDE_FIRST_DOWN))
if ((i = ShouldDoTrainerSlide(gActiveBattler, TRAINER_SLIDE_FIRST_DOWN)))
{
gBattleScripting.battler = gActiveBattler;
BattleScriptPush(cmd->nextInstr);
gBattlescriptCurrInstr = BattleScript_TrainerSlideMsgRet;
gBattlescriptCurrInstr = (i == 1 ? BattleScript_TrainerASlideMsgRet : BattleScript_TrainerBSlideMsgRet);
return;
}
break;
@ -10155,11 +10171,11 @@ static void Cmd_various(void)
case VARIOUS_TRY_TRAINER_SLIDE_MSG_LAST_ON:
{
VARIOUS_ARGS();
if (ShouldDoTrainerSlide(gActiveBattler, gTrainerBattleOpponent_A, TRAINER_SLIDE_LAST_SWITCHIN))
if ((i = ShouldDoTrainerSlide(gActiveBattler, TRAINER_SLIDE_LAST_SWITCHIN)))
{
gBattleScripting.battler = gActiveBattler;
BattleScriptPush(cmd->nextInstr);
gBattlescriptCurrInstr = BattleScript_TrainerSlideMsgRet;
gBattlescriptCurrInstr = (i == 1 ? BattleScript_TrainerASlideMsgRet : BattleScript_TrainerBSlideMsgRet);
return;
}
break;

View File

@ -8249,9 +8249,15 @@ bool32 IsBattlerProtected(u8 battlerId, u16 move)
return FALSE;
}
if (move == MOVE_TEATIME)
if (move == MOVE_TEATIME)
{
return FALSE;
return FALSE;
}
// Z-Moves and Max Moves bypass protection
if (gBattleStruct->zmove.active)
{
return FALSE;
}
// Protective Pads doesn't stop Unseen Fist from bypassing Protect effects, so IsMoveMakingContact() isn't used here.
@ -9638,6 +9644,12 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move
MulModifier(&finalModifier, UQ_4_12(0.25));
}
// Z-Moves and Max Moves bypass Protect and do 25% of their original damage
if (gBattleStruct->zmove.active && IS_BATTLER_PROTECTED(battlerDef))
{
MulModifier(&finalModifier, UQ_4_12(0.25));
}
// attacker's abilities
switch (abilityAtk)
{
@ -9823,6 +9835,18 @@ static void MulByTypeEffectiveness(u16 *modifier, u16 move, u8 moveType, u8 batt
MulModifier(modifier, mod);
}
static void TryNoticeIllusionInTypeEffectiveness(u32 move, u32 moveType, u32 battlerAtk, u32 battlerDef, u16 resultingModifier, u32 illusionSpecies)
{
// Check if the type effectiveness would've been different if the pokemon really had the types as the disguise.
u16 presumedModifier = UQ_4_12(1.0);
MulByTypeEffectiveness(&presumedModifier, move, moveType, battlerDef, gSpeciesInfo[illusionSpecies].types[0], battlerAtk, FALSE);
if (gSpeciesInfo[illusionSpecies].types[1] != gSpeciesInfo[illusionSpecies].types[0])
MulByTypeEffectiveness(&presumedModifier, move, moveType, battlerDef, gSpeciesInfo[illusionSpecies].types[1], battlerAtk, FALSE);
if (presumedModifier != resultingModifier)
RecordAbilityBattle(battlerDef, ABILITY_ILLUSION);
}
static void UpdateMoveResultFlags(u16 modifier)
{
if (modifier == UQ_4_12(0.0))
@ -9848,6 +9872,7 @@ static void UpdateMoveResultFlags(u16 modifier)
static u16 CalcTypeEffectivenessMultiplierInternal(u16 move, u8 moveType, u8 battlerAtk, u8 battlerDef, bool32 recordAbilities, u16 modifier)
{
u32 illusionSpecies;
u16 defAbility = GetBattlerAbility(battlerDef);
MulByTypeEffectiveness(&modifier, move, moveType, battlerDef, gBattleMons[battlerDef].type1, battlerAtk, recordAbilities);
@ -9857,15 +9882,18 @@ static u16 CalcTypeEffectivenessMultiplierInternal(u16 move, u8 moveType, u8 bat
&& gBattleMons[battlerDef].type3 != gBattleMons[battlerDef].type1)
MulByTypeEffectiveness(&modifier, move, moveType, battlerDef, gBattleMons[battlerDef].type3, battlerAtk, recordAbilities);
if (recordAbilities && (illusionSpecies = GetIllusionMonSpecies(battlerDef)))
TryNoticeIllusionInTypeEffectiveness(move, moveType, battlerAtk, battlerDef, modifier, illusionSpecies);
if (gBattleMoves[move].split == SPLIT_STATUS && move != MOVE_THUNDER_WAVE)
{
modifier = UQ_4_12(1.0);
#if B_GLARE_GHOST <= GEN_3
if (move == MOVE_GLARE && IS_BATTLER_OF_TYPE(battlerDef, TYPE_GHOST))
{
modifier = UQ_4_12(0.0);
}
#endif
#if B_GLARE_GHOST <= GEN_3
if (move == MOVE_GLARE && IS_BATTLER_OF_TYPE(battlerDef, TYPE_GHOST))
{
modifier = UQ_4_12(0.0);
}
#endif
}
else if (moveType == TYPE_GROUND && !IsBattlerGrounded2(battlerDef, TRUE) && !(gBattleMoves[move].flags & FLAG_DMG_UNGROUNDED_IGNORE_TYPE_IF_FLYING))
{