mirror of
https://github.com/Ninjdai1/pokeemerald.git
synced 2024-11-16 11:37:40 +01:00
Added new trainer slide-in msg conditions
Now they can say something: -When their last Pokémon's HP is between 25% and 50%. -When a critical hit is dealt to their first Pokémon for the first time. -When a super effective hit is dealt to their first Pokémon for the first time. -When a STAB move is used against (but doesn't faint) the opponent's Pokémon. -When the Player's Pokémon's move doesn't affect the opponent's Pokémon. -When they're about to trigger a Mega Evolution. -When they're about to trigger a Z-Move. Misc. changes: -Split GetEnemyMonCount for readability's sake. -Optimized the size allocated to trainerSlideLowHpMsgDone.
This commit is contained in:
parent
6e134bb7dc
commit
3a91a5c930
@ -2049,6 +2049,14 @@
|
||||
.4byte \jumpInstr
|
||||
.endm
|
||||
|
||||
.macro trytrainerslidezmovemsg battler:req
|
||||
various \battler, VARIOUS_TRY_TRAINER_SLIDE_MSG_Z_MOVE
|
||||
.endm
|
||||
|
||||
.macro trytrainerslidemegaevolutionmsg battler:req
|
||||
various \battler, VARIOUS_TRY_TRAINER_SLIDE_MSG_MEGA_EVOLUTION
|
||||
.endm
|
||||
|
||||
@ helpful macros
|
||||
.macro setstatchanger stat:req, stages:req, down:req
|
||||
setbyte sSTATCHANGER, \stat | \stages << 3 | \down << 7
|
||||
|
@ -7763,6 +7763,8 @@ BattleScript_FocusPunchSetUp::
|
||||
end2
|
||||
|
||||
BattleScript_MegaEvolution::
|
||||
printstring STRINGID_EMPTYSTRING3
|
||||
trytrainerslidemegaevolutionmsg BS_ATTACKER
|
||||
printstring STRINGID_MEGAEVOREACTING
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
setbyte gIsCriticalHit, 0
|
||||
@ -7777,6 +7779,8 @@ BattleScript_MegaEvolution::
|
||||
end2
|
||||
|
||||
BattleScript_WishMegaEvolution::
|
||||
printstring STRINGID_EMPTYSTRING3
|
||||
trytrainerslidemegaevolutionmsg BS_ATTACKER
|
||||
printstring STRINGID_FERVENTWISHREACHED
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
setbyte gIsCriticalHit, 0
|
||||
@ -9989,6 +9993,8 @@ BattleScript_JabocaRowapBerryActivate_Dmg:
|
||||
|
||||
@ z moves / effects
|
||||
BattleScript_ZMoveActivateDamaging::
|
||||
printstring STRINGID_EMPTYSTRING3
|
||||
trytrainerslidezmovemsg BS_ATTACKER
|
||||
printstring STRINGID_ZPOWERSURROUNDS
|
||||
playanimation BS_ATTACKER, B_ANIM_ZMOVE_ACTIVATE, NULL
|
||||
printstring STRINGID_ZMOVEUNLEASHED
|
||||
@ -9996,6 +10002,8 @@ BattleScript_ZMoveActivateDamaging::
|
||||
return
|
||||
|
||||
BattleScript_ZMoveActivateStatus::
|
||||
printstring STRINGID_EMPTYSTRING3
|
||||
trytrainerslidezmovemsg BS_ATTACKER
|
||||
savetarget
|
||||
printstring STRINGID_ZPOWERSURROUNDS
|
||||
playanimation BS_ATTACKER, B_ANIM_ZMOVE_ACTIVATE, NULL
|
||||
|
@ -620,7 +620,7 @@ struct BattleStruct
|
||||
struct MegaEvolutionData mega;
|
||||
struct ZMoveData zmove;
|
||||
const u8 *trainerSlideMsg;
|
||||
bool8 trainerSlideLowHpMsgDone;
|
||||
bool8 trainerSlideLowHpMsgDone:1;
|
||||
u8 introState;
|
||||
u8 ateBerry[2]; // array id determined by side, each party pokemon as bit
|
||||
u8 stolenStats[NUM_BATTLE_STATS]; // hp byte is used for which stats to raise, other inform about by how many stages
|
||||
@ -655,6 +655,13 @@ struct BattleStruct
|
||||
u16 overwrittenAbilities[MAX_BATTLERS_COUNT]; // abilities overwritten during battle (keep separate from battle history in case of switching)
|
||||
bool8 allowedToChangeFormInWeather[PARTY_SIZE][2]; // For each party member and side, used by Ice Face.
|
||||
u8 battleBondTransformed[NUM_BATTLE_SIDES]; // Bitfield for each party.
|
||||
bool8 trainerSlideHalfHpMsgDone:1;
|
||||
u8 trainerSlideFirstCriticalHitMsgState:2;
|
||||
u8 trainerSlideFirstSuperEffectiveHitMsgState:2;
|
||||
u8 trainerSlideFirstSTABMoveMsgState:2;
|
||||
u8 trainerSlidePlayerMonUnaffectedMsgState:2;
|
||||
bool8 trainerSlideMegaEvolutionMsgDone:1;
|
||||
bool8 trainerSlideZMoveMsgDone:1;
|
||||
};
|
||||
|
||||
#define F_DYNAMIC_TYPE_1 (1 << 6)
|
||||
|
@ -229,6 +229,13 @@ enum
|
||||
TRAINER_SLIDE_LAST_SWITCHIN,
|
||||
TRAINER_SLIDE_LAST_LOW_HP,
|
||||
TRAINER_SLIDE_FIRST_DOWN,
|
||||
TRAINER_SLIDE_LAST_HALF_HP,
|
||||
TRAINER_SLIDE_FIRST_CRITICAL_HIT,
|
||||
TRAINER_SLIDE_FIRST_SUPER_EFFECTIVE_HIT,
|
||||
TRAINER_SLIDE_FIRST_STAB_MOVE,
|
||||
TRAINER_SLIDE_PLAYER_MON_UNAFFECTED,
|
||||
TRAINER_SLIDE_MEGA_EVOLUTION,
|
||||
TRAINER_SLIDE_Z_MOVE,
|
||||
};
|
||||
|
||||
void BufferStringBattle(u16 stringID);
|
||||
|
@ -257,6 +257,8 @@
|
||||
#define VARIOUS_ACTIVATE_TERRAIN_CHANGE_ABILITIES 165
|
||||
#define VARIOUS_JUMP_IF_NO_VALID_TARGETS 166
|
||||
#define VARIOUS_JUMP_IF_EMERGENCY_EXITED 167
|
||||
#define VARIOUS_TRY_TRAINER_SLIDE_MSG_Z_MOVE 168
|
||||
#define VARIOUS_TRY_TRAINER_SLIDE_MSG_MEGA_EVOLUTION 169
|
||||
|
||||
// Cmd_manipulatedamage
|
||||
#define DMG_CHANGE_SIGN 0
|
||||
|
@ -3868,6 +3868,16 @@ void BattleTurnPassed(void)
|
||||
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);
|
||||
}
|
||||
|
||||
u8 IsRunningFromBattleImpossible(void)
|
||||
|
@ -3868,6 +3868,13 @@ struct TrainerSlide
|
||||
const u8 *msgLastSwitchIn;
|
||||
const u8 *msgLastLowHp;
|
||||
const u8 *msgFirstDown;
|
||||
const u8 *msgLastHalfHp;
|
||||
const u8 *msgFirstCriticalHit;
|
||||
const u8 *msgFirstSuperEffectiveHit;
|
||||
const u8 *msgFirstSTABMove;
|
||||
const u8 *msgPlayerMonUnaffected;
|
||||
const u8 *msgMegaEvolution;
|
||||
const u8 *msgZMove;
|
||||
};
|
||||
|
||||
static const struct TrainerSlide sTrainerSlides[] =
|
||||
@ -3879,20 +3886,39 @@ static const struct TrainerSlide sTrainerSlides[] =
|
||||
.msgLastSwitchIn = sText_AarghAlmostHadIt,
|
||||
.msgLastLowHp = sText_BoxIsFull,
|
||||
.msgFirstDown = sText_123Poof,
|
||||
.msgLastHalfHp = sText_ShootSoClose,
|
||||
.msgFirstCriticalHit = sText_CriticalHit,
|
||||
.msgFirstSuperEffectiveHit = sText_SuperEffective,
|
||||
.msgFirstSTABMove = sText_ABoosted,
|
||||
.msgPlayerMonUnaffected = sText_ButNoEffect,
|
||||
.msgMegaEvolution = sText_PowderExplodes,
|
||||
.msgZMove = sText_Electromagnetism,
|
||||
},
|
||||
*/
|
||||
};
|
||||
|
||||
static u32 GetEnemyMonCount(bool32 onlyAlive)
|
||||
static u32 GetAliveEnemyMonCount(void)
|
||||
{
|
||||
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
|
||||
&& (!onlyAlive || GetMonData(&gEnemyParty[i], MON_DATA_HP, NULL)))
|
||||
if (species != SPECIES_NONE && species != SPECIES_EGG && GetMonData(&gEnemyParty[i], MON_DATA_HP, NULL))
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static u32 GetTotalEnemyMonCount(void)
|
||||
{
|
||||
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++;
|
||||
}
|
||||
|
||||
@ -3914,7 +3940,7 @@ bool32 ShouldDoTrainerSlide(u32 battlerId, u32 trainerId, u32 which)
|
||||
switch (which)
|
||||
{
|
||||
case TRAINER_SLIDE_LAST_SWITCHIN:
|
||||
if (sTrainerSlides[i].msgLastSwitchIn != NULL && GetEnemyMonCount(TRUE) == 1)
|
||||
if (sTrainerSlides[i].msgLastSwitchIn != NULL && GetAliveEnemyMonCount() == 1)
|
||||
{
|
||||
gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgLastSwitchIn;
|
||||
return TRUE;
|
||||
@ -3922,7 +3948,7 @@ bool32 ShouldDoTrainerSlide(u32 battlerId, u32 trainerId, u32 which)
|
||||
break;
|
||||
case TRAINER_SLIDE_LAST_LOW_HP:
|
||||
if (sTrainerSlides[i].msgLastLowHp != NULL
|
||||
&& GetEnemyMonCount(TRUE) == 1
|
||||
&& GetAliveEnemyMonCount() == 1
|
||||
&& gBattleMons[battlerId].hp <= (gBattleMons[battlerId].maxHP / 4)
|
||||
&& !gBattleStruct->trainerSlideLowHpMsgDone)
|
||||
{
|
||||
@ -3932,12 +3958,77 @@ bool32 ShouldDoTrainerSlide(u32 battlerId, u32 trainerId, u32 which)
|
||||
}
|
||||
break;
|
||||
case TRAINER_SLIDE_FIRST_DOWN:
|
||||
if (sTrainerSlides[i].msgFirstDown != NULL && GetEnemyMonCount(TRUE) == GetEnemyMonCount(FALSE) - 1)
|
||||
if (sTrainerSlides[i].msgFirstDown != NULL && GetAliveEnemyMonCount() == GetTotalEnemyMonCount() - 1)
|
||||
{
|
||||
gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgFirstDown;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case TRAINER_SLIDE_LAST_HALF_HP:
|
||||
if (sTrainerSlides[i].msgLastHalfHp != NULL
|
||||
&& GetAliveEnemyMonCount() == 1
|
||||
&& (gBattleMons[battlerId].hp <= (gBattleMons[battlerId].maxHP / 2) && gBattleMons[battlerId].hp > (gBattleMons[battlerId].maxHP / 4))
|
||||
&& !gBattleStruct->trainerSlideHalfHpMsgDone)
|
||||
{
|
||||
gBattleStruct->trainerSlideHalfHpMsgDone = TRUE;
|
||||
gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgLastHalfHp;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case TRAINER_SLIDE_FIRST_CRITICAL_HIT:
|
||||
if (sTrainerSlides[i].msgFirstCriticalHit != NULL && gBattleStruct->trainerSlideFirstCriticalHitMsgState == 1)
|
||||
{
|
||||
gBattleStruct->trainerSlideFirstCriticalHitMsgState = 2;
|
||||
gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgFirstCriticalHit;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case TRAINER_SLIDE_FIRST_SUPER_EFFECTIVE_HIT:
|
||||
if (sTrainerSlides[i].msgFirstSuperEffectiveHit != NULL
|
||||
&& gBattleStruct->trainerSlideFirstSuperEffectiveHitMsgState == 1
|
||||
&& gBattleMons[battlerId].hp)
|
||||
{
|
||||
gBattleStruct->trainerSlideFirstSuperEffectiveHitMsgState = 2;
|
||||
gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgFirstSuperEffectiveHit;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case TRAINER_SLIDE_FIRST_STAB_MOVE:
|
||||
if (sTrainerSlides[i].msgFirstSTABMove != NULL
|
||||
&& gBattleStruct->trainerSlideFirstSTABMoveMsgState == 1
|
||||
&& GetAliveEnemyMonCount() == GetTotalEnemyMonCount())
|
||||
{
|
||||
gBattleStruct->trainerSlideFirstSTABMoveMsgState = 2;
|
||||
gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgFirstSTABMove;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case TRAINER_SLIDE_PLAYER_MON_UNAFFECTED:
|
||||
if (sTrainerSlides[i].msgPlayerMonUnaffected != NULL
|
||||
&& gBattleStruct->trainerSlidePlayerMonUnaffectedMsgState == 1
|
||||
&& GetAliveEnemyMonCount() == GetTotalEnemyMonCount())
|
||||
{
|
||||
gBattleStruct->trainerSlidePlayerMonUnaffectedMsgState = 2;
|
||||
gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgPlayerMonUnaffected;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case TRAINER_SLIDE_MEGA_EVOLUTION:
|
||||
if (sTrainerSlides[i].msgMegaEvolution != NULL && !gBattleStruct->trainerSlideMegaEvolutionMsgDone)
|
||||
{
|
||||
gBattleStruct->trainerSlideMegaEvolutionMsgDone = TRUE;
|
||||
gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgMegaEvolution;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case TRAINER_SLIDE_Z_MOVE:
|
||||
if (sTrainerSlides[i].msgZMove != NULL && !gBattleStruct->trainerSlideZMoveMsgDone)
|
||||
{
|
||||
gBattleStruct->trainerSlideZMoveMsgDone = TRUE;
|
||||
gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgZMove;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -2540,6 +2540,11 @@ static void Cmd_critmessage(void)
|
||||
if (gIsCriticalHit == TRUE && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT))
|
||||
{
|
||||
PrepareStringBattle(STRINGID_CRITICALHIT, gBattlerAttacker);
|
||||
|
||||
// Signal for the trainer slide-in system.
|
||||
if (GetBattlerSide(gBattlerTarget) != B_SIDE_PLAYER && gBattleStruct->trainerSlideFirstCriticalHitMsgState != 2)
|
||||
gBattleStruct->trainerSlideFirstCriticalHitMsgState = 1;
|
||||
|
||||
gBattleCommunication[MSG_DISPLAY] = 1;
|
||||
}
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
@ -2619,7 +2624,13 @@ static void Cmd_resultmessage(void)
|
||||
{
|
||||
case MOVE_RESULT_SUPER_EFFECTIVE:
|
||||
if (!gMultiHitCounter) // Don't print effectiveness on each hit in a multi hit attack
|
||||
{
|
||||
// Signal for the trainer slide-in system.
|
||||
if (GetBattlerSide(gBattlerTarget) != B_SIDE_PLAYER && gBattleStruct->trainerSlideFirstSuperEffectiveHitMsgState != 2)
|
||||
gBattleStruct->trainerSlideFirstSuperEffectiveHitMsgState = 1;
|
||||
|
||||
stringId = STRINGID_SUPEREFFECTIVE;
|
||||
}
|
||||
break;
|
||||
case MOVE_RESULT_NOT_VERY_EFFECTIVE:
|
||||
if (!gMultiHitCounter)
|
||||
@ -11040,6 +11051,30 @@ static void Cmd_various(void)
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
return;
|
||||
}
|
||||
case VARIOUS_TRY_TRAINER_SLIDE_MSG_Z_MOVE:
|
||||
{
|
||||
VARIOUS_ARGS();
|
||||
if (ShouldDoTrainerSlide(gActiveBattler, gTrainerBattleOpponent_A, TRAINER_SLIDE_Z_MOVE))
|
||||
{
|
||||
gBattleScripting.battler = gActiveBattler;
|
||||
BattleScriptPush(cmd->nextInstr);
|
||||
gBattlescriptCurrInstr = BattleScript_TrainerSlideMsgRet;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VARIOUS_TRY_TRAINER_SLIDE_MSG_MEGA_EVOLUTION:
|
||||
{
|
||||
VARIOUS_ARGS();
|
||||
if (ShouldDoTrainerSlide(gActiveBattler, gTrainerBattleOpponent_A, TRAINER_SLIDE_MEGA_EVOLUTION))
|
||||
{
|
||||
gBattleScripting.battler = gActiveBattler;
|
||||
BattleScriptPush(cmd->nextInstr);
|
||||
gBattlescriptCurrInstr = BattleScript_TrainerSlideMsgRet;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} // End of switch (cmd->id)
|
||||
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
|
@ -1607,6 +1607,12 @@ void PrepareStringBattle(u16 stringId, u8 battler)
|
||||
}
|
||||
#endif
|
||||
|
||||
// Signal for the trainer slide-in system.
|
||||
if ((stringId == STRINGID_ITDOESNTAFFECT || stringId == STRINGID_PKMNWASNTAFFECTED || stringId == STRINGID_PKMNUNAFFECTED)
|
||||
&& GetBattlerSide(gBattlerTarget) == B_SIDE_OPPONENT
|
||||
&& gBattleStruct->trainerSlidePlayerMonUnaffectedMsgState != 2)
|
||||
gBattleStruct->trainerSlidePlayerMonUnaffectedMsgState = 1;
|
||||
|
||||
gActiveBattler = battler;
|
||||
BtlController_EmitPrintString(BUFFER_A, stringId);
|
||||
MarkBattlerForControllerExec(gActiveBattler);
|
||||
@ -9884,6 +9890,10 @@ static u16 CalcTypeEffectivenessMultiplierInternal(u16 move, u8 moveType, u8 bat
|
||||
}
|
||||
}
|
||||
|
||||
// Signal for the trainer slide-in system.
|
||||
if (GetBattlerSide(battlerDef) != B_SIDE_PLAYER && modifier && gBattleStruct->trainerSlideFirstSTABMoveMsgState != 2)
|
||||
gBattleStruct->trainerSlideFirstSTABMoveMsgState = 1;
|
||||
|
||||
return modifier;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user