2017-09-17 14:10:32 +02:00
# include "global.h"
# include "battle.h"
# include "abilities.h"
# include "moves.h"
# include "hold_effects.h"
# include "pokemon.h"
# include "species.h"
# include "item.h"
# include "items.h"
# include "util.h"
# include "battle_move_effects.h"
2017-11-25 18:42:31 +01:00
# include "battle_scripts.h"
2017-09-17 14:10:32 +02:00
# include "rng.h"
# include "text.h"
# include "string_util.h"
# include "battle_message.h"
2017-11-26 11:55:17 +01:00
# include "battle_string_ids.h"
2017-09-28 17:38:07 +02:00
# include "battle_ai_script_commands.h"
2017-09-20 00:28:00 +02:00
# include "battle_controllers.h"
2017-09-17 17:14:32 +02:00
# include "event_data.h"
2017-09-19 21:01:12 +02:00
# include "calculate_base_damage.h"
2017-10-06 17:06:45 +02:00
# include "link.h"
2017-11-27 21:24:34 +01:00
# include "berry.h"
2017-09-17 14:10:32 +02:00
extern const u8 * gBattlescriptCurrInstr ;
2017-11-26 14:17:02 +01:00
extern const u8 * gSelectionBattleScripts [ BATTLE_BANKS_COUNT ] ;
2017-11-26 17:15:28 +01:00
extern const u8 * gPalaceSelectionBattleScripts [ BATTLE_BANKS_COUNT ] ;
2017-09-17 14:10:32 +02:00
extern struct BattlePokemon gBattleMons [ BATTLE_BANKS_COUNT ] ;
extern u8 gActiveBank ;
extern u8 gStringBank ;
extern u16 gCurrentMove ;
extern u16 gLastUsedItem ;
extern u8 gNoOfAllBanks ;
extern u32 gStatuses3 [ BATTLE_BANKS_COUNT ] ;
extern u8 gBankAttacker ;
extern u8 gBankTarget ;
extern u8 gAbsentBankFlags ;
extern u16 gBattleWeather ;
2017-10-04 19:25:14 +02:00
extern u8 gBanksByTurnOrder [ BATTLE_BANKS_COUNT ] ;
2017-10-06 17:06:45 +02:00
extern u16 gSideAffecting [ 2 ] ;
2017-09-17 14:10:32 +02:00
extern u8 gBattleCommunication [ ] ;
extern void ( * gBattleMainFunc ) ( void ) ;
extern s32 gBattleMoveDamage ;
extern struct BattleEnigmaBerry gEnigmaBerries [ BATTLE_BANKS_COUNT ] ;
extern u8 gBattleBufferB [ BATTLE_BANKS_COUNT ] [ 0x200 ] ;
extern u32 gBattleTypeFlags ;
2017-11-26 18:07:00 +01:00
extern u16 gLastMoves [ BATTLE_BANKS_COUNT ] ;
2017-09-17 14:10:32 +02:00
extern u32 gHitMarker ;
extern u8 gEffectBank ;
extern u16 gBattlePartyID [ BATTLE_BANKS_COUNT ] ;
extern u8 gBank1 ;
2017-10-06 17:06:45 +02:00
extern u16 gChosenMovesByBanks [ BATTLE_BANKS_COUNT ] ;
2017-09-17 14:10:32 +02:00
extern u8 gBattleMoveFlags ;
extern s32 gTakenDmg [ BATTLE_BANKS_COUNT ] ;
extern u8 gTakenDmgBanks [ BATTLE_BANKS_COUNT ] ;
2017-09-17 15:19:15 +02:00
extern u8 gLastUsedAbility ;
2017-10-06 00:12:01 +02:00
extern u8 gCurrentActionFuncId ;
2017-09-17 17:14:32 +02:00
extern u32 gBattleExecBuffer ;
extern u16 gRandomMove ;
extern u8 gCurrMovePos ;
extern u8 gUnknown_020241E9 ;
2017-10-06 17:06:45 +02:00
extern u8 gSentPokesToOpponent [ 2 ] ;
2017-09-17 14:10:32 +02:00
extern const struct BattleMove gBattleMoves [ ] ;
2017-09-17 15:19:15 +02:00
extern u8 weather_get_current ( void ) ;
2017-10-06 17:06:45 +02:00
2017-10-06 19:09:37 +02:00
// rom const data
static const u16 sSoundMovesTable [ ] =
{
MOVE_GROWL , MOVE_ROAR , MOVE_SING , MOVE_SUPERSONIC , MOVE_SCREECH , MOVE_SNORE ,
MOVE_UPROAR , MOVE_METAL_SOUND , MOVE_GRASS_WHISTLE , MOVE_HYPER_VOICE , 0xFFFF
} ;
2017-10-06 17:06:45 +02:00
u8 GetBattleBank ( u8 caseId )
{
u8 ret = 0 ;
switch ( caseId )
{
case BS_GET_TARGET :
ret = gBankTarget ;
break ;
case BS_GET_ATTACKER :
ret = gBankAttacker ;
break ;
case BS_GET_EFFECT_BANK :
ret = gEffectBank ;
break ;
2017-11-25 18:42:31 +01:00
case BS_GET_BANK_0 :
2017-10-06 17:06:45 +02:00
ret = 0 ;
break ;
case BS_GET_SCRIPTING_BANK :
ret = gBattleScripting . bank ;
break ;
2017-11-25 18:42:31 +01:00
case BS_GET_gBank1 :
2017-10-06 17:06:45 +02:00
ret = gBank1 ;
break ;
case 5 :
ret = gBank1 ;
break ;
case 4 :
case 6 :
case 8 :
case 9 :
case BS_GET_PLAYER1 :
ret = GetBankByIdentity ( IDENTITY_PLAYER_MON1 ) ;
break ;
case BS_GET_OPPONENT1 :
ret = GetBankByIdentity ( IDENTITY_OPPONENT_MON1 ) ;
break ;
case BS_GET_PLAYER2 :
ret = GetBankByIdentity ( IDENTITY_PLAYER_MON2 ) ;
break ;
case BS_GET_OPPONENT2 :
ret = GetBankByIdentity ( IDENTITY_OPPONENT_MON2 ) ;
break ;
}
return ret ;
}
void PressurePPLose ( u8 bankDef , u8 bankAtk , u16 move )
{
s32 i ;
if ( gBattleMons [ bankDef ] . ability ! = ABILITY_PRESSURE )
return ;
for ( i = 0 ; i < 4 ; i + + )
{
if ( gBattleMons [ bankAtk ] . moves [ i ] = = move )
break ;
}
if ( i = = 4 ) // mons don't share any moves
return ;
if ( gBattleMons [ bankAtk ] . pp [ i ] ! = 0 )
gBattleMons [ bankAtk ] . pp [ i ] - - ;
if ( ! ( gBattleMons [ bankAtk ] . status2 & STATUS2_TRANSFORMED )
& & ! ( gDisableStructs [ bankAtk ] . unk18_b & gBitTable [ i ] ) )
{
gActiveBank = bankAtk ;
EmitSetMonData ( 0 , REQUEST_PPMOVE1_BATTLE + i , 0 , 1 , & gBattleMons [ gActiveBank ] . pp [ i ] ) ;
MarkBufferBankForExecution ( gActiveBank ) ;
}
}
void PressurePPLoseOnUsingImprision ( u8 bankAtk )
{
s32 i , j ;
s32 imprisionPos = 4 ;
u8 atkSide = GetBankSide ( bankAtk ) ;
for ( i = 0 ; i < gNoOfAllBanks ; i + + )
{
if ( atkSide ! = GetBankSide ( i ) & & gBattleMons [ i ] . ability = = ABILITY_PRESSURE )
{
for ( j = 0 ; j < 4 ; j + + )
{
if ( gBattleMons [ bankAtk ] . moves [ j ] = = MOVE_IMPRISON )
break ;
}
if ( j ! = 4 )
{
imprisionPos = j ;
if ( gBattleMons [ bankAtk ] . pp [ j ] ! = 0 )
gBattleMons [ bankAtk ] . pp [ j ] - - ;
}
}
}
if ( imprisionPos ! = 4
& & ! ( gBattleMons [ bankAtk ] . status2 & STATUS2_TRANSFORMED )
& & ! ( gDisableStructs [ bankAtk ] . unk18_b & gBitTable [ imprisionPos ] ) )
{
gActiveBank = bankAtk ;
EmitSetMonData ( 0 , REQUEST_PPMOVE1_BATTLE + imprisionPos , 0 , 1 , & gBattleMons [ gActiveBank ] . pp [ imprisionPos ] ) ;
MarkBufferBankForExecution ( gActiveBank ) ;
}
}
void PressurePPLoseOnUsingPerishSong ( u8 bankAtk )
{
s32 i , j ;
s32 perishSongPos = 4 ;
for ( i = 0 ; i < gNoOfAllBanks ; i + + )
{
if ( gBattleMons [ i ] . ability = = ABILITY_PRESSURE & & i ! = bankAtk )
{
for ( j = 0 ; j < 4 ; j + + )
{
if ( gBattleMons [ bankAtk ] . moves [ j ] = = MOVE_PERISH_SONG )
break ;
}
if ( j ! = 4 )
{
perishSongPos = j ;
if ( gBattleMons [ bankAtk ] . pp [ j ] ! = 0 )
gBattleMons [ bankAtk ] . pp [ j ] - - ;
}
}
}
if ( perishSongPos ! = 4
& & ! ( gBattleMons [ bankAtk ] . status2 & STATUS2_TRANSFORMED )
& & ! ( gDisableStructs [ bankAtk ] . unk18_b & gBitTable [ perishSongPos ] ) )
{
gActiveBank = bankAtk ;
EmitSetMonData ( 0 , REQUEST_PPMOVE1_BATTLE + perishSongPos , 0 , 1 , & gBattleMons [ gActiveBank ] . pp [ perishSongPos ] ) ;
MarkBufferBankForExecution ( gActiveBank ) ;
}
}
void MarkAllBufferBanksForExecution ( void ) // unused
{
s32 i ;
if ( gBattleTypeFlags & BATTLE_TYPE_LINK )
{
for ( i = 0 ; i < gNoOfAllBanks ; i + + )
gBattleExecBuffer | = gBitTable [ i ] < < 0x1C ;
}
else
{
for ( i = 0 ; i < gNoOfAllBanks ; i + + )
gBattleExecBuffer | = gBitTable [ i ] ;
}
}
void MarkBufferBankForExecution ( u8 bank )
{
if ( gBattleTypeFlags & BATTLE_TYPE_LINK )
{
gBattleExecBuffer | = gBitTable [ bank ] < < 0x1C ;
}
else
{
gBattleExecBuffer | = gBitTable [ bank ] ;
}
}
void sub_803F850 ( u8 arg0 )
{
s32 i ;
2017-10-13 17:09:36 +02:00
for ( i = 0 ; i < GetLinkPlayerCount ( ) ; i + + )
2017-10-06 17:06:45 +02:00
gBattleExecBuffer | = gBitTable [ arg0 ] < < ( i < < 2 ) ;
gBattleExecBuffer & = ~ ( 0x10000000 < < arg0 ) ;
}
void CancelMultiTurnMoves ( u8 bank )
{
gBattleMons [ bank ] . status2 & = ~ ( STATUS2_MULTIPLETURNS ) ;
gBattleMons [ bank ] . status2 & = ~ ( STATUS2_LOCK_CONFUSE ) ;
gBattleMons [ bank ] . status2 & = ~ ( STATUS2_UPROAR ) ;
gBattleMons [ bank ] . status2 & = ~ ( STATUS2_BIDE ) ;
gStatuses3 [ bank ] & = ~ ( STATUS3_SEMI_INVULNERABLE ) ;
gDisableStructs [ bank ] . rolloutCounter1 = 0 ;
gDisableStructs [ bank ] . furyCutterCounter = 0 ;
}
bool8 WasUnableToUseMove ( u8 bank )
{
if ( gProtectStructs [ bank ] . prlzImmobility
| | gProtectStructs [ bank ] . targetNotAffected
| | gProtectStructs [ bank ] . usedImprisionedMove
| | gProtectStructs [ bank ] . loveImmobility
| | gProtectStructs [ bank ] . usedDisabledMove
| | gProtectStructs [ bank ] . usedTauntedMove
| | gProtectStructs [ bank ] . flag2Unknown
| | gProtectStructs [ bank ] . flinchImmobility
| | gProtectStructs [ bank ] . confusionSelfDmg )
return TRUE ;
else
return FALSE ;
}
void PrepareStringBattle ( u16 stringId , u8 bank )
{
gActiveBank = bank ;
EmitPrintString ( 0 , stringId ) ;
MarkBufferBankForExecution ( gActiveBank ) ;
}
void ResetSentPokesToOpponentValue ( void )
{
s32 i ;
u32 bits = 0 ;
gSentPokesToOpponent [ 0 ] = 0 ;
gSentPokesToOpponent [ 1 ] = 0 ;
for ( i = 0 ; i < gNoOfAllBanks ; i + = 2 )
bits | = gBitTable [ gBattlePartyID [ i ] ] ;
for ( i = 1 ; i < gNoOfAllBanks ; i + = 2 )
gSentPokesToOpponent [ ( i & BIT_MON ) > > 1 ] = bits ;
}
void sub_803F9EC ( u8 bank )
{
s32 i = 0 ;
u32 bits = 0 ;
if ( GetBankSide ( bank ) = = SIDE_OPPONENT )
{
u8 id = ( ( bank & BIT_MON ) > > 1 ) ;
gSentPokesToOpponent [ id ] = 0 ;
for ( i = 0 ; i < gNoOfAllBanks ; i + = 2 )
{
if ( ! ( gAbsentBankFlags & gBitTable [ i ] ) )
bits | = gBitTable [ gBattlePartyID [ i ] ] ;
}
gSentPokesToOpponent [ id ] = bits ;
}
}
void sub_803FA70 ( u8 bank )
{
if ( GetBankSide ( bank ) = = SIDE_OPPONENT )
{
sub_803F9EC ( bank ) ;
}
else
{
s32 i ;
for ( i = 1 ; i < gNoOfAllBanks ; i + + )
gSentPokesToOpponent [ ( i & BIT_MON ) > > 1 ] | = gBitTable [ gBattlePartyID [ bank ] ] ;
}
}
2017-09-17 14:10:32 +02:00
2017-09-22 21:33:49 +02:00
void BattleScriptPush ( const u8 * bsPtr )
2017-09-17 14:10:32 +02:00
{
BATTLESCRIPTS_STACK - > ptr [ BATTLESCRIPTS_STACK - > size + + ] = bsPtr ;
}
2017-09-22 21:33:49 +02:00
void BattleScriptPushCursor ( void )
2017-09-17 14:10:32 +02:00
{
BATTLESCRIPTS_STACK - > ptr [ BATTLESCRIPTS_STACK - > size + + ] = gBattlescriptCurrInstr ;
}
2017-09-22 21:33:49 +02:00
void BattleScriptPop ( void )
2017-09-17 14:10:32 +02:00
{
gBattlescriptCurrInstr = BATTLESCRIPTS_STACK - > ptr [ - - BATTLESCRIPTS_STACK - > size ] ;
}
2017-10-03 21:35:27 +02:00
u8 TrySetCantSelectMoveBattleScript ( void )
2017-09-17 14:10:32 +02:00
{
u8 limitations = 0 ;
u16 move = gBattleMons [ gActiveBank ] . moves [ gBattleBufferB [ gActiveBank ] [ 2 ] ] ;
u8 holdEffect ;
u16 * choicedMove = & gBattleStruct - > choicedMove [ gActiveBank ] ;
if ( gDisableStructs [ gActiveBank ] . disabledMove = = move & & move ! = 0 )
{
gBattleScripting . bank = gActiveBank ;
gCurrentMove = move ;
if ( gBattleTypeFlags & BATTLE_TYPE_PALACE )
{
2017-11-26 17:15:28 +01:00
gPalaceSelectionBattleScripts [ gActiveBank ] = BattleScript_82DAE2A ;
2017-09-17 14:10:32 +02:00
gProtectStructs [ gActiveBank ] . flag_x10 = 1 ;
}
else
{
2017-11-26 17:15:28 +01:00
gSelectionBattleScripts [ gActiveBank ] = BattleScript_SelectingDisabledMove ;
2017-09-17 14:10:32 +02:00
limitations = 1 ;
}
}
2017-11-26 18:07:00 +01:00
if ( move = = gLastMoves [ gActiveBank ] & & move ! = MOVE_STRUGGLE & & ( gBattleMons [ gActiveBank ] . status2 & STATUS2_TORMENT ) )
2017-09-17 14:10:32 +02:00
{
CancelMultiTurnMoves ( gActiveBank ) ;
if ( gBattleTypeFlags & BATTLE_TYPE_PALACE )
{
2017-11-26 17:15:28 +01:00
gPalaceSelectionBattleScripts [ gActiveBank ] = BattleScript_82DB098 ;
2017-09-17 14:10:32 +02:00
gProtectStructs [ gActiveBank ] . flag_x10 = 1 ;
}
else
{
2017-11-26 17:15:28 +01:00
gSelectionBattleScripts [ gActiveBank ] = BattleScript_SelectingTormentedMove ;
2017-09-17 14:10:32 +02:00
limitations + + ;
}
}
if ( gDisableStructs [ gActiveBank ] . tauntTimer1 ! = 0 & & gBattleMoves [ move ] . power = = 0 )
{
gCurrentMove = move ;
if ( gBattleTypeFlags & BATTLE_TYPE_PALACE )
{
2017-11-26 17:15:28 +01:00
gPalaceSelectionBattleScripts [ gActiveBank ] = BattleScript_82DB0AF ;
2017-09-17 14:10:32 +02:00
gProtectStructs [ gActiveBank ] . flag_x10 = 1 ;
}
else
{
2017-11-26 17:15:28 +01:00
gSelectionBattleScripts [ gActiveBank ] = BattleScript_SelectingNotAllowedMoveTaunt ;
2017-09-17 14:10:32 +02:00
limitations + + ;
}
}
2017-09-27 23:43:45 +02:00
if ( GetImprisonedMovesCount ( gActiveBank , move ) )
2017-09-17 14:10:32 +02:00
{
gCurrentMove = move ;
if ( gBattleTypeFlags & BATTLE_TYPE_PALACE )
{
2017-11-26 17:15:28 +01:00
gPalaceSelectionBattleScripts [ gActiveBank ] = BattleScript_82DB185 ;
2017-09-17 14:10:32 +02:00
gProtectStructs [ gActiveBank ] . flag_x10 = 1 ;
}
else
{
2017-11-26 17:15:28 +01:00
gSelectionBattleScripts [ gActiveBank ] = BattleScript_SelectingImprisionedMove ;
2017-09-17 14:10:32 +02:00
limitations + + ;
}
}
if ( gBattleMons [ gActiveBank ] . item = = ITEM_ENIGMA_BERRY )
holdEffect = gEnigmaBerries [ gActiveBank ] . holdEffect ;
else
holdEffect = ItemId_GetHoldEffect ( gBattleMons [ gActiveBank ] . item ) ;
gStringBank = gActiveBank ;
if ( holdEffect = = HOLD_EFFECT_CHOICE_BAND & & * choicedMove ! = 0 & & * choicedMove ! = 0xFFFF & & * choicedMove ! = move )
{
gCurrentMove = * choicedMove ;
gLastUsedItem = gBattleMons [ gActiveBank ] . item ;
if ( gBattleTypeFlags & BATTLE_TYPE_PALACE )
{
gProtectStructs [ gActiveBank ] . flag_x10 = 1 ;
}
else
{
2017-11-26 17:15:28 +01:00
gSelectionBattleScripts [ gActiveBank ] = BattleScript_SelectingNotAllowedMoveChoiceItem ;
2017-09-17 14:10:32 +02:00
limitations + + ;
}
}
if ( gBattleMons [ gActiveBank ] . pp [ gBattleBufferB [ gActiveBank ] [ 2 ] ] = = 0 )
{
if ( gBattleTypeFlags & BATTLE_TYPE_PALACE )
{
gProtectStructs [ gActiveBank ] . flag_x10 = 1 ;
}
else
{
2017-11-26 17:15:28 +01:00
gSelectionBattleScripts [ gActiveBank ] = BattleScript_SelectingMoveWithNoPP ;
2017-09-17 14:10:32 +02:00
limitations + + ;
}
}
return limitations ;
}
u8 CheckMoveLimitations ( u8 bank , u8 unusableMoves , u8 check )
{
u8 holdEffect ;
2017-11-26 13:26:58 +01:00
u16 * choicedMove = & gBattleStruct - > choicedMove [ bank ] ;
2017-09-17 14:10:32 +02:00
s32 i ;
if ( gBattleMons [ bank ] . item = = ITEM_ENIGMA_BERRY )
holdEffect = gEnigmaBerries [ bank ] . holdEffect ;
else
holdEffect = ItemId_GetHoldEffect ( gBattleMons [ bank ] . item ) ;
gStringBank = bank ;
for ( i = 0 ; i < BATTLE_BANKS_COUNT ; i + + )
{
if ( gBattleMons [ bank ] . moves [ i ] = = 0 & & check & MOVE_LIMITATION_ZEROMOVE )
unusableMoves | = gBitTable [ i ] ;
if ( gBattleMons [ bank ] . pp [ i ] = = 0 & & check & MOVE_LIMITATION_PP )
unusableMoves | = gBitTable [ i ] ;
if ( gBattleMons [ bank ] . moves [ i ] = = gDisableStructs [ bank ] . disabledMove & & check & MOVE_LIMITATION_DISABLED )
unusableMoves | = gBitTable [ i ] ;
2017-11-26 18:07:00 +01:00
if ( gBattleMons [ bank ] . moves [ i ] = = gLastMoves [ bank ] & & check & MOVE_LIMITATION_TORMENTED & & gBattleMons [ bank ] . status2 & STATUS2_TORMENT )
2017-09-17 14:10:32 +02:00
unusableMoves | = gBitTable [ i ] ;
if ( gDisableStructs [ bank ] . tauntTimer1 & & check & MOVE_LIMITATION_TAUNT & & gBattleMoves [ gBattleMons [ bank ] . moves [ i ] ] . power = = 0 )
unusableMoves | = gBitTable [ i ] ;
2017-09-27 23:43:45 +02:00
if ( GetImprisonedMovesCount ( bank , gBattleMons [ bank ] . moves [ i ] ) & & check & MOVE_LIMITATION_IMPRISION )
2017-09-17 14:10:32 +02:00
unusableMoves | = gBitTable [ i ] ;
if ( gDisableStructs [ bank ] . encoreTimer1 & & gDisableStructs [ bank ] . encoredMove ! = gBattleMons [ bank ] . moves [ i ] )
unusableMoves | = gBitTable [ i ] ;
if ( holdEffect = = HOLD_EFFECT_CHOICE_BAND & & * choicedMove ! = 0 & & * choicedMove ! = 0xFFFF & & * choicedMove ! = gBattleMons [ bank ] . moves [ i ] )
unusableMoves | = gBitTable [ i ] ;
}
return unusableMoves ;
}
bool8 AreAllMovesUnusable ( void )
{
u8 unusable ;
unusable = CheckMoveLimitations ( gActiveBank , 0 , 0xFF ) ;
if ( unusable = = 0xF ) // all moves are unusable
{
gProtectStructs [ gActiveBank ] . onlyStruggle = 1 ;
2017-11-26 17:15:28 +01:00
gSelectionBattleScripts [ gActiveBank ] = BattleScript_NoMovesLeft ;
2017-09-17 14:10:32 +02:00
}
else
{
gProtectStructs [ gActiveBank ] . onlyStruggle = 0 ;
}
return ( unusable = = 0xF ) ;
}
2017-09-27 23:43:45 +02:00
u8 GetImprisonedMovesCount ( u8 bank , u16 move )
2017-09-17 14:10:32 +02:00
{
s32 i ;
u8 imprisionedMoves = 0 ;
u8 bankSide = GetBankSide ( bank ) ;
for ( i = 0 ; i < gNoOfAllBanks ; i + + )
{
2017-09-27 23:43:45 +02:00
if ( bankSide ! = GetBankSide ( i ) & & gStatuses3 [ i ] & STATUS3_IMPRISONED_OTHERS )
2017-09-17 14:10:32 +02:00
{
s32 j ;
for ( j = 0 ; j < 4 ; j + + )
{
if ( move = = gBattleMons [ i ] . moves [ j ] )
break ;
}
if ( j < 4 )
imprisionedMoves + + ;
}
}
return imprisionedMoves ;
}
u8 UpdateTurnCounters ( void )
{
u8 effect = 0 ;
s32 i ;
for ( gBankAttacker = 0 ; gBankAttacker < gNoOfAllBanks & & gAbsentBankFlags & gBitTable [ gBankAttacker ] ; gBankAttacker + + )
{
}
for ( gBankTarget = 0 ; gBankTarget < gNoOfAllBanks & & gAbsentBankFlags & gBitTable [ gBankTarget ] ; gBankTarget + + )
{
}
do
{
u8 sideBank ;
switch ( gBattleStruct - > turncountersTracker )
{
case 0 :
for ( i = 0 ; i < gNoOfAllBanks ; i + + )
{
2017-10-04 19:25:14 +02:00
gBanksByTurnOrder [ i ] = i ;
2017-09-17 14:10:32 +02:00
}
for ( i = 0 ; i < gNoOfAllBanks - 1 ; i + + )
{
s32 j ;
for ( j = i + 1 ; j < gNoOfAllBanks ; j + + )
{
2017-10-04 19:25:14 +02:00
if ( GetWhoStrikesFirst ( gBanksByTurnOrder [ i ] , gBanksByTurnOrder [ j ] , 0 ) )
SwapTurnOrder ( i , j ) ;
2017-09-17 14:10:32 +02:00
}
}
// It's stupid, but won't match without it
{
u8 * var = & gBattleStruct - > turncountersTracker ;
( * var ) + + ;
gBattleStruct - > turnSideTracker = 0 ;
}
// fall through
case 1 :
while ( gBattleStruct - > turnSideTracker < 2 )
{
sideBank = gBattleStruct - > turnSideTracker ;
gActiveBank = gBankAttacker = gSideTimers [ sideBank ] . reflectBank ;
if ( gSideAffecting [ sideBank ] & SIDE_STATUS_REFLECT )
{
if ( - - gSideTimers [ sideBank ] . reflectTimer = = 0 )
{
gSideAffecting [ sideBank ] & = ~ SIDE_STATUS_REFLECT ;
2017-11-26 17:15:28 +01:00
BattleScriptExecute ( BattleScript_SideStatusWoreOff ) ;
2017-11-26 13:26:58 +01:00
PREPARE_MOVE_BUFFER ( gBattleTextBuff1 , MOVE_REFLECT ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
}
gBattleStruct - > turnSideTracker + + ;
if ( effect )
break ;
}
if ( ! effect )
{
gBattleStruct - > turncountersTracker + + ;
gBattleStruct - > turnSideTracker = 0 ;
}
break ;
case 2 :
while ( gBattleStruct - > turnSideTracker < 2 )
{
sideBank = gBattleStruct - > turnSideTracker ;
gActiveBank = gBankAttacker = gSideTimers [ sideBank ] . lightscreenBank ;
if ( gSideAffecting [ sideBank ] & SIDE_STATUS_LIGHTSCREEN )
{
if ( - - gSideTimers [ sideBank ] . lightscreenTimer = = 0 )
{
gSideAffecting [ sideBank ] & = ~ SIDE_STATUS_LIGHTSCREEN ;
2017-11-26 17:15:28 +01:00
BattleScriptExecute ( BattleScript_SideStatusWoreOff ) ;
2017-09-17 14:10:32 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = sideBank ;
2017-11-26 13:26:58 +01:00
PREPARE_MOVE_BUFFER ( gBattleTextBuff1 , MOVE_LIGHT_SCREEN ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
}
gBattleStruct - > turnSideTracker + + ;
if ( effect )
break ;
}
if ( ! effect )
{
gBattleStruct - > turncountersTracker + + ;
gBattleStruct - > turnSideTracker = 0 ;
}
break ;
case 3 :
while ( gBattleStruct - > turnSideTracker < 2 )
{
sideBank = gBattleStruct - > turnSideTracker ;
gActiveBank = gBankAttacker = gSideTimers [ sideBank ] . mistBank ;
if ( gSideTimers [ sideBank ] . mistTimer ! = 0
& & - - gSideTimers [ sideBank ] . mistTimer = = 0 )
{
gSideAffecting [ sideBank ] & = ~ SIDE_STATUS_MIST ;
2017-11-26 17:15:28 +01:00
BattleScriptExecute ( BattleScript_SideStatusWoreOff ) ;
2017-09-17 14:10:32 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = sideBank ;
2017-11-26 13:26:58 +01:00
PREPARE_MOVE_BUFFER ( gBattleTextBuff1 , MOVE_MIST ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
gBattleStruct - > turnSideTracker + + ;
if ( effect )
break ;
}
if ( ! effect )
{
gBattleStruct - > turncountersTracker + + ;
gBattleStruct - > turnSideTracker = 0 ;
}
break ;
case 4 :
while ( gBattleStruct - > turnSideTracker < 2 )
{
sideBank = gBattleStruct - > turnSideTracker ;
gActiveBank = gBankAttacker = gSideTimers [ sideBank ] . safeguardBank ;
if ( gSideAffecting [ sideBank ] & SIDE_STATUS_SAFEGUARD )
{
if ( - - gSideTimers [ sideBank ] . safeguardTimer = = 0 )
{
gSideAffecting [ sideBank ] & = ~ SIDE_STATUS_SAFEGUARD ;
2017-11-26 17:15:28 +01:00
BattleScriptExecute ( BattleScript_SafeguardEnds ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
}
gBattleStruct - > turnSideTracker + + ;
if ( effect )
break ;
}
if ( ! effect )
{
gBattleStruct - > turncountersTracker + + ;
gBattleStruct - > turnSideTracker = 0 ;
}
break ;
case 5 :
while ( gBattleStruct - > turnSideTracker < gNoOfAllBanks )
{
2017-10-04 19:25:14 +02:00
gActiveBank = gBanksByTurnOrder [ gBattleStruct - > turnSideTracker ] ;
2017-09-17 14:10:32 +02:00
if ( gWishFutureKnock . wishCounter [ gActiveBank ] ! = 0
& & - - gWishFutureKnock . wishCounter [ gActiveBank ] = = 0
& & gBattleMons [ gActiveBank ] . hp ! = 0 )
{
gBankTarget = gActiveBank ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_WishComesTrue ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
gBattleStruct - > turnSideTracker + + ;
if ( effect )
break ;
}
if ( ! effect )
{
gBattleStruct - > turncountersTracker + + ;
}
break ;
case 6 :
if ( gBattleWeather & WEATHER_RAIN_ANY )
{
if ( ! ( gBattleWeather & WEATHER_RAIN_PERMANENT ) )
{
if ( - - gWishFutureKnock . weatherDuration = = 0 )
{
gBattleWeather & = ~ WEATHER_RAIN_TEMPORARY ;
gBattleWeather & = ~ WEATHER_RAIN_DOWNPOUR ;
gBattleCommunication [ MULTISTRING_CHOOSER ] = 2 ;
}
else if ( gBattleWeather & WEATHER_RAIN_DOWNPOUR )
gBattleCommunication [ MULTISTRING_CHOOSER ] = 1 ;
else
gBattleCommunication [ MULTISTRING_CHOOSER ] = 0 ;
}
else if ( gBattleWeather & WEATHER_RAIN_DOWNPOUR )
2017-11-26 17:15:28 +01:00
{
2017-09-17 14:10:32 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = 1 ;
2017-11-26 17:15:28 +01:00
}
2017-09-17 14:10:32 +02:00
else
2017-11-26 17:15:28 +01:00
{
2017-09-17 14:10:32 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = 0 ;
2017-11-26 17:15:28 +01:00
}
BattleScriptExecute ( BattleScript_RainContinuesOrEnds ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
gBattleStruct - > turncountersTracker + + ;
break ;
case 7 :
if ( gBattleWeather & WEATHER_SANDSTORM_ANY )
{
if ( ! ( gBattleWeather & WEATHER_SANDSTORM_PERMANENT ) & & - - gWishFutureKnock . weatherDuration = = 0 )
{
gBattleWeather & = ~ WEATHER_SANDSTORM_TEMPORARY ;
2017-11-26 17:15:28 +01:00
gBattlescriptCurrInstr = BattleScript_SandStormHailEnds ;
2017-09-17 14:10:32 +02:00
}
else
2017-11-26 17:15:28 +01:00
{
gBattlescriptCurrInstr = BattleScript_DamagingWeatherContinues ;
}
2017-09-17 14:10:32 +02:00
2017-11-26 17:15:28 +01:00
gBattleScripting . animArg1 = B_ANIM_SANDSTORM_CONTINUES ;
2017-09-17 14:10:32 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = 0 ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( gBattlescriptCurrInstr ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
gBattleStruct - > turncountersTracker + + ;
break ;
case 8 :
if ( gBattleWeather & WEATHER_SUN_ANY )
{
if ( ! ( gBattleWeather & WEATHER_SUN_PERMANENT ) & & - - gWishFutureKnock . weatherDuration = = 0 )
{
gBattleWeather & = ~ WEATHER_SUN_TEMPORARY ;
2017-11-26 17:15:28 +01:00
gBattlescriptCurrInstr = BattleScript_SunlightFaded ;
2017-09-17 14:10:32 +02:00
}
else
2017-11-26 17:15:28 +01:00
{
gBattlescriptCurrInstr = BattleScript_SunlightContinues ;
}
2017-09-17 14:10:32 +02:00
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( gBattlescriptCurrInstr ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
gBattleStruct - > turncountersTracker + + ;
break ;
case 9 :
if ( gBattleWeather & WEATHER_HAIL )
{
if ( - - gWishFutureKnock . weatherDuration = = 0 )
{
gBattleWeather & = ~ WEATHER_HAIL ;
2017-11-26 17:15:28 +01:00
gBattlescriptCurrInstr = BattleScript_SandStormHailEnds ;
2017-09-17 14:10:32 +02:00
}
else
2017-11-26 13:26:58 +01:00
{
2017-11-26 17:15:28 +01:00
gBattlescriptCurrInstr = BattleScript_DamagingWeatherContinues ;
2017-11-26 13:26:58 +01:00
}
2017-09-17 14:10:32 +02:00
2017-11-26 13:26:58 +01:00
gBattleScripting . animArg1 = B_ANIM_HAIL_CONTINUES ;
2017-09-17 14:10:32 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = 1 ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( gBattlescriptCurrInstr ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
gBattleStruct - > turncountersTracker + + ;
break ;
case 10 :
effect + + ;
break ;
}
} while ( effect = = 0 ) ;
return ( gBattleMainFunc ! = BattleTurnPassed ) ;
}
# define TURNBASED_MAX_CASE 19
u8 TurnBasedEffects ( void )
{
u8 effect = 0 ;
gHitMarker | = ( HITMARKER_GRUDGE | HITMARKER_x20 ) ;
while ( gBattleStruct - > turnEffectsBank < gNoOfAllBanks & & gBattleStruct - > turnEffectsTracker < = TURNBASED_MAX_CASE )
{
2017-10-04 19:25:14 +02:00
gActiveBank = gBankAttacker = gBanksByTurnOrder [ gBattleStruct - > turnEffectsBank ] ;
2017-09-17 14:10:32 +02:00
if ( gAbsentBankFlags & gBitTable [ gActiveBank ] )
{
gBattleStruct - > turnEffectsBank + + ;
}
else
{
switch ( gBattleStruct - > turnEffectsTracker )
{
case 0 : // ingrain
if ( ( gStatuses3 [ gActiveBank ] & STATUS3_ROOTED )
& & gBattleMons [ gActiveBank ] . hp ! = gBattleMons [ gActiveBank ] . maxHP
& & gBattleMons [ gActiveBank ] . hp ! = 0 )
{
gBattleMoveDamage = gBattleMons [ gActiveBank ] . maxHP / 16 ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
gBattleMoveDamage * = - 1 ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_IngrainTurnHeal ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
case 1 : // end turn abilities
if ( AbilityBattleEffects ( ABILITYEFFECT_ENDTURN , gActiveBank , 0 , 0 , 0 ) )
effect + + ;
gBattleStruct - > turnEffectsTracker + + ;
break ;
case 2 : // item effects
if ( ItemBattleEffects ( 1 , gActiveBank , 0 ) )
effect + + ;
gBattleStruct - > turnEffectsTracker + + ;
break ;
case 18 : // item effects again
if ( ItemBattleEffects ( 1 , gActiveBank , 1 ) )
effect + + ;
gBattleStruct - > turnEffectsTracker + + ;
break ;
case 3 : // leech seed
if ( ( gStatuses3 [ gActiveBank ] & STATUS3_LEECHSEED )
& & gBattleMons [ gStatuses3 [ gActiveBank ] & STATUS3_LEECHSEED_BANK ] . hp ! = 0
& & gBattleMons [ gActiveBank ] . hp ! = 0 )
{
gBankTarget = gStatuses3 [ gActiveBank ] & STATUS3_LEECHSEED_BANK ; //funny how the 'target' is actually the bank that receives HP
gBattleMoveDamage = gBattleMons [ gActiveBank ] . maxHP / 8 ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
gBattleScripting . animArg1 = gBankTarget ;
gBattleScripting . animArg2 = gBankAttacker ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_LeechSeedTurnDrain ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
case 4 : // poison
if ( ( gBattleMons [ gActiveBank ] . status1 & STATUS_POISON ) & & gBattleMons [ gActiveBank ] . hp ! = 0 )
{
gBattleMoveDamage = gBattleMons [ gActiveBank ] . maxHP / 8 ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_PoisonTurnDmg ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
case 5 : // toxic poison
if ( ( gBattleMons [ gActiveBank ] . status1 & STATUS_TOXIC_POISON ) & & gBattleMons [ gActiveBank ] . hp ! = 0 )
{
gBattleMoveDamage = gBattleMons [ gActiveBank ] . maxHP / 16 ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
2017-11-26 13:26:58 +01:00
if ( ( gBattleMons [ gActiveBank ] . status1 & 0xF00 ) ! = 0xF00 ) // not 16 turns
2017-09-17 14:10:32 +02:00
gBattleMons [ gActiveBank ] . status1 + = 0x100 ;
gBattleMoveDamage * = ( gBattleMons [ gActiveBank ] . status1 & 0xF00 ) > > 8 ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_PoisonTurnDmg ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
case 6 : // burn
if ( ( gBattleMons [ gActiveBank ] . status1 & STATUS_BURN ) & & gBattleMons [ gActiveBank ] . hp ! = 0 )
{
gBattleMoveDamage = gBattleMons [ gActiveBank ] . maxHP / 8 ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BurnTurnDmg ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
case 7 : // spooky nightmares
if ( ( gBattleMons [ gActiveBank ] . status2 & STATUS2_NIGHTMARE ) & & gBattleMons [ gActiveBank ] . hp ! = 0 )
{
// R/S does not perform this sleep check, which causes the nighmare effect to
// persist even after the affected Pokemon has been awakened by Shed Skin
if ( gBattleMons [ gActiveBank ] . status1 & STATUS_SLEEP )
{
gBattleMoveDamage = gBattleMons [ gActiveBank ] . maxHP / 4 ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_NightmareTurnDmg ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
else
{
gBattleMons [ gActiveBank ] . status2 & = ~ STATUS2_NIGHTMARE ;
}
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
case 8 : // curse
if ( ( gBattleMons [ gActiveBank ] . status2 & STATUS2_CURSED ) & & gBattleMons [ gActiveBank ] . hp ! = 0 )
{
gBattleMoveDamage = gBattleMons [ gActiveBank ] . maxHP / 4 ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_CurseTurnDmg ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
case 9 : // wrap
if ( ( gBattleMons [ gActiveBank ] . status2 & STATUS2_WRAPPED ) & & gBattleMons [ gActiveBank ] . hp ! = 0 )
{
gBattleMons [ gActiveBank ] . status2 - = 0x2000 ;
if ( gBattleMons [ gActiveBank ] . status2 & STATUS2_WRAPPED ) // damaged by wrap
{
// This is the only way I could get this array access to match.
gBattleScripting . animArg1 = * ( gBattleStruct - > wrappedMove + gActiveBank * 2 + 0 ) ;
gBattleScripting . animArg2 = * ( gBattleStruct - > wrappedMove + gActiveBank * 2 + 1 ) ;
2017-11-26 13:26:58 +01:00
gBattleTextBuff1 [ 0 ] = B_BUFF_PLACEHOLDER_BEGIN ;
gBattleTextBuff1 [ 1 ] = B_BUFF_MOVE ;
2017-09-17 14:10:32 +02:00
gBattleTextBuff1 [ 2 ] = * ( gBattleStruct - > wrappedMove + gActiveBank * 2 + 0 ) ;
gBattleTextBuff1 [ 3 ] = * ( gBattleStruct - > wrappedMove + gActiveBank * 2 + 1 ) ;
gBattleTextBuff1 [ 4 ] = EOS ;
gBattlescriptCurrInstr = BattleScript_WrapTurnDmg ;
gBattleMoveDamage = gBattleMons [ gActiveBank ] . maxHP / 16 ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
}
else // broke free
{
2017-11-26 13:26:58 +01:00
gBattleTextBuff1 [ 0 ] = B_BUFF_PLACEHOLDER_BEGIN ;
gBattleTextBuff1 [ 1 ] = B_BUFF_MOVE ;
2017-09-17 14:10:32 +02:00
gBattleTextBuff1 [ 2 ] = * ( gBattleStruct - > wrappedMove + gActiveBank * 2 + 0 ) ;
gBattleTextBuff1 [ 3 ] = * ( gBattleStruct - > wrappedMove + gActiveBank * 2 + 1 ) ;
gBattleTextBuff1 [ 4 ] = EOS ;
gBattlescriptCurrInstr = BattleScript_WrapEnds ;
}
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( gBattlescriptCurrInstr ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
case 10 : // uproar
if ( gBattleMons [ gActiveBank ] . status2 & STATUS2_UPROAR )
{
for ( gBankAttacker = 0 ; gBankAttacker < gNoOfAllBanks ; gBankAttacker + + )
{
if ( ( gBattleMons [ gBankAttacker ] . status1 & STATUS_SLEEP )
& & gBattleMons [ gBankAttacker ] . ability ! = ABILITY_SOUNDPROOF )
{
gBattleMons [ gBankAttacker ] . status1 & = ~ ( STATUS_SLEEP ) ;
gBattleMons [ gBankAttacker ] . status2 & = ~ ( STATUS2_NIGHTMARE ) ;
gBattleCommunication [ MULTISTRING_CHOOSER ] = 1 ;
2017-11-26 17:26:11 +01:00
BattleScriptExecute ( BattleScript_MonWokeUpInUproar ) ;
2017-09-17 14:10:32 +02:00
gActiveBank = gBankAttacker ;
2017-09-26 22:39:59 +02:00
EmitSetMonData ( 0 , REQUEST_STATUS_BATTLE , 0 , 4 , & gBattleMons [ gActiveBank ] . status1 ) ;
2017-09-17 14:10:32 +02:00
MarkBufferBankForExecution ( gActiveBank ) ;
break ;
}
}
if ( gBankAttacker ! = gNoOfAllBanks )
{
effect = 2 ; // a pokemon was awaken
break ;
}
else
{
gBankAttacker = gActiveBank ;
gBattleMons [ gActiveBank ] . status2 - = 0x10 ; // uproar timer goes down
2017-10-06 17:06:45 +02:00
if ( WasUnableToUseMove ( gActiveBank ) )
2017-09-17 14:10:32 +02:00
{
CancelMultiTurnMoves ( gActiveBank ) ;
gBattleCommunication [ MULTISTRING_CHOOSER ] = 1 ;
}
else if ( gBattleMons [ gActiveBank ] . status2 & STATUS2_UPROAR )
{
gBattleCommunication [ MULTISTRING_CHOOSER ] = 0 ;
gBattleMons [ gActiveBank ] . status2 | = STATUS2_MULTIPLETURNS ;
}
else
{
gBattleCommunication [ MULTISTRING_CHOOSER ] = 1 ;
CancelMultiTurnMoves ( gActiveBank ) ;
}
2017-11-26 17:26:11 +01:00
BattleScriptExecute ( BattleScript_PrintUproarOverTurns ) ;
2017-09-17 14:10:32 +02:00
effect = 1 ;
}
}
if ( effect ! = 2 )
gBattleStruct - > turnEffectsTracker + + ;
break ;
case 11 : // thrash
if ( gBattleMons [ gActiveBank ] . status2 & STATUS2_LOCK_CONFUSE )
{
gBattleMons [ gActiveBank ] . status2 - = 0x400 ;
2017-10-06 17:06:45 +02:00
if ( WasUnableToUseMove ( gActiveBank ) )
2017-09-17 14:10:32 +02:00
CancelMultiTurnMoves ( gActiveBank ) ;
else if ( ! ( gBattleMons [ gActiveBank ] . status2 & STATUS2_LOCK_CONFUSE )
& & ( gBattleMons [ gActiveBank ] . status2 & STATUS2_MULTIPLETURNS ) )
{
gBattleMons [ gActiveBank ] . status2 & = ~ ( STATUS2_MULTIPLETURNS ) ;
if ( ! ( gBattleMons [ gActiveBank ] . status2 & STATUS2_CONFUSION ) )
{
2017-11-26 13:26:58 +01:00
gBattleCommunication [ MOVE_EFFECT_BYTE ] = MOVE_EFFECT_CONFUSION | MOVE_EFFECT_AFFECTS_USER ;
2017-09-17 14:10:32 +02:00
SetMoveEffect ( 1 , 0 ) ;
if ( gBattleMons [ gActiveBank ] . status2 & STATUS2_CONFUSION )
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_ThrashConfuses ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
}
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
case 12 : // disable
if ( gDisableStructs [ gActiveBank ] . disableTimer1 ! = 0 )
{
int i ;
for ( i = 0 ; i < 4 ; i + + )
{
if ( gDisableStructs [ gActiveBank ] . disabledMove = = gBattleMons [ gActiveBank ] . moves [ i ] )
break ;
}
if ( i = = 4 ) // pokemon does not have the disabled move anymore
{
gDisableStructs [ gActiveBank ] . disabledMove = 0 ;
gDisableStructs [ gActiveBank ] . disableTimer1 = 0 ;
}
else if ( - - gDisableStructs [ gActiveBank ] . disableTimer1 = = 0 ) // disable ends
{
gDisableStructs [ gActiveBank ] . disabledMove = 0 ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_DisabledNoMore ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
case 13 : // encore
if ( gDisableStructs [ gActiveBank ] . encoreTimer1 ! = 0 )
{
if ( gBattleMons [ gActiveBank ] . moves [ gDisableStructs [ gActiveBank ] . encoredMovePos ] ! = gDisableStructs [ gActiveBank ] . encoredMove ) // pokemon does not have the encored move anymore
{
gDisableStructs [ gActiveBank ] . encoredMove = 0 ;
gDisableStructs [ gActiveBank ] . encoreTimer1 = 0 ;
}
else if ( - - gDisableStructs [ gActiveBank ] . encoreTimer1 = = 0
| | gBattleMons [ gActiveBank ] . pp [ gDisableStructs [ gActiveBank ] . encoredMovePos ] = = 0 )
{
gDisableStructs [ gActiveBank ] . encoredMove = 0 ;
gDisableStructs [ gActiveBank ] . encoreTimer1 = 0 ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_EncoredNoMore ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
case 14 : // lock-on decrement
if ( gStatuses3 [ gActiveBank ] & STATUS3_ALWAYS_HITS )
gStatuses3 [ gActiveBank ] - = 0x8 ;
gBattleStruct - > turnEffectsTracker + + ;
break ;
case 15 : // charge
if ( gDisableStructs [ gActiveBank ] . chargeTimer1 & & - - gDisableStructs [ gActiveBank ] . chargeTimer1 = = 0 )
gStatuses3 [ gActiveBank ] & = ~ STATUS3_CHARGED_UP ;
gBattleStruct - > turnEffectsTracker + + ;
break ;
case 16 : // taunt
if ( gDisableStructs [ gActiveBank ] . tauntTimer1 )
gDisableStructs [ gActiveBank ] . tauntTimer1 - - ;
gBattleStruct - > turnEffectsTracker + + ;
break ;
case 17 : // yawn
if ( gStatuses3 [ gActiveBank ] & STATUS3_YAWN )
{
gStatuses3 [ gActiveBank ] - = 0x800 ;
if ( ! ( gStatuses3 [ gActiveBank ] & STATUS3_YAWN ) & & ! ( gBattleMons [ gActiveBank ] . status1 & STATUS_ANY )
& & gBattleMons [ gActiveBank ] . ability ! = ABILITY_VITAL_SPIRIT
& & gBattleMons [ gActiveBank ] . ability ! = ABILITY_INSOMNIA & & ! UproarWakeUpCheck ( gActiveBank ) )
{
CancelMultiTurnMoves ( gActiveBank ) ;
gBattleMons [ gActiveBank ] . status1 | = ( Random ( ) & 3 ) + 2 ;
2017-09-26 22:39:59 +02:00
EmitSetMonData ( 0 , REQUEST_STATUS_BATTLE , 0 , 4 , & gBattleMons [ gActiveBank ] . status1 ) ;
2017-09-17 14:10:32 +02:00
MarkBufferBankForExecution ( gActiveBank ) ;
gEffectBank = gActiveBank ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_YawnMakesAsleep ) ;
2017-09-17 14:10:32 +02:00
effect + + ;
}
}
gBattleStruct - > turnEffectsTracker + + ;
break ;
case 19 : // done
gBattleStruct - > turnEffectsTracker = 0 ;
gBattleStruct - > turnEffectsBank + + ;
break ;
}
if ( effect ! = 0 )
return effect ;
}
}
gHitMarker & = ~ ( HITMARKER_GRUDGE | HITMARKER_x20 ) ;
return 0 ;
}
2017-12-02 14:08:55 +01:00
bool8 HandleWishPerishSongOnTurnEnd ( void )
2017-09-17 14:10:32 +02:00
{
gHitMarker | = ( HITMARKER_GRUDGE | HITMARKER_x20 ) ;
2017-12-02 14:08:55 +01:00
switch ( gBattleStruct - > wishPerishSongState )
2017-09-17 14:10:32 +02:00
{
case 0 :
2017-12-02 14:08:55 +01:00
while ( gBattleStruct - > wishPerishSongBank < gNoOfAllBanks )
2017-09-17 14:10:32 +02:00
{
2017-12-02 14:08:55 +01:00
gActiveBank = gBattleStruct - > wishPerishSongBank ;
2017-09-17 14:10:32 +02:00
if ( gAbsentBankFlags & gBitTable [ gActiveBank ] )
{
2017-12-02 14:08:55 +01:00
gBattleStruct - > wishPerishSongBank + + ;
2017-09-17 14:10:32 +02:00
continue ;
}
2017-12-02 14:08:55 +01:00
gBattleStruct - > wishPerishSongBank + + ;
2017-09-17 14:10:32 +02:00
if ( gWishFutureKnock . futureSightCounter [ gActiveBank ] ! = 0
& & - - gWishFutureKnock . futureSightCounter [ gActiveBank ] = = 0
& & gBattleMons [ gActiveBank ] . hp ! = 0 )
{
if ( gWishFutureKnock . futureSightMove [ gActiveBank ] = = MOVE_FUTURE_SIGHT )
gBattleCommunication [ MULTISTRING_CHOOSER ] = 0 ;
else
gBattleCommunication [ MULTISTRING_CHOOSER ] = 1 ;
2017-11-26 13:26:58 +01:00
PREPARE_MOVE_BUFFER ( gBattleTextBuff1 , gWishFutureKnock . futureSightMove [ gActiveBank ] ) ;
2017-09-17 14:10:32 +02:00
gBankTarget = gActiveBank ;
gBankAttacker = gWishFutureKnock . futureSightAttacker [ gActiveBank ] ;
gBattleMoveDamage = gWishFutureKnock . futureSightDmg [ gActiveBank ] ;
gSpecialStatuses [ gBankTarget ] . moveturnLostHP = 0xFFFF ;
2017-11-26 17:26:11 +01:00
BattleScriptExecute ( BattleScript_MonTookFutureAttack ) ;
2017-09-17 14:10:32 +02:00
if ( gWishFutureKnock . futureSightCounter [ gActiveBank ] = = 0
2017-11-26 13:26:58 +01:00
& & gWishFutureKnock . futureSightCounter [ gActiveBank ^ BIT_MON ] = = 0 )
2017-09-17 14:10:32 +02:00
{
2017-11-26 13:26:58 +01:00
gSideAffecting [ GET_BANK_SIDE ( gBankTarget ) ] & = ~ ( SIDE_STATUS_FUTUREATTACK ) ;
2017-09-17 14:10:32 +02:00
}
2017-11-26 13:26:58 +01:00
return TRUE ;
2017-09-17 14:10:32 +02:00
}
}
// Why do I have to keep doing this to match?
{
2017-12-02 14:08:55 +01:00
u8 * state = & gBattleStruct - > wishPerishSongState ;
* state = 1 ;
gBattleStruct - > wishPerishSongBank = 0 ;
2017-09-17 14:10:32 +02:00
}
// fall through
case 1 :
2017-12-02 14:08:55 +01:00
while ( gBattleStruct - > wishPerishSongBank < gNoOfAllBanks )
2017-09-17 14:10:32 +02:00
{
2017-12-02 14:08:55 +01:00
gActiveBank = gBankAttacker = gBanksByTurnOrder [ gBattleStruct - > wishPerishSongBank ] ;
2017-09-17 14:10:32 +02:00
if ( gAbsentBankFlags & gBitTable [ gActiveBank ] )
{
2017-12-02 14:08:55 +01:00
gBattleStruct - > wishPerishSongBank + + ;
2017-09-17 14:10:32 +02:00
continue ;
}
2017-12-02 14:08:55 +01:00
gBattleStruct - > wishPerishSongBank + + ;
2017-09-17 14:10:32 +02:00
if ( gStatuses3 [ gActiveBank ] & STATUS3_PERISH_SONG )
{
2017-11-26 13:26:58 +01:00
PREPARE_BYTE_NUMBER_BUFFER ( gBattleTextBuff1 , 1 , gDisableStructs [ gActiveBank ] . perishSongTimer1 ) ;
2017-11-12 17:11:06 +01:00
if ( gDisableStructs [ gActiveBank ] . perishSongTimer1 = = 0 )
2017-09-17 14:10:32 +02:00
{
gStatuses3 [ gActiveBank ] & = ~ STATUS3_PERISH_SONG ;
gBattleMoveDamage = gBattleMons [ gActiveBank ] . hp ;
2017-11-26 17:26:11 +01:00
gBattlescriptCurrInstr = BattleScript_PerishSongTakesLife ;
2017-09-17 14:10:32 +02:00
}
else
{
2017-11-12 17:11:06 +01:00
gDisableStructs [ gActiveBank ] . perishSongTimer1 - - ;
2017-11-26 17:26:11 +01:00
gBattlescriptCurrInstr = BattleScript_PerishSongCountGoesDown ;
2017-09-17 14:10:32 +02:00
}
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( gBattlescriptCurrInstr ) ;
2017-11-26 13:26:58 +01:00
return TRUE ;
2017-09-17 14:10:32 +02:00
}
}
// Hm...
{
2017-12-02 14:08:55 +01:00
u8 * state = & gBattleStruct - > wishPerishSongState ;
* state = 2 ;
gBattleStruct - > wishPerishSongBank = 0 ;
2017-09-17 14:10:32 +02:00
}
// fall through
case 2 :
if ( ( gBattleTypeFlags & BATTLE_TYPE_ARENA )
2017-09-17 15:19:15 +02:00
& & gBattleStruct - > field_DA = = 2
2017-09-17 14:10:32 +02:00
& & gBattleMons [ 0 ] . hp ! = 0 & & gBattleMons [ 1 ] . hp ! = 0 )
{
s32 i ;
for ( i = 0 ; i < 2 ; i + + )
CancelMultiTurnMoves ( i ) ;
2017-11-25 18:42:31 +01:00
gBattlescriptCurrInstr = BattleScript_82DB8F3 ;
BattleScriptExecute ( BattleScript_82DB8F3 ) ;
2017-12-02 14:08:55 +01:00
gBattleStruct - > wishPerishSongState + + ;
2017-11-26 13:26:58 +01:00
return TRUE ;
2017-09-17 14:10:32 +02:00
}
break ;
}
gHitMarker & = ~ ( HITMARKER_GRUDGE | HITMARKER_x20 ) ;
2017-11-26 13:26:58 +01:00
return FALSE ;
2017-09-17 14:10:32 +02:00
}
2017-12-02 14:08:55 +01:00
# define FAINTED_ACTIONS_MAX_CASE 7
2017-09-17 14:10:32 +02:00
2017-12-02 14:08:55 +01:00
bool8 HandleFaintedMonActions ( void )
2017-09-17 14:10:32 +02:00
{
if ( gBattleTypeFlags & BATTLE_TYPE_SAFARI )
return FALSE ;
do
{
int i ;
2017-12-02 14:08:55 +01:00
switch ( gBattleStruct - > faintedActionsState )
2017-09-17 14:10:32 +02:00
{
case 0 :
2017-12-02 14:08:55 +01:00
gBattleStruct - > faintedActionsBank = 0 ;
gBattleStruct - > faintedActionsState + + ;
2017-09-17 14:10:32 +02:00
for ( i = 0 ; i < gNoOfAllBanks ; i + + )
{
if ( gAbsentBankFlags & gBitTable [ i ] & & ! sub_80423F4 ( i , 6 , 6 ) )
gAbsentBankFlags & = ~ ( gBitTable [ i ] ) ;
}
// fall through
case 1 :
do
{
2017-12-02 14:08:55 +01:00
gBank1 = gBankTarget = gBattleStruct - > faintedActionsBank ;
if ( gBattleMons [ gBattleStruct - > faintedActionsBank ] . hp = = 0
& & ! ( gBattleStruct - > field_DF & gBitTable [ gBattlePartyID [ gBattleStruct - > faintedActionsBank ] ] )
& & ! ( gAbsentBankFlags & gBitTable [ gBattleStruct - > faintedActionsBank ] ) )
2017-09-17 14:10:32 +02:00
{
2017-12-02 14:08:55 +01:00
BattleScriptExecute ( BattleScript_GiveExp ) ;
gBattleStruct - > faintedActionsState = 2 ;
2017-09-17 14:10:32 +02:00
return TRUE ;
}
2017-12-02 14:08:55 +01:00
} while ( + + gBattleStruct - > faintedActionsBank ! = gNoOfAllBanks ) ;
gBattleStruct - > faintedActionsState = 3 ;
2017-09-17 14:10:32 +02:00
break ;
case 2 :
sub_803F9EC ( gBank1 ) ;
2017-12-02 14:08:55 +01:00
if ( + + gBattleStruct - > faintedActionsBank = = gNoOfAllBanks )
gBattleStruct - > faintedActionsState = 3 ;
2017-09-17 14:10:32 +02:00
else
2017-12-02 14:08:55 +01:00
gBattleStruct - > faintedActionsState = 1 ;
2017-09-17 14:10:32 +02:00
break ;
case 3 :
2017-12-02 14:08:55 +01:00
gBattleStruct - > faintedActionsBank = 0 ;
gBattleStruct - > faintedActionsState + + ;
2017-09-17 14:10:32 +02:00
// fall through
case 4 :
do
{
2017-12-02 14:08:55 +01:00
gBank1 = gBankTarget = gBattleStruct - > faintedActionsBank ;
if ( gBattleMons [ gBattleStruct - > faintedActionsBank ] . hp = = 0
& & ! ( gAbsentBankFlags & gBitTable [ gBattleStruct - > faintedActionsBank ] ) )
2017-09-17 14:10:32 +02:00
{
2017-12-02 14:08:55 +01:00
BattleScriptExecute ( BattleScript_HandleFaintedMon ) ;
gBattleStruct - > faintedActionsState = 5 ;
2017-09-17 14:10:32 +02:00
return TRUE ;
}
2017-12-02 14:08:55 +01:00
} while ( + + gBattleStruct - > faintedActionsBank ! = gNoOfAllBanks ) ;
gBattleStruct - > faintedActionsState = 6 ;
2017-09-17 14:10:32 +02:00
break ;
case 5 :
2017-12-02 14:08:55 +01:00
if ( + + gBattleStruct - > faintedActionsBank = = gNoOfAllBanks )
gBattleStruct - > faintedActionsState = 6 ;
2017-09-17 14:10:32 +02:00
else
2017-12-02 14:08:55 +01:00
gBattleStruct - > faintedActionsState = 4 ;
2017-09-17 14:10:32 +02:00
break ;
case 6 :
2017-09-17 15:19:15 +02:00
if ( AbilityBattleEffects ( ABILITYEFFECT_INTIMIDATE1 , 0 , 0 , 0 , 0 ) | | AbilityBattleEffects ( ABILITYEFFECT_TRACE , 0 , 0 , 0 , 0 ) | | ItemBattleEffects ( 1 , 0 , 1 ) | | AbilityBattleEffects ( ABILITYEFFECT_FORECAST , 0 , 0 , 0 , 0 ) )
2017-09-17 14:10:32 +02:00
return TRUE ;
2017-12-02 14:08:55 +01:00
gBattleStruct - > faintedActionsState + + ;
2017-09-17 14:10:32 +02:00
break ;
2017-12-02 14:08:55 +01:00
case FAINTED_ACTIONS_MAX_CASE :
2017-09-17 14:10:32 +02:00
break ;
}
2017-12-02 14:08:55 +01:00
} while ( gBattleStruct - > faintedActionsState ! = FAINTED_ACTIONS_MAX_CASE ) ;
2017-09-17 14:10:32 +02:00
return FALSE ;
}
2017-10-06 00:12:01 +02:00
void TryClearRageStatuses ( void )
2017-09-17 14:10:32 +02:00
{
int i ;
for ( i = 0 ; i < gNoOfAllBanks ; i + + )
{
if ( ( gBattleMons [ i ] . status2 & STATUS2_RAGE ) & & gChosenMovesByBanks [ i ] ! = MOVE_RAGE )
gBattleMons [ i ] . status2 & = ~ ( STATUS2_RAGE ) ;
}
}
# define ATKCANCELLER_MAX_CASE 14
u8 AtkCanceller_UnableToUseMove ( void )
{
u8 effect = 0 ;
s32 * bideDmg = & gBattleScripting . bideDmg ;
do
{
switch ( gBattleStruct - > atkCancellerTracker )
{
case 0 : // flags clear
gBattleMons [ gBankAttacker ] . status2 & = ~ ( STATUS2_DESTINY_BOND ) ;
gStatuses3 [ gBankAttacker ] & = ~ ( STATUS3_GRUDGE ) ;
gBattleStruct - > atkCancellerTracker + + ;
break ;
case 1 : // check being asleep
if ( gBattleMons [ gBankAttacker ] . status1 & STATUS_SLEEP )
{
if ( UproarWakeUpCheck ( gBankAttacker ) )
{
gBattleMons [ gBankAttacker ] . status1 & = ~ ( STATUS_SLEEP ) ;
gBattleMons [ gBankAttacker ] . status2 & = ~ ( STATUS2_NIGHTMARE ) ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 14:10:32 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = 1 ;
gBattlescriptCurrInstr = BattleScript_MoveUsedWokeUp ;
effect = 2 ;
}
else
{
u8 toSub ;
if ( gBattleMons [ gBankAttacker ] . ability = = ABILITY_EARLY_BIRD )
toSub = 2 ;
else
toSub = 1 ;
if ( ( gBattleMons [ gBankAttacker ] . status1 & STATUS_SLEEP ) < toSub )
gBattleMons [ gBankAttacker ] . status1 & = ~ ( STATUS_SLEEP ) ;
else
gBattleMons [ gBankAttacker ] . status1 - = toSub ;
if ( gBattleMons [ gBankAttacker ] . status1 & STATUS_SLEEP )
{
if ( gCurrentMove ! = MOVE_SNORE & & gCurrentMove ! = MOVE_SLEEP_TALK )
{
gBattlescriptCurrInstr = BattleScript_MoveUsedIsAsleep ;
gHitMarker | = HITMARKER_UNABLE_TO_USE_MOVE ;
effect = 2 ;
}
}
else
{
gBattleMons [ gBankAttacker ] . status2 & = ~ ( STATUS2_NIGHTMARE ) ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 14:10:32 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = 0 ;
gBattlescriptCurrInstr = BattleScript_MoveUsedWokeUp ;
effect = 2 ;
}
}
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
case 2 : // check being frozen
if ( gBattleMons [ gBankAttacker ] . status1 & STATUS_FREEZE )
{
if ( Random ( ) % 5 )
{
if ( gBattleMoves [ gCurrentMove ] . effect ! = EFFECT_THAW_HIT ) // unfreezing via a move effect happens in case 13
{
gBattlescriptCurrInstr = BattleScript_MoveUsedIsFrozen ;
gHitMarker | = HITMARKER_NO_ATTACKSTRING ;
}
else
{
gBattleStruct - > atkCancellerTracker + + ;
break ;
}
}
else // unfreeze
{
gBattleMons [ gBankAttacker ] . status1 & = ~ ( STATUS_FREEZE ) ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 14:10:32 +02:00
gBattlescriptCurrInstr = BattleScript_MoveUsedUnfroze ;
gBattleCommunication [ MULTISTRING_CHOOSER ] = 0 ;
}
effect = 2 ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
case 3 : // truant
if ( gBattleMons [ gBankAttacker ] . ability = = ABILITY_TRUANT & & gDisableStructs [ gBankAttacker ] . truantCounter )
{
CancelMultiTurnMoves ( gBankAttacker ) ;
gHitMarker | = HITMARKER_UNABLE_TO_USE_MOVE ;
gBattleCommunication [ MULTISTRING_CHOOSER ] = 0 ;
gBattlescriptCurrInstr = BattleScript_MoveUsedLoafingAround ;
gBattleMoveFlags | = MOVESTATUS_MISSED ;
effect = 1 ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
case 4 : // recharge
if ( gBattleMons [ gBankAttacker ] . status2 & STATUS2_RECHARGE )
{
gBattleMons [ gBankAttacker ] . status2 & = ~ ( STATUS2_RECHARGE ) ;
gDisableStructs [ gBankAttacker ] . rechargeCounter = 0 ;
CancelMultiTurnMoves ( gBankAttacker ) ;
gBattlescriptCurrInstr = BattleScript_MoveUsedMustRecharge ;
gHitMarker | = HITMARKER_UNABLE_TO_USE_MOVE ;
effect = 1 ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
case 5 : // flinch
if ( gBattleMons [ gBankAttacker ] . status2 & STATUS2_FLINCHED )
{
gBattleMons [ gBankAttacker ] . status2 & = ~ ( STATUS2_FLINCHED ) ;
gProtectStructs [ gBankAttacker ] . flinchImmobility = 1 ;
CancelMultiTurnMoves ( gBankAttacker ) ;
gBattlescriptCurrInstr = BattleScript_MoveUsedFlinched ;
gHitMarker | = HITMARKER_UNABLE_TO_USE_MOVE ;
effect = 1 ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
case 6 : // disabled move
if ( gDisableStructs [ gBankAttacker ] . disabledMove = = gCurrentMove & & gDisableStructs [ gBankAttacker ] . disabledMove ! = 0 )
{
gProtectStructs [ gBankAttacker ] . usedDisabledMove = 1 ;
gBattleScripting . bank = gBankAttacker ;
CancelMultiTurnMoves ( gBankAttacker ) ;
gBattlescriptCurrInstr = BattleScript_MoveUsedIsDisabled ;
gHitMarker | = HITMARKER_UNABLE_TO_USE_MOVE ;
effect = 1 ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
case 7 : // taunt
if ( gDisableStructs [ gBankAttacker ] . tauntTimer1 & & gBattleMoves [ gCurrentMove ] . power = = 0 )
{
gProtectStructs [ gBankAttacker ] . usedTauntedMove = 1 ;
CancelMultiTurnMoves ( gBankAttacker ) ;
gBattlescriptCurrInstr = BattleScript_MoveUsedIsTaunted ;
gHitMarker | = HITMARKER_UNABLE_TO_USE_MOVE ;
effect = 1 ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
case 8 : // imprisoned
2017-09-27 23:43:45 +02:00
if ( GetImprisonedMovesCount ( gBankAttacker , gCurrentMove ) )
2017-09-17 14:10:32 +02:00
{
gProtectStructs [ gBankAttacker ] . usedImprisionedMove = 1 ;
CancelMultiTurnMoves ( gBankAttacker ) ;
gBattlescriptCurrInstr = BattleScript_MoveUsedIsImprisoned ;
gHitMarker | = HITMARKER_UNABLE_TO_USE_MOVE ;
effect = 1 ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
case 9 : // confusion
if ( gBattleMons [ gBankAttacker ] . status2 & STATUS2_CONFUSION )
{
gBattleMons [ gBankAttacker ] . status2 - - ;
if ( gBattleMons [ gBankAttacker ] . status2 & STATUS2_CONFUSION )
{
if ( Random ( ) & 1 )
{
gBattleCommunication [ MULTISTRING_CHOOSER ] = 0 ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 14:10:32 +02:00
}
else // confusion dmg
{
gBattleCommunication [ MULTISTRING_CHOOSER ] = 1 ;
gBankTarget = gBankAttacker ;
gBattleMoveDamage = CalculateBaseDamage ( & gBattleMons [ gBankAttacker ] , & gBattleMons [ gBankAttacker ] , MOVE_POUND , 0 , 40 , 0 , gBankAttacker , gBankAttacker ) ;
gProtectStructs [ gBankAttacker ] . confusionSelfDmg = 1 ;
gHitMarker | = HITMARKER_UNABLE_TO_USE_MOVE ;
}
gBattlescriptCurrInstr = BattleScript_MoveUsedIsConfused ;
}
else // snapped out of confusion
{
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 14:10:32 +02:00
gBattlescriptCurrInstr = BattleScript_MoveUsedIsConfusedNoMore ;
}
effect = 1 ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
case 10 : // paralysis
if ( ( gBattleMons [ gBankAttacker ] . status1 & STATUS_PARALYSIS ) & & ( Random ( ) % 4 ) = = 0 )
{
gProtectStructs [ gBankAttacker ] . prlzImmobility = 1 ;
// This is removed in Emerald for some reason
//CancelMultiTurnMoves(gBankAttacker);
gBattlescriptCurrInstr = BattleScript_MoveUsedIsParalyzed ;
gHitMarker | = HITMARKER_UNABLE_TO_USE_MOVE ;
effect = 1 ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
case 11 : // infatuation
if ( gBattleMons [ gBankAttacker ] . status2 & STATUS2_INFATUATION )
{
gBattleScripting . bank = CountTrailingZeroBits ( ( gBattleMons [ gBankAttacker ] . status2 & STATUS2_INFATUATION ) > > 0x10 ) ;
if ( Random ( ) & 1 )
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 14:10:32 +02:00
else
{
2017-09-22 21:33:49 +02:00
BattleScriptPush ( BattleScript_MoveUsedIsParalyzedCantAttack ) ;
2017-09-17 14:10:32 +02:00
gHitMarker | = HITMARKER_UNABLE_TO_USE_MOVE ;
gProtectStructs [ gBankAttacker ] . loveImmobility = 1 ;
CancelMultiTurnMoves ( gBankAttacker ) ;
}
gBattlescriptCurrInstr = BattleScript_MoveUsedIsInLove ;
effect = 1 ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
case 12 : // bide
if ( gBattleMons [ gBankAttacker ] . status2 & STATUS2_BIDE )
{
gBattleMons [ gBankAttacker ] . status2 - = 0x100 ;
if ( gBattleMons [ gBankAttacker ] . status2 & STATUS2_BIDE )
gBattlescriptCurrInstr = BattleScript_BideStoringEnergy ;
else
{
// This is removed in Emerald for some reason
//gBattleMons[gBankAttacker].status2 &= ~(STATUS2_MULTIPLETURNS);
if ( gTakenDmg [ gBankAttacker ] )
{
gCurrentMove = MOVE_BIDE ;
* bideDmg = gTakenDmg [ gBankAttacker ] * 2 ;
gBankTarget = gTakenDmgBanks [ gBankAttacker ] ;
if ( gAbsentBankFlags & gBitTable [ gBankTarget ] )
gBankTarget = GetMoveTarget ( MOVE_BIDE , 1 ) ;
gBattlescriptCurrInstr = BattleScript_BideAttack ;
}
else
gBattlescriptCurrInstr = BattleScript_BideNoEnergyToAttack ;
}
effect = 1 ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
case 13 : // move thawing
if ( gBattleMons [ gBankAttacker ] . status1 & STATUS_FREEZE )
{
if ( gBattleMoves [ gCurrentMove ] . effect = = EFFECT_THAW_HIT )
{
gBattleMons [ gBankAttacker ] . status1 & = ~ ( STATUS_FREEZE ) ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 14:10:32 +02:00
gBattlescriptCurrInstr = BattleScript_MoveUsedUnfroze ;
gBattleCommunication [ MULTISTRING_CHOOSER ] = 1 ;
}
effect = 2 ;
}
gBattleStruct - > atkCancellerTracker + + ;
break ;
2017-11-26 13:26:58 +01:00
case ATKCANCELLER_MAX_CASE :
2017-09-17 14:10:32 +02:00
break ;
}
} while ( gBattleStruct - > atkCancellerTracker ! = ATKCANCELLER_MAX_CASE & & effect = = 0 ) ;
if ( effect = = 2 )
{
gActiveBank = gBankAttacker ;
2017-09-26 22:39:59 +02:00
EmitSetMonData ( 0 , REQUEST_STATUS_BATTLE , 0 , 4 , & gBattleMons [ gActiveBank ] . status1 ) ;
2017-09-17 14:10:32 +02:00
MarkBufferBankForExecution ( gActiveBank ) ;
}
return effect ;
}
2017-09-17 15:19:15 +02:00
bool8 sub_80423F4 ( u8 bank , u8 r1 , u8 r2 )
{
struct Pokemon * party ;
u8 r7 ;
u8 r6 ;
s32 i ;
if ( ! ( gBattleTypeFlags & BATTLE_TYPE_DOUBLE ) )
return FALSE ;
if ( gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER )
{
2017-09-18 12:51:16 +02:00
if ( GetBankSide ( bank ) = = SIDE_PLAYER )
2017-09-17 15:19:15 +02:00
party = gPlayerParty ;
else
party = gEnemyParty ;
2017-09-18 12:51:16 +02:00
r6 = ( ( bank & 2 ) / 2 ) ;
2017-09-17 15:19:15 +02:00
for ( i = r6 * 3 ; i < r6 * 3 + 3 ; i + + )
{
if ( GetMonData ( & party [ i ] , MON_DATA_HP ) ! = 0
& & GetMonData ( & party [ i ] , MON_DATA_SPECIES2 ) ! = 0
& & GetMonData ( & party [ i ] , MON_DATA_SPECIES2 ) ! = SPECIES_EGG )
break ;
}
return ( i = = r6 * 3 + 3 ) ;
}
else if ( gBattleTypeFlags & BATTLE_TYPE_MULTI )
{
if ( gBattleTypeFlags & BATTLE_TYPE_x800000 )
{
if ( GetBankSide ( bank ) = = SIDE_PLAYER )
{
party = gPlayerParty ;
2017-10-23 16:38:11 +02:00
r7 = GetBankMultiplayerId ( bank ) ;
2017-09-17 15:19:15 +02:00
r6 = sub_806D82C ( r7 ) ;
}
else
{
// FIXME: Compiler insists on moving r4 into r1 before doing the eor
# ifndef NONMATCHING
register u32 var asm ( " r1 " ) ;
# else
u32 var ;
# endif // NONMATCHING
party = gEnemyParty ;
var = bank ^ 1 ;
2017-09-18 12:51:16 +02:00
r6 = ( var ! = 0 ) ? 1 : 0 ;
2017-09-17 15:19:15 +02:00
}
}
else
{
2017-10-23 16:38:11 +02:00
r7 = GetBankMultiplayerId ( bank ) ;
2017-09-18 12:51:16 +02:00
if ( GetBankSide ( bank ) = = SIDE_PLAYER )
2017-09-17 15:19:15 +02:00
party = gPlayerParty ;
else
party = gEnemyParty ;
r6 = sub_806D82C ( r7 ) ;
}
for ( i = r6 * 3 ; i < r6 * 3 + 3 ; i + + )
{
if ( GetMonData ( & party [ i ] , MON_DATA_HP ) ! = 0
& & GetMonData ( & party [ i ] , MON_DATA_SPECIES2 ) ! = 0
& & GetMonData ( & party [ i ] , MON_DATA_SPECIES2 ) ! = SPECIES_EGG )
break ;
}
return ( i = = r6 * 3 + 3 ) ;
}
2017-09-18 12:51:16 +02:00
else if ( ( gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS ) & & GetBankSide ( bank ) = = SIDE_OPPONENT )
2017-09-17 15:19:15 +02:00
{
party = gEnemyParty ;
if ( bank = = 1 )
r6 = 0 ;
else
r6 = 3 ;
for ( i = r6 ; i < r6 + 3 ; i + + )
{
if ( GetMonData ( & party [ i ] , MON_DATA_HP ) ! = 0
& & GetMonData ( & party [ i ] , MON_DATA_SPECIES2 ) ! = 0
& & GetMonData ( & party [ i ] , MON_DATA_SPECIES2 ) ! = SPECIES_EGG )
break ;
}
return ( i = = r6 + 3 ) ;
}
else
{
2017-09-18 12:51:16 +02:00
if ( GetBankSide ( bank ) = = SIDE_OPPONENT )
2017-09-17 15:19:15 +02:00
{
2017-11-26 13:26:58 +01:00
r7 = GetBankByIdentity ( IDENTITY_OPPONENT_MON1 ) ;
r6 = GetBankByIdentity ( IDENTITY_OPPONENT_MON2 ) ;
2017-09-17 15:19:15 +02:00
party = gEnemyParty ;
}
else
{
2017-11-26 13:26:58 +01:00
r7 = GetBankByIdentity ( IDENTITY_PLAYER_MON1 ) ;
r6 = GetBankByIdentity ( IDENTITY_PLAYER_MON2 ) ;
2017-09-17 15:19:15 +02:00
party = gPlayerParty ;
}
if ( r1 = = 6 )
r1 = gBattlePartyID [ r7 ] ;
if ( r2 = = 6 )
r2 = gBattlePartyID [ r6 ] ;
for ( i = 0 ; i < 6 ; i + + )
{
if ( GetMonData ( & party [ i ] , MON_DATA_HP ) ! = 0
& & GetMonData ( & party [ i ] , MON_DATA_SPECIES2 ) ! = 0
& & GetMonData ( & party [ i ] , MON_DATA_SPECIES2 ) ! = SPECIES_EGG
// FIXME: Using index[array] instead of array[index] is BAD!
2017-11-12 17:06:31 +01:00
& & i ! = r1 & & i ! = r2 & & i ! = r7 [ gBattleStruct - > monToSwitchIntoId ] & & i ! = r6 [ gBattleStruct - > monToSwitchIntoId ] )
2017-09-17 15:19:15 +02:00
break ;
}
return ( i = = 6 ) ;
}
}
enum
{
CASTFORM_NO_CHANGE , //0
CASTFORM_TO_NORMAL , //1
CASTFORM_TO_FIRE , //2
CASTFORM_TO_WATER , //3
CASTFORM_TO_ICE , //4
} ;
u8 CastformDataTypeChange ( u8 bank )
{
u8 formChange = 0 ;
if ( gBattleMons [ bank ] . species ! = SPECIES_CASTFORM | | gBattleMons [ bank ] . ability ! = ABILITY_FORECAST | | gBattleMons [ bank ] . hp = = 0 )
return CASTFORM_NO_CHANGE ;
if ( ! WEATHER_HAS_EFFECT & & gBattleMons [ bank ] . type1 ! = TYPE_NORMAL & & gBattleMons [ bank ] . type2 ! = TYPE_NORMAL )
{
gBattleMons [ bank ] . type1 = TYPE_NORMAL ;
gBattleMons [ bank ] . type2 = TYPE_NORMAL ;
return CASTFORM_TO_NORMAL ;
}
if ( ! WEATHER_HAS_EFFECT )
return CASTFORM_NO_CHANGE ;
if ( ! ( gBattleWeather & ( WEATHER_RAIN_ANY | WEATHER_SUN_ANY | WEATHER_HAIL ) ) & & gBattleMons [ bank ] . type1 ! = TYPE_NORMAL & & gBattleMons [ bank ] . type2 ! = TYPE_NORMAL )
{
gBattleMons [ bank ] . type1 = TYPE_NORMAL ;
gBattleMons [ bank ] . type2 = TYPE_NORMAL ;
formChange = CASTFORM_TO_NORMAL ;
}
if ( gBattleWeather & WEATHER_SUN_ANY & & gBattleMons [ bank ] . type1 ! = TYPE_FIRE & & gBattleMons [ bank ] . type2 ! = TYPE_FIRE )
{
gBattleMons [ bank ] . type1 = TYPE_FIRE ;
gBattleMons [ bank ] . type2 = TYPE_FIRE ;
formChange = CASTFORM_TO_FIRE ;
}
if ( gBattleWeather & WEATHER_RAIN_ANY & & gBattleMons [ bank ] . type1 ! = TYPE_WATER & & gBattleMons [ bank ] . type2 ! = TYPE_WATER )
{
gBattleMons [ bank ] . type1 = TYPE_WATER ;
gBattleMons [ bank ] . type2 = TYPE_WATER ;
formChange = CASTFORM_TO_WATER ;
}
if ( gBattleWeather & WEATHER_HAIL & & gBattleMons [ bank ] . type1 ! = TYPE_ICE & & gBattleMons [ bank ] . type2 ! = TYPE_ICE )
{
gBattleMons [ bank ] . type1 = TYPE_ICE ;
gBattleMons [ bank ] . type2 = TYPE_ICE ;
formChange = CASTFORM_TO_ICE ;
}
return formChange ;
}
2017-10-12 17:49:24 +02:00
// The largest function in the game, but even it could not save itself from decompiling.
2017-09-17 15:19:15 +02:00
u8 AbilityBattleEffects ( u8 caseID , u8 bank , u8 ability , u8 special , u16 moveArg )
{
u8 effect = 0 ;
2017-10-12 17:49:24 +02:00
struct Pokemon * pokeAtk ;
struct Pokemon * pokeDef ;
2017-09-17 15:19:15 +02:00
u16 speciesAtk ;
u16 speciesDef ;
u32 pidAtk ;
u32 pidDef ;
if ( gBankAttacker > = gNoOfAllBanks )
gBankAttacker = bank ;
if ( GetBankSide ( gBankAttacker ) = = SIDE_PLAYER )
pokeAtk = & gPlayerParty [ gBattlePartyID [ gBankAttacker ] ] ;
else
pokeAtk = & gEnemyParty [ gBattlePartyID [ gBankAttacker ] ] ;
if ( gBankTarget > = gNoOfAllBanks )
gBankTarget = bank ;
if ( GetBankSide ( gBankTarget ) = = SIDE_PLAYER )
pokeDef = & gPlayerParty [ gBattlePartyID [ gBankTarget ] ] ;
else
pokeDef = & gEnemyParty [ gBattlePartyID [ gBankTarget ] ] ;
speciesAtk = GetMonData ( pokeAtk , MON_DATA_SPECIES ) ;
pidAtk = GetMonData ( pokeAtk , MON_DATA_PERSONALITY ) ;
speciesDef = GetMonData ( pokeDef , MON_DATA_SPECIES ) ;
pidDef = GetMonData ( pokeDef , MON_DATA_PERSONALITY ) ;
if ( ! ( gBattleTypeFlags & BATTLE_TYPE_SAFARI ) ) // why isn't that check done at the beginning?
{
2017-10-12 17:49:24 +02:00
u8 moveType ;
s32 i ;
2017-09-17 15:19:15 +02:00
u16 move ;
u8 side ;
2017-10-12 17:49:24 +02:00
u8 target1 ;
2017-09-17 15:19:15 +02:00
if ( special )
gLastUsedAbility = special ;
else
gLastUsedAbility = gBattleMons [ bank ] . ability ;
if ( moveArg )
move = moveArg ;
else
move = gCurrentMove ;
2017-11-26 13:26:58 +01:00
GET_MOVE_TYPE ( move , moveType ) ;
2017-09-17 15:19:15 +02:00
switch ( caseID )
{
case ABILITYEFFECT_ON_SWITCHIN : // 0
if ( gBankAttacker > = gNoOfAllBanks )
gBankAttacker = bank ;
switch ( gLastUsedAbility )
2017-09-18 23:44:55 +02:00
{
2017-10-02 23:32:39 +02:00
case ABILITYEFFECT_SWITCH_IN_WEATHER :
2017-10-12 17:49:24 +02:00
if ( ! ( gBattleTypeFlags & BATTLE_TYPE_RECORDED ) )
2017-09-18 23:44:55 +02:00
{
2017-10-12 17:49:24 +02:00
switch ( weather_get_current ( ) )
2017-09-17 15:19:15 +02:00
{
2017-10-12 17:49:24 +02:00
case 3 :
case 5 :
case 13 :
if ( ! ( gBattleWeather & WEATHER_RAIN_ANY ) )
{
gBattleWeather = ( WEATHER_RAIN_TEMPORARY | WEATHER_RAIN_PERMANENT ) ;
gBattleScripting . animArg1 = B_ANIM_RAIN_CONTINUES ;
gBattleScripting . bank = bank ;
effect + + ;
}
break ;
case 8 :
if ( ! ( gBattleWeather & WEATHER_SANDSTORM_ANY ) )
{
gBattleWeather = ( WEATHER_SANDSTORM_PERMANENT | WEATHER_SANDSTORM_TEMPORARY ) ;
gBattleScripting . animArg1 = B_ANIM_SANDSTORM_CONTINUES ;
gBattleScripting . bank = bank ;
effect + + ;
}
break ;
case 12 :
if ( ! ( gBattleWeather & WEATHER_SUN_ANY ) )
{
gBattleWeather = ( WEATHER_SUN_PERMANENT | WEATHER_SUN_TEMPORARY ) ;
gBattleScripting . animArg1 = B_ANIM_SUN_CONTINUES ;
gBattleScripting . bank = bank ;
effect + + ;
}
break ;
2017-09-17 15:19:15 +02:00
}
2017-09-18 23:44:55 +02:00
}
if ( effect )
2017-09-17 15:19:15 +02:00
{
gBattleCommunication [ MULTISTRING_CHOOSER ] = weather_get_current ( ) ;
2017-11-26 17:15:28 +01:00
BattleScriptPushCursorAndCallback ( BattleScript_OverworldWeatherStarts ) ;
2017-09-17 15:19:15 +02:00
}
2017-09-18 23:44:55 +02:00
break ;
case ABILITY_DRIZZLE :
if ( ! ( gBattleWeather & WEATHER_RAIN_PERMANENT ) )
2017-09-17 15:19:15 +02:00
{
gBattleWeather = ( WEATHER_RAIN_PERMANENT | WEATHER_RAIN_TEMPORARY ) ;
2017-09-28 15:34:21 +02:00
BattleScriptPushCursorAndCallback ( BattleScript_DrizzleActivates ) ;
2017-09-17 15:19:15 +02:00
gBattleScripting . bank = bank ;
effect + + ;
}
2017-09-18 23:44:55 +02:00
break ;
case ABILITY_SAND_STREAM :
if ( ! ( gBattleWeather & WEATHER_SANDSTORM_PERMANENT ) )
2017-09-17 15:19:15 +02:00
{
gBattleWeather = ( WEATHER_SANDSTORM_PERMANENT | WEATHER_SANDSTORM_TEMPORARY ) ;
2017-09-28 15:34:21 +02:00
BattleScriptPushCursorAndCallback ( BattleScript_SandstreamActivates ) ;
2017-09-17 15:19:15 +02:00
gBattleScripting . bank = bank ;
effect + + ;
}
2017-09-18 23:44:55 +02:00
break ;
case ABILITY_DROUGHT :
2017-09-17 15:19:15 +02:00
if ( ! ( gBattleWeather & WEATHER_SUN_PERMANENT ) )
{
gBattleWeather = ( WEATHER_SUN_PERMANENT | WEATHER_SUN_TEMPORARY ) ;
2017-09-28 15:34:21 +02:00
BattleScriptPushCursorAndCallback ( BattleScript_DroughtActivates ) ;
2017-09-17 15:19:15 +02:00
gBattleScripting . bank = bank ;
effect + + ;
}
2017-09-18 23:44:55 +02:00
break ;
case ABILITY_INTIMIDATE :
2017-09-17 15:19:15 +02:00
if ( ! ( gSpecialStatuses [ bank ] . intimidatedPoke ) )
{
gStatuses3 [ bank ] | = STATUS3_INTIMIDATE_POKES ;
gSpecialStatuses [ bank ] . intimidatedPoke = 1 ;
}
2017-09-18 23:44:55 +02:00
break ;
case ABILITY_FORECAST :
2017-09-17 15:19:15 +02:00
effect = CastformDataTypeChange ( bank ) ;
if ( effect ! = 0 )
{
2017-09-28 15:34:21 +02:00
BattleScriptPushCursorAndCallback ( BattleScript_CastformChange ) ;
2017-09-17 15:19:15 +02:00
gBattleScripting . bank = bank ;
2017-10-12 17:49:24 +02:00
* ( & gBattleStruct - > formToChangeInto ) = effect - 1 ;
2017-09-17 15:19:15 +02:00
}
2017-09-18 23:44:55 +02:00
break ;
case ABILITY_TRACE :
if ( ! ( gSpecialStatuses [ bank ] . traced ) )
2017-09-17 15:19:15 +02:00
{
gStatuses3 [ bank ] | = STATUS3_TRACE ;
gSpecialStatuses [ bank ] . traced = 1 ;
}
2017-09-18 23:44:55 +02:00
break ;
case ABILITY_CLOUD_NINE :
case ABILITY_AIR_LOCK :
{
2017-10-12 17:49:24 +02:00
// that's a weird choice for a variable, why not use i or bank?
for ( target1 = 0 ; target1 < gNoOfAllBanks ; target1 + + )
2017-09-17 15:19:15 +02:00
{
2017-10-12 17:49:24 +02:00
effect = CastformDataTypeChange ( target1 ) ;
2017-09-17 15:19:15 +02:00
if ( effect ! = 0 )
{
2017-09-28 15:34:21 +02:00
BattleScriptPushCursorAndCallback ( BattleScript_CastformChange ) ;
2017-10-12 17:49:24 +02:00
gBattleScripting . bank = target1 ;
* ( & gBattleStruct - > formToChangeInto ) = effect - 1 ;
2017-09-17 15:19:15 +02:00
break ;
}
}
2017-09-18 23:44:55 +02:00
}
break ;
}
break ;
2017-09-17 15:19:15 +02:00
case ABILITYEFFECT_ENDTURN : // 1
if ( gBattleMons [ bank ] . hp ! = 0 )
{
gBankAttacker = bank ;
switch ( gLastUsedAbility )
{
case ABILITY_RAIN_DISH :
if ( WEATHER_HAS_EFFECT & & ( gBattleWeather & WEATHER_RAIN_ANY )
& & gBattleMons [ bank ] . maxHP > gBattleMons [ bank ] . hp )
{
2017-10-12 17:49:24 +02:00
gLastUsedAbility = ABILITY_RAIN_DISH ; // why
2017-09-28 15:34:21 +02:00
BattleScriptPushCursorAndCallback ( BattleScript_RainDishActivates ) ;
2017-09-17 15:19:15 +02:00
gBattleMoveDamage = gBattleMons [ bank ] . maxHP / 16 ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
gBattleMoveDamage * = - 1 ;
effect + + ;
}
break ;
case ABILITY_SHED_SKIN :
if ( ( gBattleMons [ bank ] . status1 & STATUS_ANY ) & & ( Random ( ) % 3 ) = = 0 )
{
if ( gBattleMons [ bank ] . status1 & ( STATUS_POISON | STATUS_TOXIC_POISON ) )
StringCopy ( gBattleTextBuff1 , gStatusConditionString_PoisonJpn ) ;
if ( gBattleMons [ bank ] . status1 & STATUS_SLEEP )
StringCopy ( gBattleTextBuff1 , gStatusConditionString_SleepJpn ) ;
if ( gBattleMons [ bank ] . status1 & STATUS_PARALYSIS )
StringCopy ( gBattleTextBuff1 , gStatusConditionString_ParalysisJpn ) ;
if ( gBattleMons [ bank ] . status1 & STATUS_BURN )
StringCopy ( gBattleTextBuff1 , gStatusConditionString_BurnJpn ) ;
if ( gBattleMons [ bank ] . status1 & STATUS_FREEZE )
StringCopy ( gBattleTextBuff1 , gStatusConditionString_IceJpn ) ;
gBattleMons [ bank ] . status1 = 0 ;
2017-10-12 17:49:24 +02:00
gBattleMons [ bank ] . status2 & = ~ ( STATUS2_NIGHTMARE ) ; // fix nightmare glitch
2017-09-17 15:19:15 +02:00
gBattleScripting . bank = gActiveBank = bank ;
2017-09-28 15:34:21 +02:00
BattleScriptPushCursorAndCallback ( BattleScript_ShedSkinActivates ) ;
2017-09-26 22:39:59 +02:00
EmitSetMonData ( 0 , REQUEST_STATUS_BATTLE , 0 , 4 , & gBattleMons [ bank ] . status1 ) ;
2017-09-17 15:19:15 +02:00
MarkBufferBankForExecution ( gActiveBank ) ;
effect + + ;
}
break ;
case ABILITY_SPEED_BOOST :
if ( gBattleMons [ bank ] . statStages [ STAT_STAGE_SPEED ] < 0xC & & gDisableStructs [ bank ] . isFirstTurn ! = 2 )
{
gBattleMons [ bank ] . statStages [ STAT_STAGE_SPEED ] + + ;
gBattleScripting . animArg1 = 0x11 ;
gBattleScripting . animArg2 = 0 ;
2017-09-28 15:34:21 +02:00
BattleScriptPushCursorAndCallback ( BattleScript_SpeedBoostActivates ) ;
2017-09-17 15:19:15 +02:00
gBattleScripting . bank = bank ;
effect + + ;
}
break ;
case ABILITY_TRUANT :
gDisableStructs [ gBankAttacker ] . truantCounter ^ = 1 ;
break ;
}
}
break ;
case ABILITYEFFECT_MOVES_BLOCK : // 2
if ( gLastUsedAbility = = ABILITY_SOUNDPROOF )
{
2017-10-06 19:09:37 +02:00
for ( i = 0 ; sSoundMovesTable [ i ] ! = 0xFFFF ; i + + )
2017-09-17 15:19:15 +02:00
{
2017-10-06 19:09:37 +02:00
if ( sSoundMovesTable [ i ] = = move )
2017-09-17 15:19:15 +02:00
break ;
}
2017-10-06 19:09:37 +02:00
if ( sSoundMovesTable [ i ] ! = 0xFFFF )
2017-09-17 15:19:15 +02:00
{
if ( gBattleMons [ gBankAttacker ] . status2 & STATUS2_MULTIPLETURNS )
gHitMarker | = HITMARKER_NO_PPDEDUCT ;
gBattlescriptCurrInstr = BattleScript_SoundproofProtected ;
effect = 1 ;
}
}
break ;
case ABILITYEFFECT_ABSORBING : // 3
if ( move )
{
switch ( gLastUsedAbility )
{
case ABILITY_VOLT_ABSORB :
if ( moveType = = TYPE_ELECTRIC & & gBattleMoves [ move ] . power ! = 0 )
{
if ( gProtectStructs [ gBankAttacker ] . notFirstStrike )
gBattlescriptCurrInstr = BattleScript_MoveHPDrain ;
else
gBattlescriptCurrInstr = BattleScript_MoveHPDrain_PPLoss ;
2017-10-12 17:49:24 +02:00
2017-09-17 15:19:15 +02:00
effect = 1 ;
}
break ;
case ABILITY_WATER_ABSORB :
if ( moveType = = TYPE_WATER & & gBattleMoves [ move ] . power ! = 0 )
{
if ( gProtectStructs [ gBankAttacker ] . notFirstStrike )
gBattlescriptCurrInstr = BattleScript_MoveHPDrain ;
else
gBattlescriptCurrInstr = BattleScript_MoveHPDrain_PPLoss ;
2017-10-12 17:49:24 +02:00
2017-09-17 15:19:15 +02:00
effect = 1 ;
}
break ;
case ABILITY_FLASH_FIRE :
if ( moveType = = TYPE_FIRE & & ! ( gBattleMons [ bank ] . status1 & STATUS_FREEZE ) )
{
if ( ! ( gBattleResources - > flags - > flags [ bank ] & UNKNOWN_FLAG_FLASH_FIRE ) )
{
gBattleCommunication [ MULTISTRING_CHOOSER ] = 0 ;
if ( gProtectStructs [ gBankAttacker ] . notFirstStrike )
gBattlescriptCurrInstr = BattleScript_FlashFireBoost ;
else
gBattlescriptCurrInstr = BattleScript_FlashFireBoost_PPLoss ;
2017-10-12 17:49:24 +02:00
2017-09-17 15:19:15 +02:00
gBattleResources - > flags - > flags [ bank ] | = UNKNOWN_FLAG_FLASH_FIRE ;
effect = 2 ;
}
else
{
gBattleCommunication [ MULTISTRING_CHOOSER ] = 1 ;
if ( gProtectStructs [ gBankAttacker ] . notFirstStrike )
gBattlescriptCurrInstr = BattleScript_FlashFireBoost ;
else
gBattlescriptCurrInstr = BattleScript_FlashFireBoost_PPLoss ;
2017-10-12 17:49:24 +02:00
2017-09-17 15:19:15 +02:00
effect = 2 ;
}
}
break ;
}
if ( effect = = 1 )
{
if ( gBattleMons [ bank ] . maxHP = = gBattleMons [ bank ] . hp )
{
if ( ( gProtectStructs [ gBankAttacker ] . notFirstStrike ) )
2017-11-26 17:15:28 +01:00
gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless ;
2017-09-17 15:19:15 +02:00
else
2017-11-26 17:15:28 +01:00
gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless_PPLoss ;
2017-09-17 15:19:15 +02:00
}
else
{
gBattleMoveDamage = gBattleMons [ bank ] . maxHP / 4 ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
gBattleMoveDamage * = - 1 ;
}
}
}
break ;
case ABILITYEFFECT_CONTACT : // 4
switch ( gLastUsedAbility )
{
case ABILITY_COLOR_CHANGE :
if ( ! ( gBattleMoveFlags & MOVESTATUS_NOEFFECT )
& & move ! = MOVE_STRUGGLE
& & gBattleMoves [ move ] . power ! = 0
& & ( gSpecialStatuses [ gBankTarget ] . moveturnLostHP_physical | | gSpecialStatuses [ gBankTarget ] . moveturnLostHP_special )
& & gBattleMons [ bank ] . type1 ! = moveType
& & gBattleMons [ bank ] . type2 ! = moveType
& & gBattleMons [ bank ] . hp ! = 0 )
{
gBattleMons [ bank ] . type1 = moveType ;
gBattleMons [ bank ] . type2 = moveType ;
2017-10-12 17:49:24 +02:00
PREPARE_TYPE_BUFFER ( gBattleTextBuff1 , moveType )
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 15:19:15 +02:00
gBattlescriptCurrInstr = BattleScript_ColorChangeActivates ;
effect + + ;
}
break ;
case ABILITY_ROUGH_SKIN :
if ( ! ( gBattleMoveFlags & MOVESTATUS_NOEFFECT )
& & gBattleMons [ gBankAttacker ] . hp ! = 0
& & ! gProtectStructs [ gBankAttacker ] . confusionSelfDmg
& & ( gSpecialStatuses [ gBankTarget ] . moveturnLostHP_physical | | gSpecialStatuses [ gBankTarget ] . moveturnLostHP_special )
& & ( gBattleMoves [ move ] . flags & FLAG_MAKES_CONTACT ) )
{
gBattleMoveDamage = gBattleMons [ gBankAttacker ] . maxHP / 16 ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 15:19:15 +02:00
gBattlescriptCurrInstr = BattleScript_RoughSkinActivates ;
effect + + ;
}
break ;
case ABILITY_EFFECT_SPORE :
if ( ! ( gBattleMoveFlags & MOVESTATUS_NOEFFECT )
& & gBattleMons [ gBankAttacker ] . hp ! = 0
& & ! gProtectStructs [ gBankAttacker ] . confusionSelfDmg
& & ( gSpecialStatuses [ gBankTarget ] . moveturnLostHP_physical | | gSpecialStatuses [ gBankTarget ] . moveturnLostHP_special )
& & ( gBattleMoves [ move ] . flags & FLAG_MAKES_CONTACT )
& & ( Random ( ) % 10 ) = = 0 )
{
do
{
gBattleCommunication [ MOVE_EFFECT_BYTE ] = Random ( ) & 3 ;
} while ( gBattleCommunication [ MOVE_EFFECT_BYTE ] = = 0 ) ;
2017-10-12 17:49:24 +02:00
if ( gBattleCommunication [ MOVE_EFFECT_BYTE ] = = MOVE_EFFECT_BURN )
gBattleCommunication [ MOVE_EFFECT_BYTE ] + = 2 ; // 5 MOVE_EFFECT_PARALYSIS
gBattleCommunication [ MOVE_EFFECT_BYTE ] + = MOVE_EFFECT_AFFECTS_USER ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 15:19:15 +02:00
gBattlescriptCurrInstr = BattleScript_ApplySecondaryEffect ;
gHitMarker | = HITMARKER_IGNORE_SAFEGUARD ;
effect + + ;
}
break ;
case ABILITY_POISON_POINT :
if ( ! ( gBattleMoveFlags & MOVESTATUS_NOEFFECT )
& & gBattleMons [ gBankAttacker ] . hp ! = 0
& & ! gProtectStructs [ gBankAttacker ] . confusionSelfDmg
& & ( gSpecialStatuses [ gBankTarget ] . moveturnLostHP_physical | | gSpecialStatuses [ gBankTarget ] . moveturnLostHP_special )
& & ( gBattleMoves [ move ] . flags & FLAG_MAKES_CONTACT )
& & ( Random ( ) % 3 ) = = 0 )
{
2017-10-12 17:49:24 +02:00
gBattleCommunication [ MOVE_EFFECT_BYTE ] = MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_POISON ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 15:19:15 +02:00
gBattlescriptCurrInstr = BattleScript_ApplySecondaryEffect ;
gHitMarker | = HITMARKER_IGNORE_SAFEGUARD ;
effect + + ;
}
break ;
case ABILITY_STATIC :
if ( ! ( gBattleMoveFlags & MOVESTATUS_NOEFFECT )
& & gBattleMons [ gBankAttacker ] . hp ! = 0
& & ! gProtectStructs [ gBankAttacker ] . confusionSelfDmg
& & ( gSpecialStatuses [ gBankTarget ] . moveturnLostHP_physical | | gSpecialStatuses [ gBankTarget ] . moveturnLostHP_special )
& & ( gBattleMoves [ move ] . flags & FLAG_MAKES_CONTACT )
& & ( Random ( ) % 3 ) = = 0 )
{
2017-10-12 17:49:24 +02:00
gBattleCommunication [ MOVE_EFFECT_BYTE ] = MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_PARALYSIS ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 15:19:15 +02:00
gBattlescriptCurrInstr = BattleScript_ApplySecondaryEffect ;
gHitMarker | = HITMARKER_IGNORE_SAFEGUARD ;
effect + + ;
}
break ;
case ABILITY_FLAME_BODY :
if ( ! ( gBattleMoveFlags & MOVESTATUS_NOEFFECT )
& & gBattleMons [ gBankAttacker ] . hp ! = 0
& & ! gProtectStructs [ gBankAttacker ] . confusionSelfDmg
& & ( gBattleMoves [ move ] . flags & FLAG_MAKES_CONTACT )
& & ( gSpecialStatuses [ gBankTarget ] . moveturnLostHP_physical | | gSpecialStatuses [ gBankTarget ] . moveturnLostHP_special )
& & ( Random ( ) % 3 ) = = 0 )
{
2017-10-12 17:49:24 +02:00
gBattleCommunication [ MOVE_EFFECT_BYTE ] = MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_BURN ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 15:19:15 +02:00
gBattlescriptCurrInstr = BattleScript_ApplySecondaryEffect ;
gHitMarker | = HITMARKER_IGNORE_SAFEGUARD ;
effect + + ;
}
break ;
case ABILITY_CUTE_CHARM :
if ( ! ( gBattleMoveFlags & MOVESTATUS_NOEFFECT )
& & gBattleMons [ gBankAttacker ] . hp ! = 0
& & ! gProtectStructs [ gBankAttacker ] . confusionSelfDmg
& & ( gBattleMoves [ move ] . flags & FLAG_MAKES_CONTACT )
& & ( gSpecialStatuses [ gBankTarget ] . moveturnLostHP_physical | | gSpecialStatuses [ gBankTarget ] . moveturnLostHP_special )
& & gBattleMons [ gBankTarget ] . hp ! = 0
& & ( Random ( ) % 3 ) = = 0
& & gBattleMons [ gBankAttacker ] . ability ! = ABILITY_OBLIVIOUS
& & GetGenderFromSpeciesAndPersonality ( speciesAtk , pidAtk ) ! = GetGenderFromSpeciesAndPersonality ( speciesDef , pidDef )
& & ! ( gBattleMons [ gBankAttacker ] . status2 & STATUS2_INFATUATION )
2017-10-12 17:49:24 +02:00
& & GetGenderFromSpeciesAndPersonality ( speciesAtk , pidAtk ) ! = MON_GENDERLESS
& & GetGenderFromSpeciesAndPersonality ( speciesDef , pidDef ) ! = MON_GENDERLESS )
2017-09-17 15:19:15 +02:00
{
2017-10-12 17:49:24 +02:00
gBattleMons [ gBankAttacker ] . status2 | = STATUS2_INFATUATED_WITH ( gBankTarget ) ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 15:19:15 +02:00
gBattlescriptCurrInstr = BattleScript_CuteCharmActivates ;
effect + + ;
}
break ;
}
break ;
case ABILITYEFFECT_IMMUNITY : // 5
2017-11-26 17:15:28 +01:00
for ( bank = 0 ; bank < gNoOfAllBanks ; bank + + )
2017-09-17 15:19:15 +02:00
{
2017-11-26 17:15:28 +01:00
switch ( gBattleMons [ bank ] . ability )
2017-09-17 15:19:15 +02:00
{
2017-11-26 17:15:28 +01:00
case ABILITY_IMMUNITY :
if ( gBattleMons [ bank ] . status1 & ( STATUS_POISON | STATUS_TOXIC_POISON | STATUS_TOXIC_COUNTER ) )
2017-09-17 15:19:15 +02:00
{
2017-11-26 17:15:28 +01:00
StringCopy ( gBattleTextBuff1 , gStatusConditionString_PoisonJpn ) ;
effect = 1 ;
}
break ;
case ABILITY_OWN_TEMPO :
if ( gBattleMons [ bank ] . status2 & STATUS2_CONFUSION )
{
StringCopy ( gBattleTextBuff1 , gStatusConditionString_ConfusionJpn ) ;
effect = 2 ;
}
break ;
case ABILITY_LIMBER :
if ( gBattleMons [ bank ] . status1 & STATUS_PARALYSIS )
{
StringCopy ( gBattleTextBuff1 , gStatusConditionString_ParalysisJpn ) ;
effect = 1 ;
}
break ;
case ABILITY_INSOMNIA :
case ABILITY_VITAL_SPIRIT :
if ( gBattleMons [ bank ] . status1 & STATUS_SLEEP )
{
gBattleMons [ bank ] . status2 & = ~ ( STATUS2_NIGHTMARE ) ;
StringCopy ( gBattleTextBuff1 , gStatusConditionString_SleepJpn ) ;
effect = 1 ;
}
break ;
case ABILITY_WATER_VEIL :
if ( gBattleMons [ bank ] . status1 & STATUS_BURN )
{
StringCopy ( gBattleTextBuff1 , gStatusConditionString_BurnJpn ) ;
effect = 1 ;
}
break ;
case ABILITY_MAGMA_ARMOR :
if ( gBattleMons [ bank ] . status1 & STATUS_FREEZE )
{
StringCopy ( gBattleTextBuff1 , gStatusConditionString_IceJpn ) ;
effect = 1 ;
}
break ;
case ABILITY_OBLIVIOUS :
if ( gBattleMons [ bank ] . status2 & STATUS2_INFATUATION )
{
StringCopy ( gBattleTextBuff1 , gStatusConditionString_LoveJpn ) ;
effect = 3 ;
}
break ;
}
if ( effect )
{
switch ( effect )
{
case 1 : // status cleared
gBattleMons [ bank ] . status1 = 0 ;
2017-09-17 15:19:15 +02:00
break ;
2017-11-26 17:15:28 +01:00
case 2 : // get rid of confusion
gBattleMons [ bank ] . status2 & = ~ ( STATUS2_CONFUSION ) ;
2017-09-17 15:19:15 +02:00
break ;
2017-11-26 17:15:28 +01:00
case 3 : // get rid of infatuation
gBattleMons [ bank ] . status2 & = ~ ( STATUS2_INFATUATION ) ;
2017-09-17 15:19:15 +02:00
break ;
}
2017-10-12 17:49:24 +02:00
2017-11-26 17:15:28 +01:00
BattleScriptPushCursor ( ) ;
gBattlescriptCurrInstr = BattleScript_AbilityCuredStatus ;
gBattleScripting . bank = bank ;
gActiveBank = bank ;
EmitSetMonData ( 0 , REQUEST_STATUS_BATTLE , 0 , 4 , & gBattleMons [ gActiveBank ] . status1 ) ;
MarkBufferBankForExecution ( gActiveBank ) ;
return effect ;
2017-09-17 15:19:15 +02:00
}
}
break ;
case ABILITYEFFECT_FORECAST : // 6
2017-10-12 17:49:24 +02:00
for ( bank = 0 ; bank < gNoOfAllBanks ; bank + + )
2017-09-17 15:19:15 +02:00
{
2017-10-12 17:49:24 +02:00
if ( gBattleMons [ bank ] . ability = = ABILITY_FORECAST )
2017-09-17 15:19:15 +02:00
{
2017-10-12 17:49:24 +02:00
effect = CastformDataTypeChange ( bank ) ;
if ( effect )
2017-09-17 15:19:15 +02:00
{
2017-10-12 17:49:24 +02:00
BattleScriptPushCursorAndCallback ( BattleScript_CastformChange ) ;
gBattleScripting . bank = bank ;
* ( & gBattleStruct - > formToChangeInto ) = effect - 1 ;
return effect ;
2017-09-17 15:19:15 +02:00
}
}
}
break ;
case ABILITYEFFECT_SYNCHRONIZE : // 7
if ( gLastUsedAbility = = ABILITY_SYNCHRONIZE & & ( gHitMarker & HITMARKER_SYNCHRONISE_EFFECT ) )
{
gHitMarker & = ~ ( HITMARKER_SYNCHRONISE_EFFECT ) ;
2017-10-12 17:49:24 +02:00
gBattleStruct - > synchronizeMoveEffect & = ~ ( MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN ) ;
if ( gBattleStruct - > synchronizeMoveEffect = = MOVE_EFFECT_TOXIC )
gBattleStruct - > synchronizeMoveEffect = MOVE_EFFECT_POISON ;
gBattleCommunication [ MOVE_EFFECT_BYTE ] = gBattleStruct - > synchronizeMoveEffect + MOVE_EFFECT_AFFECTS_USER ;
2017-09-17 15:19:15 +02:00
gBattleScripting . bank = gBankTarget ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 15:19:15 +02:00
gBattlescriptCurrInstr = BattleScript_SynchronizeActivates ;
gHitMarker | = HITMARKER_IGNORE_SAFEGUARD ;
effect + + ;
}
break ;
case ABILITYEFFECT_ATK_SYNCHRONIZE : // 8
if ( gLastUsedAbility = = ABILITY_SYNCHRONIZE & & ( gHitMarker & HITMARKER_SYNCHRONISE_EFFECT ) )
{
gHitMarker & = ~ ( HITMARKER_SYNCHRONISE_EFFECT ) ;
2017-10-12 17:49:24 +02:00
gBattleStruct - > synchronizeMoveEffect & = ~ ( MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN ) ;
if ( gBattleStruct - > synchronizeMoveEffect = = MOVE_EFFECT_TOXIC )
gBattleStruct - > synchronizeMoveEffect = MOVE_EFFECT_POISON ;
2017-09-17 15:19:15 +02:00
gBattleCommunication [ MOVE_EFFECT_BYTE ] = gBattleStruct - > synchronizeMoveEffect ;
gBattleScripting . bank = gBankAttacker ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 15:19:15 +02:00
gBattlescriptCurrInstr = BattleScript_SynchronizeActivates ;
gHitMarker | = HITMARKER_IGNORE_SAFEGUARD ;
effect + + ;
}
break ;
case ABILITYEFFECT_INTIMIDATE1 : // 9
for ( i = 0 ; i < gNoOfAllBanks ; i + + )
{
if ( gBattleMons [ i ] . ability = = ABILITY_INTIMIDATE & & gStatuses3 [ i ] & STATUS3_INTIMIDATE_POKES )
{
gLastUsedAbility = ABILITY_INTIMIDATE ;
gStatuses3 [ i ] & = ~ ( STATUS3_INTIMIDATE_POKES ) ;
2017-11-25 18:42:31 +01:00
BattleScriptPushCursorAndCallback ( BattleScript_82DB4B8 ) ;
2017-09-17 15:19:15 +02:00
gBattleStruct - > intimidateBank = i ;
effect + + ;
break ;
}
}
break ;
case ABILITYEFFECT_TRACE : // 11
for ( i = 0 ; i < gNoOfAllBanks ; i + + )
{
if ( gBattleMons [ i ] . ability = = ABILITY_TRACE & & ( gStatuses3 [ i ] & STATUS3_TRACE ) )
{
2017-10-12 17:49:24 +02:00
u8 target2 ;
side = ( GetBankIdentity ( i ) ^ BIT_SIDE ) & BIT_SIDE ; // side of the opposing pokemon
target1 = GetBankByIdentity ( side ) ;
target2 = GetBankByIdentity ( side + BIT_MON ) ;
2017-09-17 15:19:15 +02:00
if ( gBattleTypeFlags & BATTLE_TYPE_DOUBLE )
{
if ( gBattleMons [ target1 ] . ability ! = 0 & & gBattleMons [ target1 ] . hp ! = 0
& & gBattleMons [ target2 ] . ability ! = 0 & & gBattleMons [ target2 ] . hp ! = 0 )
{
2017-10-12 17:49:24 +02:00
gActiveBank = GetBankByIdentity ( ( ( Random ( ) & 1 ) * 2 ) | side ) ;
2017-09-17 15:19:15 +02:00
gBattleMons [ i ] . ability = gBattleMons [ gActiveBank ] . ability ;
gLastUsedAbility = gBattleMons [ gActiveBank ] . ability ;
effect + + ;
}
else if ( gBattleMons [ target1 ] . ability ! = 0 & & gBattleMons [ target1 ] . hp ! = 0 )
{
gActiveBank = target1 ;
gBattleMons [ i ] . ability = gBattleMons [ gActiveBank ] . ability ;
gLastUsedAbility = gBattleMons [ gActiveBank ] . ability ;
effect + + ;
}
else if ( gBattleMons [ target2 ] . ability ! = 0 & & gBattleMons [ target2 ] . hp ! = 0 )
{
gActiveBank = target2 ;
gBattleMons [ i ] . ability = gBattleMons [ gActiveBank ] . ability ;
gLastUsedAbility = gBattleMons [ gActiveBank ] . ability ;
effect + + ;
}
}
else
{
gActiveBank = target1 ;
if ( gBattleMons [ target1 ] . ability & & gBattleMons [ target1 ] . hp )
{
gBattleMons [ i ] . ability = gBattleMons [ target1 ] . ability ;
gLastUsedAbility = gBattleMons [ target1 ] . ability ;
effect + + ;
}
}
if ( effect )
{
2017-09-28 15:34:21 +02:00
BattleScriptPushCursorAndCallback ( BattleScript_TraceActivates ) ;
2017-09-17 15:19:15 +02:00
gStatuses3 [ i ] & = ~ ( STATUS3_TRACE ) ;
gBattleScripting . bank = i ;
2017-10-12 17:49:24 +02:00
PREPARE_MON_NICK_WITH_PREFIX_BUFFER ( gBattleTextBuff1 , gActiveBank , gBattlePartyID [ gActiveBank ] )
PREPARE_ABILITY_BUFFER ( gBattleTextBuff2 , gLastUsedAbility )
2017-09-17 15:19:15 +02:00
break ;
}
}
}
break ;
case ABILITYEFFECT_INTIMIDATE2 : // 10
for ( i = 0 ; i < gNoOfAllBanks ; i + + )
{
if ( gBattleMons [ i ] . ability = = ABILITY_INTIMIDATE & & ( gStatuses3 [ i ] & STATUS3_INTIMIDATE_POKES ) )
{
gLastUsedAbility = ABILITY_INTIMIDATE ;
gStatuses3 [ i ] & = ~ ( STATUS3_INTIMIDATE_POKES ) ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-11-25 18:42:31 +01:00
gBattlescriptCurrInstr = BattleScript_82DB4C1 ;
2017-09-17 15:19:15 +02:00
gBattleStruct - > intimidateBank = i ;
effect + + ;
break ;
}
}
break ;
case ABILITYEFFECT_CHECK_OTHER_SIDE : // 12
side = GetBankSide ( bank ) ;
for ( i = 0 ; i < gNoOfAllBanks ; i + + )
{
if ( GetBankSide ( i ) ! = side & & gBattleMons [ i ] . ability = = ability )
{
gLastUsedAbility = ability ;
effect = i + 1 ;
}
}
break ;
case ABILITYEFFECT_CHECK_BANK_SIDE : // 13
side = GetBankSide ( bank ) ;
for ( i = 0 ; i < gNoOfAllBanks ; i + + )
{
if ( GetBankSide ( i ) = = side & & gBattleMons [ i ] . ability = = ability )
{
gLastUsedAbility = ability ;
effect = i + 1 ;
}
}
break ;
case ABILITYEFFECT_FIELD_SPORT : // 14
switch ( gLastUsedAbility )
{
case 0xFD :
for ( i = 0 ; i < gNoOfAllBanks ; i + + )
{
if ( gStatuses3 [ i ] & STATUS3_MUDSPORT )
effect = i + 1 ;
}
break ;
case 0xFE :
for ( i = 0 ; i < gNoOfAllBanks ; i + + )
{
if ( gStatuses3 [ i ] & STATUS3_WATERSPORT )
effect = i + 1 ;
}
break ;
default :
for ( i = 0 ; i < gNoOfAllBanks ; i + + )
{
if ( gBattleMons [ i ] . ability = = ability )
{
gLastUsedAbility = ability ;
effect = i + 1 ;
}
}
break ;
}
break ;
case ABILITYEFFECT_CHECK_ON_FIELD : // 19
for ( i = 0 ; i < gNoOfAllBanks ; i + + )
{
if ( gBattleMons [ i ] . ability = = ability & & gBattleMons [ i ] . hp ! = 0 )
{
gLastUsedAbility = ability ;
effect = i + 1 ;
}
}
break ;
case ABILITYEFFECT_CHECK_FIELD_EXCEPT_BANK : // 15
for ( i = 0 ; i < gNoOfAllBanks ; i + + )
{
if ( gBattleMons [ i ] . ability = = ability & & i ! = bank )
{
gLastUsedAbility = ability ;
effect = i + 1 ;
}
}
break ;
2017-09-27 23:43:45 +02:00
case ABILITYEFFECT_COUNT_OTHER_SIDE : // 16
2017-09-17 15:19:15 +02:00
side = GetBankSide ( bank ) ;
for ( i = 0 ; i < gNoOfAllBanks ; i + + )
{
if ( GetBankSide ( i ) ! = side & & gBattleMons [ i ] . ability = = ability )
{
gLastUsedAbility = ability ;
effect + + ;
}
}
break ;
case ABILITYEFFECT_COUNT_BANK_SIDE : // 17
side = GetBankSide ( bank ) ;
for ( i = 0 ; i < gNoOfAllBanks ; i + + )
{
if ( GetBankSide ( i ) = = side & & gBattleMons [ i ] . ability = = ability )
{
gLastUsedAbility = ability ;
effect + + ;
}
}
break ;
case ABILITYEFFECT_COUNT_ON_FIELD : // 18
for ( i = 0 ; i < gNoOfAllBanks ; i + + )
{
if ( gBattleMons [ i ] . ability = = ability & & i ! = bank )
{
gLastUsedAbility = ability ;
effect + + ;
}
}
break ;
}
2017-10-12 17:49:24 +02:00
if ( effect & & caseID < ABILITYEFFECT_CHECK_OTHER_SIDE & & gLastUsedAbility ! = 0xFF )
2017-09-17 15:19:15 +02:00
RecordAbilityBattle ( bank , gLastUsedAbility ) ;
}
return effect ;
}
2017-09-17 17:14:32 +02:00
2017-11-26 13:26:58 +01:00
void BattleScriptExecute ( const u8 * BS_ptr )
2017-09-17 17:14:32 +02:00
{
gBattlescriptCurrInstr = BS_ptr ;
BATTLE_CALLBACKS_STACK - > function [ BATTLE_CALLBACKS_STACK - > size + + ] = gBattleMainFunc ;
2017-10-06 00:12:01 +02:00
gBattleMainFunc = RunBattleScriptCommands_PopCallbacksStack ;
gCurrentActionFuncId = 0 ;
2017-09-17 17:14:32 +02:00
}
2017-11-26 13:26:58 +01:00
void BattleScriptPushCursorAndCallback ( const u8 * BS_ptr )
2017-09-17 17:14:32 +02:00
{
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 17:14:32 +02:00
gBattlescriptCurrInstr = BS_ptr ;
BATTLE_CALLBACKS_STACK - > function [ BATTLE_CALLBACKS_STACK - > size + + ] = gBattleMainFunc ;
2017-10-06 00:12:01 +02:00
gBattleMainFunc = RunBattleScriptCommands ;
2017-09-17 17:14:32 +02:00
}
enum
{
ITEM_NO_EFFECT , // 0
ITEM_STATUS_CHANGE , // 1
ITEM_EFFECT_OTHER , // 2
ITEM_PP_CHANGE , // 3
ITEM_HP_CHANGE , // 4
ITEM_STATS_CHANGE , // 5
} ;
u8 ItemBattleEffects ( u8 caseID , u8 bank , bool8 moveTurn )
{
int i = 0 ;
u8 effect = ITEM_NO_EFFECT ;
u8 changedPP = 0 ;
u8 bankHoldEffect , atkHoldEffect , defHoldEffect ;
u8 bankQuality , atkQuality , defQuality ;
u16 atkItem , defItem ;
gLastUsedItem = gBattleMons [ bank ] . item ;
if ( gLastUsedItem = = ITEM_ENIGMA_BERRY )
{
bankHoldEffect = gEnigmaBerries [ bank ] . holdEffect ;
bankQuality = gEnigmaBerries [ bank ] . holdEffectParam ;
}
else
{
bankHoldEffect = ItemId_GetHoldEffect ( gLastUsedItem ) ;
bankQuality = ItemId_GetHoldEffectParam ( gLastUsedItem ) ;
}
atkItem = gBattleMons [ gBankAttacker ] . item ;
if ( atkItem = = ITEM_ENIGMA_BERRY )
{
atkHoldEffect = gEnigmaBerries [ gBankAttacker ] . holdEffect ;
atkQuality = gEnigmaBerries [ gBankAttacker ] . holdEffectParam ;
}
else
{
atkHoldEffect = ItemId_GetHoldEffect ( atkItem ) ;
atkQuality = ItemId_GetHoldEffectParam ( atkItem ) ;
}
// def variables are unused
defItem = gBattleMons [ gBankTarget ] . item ;
if ( defItem = = ITEM_ENIGMA_BERRY )
{
defHoldEffect = gEnigmaBerries [ gBankTarget ] . holdEffect ;
defQuality = gEnigmaBerries [ gBankTarget ] . holdEffectParam ;
}
else
{
defHoldEffect = ItemId_GetHoldEffect ( defItem ) ;
defQuality = ItemId_GetHoldEffectParam ( defItem ) ;
}
switch ( caseID )
{
2017-10-06 00:12:01 +02:00
case ITEMEFFECT_ON_SWITCH_IN :
2017-09-17 17:14:32 +02:00
switch ( bankHoldEffect )
{
case HOLD_EFFECT_DOUBLE_PRIZE :
if ( GetBankSide ( bank ) = = SIDE_PLAYER )
gBattleStruct - > moneyMultiplier = 2 ;
break ;
case HOLD_EFFECT_RESTORE_STATS :
2017-11-26 11:55:17 +01:00
for ( i = 0 ; i < BATTLE_STATS_NO ; i + + )
2017-09-17 17:14:32 +02:00
{
if ( gBattleMons [ bank ] . statStages [ i ] < 6 )
{
gBattleMons [ bank ] . statStages [ i ] = 6 ;
effect = ITEM_STATS_CHANGE ;
}
}
if ( effect )
{
gBattleScripting . bank = bank ;
gStringBank = bank ;
gActiveBank = gBankAttacker = bank ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_WhiteHerbEnd2 ) ;
2017-09-17 17:14:32 +02:00
}
break ;
}
break ;
case 1 :
if ( gBattleMons [ bank ] . hp )
{
switch ( bankHoldEffect )
{
case HOLD_EFFECT_RESTORE_HP :
if ( gBattleMons [ bank ] . hp < = gBattleMons [ bank ] . maxHP / 2 & & ! moveTurn )
{
gBattleMoveDamage = bankQuality ;
if ( gBattleMons [ bank ] . hp + bankQuality > gBattleMons [ bank ] . maxHP )
gBattleMoveDamage = gBattleMons [ bank ] . maxHP - gBattleMons [ bank ] . hp ;
gBattleMoveDamage * = - 1 ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_ItemHealHP_RemoveItem ) ;
2017-09-17 17:14:32 +02:00
effect = 4 ;
}
break ;
case HOLD_EFFECT_RESTORE_PP :
if ( ! moveTurn )
{
2017-11-26 11:55:17 +01:00
struct Pokemon * mon ;
2017-09-17 17:14:32 +02:00
u8 ppBonuses ;
u16 move ;
2017-09-18 12:51:16 +02:00
if ( GetBankSide ( bank ) = = SIDE_PLAYER )
2017-11-26 11:55:17 +01:00
mon = & gPlayerParty [ gBattlePartyID [ bank ] ] ;
2017-09-17 17:14:32 +02:00
else
2017-11-26 11:55:17 +01:00
mon = & gEnemyParty [ gBattlePartyID [ bank ] ] ;
2017-09-17 17:14:32 +02:00
for ( i = 0 ; i < 4 ; i + + )
{
2017-11-26 11:55:17 +01:00
move = GetMonData ( mon , MON_DATA_MOVE1 + i ) ;
changedPP = GetMonData ( mon , MON_DATA_PP1 + i ) ;
ppBonuses = GetMonData ( mon , MON_DATA_PP_BONUSES ) ;
2017-09-17 17:14:32 +02:00
if ( move & & changedPP = = 0 )
break ;
}
if ( i ! = 4 )
{
u8 maxPP = CalculatePPWithBonus ( move , ppBonuses , i ) ;
if ( changedPP + bankQuality > maxPP )
changedPP = maxPP ;
else
changedPP = changedPP + bankQuality ;
2017-11-26 11:55:17 +01:00
PREPARE_MOVE_BUFFER ( gBattleTextBuff1 , move ) ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryPPHealEnd2 ) ;
2017-09-26 22:39:59 +02:00
EmitSetMonData ( 0 , i + REQUEST_PPMOVE1_BATTLE , 0 , 1 , & changedPP ) ;
2017-09-17 17:14:32 +02:00
MarkBufferBankForExecution ( gActiveBank ) ;
effect = ITEM_PP_CHANGE ;
}
}
break ;
case HOLD_EFFECT_RESTORE_STATS :
2017-11-26 11:55:17 +01:00
for ( i = 0 ; i < BATTLE_STATS_NO ; i + + )
2017-09-17 17:14:32 +02:00
{
if ( gBattleMons [ bank ] . statStages [ i ] < 6 )
{
gBattleMons [ bank ] . statStages [ i ] = 6 ;
effect = ITEM_STATS_CHANGE ;
}
}
if ( effect )
{
gBattleScripting . bank = bank ;
gStringBank = bank ;
gActiveBank = gBankAttacker = bank ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_WhiteHerbEnd2 ) ;
2017-09-17 17:14:32 +02:00
}
break ;
case HOLD_EFFECT_LEFTOVERS :
if ( gBattleMons [ bank ] . hp < gBattleMons [ bank ] . maxHP & & ! moveTurn )
{
gBattleMoveDamage = gBattleMons [ bank ] . maxHP / 16 ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
if ( gBattleMons [ bank ] . hp + gBattleMoveDamage > gBattleMons [ bank ] . maxHP )
gBattleMoveDamage = gBattleMons [ bank ] . maxHP - gBattleMons [ bank ] . hp ;
gBattleMoveDamage * = - 1 ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_ItemHealHP_End2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_HP_CHANGE ;
RecordItemEffectBattle ( bank , bankHoldEffect ) ;
}
break ;
// nice copy/paste there gamefreak, making a function for confuse berries was too much eh?
case HOLD_EFFECT_CONFUSE_SPICY :
if ( gBattleMons [ bank ] . hp < = gBattleMons [ bank ] . maxHP / 2 & & ! moveTurn )
{
2017-11-27 21:24:34 +01:00
PREPARE_FLAVOR_BUFFER ( gBattleTextBuff1 , FLAVOR_SPICY ) ;
2017-11-26 11:55:17 +01:00
2017-09-17 17:14:32 +02:00
gBattleMoveDamage = gBattleMons [ bank ] . maxHP / bankQuality ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
if ( gBattleMons [ bank ] . hp + gBattleMoveDamage > gBattleMons [ bank ] . maxHP )
gBattleMoveDamage = gBattleMons [ bank ] . maxHP - gBattleMons [ bank ] . hp ;
gBattleMoveDamage * = - 1 ;
2017-11-27 20:03:41 +01:00
if ( GetFlavorRelationByPersonality ( gBattleMons [ bank ] . personality , FLAVOR_SPICY ) < 0 )
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryConfuseHealEnd2 ) ;
2017-09-17 17:14:32 +02:00
else
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_ItemHealHP_RemoveItem ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_HP_CHANGE ;
}
break ;
case HOLD_EFFECT_CONFUSE_DRY :
if ( gBattleMons [ bank ] . hp < = gBattleMons [ bank ] . maxHP / 2 & & ! moveTurn )
{
2017-11-27 21:24:34 +01:00
PREPARE_FLAVOR_BUFFER ( gBattleTextBuff1 , FLAVOR_DRY ) ;
2017-11-26 11:55:17 +01:00
2017-09-17 17:14:32 +02:00
gBattleMoveDamage = gBattleMons [ bank ] . maxHP / bankQuality ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
if ( gBattleMons [ bank ] . hp + gBattleMoveDamage > gBattleMons [ bank ] . maxHP )
gBattleMoveDamage = gBattleMons [ bank ] . maxHP - gBattleMons [ bank ] . hp ;
gBattleMoveDamage * = - 1 ;
2017-11-27 20:03:41 +01:00
if ( GetFlavorRelationByPersonality ( gBattleMons [ bank ] . personality , FLAVOR_DRY ) < 0 )
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryConfuseHealEnd2 ) ;
2017-09-17 17:14:32 +02:00
else
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_ItemHealHP_RemoveItem ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_HP_CHANGE ;
}
break ;
case HOLD_EFFECT_CONFUSE_SWEET :
if ( gBattleMons [ bank ] . hp < = gBattleMons [ bank ] . maxHP / 2 & & ! moveTurn )
{
2017-11-27 21:24:34 +01:00
PREPARE_FLAVOR_BUFFER ( gBattleTextBuff1 , FLAVOR_SWEET ) ;
2017-11-26 11:55:17 +01:00
2017-09-17 17:14:32 +02:00
gBattleMoveDamage = gBattleMons [ bank ] . maxHP / bankQuality ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
if ( gBattleMons [ bank ] . hp + gBattleMoveDamage > gBattleMons [ bank ] . maxHP )
gBattleMoveDamage = gBattleMons [ bank ] . maxHP - gBattleMons [ bank ] . hp ;
gBattleMoveDamage * = - 1 ;
2017-11-27 20:03:41 +01:00
if ( GetFlavorRelationByPersonality ( gBattleMons [ bank ] . personality , FLAVOR_SWEET ) < 0 )
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryConfuseHealEnd2 ) ;
2017-09-17 17:14:32 +02:00
else
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_ItemHealHP_RemoveItem ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_HP_CHANGE ;
}
break ;
case HOLD_EFFECT_CONFUSE_BITTER :
if ( gBattleMons [ bank ] . hp < = gBattleMons [ bank ] . maxHP / 2 & & ! moveTurn )
{
2017-11-27 21:24:34 +01:00
PREPARE_FLAVOR_BUFFER ( gBattleTextBuff1 , FLAVOR_BITTER ) ;
2017-11-26 11:55:17 +01:00
2017-09-17 17:14:32 +02:00
gBattleMoveDamage = gBattleMons [ bank ] . maxHP / bankQuality ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
if ( gBattleMons [ bank ] . hp + gBattleMoveDamage > gBattleMons [ bank ] . maxHP )
gBattleMoveDamage = gBattleMons [ bank ] . maxHP - gBattleMons [ bank ] . hp ;
gBattleMoveDamage * = - 1 ;
2017-11-27 20:03:41 +01:00
if ( GetFlavorRelationByPersonality ( gBattleMons [ bank ] . personality , FLAVOR_BITTER ) < 0 )
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryConfuseHealEnd2 ) ;
2017-09-17 17:14:32 +02:00
else
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_ItemHealHP_RemoveItem ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_HP_CHANGE ;
}
break ;
case HOLD_EFFECT_CONFUSE_SOUR :
if ( gBattleMons [ bank ] . hp < = gBattleMons [ bank ] . maxHP / 2 & & ! moveTurn )
{
2017-11-27 21:24:34 +01:00
PREPARE_FLAVOR_BUFFER ( gBattleTextBuff1 , FLAVOR_SOUR ) ;
2017-11-26 11:55:17 +01:00
2017-09-17 17:14:32 +02:00
gBattleMoveDamage = gBattleMons [ bank ] . maxHP / bankQuality ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = 1 ;
if ( gBattleMons [ bank ] . hp + gBattleMoveDamage > gBattleMons [ bank ] . maxHP )
gBattleMoveDamage = gBattleMons [ bank ] . maxHP - gBattleMons [ bank ] . hp ;
gBattleMoveDamage * = - 1 ;
2017-11-27 20:03:41 +01:00
if ( GetFlavorRelationByPersonality ( gBattleMons [ bank ] . personality , FLAVOR_SOUR ) < 0 )
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryConfuseHealEnd2 ) ;
2017-09-17 17:14:32 +02:00
else
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_ItemHealHP_RemoveItem ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_HP_CHANGE ;
}
break ;
// copy/paste again, smh
case HOLD_EFFECT_ATTACK_UP :
if ( gBattleMons [ bank ] . hp < = gBattleMons [ bank ] . maxHP / bankQuality & & ! moveTurn & & gBattleMons [ bank ] . statStages [ STAT_STAGE_ATK ] < 0xC )
{
2017-11-26 11:55:17 +01:00
PREPARE_STAT_BUFFER ( gBattleTextBuff1 , STAT_STAGE_ATK ) ;
PREPARE_STRING_BUFFER ( gBattleTextBuff2 , STRINGID_STATROSE ) ;
2017-09-17 17:14:32 +02:00
gEffectBank = bank ;
2017-11-26 11:55:17 +01:00
SET_STATCHANGER ( STAT_STAGE_ATK , 1 , FALSE ) ;
2017-09-17 17:14:32 +02:00
gBattleScripting . animArg1 = 0xE + STAT_STAGE_ATK ;
gBattleScripting . animArg2 = 0 ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryStatRaiseEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_STATS_CHANGE ;
}
break ;
case HOLD_EFFECT_DEFENSE_UP :
if ( gBattleMons [ bank ] . hp < = gBattleMons [ bank ] . maxHP / bankQuality & & ! moveTurn & & gBattleMons [ bank ] . statStages [ STAT_STAGE_DEF ] < 0xC )
{
2017-11-26 11:55:17 +01:00
PREPARE_STAT_BUFFER ( gBattleTextBuff1 , STAT_STAGE_DEF ) ;
2017-09-17 17:14:32 +02:00
gEffectBank = bank ;
2017-11-26 11:55:17 +01:00
SET_STATCHANGER ( STAT_STAGE_DEF , 1 , FALSE ) ;
2017-09-17 17:14:32 +02:00
gBattleScripting . animArg1 = 0xE + STAT_STAGE_DEF ;
gBattleScripting . animArg2 = 0 ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryStatRaiseEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_STATS_CHANGE ;
}
break ;
case HOLD_EFFECT_SPEED_UP :
if ( gBattleMons [ bank ] . hp < = gBattleMons [ bank ] . maxHP / bankQuality & & ! moveTurn & & gBattleMons [ bank ] . statStages [ STAT_STAGE_SPEED ] < 0xC )
{
2017-11-26 11:55:17 +01:00
PREPARE_STAT_BUFFER ( gBattleTextBuff1 , STAT_STAGE_SPEED ) ;
2017-09-17 17:14:32 +02:00
gEffectBank = bank ;
2017-11-26 11:55:17 +01:00
SET_STATCHANGER ( STAT_STAGE_SPEED , 1 , FALSE ) ;
2017-09-17 17:14:32 +02:00
gBattleScripting . animArg1 = 0xE + STAT_STAGE_SPEED ;
gBattleScripting . animArg2 = 0 ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryStatRaiseEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_STATS_CHANGE ;
}
break ;
case HOLD_EFFECT_SP_ATTACK_UP :
if ( gBattleMons [ bank ] . hp < = gBattleMons [ bank ] . maxHP / bankQuality & & ! moveTurn & & gBattleMons [ bank ] . statStages [ STAT_STAGE_SPATK ] < 0xC )
{
2017-11-26 11:55:17 +01:00
PREPARE_STAT_BUFFER ( gBattleTextBuff1 , STAT_STAGE_SPATK ) ;
2017-09-17 17:14:32 +02:00
gEffectBank = bank ;
2017-11-26 11:55:17 +01:00
SET_STATCHANGER ( STAT_STAGE_SPATK , 1 , FALSE ) ;
2017-09-17 17:14:32 +02:00
gBattleScripting . animArg1 = 0xE + STAT_STAGE_SPATK ;
gBattleScripting . animArg2 = 0 ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryStatRaiseEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_STATS_CHANGE ;
}
break ;
case HOLD_EFFECT_SP_DEFENSE_UP :
if ( gBattleMons [ bank ] . hp < = gBattleMons [ bank ] . maxHP / bankQuality & & ! moveTurn & & gBattleMons [ bank ] . statStages [ STAT_STAGE_SPDEF ] < 0xC )
{
2017-11-26 11:55:17 +01:00
PREPARE_STAT_BUFFER ( gBattleTextBuff1 , STAT_STAGE_SPDEF ) ;
2017-09-17 17:14:32 +02:00
gEffectBank = bank ;
2017-11-26 11:55:17 +01:00
SET_STATCHANGER ( STAT_STAGE_SPDEF , 1 , FALSE ) ;
2017-09-17 17:14:32 +02:00
gBattleScripting . animArg1 = 0xE + STAT_STAGE_SPDEF ;
gBattleScripting . animArg2 = 0 ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryStatRaiseEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_STATS_CHANGE ;
}
break ;
case HOLD_EFFECT_CRITICAL_UP :
if ( gBattleMons [ bank ] . hp < = gBattleMons [ bank ] . maxHP / bankQuality & & ! moveTurn & & ! ( gBattleMons [ bank ] . status2 & STATUS2_FOCUS_ENERGY ) )
{
gBattleMons [ bank ] . status2 | = STATUS2_FOCUS_ENERGY ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryFocusEnergyEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_EFFECT_OTHER ;
}
break ;
case HOLD_EFFECT_RANDOM_STAT_UP :
if ( ! moveTurn & & gBattleMons [ bank ] . hp < = gBattleMons [ bank ] . maxHP / bankQuality )
{
for ( i = 0 ; i < 5 ; i + + )
{
if ( gBattleMons [ bank ] . statStages [ STAT_STAGE_ATK + i ] < 0xC )
break ;
}
if ( i ! = 5 )
{
do
{
i = Random ( ) % 5 ;
} while ( gBattleMons [ bank ] . statStages [ STAT_STAGE_ATK + i ] = = 0xC ) ;
2017-11-26 11:55:17 +01:00
PREPARE_STAT_BUFFER ( gBattleTextBuff1 , i + 1 ) ;
gBattleTextBuff2 [ 0 ] = B_BUFF_PLACEHOLDER_BEGIN ;
gBattleTextBuff2 [ 1 ] = B_BUFF_STRING ;
gBattleTextBuff2 [ 2 ] = STRINGID_STATSHARPLY ;
gBattleTextBuff2 [ 3 ] = STRINGID_STATSHARPLY > > 8 ;
gBattleTextBuff2 [ 4 ] = B_BUFF_STRING ;
gBattleTextBuff2 [ 5 ] = STRINGID_STATROSE ;
gBattleTextBuff2 [ 6 ] = STRINGID_STATROSE > > 8 ;
2017-09-17 17:14:32 +02:00
gBattleTextBuff2 [ 7 ] = EOS ;
gEffectBank = bank ;
2017-11-26 11:55:17 +01:00
SET_STATCHANGER ( i + 1 , 2 , FALSE ) ;
2017-09-17 17:14:32 +02:00
gBattleScripting . animArg1 = 0x21 + i + 6 ;
gBattleScripting . animArg2 = 0 ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryStatRaiseEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_STATS_CHANGE ;
}
}
break ;
case HOLD_EFFECT_CURE_PAR :
if ( gBattleMons [ bank ] . status1 & STATUS_PARALYSIS )
{
gBattleMons [ bank ] . status1 & = ~ ( STATUS_PARALYSIS ) ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryCurePrlzEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_STATUS_CHANGE ;
}
break ;
case HOLD_EFFECT_CURE_PSN :
if ( gBattleMons [ bank ] . status1 & STATUS_PSN_ANY )
{
gBattleMons [ bank ] . status1 & = ~ ( STATUS_PSN_ANY | STATUS_TOXIC_COUNTER ) ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryCurePsnEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_STATUS_CHANGE ;
}
break ;
case HOLD_EFFECT_CURE_BRN :
if ( gBattleMons [ bank ] . status1 & STATUS_BURN )
{
gBattleMons [ bank ] . status1 & = ~ ( STATUS_BURN ) ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryCureBrnEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_STATUS_CHANGE ;
}
break ;
case HOLD_EFFECT_CURE_FRZ :
if ( gBattleMons [ bank ] . status1 & STATUS_FREEZE )
{
gBattleMons [ bank ] . status1 & = ~ ( STATUS_FREEZE ) ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryCureFrzEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_STATUS_CHANGE ;
}
break ;
case HOLD_EFFECT_CURE_SLP :
if ( gBattleMons [ bank ] . status1 & STATUS_SLEEP )
{
gBattleMons [ bank ] . status1 & = ~ ( STATUS_SLEEP ) ;
gBattleMons [ bank ] . status2 & = ~ ( STATUS2_NIGHTMARE ) ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryCureSlpEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_STATUS_CHANGE ;
}
break ;
case HOLD_EFFECT_CURE_CONFUSION :
if ( gBattleMons [ bank ] . status2 & STATUS2_CONFUSION )
{
gBattleMons [ bank ] . status2 & = ~ ( STATUS2_CONFUSION ) ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryCureConfusionEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_EFFECT_OTHER ;
}
break ;
case HOLD_EFFECT_CURE_STATUS :
if ( gBattleMons [ bank ] . status1 & STATUS_ANY | | gBattleMons [ bank ] . status2 & STATUS2_CONFUSION )
{
i = 0 ;
if ( gBattleMons [ bank ] . status1 & STATUS_PSN_ANY )
{
StringCopy ( gBattleTextBuff1 , gStatusConditionString_PoisonJpn ) ;
i + + ;
}
if ( gBattleMons [ bank ] . status1 & STATUS_SLEEP )
{
gBattleMons [ bank ] . status2 & = ~ ( STATUS2_NIGHTMARE ) ;
StringCopy ( gBattleTextBuff1 , gStatusConditionString_SleepJpn ) ;
i + + ;
}
if ( gBattleMons [ bank ] . status1 & STATUS_PARALYSIS )
{
StringCopy ( gBattleTextBuff1 , gStatusConditionString_ParalysisJpn ) ;
i + + ;
}
if ( gBattleMons [ bank ] . status1 & STATUS_BURN )
{
StringCopy ( gBattleTextBuff1 , gStatusConditionString_BurnJpn ) ;
i + + ;
}
if ( gBattleMons [ bank ] . status1 & STATUS_FREEZE )
{
StringCopy ( gBattleTextBuff1 , gStatusConditionString_IceJpn ) ;
i + + ;
}
if ( gBattleMons [ bank ] . status2 & STATUS2_CONFUSION )
{
StringCopy ( gBattleTextBuff1 , gStatusConditionString_ConfusionJpn ) ;
i + + ;
}
if ( ! ( i > 1 ) )
gBattleCommunication [ MULTISTRING_CHOOSER ] = 0 ;
else
gBattleCommunication [ MULTISTRING_CHOOSER ] = 1 ;
gBattleMons [ bank ] . status1 = 0 ;
gBattleMons [ bank ] . status2 & = ~ ( STATUS2_CONFUSION ) ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryCureChosenStatusEnd2 ) ;
2017-09-17 17:14:32 +02:00
effect = ITEM_STATUS_CHANGE ;
}
break ;
case HOLD_EFFECT_CURE_ATTRACT :
if ( gBattleMons [ bank ] . status2 & STATUS2_INFATUATION )
{
gBattleMons [ bank ] . status2 & = ~ ( STATUS2_INFATUATION ) ;
StringCopy ( gBattleTextBuff1 , gStatusConditionString_LoveJpn ) ;
2017-09-28 15:34:21 +02:00
BattleScriptExecute ( BattleScript_BerryCureChosenStatusEnd2 ) ;
2017-09-17 17:14:32 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = 0 ;
effect = ITEM_EFFECT_OTHER ;
}
break ;
}
if ( effect )
{
gBattleScripting . bank = bank ;
gStringBank = bank ;
gActiveBank = gBankAttacker = bank ;
switch ( effect )
{
case ITEM_STATUS_CHANGE :
2017-09-26 22:39:59 +02:00
EmitSetMonData ( 0 , REQUEST_STATUS_BATTLE , 0 , 4 , & gBattleMons [ bank ] . status1 ) ;
2017-09-17 17:14:32 +02:00
MarkBufferBankForExecution ( gActiveBank ) ;
break ;
case ITEM_PP_CHANGE :
if ( ! ( gBattleMons [ bank ] . status2 & STATUS2_TRANSFORMED ) & & ! ( gDisableStructs [ bank ] . unk18_b & gBitTable [ i ] ) )
gBattleMons [ bank ] . pp [ i ] = changedPP ;
break ;
}
}
}
break ;
case 2 :
break ;
case 3 :
for ( bank = 0 ; bank < gNoOfAllBanks ; bank + + )
{
gLastUsedItem = gBattleMons [ bank ] . item ;
if ( gBattleMons [ bank ] . item = = ITEM_ENIGMA_BERRY )
{
bankHoldEffect = gEnigmaBerries [ bank ] . holdEffect ;
bankQuality = gEnigmaBerries [ bank ] . holdEffectParam ;
}
else
{
bankHoldEffect = ItemId_GetHoldEffect ( gLastUsedItem ) ;
bankQuality = ItemId_GetHoldEffectParam ( gLastUsedItem ) ;
}
switch ( bankHoldEffect )
{
case HOLD_EFFECT_CURE_PAR :
if ( gBattleMons [ bank ] . status1 & STATUS_PARALYSIS )
{
gBattleMons [ bank ] . status1 & = ~ ( STATUS_PARALYSIS ) ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 17:14:32 +02:00
gBattlescriptCurrInstr = BattleScript_BerryCureParRet ;
effect = ITEM_STATUS_CHANGE ;
}
break ;
case HOLD_EFFECT_CURE_PSN :
if ( gBattleMons [ bank ] . status1 & STATUS_PSN_ANY )
{
gBattleMons [ bank ] . status1 & = ~ ( STATUS_PSN_ANY | STATUS_TOXIC_COUNTER ) ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 17:14:32 +02:00
gBattlescriptCurrInstr = BattleScript_BerryCurePsnRet ;
effect = ITEM_STATUS_CHANGE ;
}
break ;
case HOLD_EFFECT_CURE_BRN :
if ( gBattleMons [ bank ] . status1 & STATUS_BURN )
{
gBattleMons [ bank ] . status1 & = ~ ( STATUS_BURN ) ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 17:14:32 +02:00
gBattlescriptCurrInstr = BattleScript_BerryCureBrnRet ;
effect = ITEM_STATUS_CHANGE ;
}
break ;
case HOLD_EFFECT_CURE_FRZ :
if ( gBattleMons [ bank ] . status1 & STATUS_FREEZE )
{
gBattleMons [ bank ] . status1 & = ~ ( STATUS_FREEZE ) ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 17:14:32 +02:00
gBattlescriptCurrInstr = BattleScript_BerryCureFrzRet ;
effect = ITEM_STATUS_CHANGE ;
}
break ;
case HOLD_EFFECT_CURE_SLP :
if ( gBattleMons [ bank ] . status1 & STATUS_SLEEP )
{
gBattleMons [ bank ] . status1 & = ~ ( STATUS_SLEEP ) ;
gBattleMons [ bank ] . status2 & = ~ ( STATUS2_NIGHTMARE ) ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 17:14:32 +02:00
gBattlescriptCurrInstr = BattleScript_BerryCureSlpRet ;
effect = ITEM_STATUS_CHANGE ;
}
break ;
case HOLD_EFFECT_CURE_CONFUSION :
if ( gBattleMons [ bank ] . status2 & STATUS2_CONFUSION )
{
gBattleMons [ bank ] . status2 & = ~ ( STATUS2_CONFUSION ) ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 17:14:32 +02:00
gBattlescriptCurrInstr = BattleScript_BerryCureConfusionRet ;
effect = ITEM_EFFECT_OTHER ;
}
break ;
case HOLD_EFFECT_CURE_ATTRACT :
if ( gBattleMons [ bank ] . status2 & STATUS2_INFATUATION )
{
gBattleMons [ bank ] . status2 & = ~ ( STATUS2_INFATUATION ) ;
StringCopy ( gBattleTextBuff1 , gStatusConditionString_LoveJpn ) ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 17:14:32 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = 0 ;
gBattlescriptCurrInstr = BattleScript_BerryCureChosenStatusRet ;
effect = ITEM_EFFECT_OTHER ;
}
break ;
case HOLD_EFFECT_CURE_STATUS :
if ( gBattleMons [ bank ] . status1 & STATUS_ANY | | gBattleMons [ bank ] . status2 & STATUS2_CONFUSION )
{
if ( gBattleMons [ bank ] . status1 & STATUS_PSN_ANY )
{
StringCopy ( gBattleTextBuff1 , gStatusConditionString_PoisonJpn ) ;
}
if ( gBattleMons [ bank ] . status1 & STATUS_SLEEP )
{
gBattleMons [ bank ] . status2 & = ~ ( STATUS2_NIGHTMARE ) ;
StringCopy ( gBattleTextBuff1 , gStatusConditionString_SleepJpn ) ;
}
if ( gBattleMons [ bank ] . status1 & STATUS_PARALYSIS )
{
StringCopy ( gBattleTextBuff1 , gStatusConditionString_ParalysisJpn ) ;
}
if ( gBattleMons [ bank ] . status1 & STATUS_BURN )
{
StringCopy ( gBattleTextBuff1 , gStatusConditionString_BurnJpn ) ;
}
if ( gBattleMons [ bank ] . status1 & STATUS_FREEZE )
{
StringCopy ( gBattleTextBuff1 , gStatusConditionString_IceJpn ) ;
}
if ( gBattleMons [ bank ] . status2 & STATUS2_CONFUSION )
{
StringCopy ( gBattleTextBuff1 , gStatusConditionString_ConfusionJpn ) ;
}
gBattleMons [ bank ] . status1 = 0 ;
gBattleMons [ bank ] . status2 & = ~ ( STATUS2_CONFUSION ) ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 17:14:32 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = 0 ;
gBattlescriptCurrInstr = BattleScript_BerryCureChosenStatusRet ;
effect = ITEM_STATUS_CHANGE ;
}
break ;
case HOLD_EFFECT_RESTORE_STATS :
2017-11-26 11:55:17 +01:00
for ( i = 0 ; i < BATTLE_STATS_NO ; i + + )
2017-09-17 17:14:32 +02:00
{
if ( gBattleMons [ bank ] . statStages [ i ] < 6 )
{
gBattleMons [ bank ] . statStages [ i ] = 6 ;
effect = ITEM_STATS_CHANGE ;
}
}
if ( effect )
{
gBattleScripting . bank = bank ;
gStringBank = bank ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 17:14:32 +02:00
gBattlescriptCurrInstr = BattleScript_WhiteHerbRet ;
return effect ; // unnecessary return
}
break ;
}
if ( effect )
{
gBattleScripting . bank = bank ;
gStringBank = bank ;
gActiveBank = bank ;
2017-09-26 22:39:59 +02:00
EmitSetMonData ( 0 , REQUEST_STATUS_BATTLE , 0 , 4 , & gBattleMons [ gActiveBank ] . status1 ) ;
2017-09-17 17:14:32 +02:00
MarkBufferBankForExecution ( gActiveBank ) ;
break ;
}
}
break ;
case 4 :
if ( gBattleMoveDamage )
{
switch ( atkHoldEffect )
{
case HOLD_EFFECT_FLINCH :
if ( ! ( gBattleMoveFlags & MOVESTATUS_NOEFFECT )
& & ( gSpecialStatuses [ gBankTarget ] . moveturnLostHP_physical | | gSpecialStatuses [ gBankTarget ] . moveturnLostHP_special )
& & ( Random ( ) % 100 ) < atkQuality
& & gBattleMoves [ gCurrentMove ] . flags & FLAG_KINGSROCK_AFFECTED
& & gBattleMons [ gBankTarget ] . hp )
{
2017-12-02 14:08:55 +01:00
gBattleCommunication [ MOVE_EFFECT_BYTE ] = MOVE_EFFECT_FLINCH ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 17:14:32 +02:00
SetMoveEffect ( 0 , 0 ) ;
2017-09-22 21:33:49 +02:00
BattleScriptPop ( ) ;
2017-09-17 17:14:32 +02:00
}
break ;
case HOLD_EFFECT_SHELL_BELL :
if ( ! ( gBattleMoveFlags & MOVESTATUS_NOEFFECT )
& & gSpecialStatuses [ gBankTarget ] . moveturnLostHP ! = 0
& & gSpecialStatuses [ gBankTarget ] . moveturnLostHP ! = 0xFFFF
& & gBankAttacker ! = gBankTarget
& & gBattleMons [ gBankAttacker ] . hp ! = gBattleMons [ gBankAttacker ] . maxHP
& & gBattleMons [ gBankAttacker ] . hp ! = 0 )
{
gLastUsedItem = atkItem ;
gStringBank = gBankAttacker ;
gBattleScripting . bank = gBankAttacker ;
gBattleMoveDamage = ( gSpecialStatuses [ gBankTarget ] . moveturnLostHP / atkQuality ) * - 1 ;
if ( gBattleMoveDamage = = 0 )
gBattleMoveDamage = - 1 ;
gSpecialStatuses [ gBankTarget ] . moveturnLostHP = 0 ;
2017-09-22 21:33:49 +02:00
BattleScriptPushCursor ( ) ;
2017-09-17 17:14:32 +02:00
gBattlescriptCurrInstr = BattleScript_ItemHealHP_Ret ;
effect + + ;
}
break ;
}
}
break ;
}
return effect ;
}
2017-10-06 00:12:01 +02:00
void ClearFuryCutterDestinyBondGrudge ( u8 bank )
2017-09-17 17:14:32 +02:00
{
gDisableStructs [ bank ] . furyCutterCounter = 0 ;
gBattleMons [ bank ] . status2 & = ~ ( STATUS2_DESTINY_BOND ) ;
gStatuses3 [ bank ] & = ~ ( STATUS3_GRUDGE ) ;
}
2017-10-06 17:06:45 +02:00
void HandleAction_RunBattleScript ( void ) // identical to RunBattleScriptCommands
2017-09-17 17:14:32 +02:00
{
if ( gBattleExecBuffer = = 0 )
gBattleScriptingCommandsTable [ * gBattlescriptCurrInstr ] ( ) ;
}
u8 GetMoveTarget ( u16 move , u8 useMoveTarget )
{
u8 targetBank = 0 ;
u8 moveTarget ;
u8 side ;
if ( useMoveTarget )
moveTarget = useMoveTarget - 1 ;
else
moveTarget = gBattleMoves [ move ] . target ;
switch ( moveTarget )
{
2017-09-19 21:01:12 +02:00
case MOVE_TARGET_SELECTED :
2017-11-26 13:26:58 +01:00
side = GetBankSide ( gBankAttacker ) ^ BIT_SIDE ;
2017-09-17 17:14:32 +02:00
if ( gSideTimers [ side ] . followmeTimer & & gBattleMons [ gSideTimers [ side ] . followmeTarget ] . hp )
targetBank = gSideTimers [ side ] . followmeTarget ;
else
{
side = GetBankSide ( gBankAttacker ) ;
do
{
targetBank = Random ( ) % gNoOfAllBanks ;
} while ( targetBank = = gBankAttacker | | side = = GetBankSide ( targetBank ) | | gAbsentBankFlags & gBitTable [ targetBank ] ) ;
if ( gBattleMoves [ move ] . type = = TYPE_ELECTRIC
2017-09-27 23:43:45 +02:00
& & AbilityBattleEffects ( ABILITYEFFECT_COUNT_OTHER_SIDE , gBankAttacker , ABILITY_LIGHTNING_ROD , 0 , 0 )
2017-09-17 17:14:32 +02:00
& & gBattleMons [ targetBank ] . ability ! = ABILITY_LIGHTNING_ROD )
{
2017-11-26 13:26:58 +01:00
targetBank ^ = BIT_MON ;
2017-09-17 17:14:32 +02:00
RecordAbilityBattle ( targetBank , gBattleMons [ targetBank ] . ability ) ;
gSpecialStatuses [ targetBank ] . lightningRodRedirected = 1 ;
}
}
break ;
2017-09-19 21:01:12 +02:00
case MOVE_TARGET_DEPENDS :
case MOVE_TARGET_BOTH :
case MOVE_TARGET_FOES_AND_ALLY :
case MOVE_TARGET_OPPONENTS_FIELD :
2017-11-26 13:26:58 +01:00
targetBank = GetBankByIdentity ( ( GetBankIdentity ( gBankAttacker ) & BIT_SIDE ) ^ BIT_SIDE ) ;
2017-09-17 17:14:32 +02:00
if ( gAbsentBankFlags & gBitTable [ targetBank ] )
2017-11-26 13:26:58 +01:00
targetBank ^ = BIT_MON ;
2017-09-17 17:14:32 +02:00
break ;
2017-09-19 21:01:12 +02:00
case MOVE_TARGET_RANDOM :
2017-11-26 13:26:58 +01:00
side = GetBankSide ( gBankAttacker ) ^ BIT_SIDE ;
2017-09-17 17:14:32 +02:00
if ( gSideTimers [ side ] . followmeTimer & & gBattleMons [ gSideTimers [ side ] . followmeTarget ] . hp )
targetBank = gSideTimers [ side ] . followmeTarget ;
2017-09-19 21:01:12 +02:00
else if ( gBattleTypeFlags & BATTLE_TYPE_DOUBLE & & moveTarget & MOVE_TARGET_RANDOM )
2017-09-17 17:14:32 +02:00
{
2017-09-18 12:51:16 +02:00
if ( GetBankSide ( gBankAttacker ) = = SIDE_PLAYER )
2017-09-17 17:14:32 +02:00
{
if ( Random ( ) & 1 )
2017-11-26 13:26:58 +01:00
targetBank = GetBankByIdentity ( IDENTITY_OPPONENT_MON1 ) ;
2017-09-17 17:14:32 +02:00
else
2017-11-26 13:26:58 +01:00
targetBank = GetBankByIdentity ( IDENTITY_OPPONENT_MON2 ) ;
2017-09-17 17:14:32 +02:00
}
else
{
if ( Random ( ) & 1 )
2017-11-26 13:26:58 +01:00
targetBank = GetBankByIdentity ( IDENTITY_PLAYER_MON1 ) ;
2017-09-17 17:14:32 +02:00
else
2017-11-26 13:26:58 +01:00
targetBank = GetBankByIdentity ( IDENTITY_PLAYER_MON2 ) ;
2017-09-17 17:14:32 +02:00
}
if ( gAbsentBankFlags & gBitTable [ targetBank ] )
2017-11-26 13:26:58 +01:00
targetBank ^ = BIT_MON ;
2017-09-17 17:14:32 +02:00
}
else
2017-11-26 13:26:58 +01:00
targetBank = GetBankByIdentity ( ( GetBankIdentity ( gBankAttacker ) & BIT_SIDE ) ^ BIT_SIDE ) ;
2017-09-17 17:14:32 +02:00
break ;
2017-09-19 21:01:12 +02:00
case MOVE_TARGET_USER :
case MOVE_TARGET_x10 :
2017-09-17 17:14:32 +02:00
targetBank = gBankAttacker ;
break ;
}
2017-11-26 13:26:58 +01:00
* ( gBattleStruct - > moveTarget + gBankAttacker ) = targetBank ;
2017-09-17 17:14:32 +02:00
return targetBank ;
}
static bool32 HasObedientBitSet ( u8 bank )
{
if ( GetBankSide ( bank ) = = SIDE_OPPONENT )
return TRUE ;
if ( GetMonData ( & gPlayerParty [ gBattlePartyID [ bank ] ] , MON_DATA_SPECIES , NULL ) ! = SPECIES_DEOXYS
& & GetMonData ( & gPlayerParty [ gBattlePartyID [ bank ] ] , MON_DATA_SPECIES , NULL ) ! = SPECIES_MEW )
return TRUE ;
return GetMonData ( & gPlayerParty [ gBattlePartyID [ bank ] ] , MON_DATA_OBEDIENCE , NULL ) ;
}
2017-12-02 14:08:55 +01:00
u8 IsMonDisobedient ( void )
2017-09-17 17:14:32 +02:00
{
s32 rnd ;
s32 calc ;
u8 obedienceLevel = 0 ;
if ( gBattleTypeFlags & ( BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000 ) )
return 0 ;
if ( GetBankSide ( gBankAttacker ) = = SIDE_OPPONENT )
return 0 ;
if ( HasObedientBitSet ( gBankAttacker ) ) // only if species is Mew or Deoxys
{
if ( gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER & & GetBankIdentity ( gBankAttacker ) = = 2 )
return 0 ;
if ( gBattleTypeFlags & BATTLE_TYPE_FRONTIER )
return 0 ;
if ( gBattleTypeFlags & BATTLE_TYPE_RECORDED )
return 0 ;
if ( ! IsOtherTrainer ( gBattleMons [ gBankAttacker ] . otId , gBattleMons [ gBankAttacker ] . otName ) )
return 0 ;
2017-11-08 22:20:10 +01:00
if ( FlagGet ( FLAG_BADGE08_GET ) )
2017-09-17 17:14:32 +02:00
return 0 ;
obedienceLevel = 10 ;
2017-11-08 22:20:10 +01:00
if ( FlagGet ( FLAG_BADGE02_GET ) )
2017-09-17 17:14:32 +02:00
obedienceLevel = 30 ;
2017-11-08 22:20:10 +01:00
if ( FlagGet ( FLAG_BADGE04_GET ) )
2017-09-17 17:14:32 +02:00
obedienceLevel = 50 ;
2017-11-08 22:20:10 +01:00
if ( FlagGet ( FLAG_BADGE06_GET ) )
2017-09-17 17:14:32 +02:00
obedienceLevel = 70 ;
}
if ( gBattleMons [ gBankAttacker ] . level < = obedienceLevel )
return 0 ;
rnd = ( Random ( ) & 255 ) ;
calc = ( gBattleMons [ gBankAttacker ] . level + obedienceLevel ) * rnd > > 8 ;
if ( calc < obedienceLevel )
return 0 ;
// is not obedient
if ( gCurrentMove = = MOVE_RAGE )
gBattleMons [ gBankAttacker ] . status2 & = ~ ( STATUS2_RAGE ) ;
if ( gBattleMons [ gBankAttacker ] . status1 & STATUS_SLEEP & & ( gCurrentMove = = MOVE_SNORE | | gCurrentMove = = MOVE_SLEEP_TALK ) )
{
2017-11-25 18:42:31 +01:00
gBattlescriptCurrInstr = BattleScript_82DB695 ;
2017-09-17 17:14:32 +02:00
return 1 ;
}
rnd = ( Random ( ) & 255 ) ;
calc = ( gBattleMons [ gBankAttacker ] . level + obedienceLevel ) * rnd > > 8 ;
if ( calc < obedienceLevel )
{
calc = CheckMoveLimitations ( gBankAttacker , gBitTable [ gCurrMovePos ] , 0xFF ) ;
if ( calc = = 0xF ) // all moves cannot be used
{
gBattleCommunication [ MULTISTRING_CHOOSER ] = Random ( ) & 3 ;
gBattlescriptCurrInstr = BattleScript_MoveUsedLoafingAround ;
return 1 ;
}
else // use a random move
{
do
{
gCurrMovePos = gUnknown_020241E9 = Random ( ) & 3 ;
} while ( gBitTable [ gCurrMovePos ] & calc ) ;
gRandomMove = gBattleMons [ gBankAttacker ] . moves [ gCurrMovePos ] ;
2017-11-26 17:15:28 +01:00
gBattlescriptCurrInstr = BattleScript_IgnoresAndUsesRandomMove ;
2017-09-17 17:14:32 +02:00
gBankTarget = GetMoveTarget ( gRandomMove , 0 ) ;
gHitMarker | = HITMARKER_x200000 ;
return 2 ;
}
}
else
{
obedienceLevel = gBattleMons [ gBankAttacker ] . level - obedienceLevel ;
calc = ( Random ( ) & 255 ) ;
if ( calc < obedienceLevel & & ! ( gBattleMons [ gBankAttacker ] . status1 & STATUS_ANY ) & & gBattleMons [ gBankAttacker ] . ability ! = ABILITY_VITAL_SPIRIT & & gBattleMons [ gBankAttacker ] . ability ! = ABILITY_INSOMNIA )
{
// try putting asleep
int i ;
for ( i = 0 ; i < gNoOfAllBanks ; i + + )
{
if ( gBattleMons [ i ] . status2 & STATUS2_UPROAR )
break ;
}
if ( i = = gNoOfAllBanks )
{
2017-11-26 17:15:28 +01:00
gBattlescriptCurrInstr = BattleScript_IgnoresAndFallsAsleep ;
2017-09-17 17:14:32 +02:00
return 1 ;
}
}
calc - = obedienceLevel ;
if ( calc < obedienceLevel )
{
gBattleMoveDamage = CalculateBaseDamage ( & gBattleMons [ gBankAttacker ] , & gBattleMons [ gBankAttacker ] , MOVE_POUND , 0 , 40 , 0 , gBankAttacker , gBankAttacker ) ;
gBankTarget = gBankAttacker ;
2017-11-25 18:42:31 +01:00
gBattlescriptCurrInstr = BattleScript_82DB6F0 ;
2017-09-17 17:14:32 +02:00
gHitMarker | = HITMARKER_UNABLE_TO_USE_MOVE ;
return 2 ;
}
else
{
gBattleCommunication [ MULTISTRING_CHOOSER ] = Random ( ) & 3 ;
gBattlescriptCurrInstr = BattleScript_MoveUsedLoafingAround ;
return 1 ;
}
}
}