mirror of
https://github.com/Ninjdai1/pokeemerald.git
synced 2024-12-27 20:24:18 +01:00
merge with be
This commit is contained in:
commit
faa963fd04
@ -1776,6 +1776,26 @@
|
||||
.macro pickpocketsteal
|
||||
various 0, VARIOUS_PICKPOCKET
|
||||
.endm
|
||||
|
||||
.macro doterrainseed battler:req, ptr:req
|
||||
various \battler, VARIOUS_TERRAIN_SEED
|
||||
.4byte \ptr
|
||||
.endm
|
||||
|
||||
.macro makeinvisible battler:req
|
||||
various \battler, VARIOUS_MAKE_INVISIBLE
|
||||
.endm
|
||||
|
||||
.macro tryroomservice battler:req, ptr:req
|
||||
various \battler, VARIOUS_ROOM_SERVICE
|
||||
.4byte \ptr
|
||||
.endm
|
||||
|
||||
.macro jumpifterrainaffected battler:req, terrainFlags:req, ptr:req
|
||||
various \battler, VARIOUS_JUMP_IF_TERRAIN_AFFECTED
|
||||
.4byte \terrainFlags
|
||||
.4byte \ptr
|
||||
.endm
|
||||
|
||||
@ helpful macros
|
||||
.macro setstatchanger stat:req, stages:req, down:req
|
||||
|
@ -1530,6 +1530,7 @@ BattleScript_EffectPsychicTerrain:
|
||||
printfromtable gTerrainStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
playanimation BS_SCRIPTING, B_ANIM_RESTORE_BG, NULL
|
||||
call BattleScript_TerrainSeedLoop
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_EffectTopsyTurvy:
|
||||
@ -1852,6 +1853,26 @@ BattleScript_EffectMagnetRise:
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_EffectTrickRoom:
|
||||
attackcanceler
|
||||
attackstring
|
||||
ppreduce
|
||||
setroom
|
||||
attackanimation
|
||||
waitanimation
|
||||
printfromtable gRoomsStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
savetarget
|
||||
setbyte gBattlerTarget, 0
|
||||
BattleScript_RoomServiceLoop:
|
||||
copybyte sBATTLER, gBattlerTarget
|
||||
tryroomservice BS_TARGET, BattleScript_RoomServiceLoop_NextBattler
|
||||
removeitem BS_TARGET
|
||||
BattleScript_RoomServiceLoop_NextBattler:
|
||||
addbyte gBattlerTarget, 0x1
|
||||
jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_RoomServiceLoop
|
||||
restoretarget
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_EffectWonderRoom:
|
||||
BattleScript_EffectMagicRoom:
|
||||
attackcanceler
|
||||
@ -2102,6 +2123,8 @@ BattleScript_EffectSleep::
|
||||
jumpifleafguard BattleScript_LeafGuardProtects
|
||||
jumpifshieldsdown BS_TARGET, BattleScript_LeafGuardProtects
|
||||
jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_ButItFailed
|
||||
jumpifterrainaffected BS_TARGET, STATUS_FIELD_ELECTRIC_TERRAIN, BattleScript_ElectricTerrainPrevents
|
||||
jumpifterrainaffected BS_TARGET, STATUS_FIELD_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents
|
||||
accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE
|
||||
jumpifsafeguard BattleScript_SafeguardProtected
|
||||
attackanimation
|
||||
@ -2109,6 +2132,26 @@ BattleScript_EffectSleep::
|
||||
setmoveeffect MOVE_EFFECT_SLEEP
|
||||
seteffectprimary
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_TerrainPreventsEnd2::
|
||||
pause B_WAIT_TIME_SHORT
|
||||
printfromtable gTerrainPreventsStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
end2
|
||||
|
||||
BattleScript_ElectricTerrainPrevents::
|
||||
pause B_WAIT_TIME_SHORT
|
||||
printstring STRINGID_ELECTRICTERRAINPREVENTS
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
orhalfword gMoveResultFlags, MOVE_RESULT_FAILED
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_MistyTerrainPrevents::
|
||||
pause B_WAIT_TIME_SHORT
|
||||
printstring STRINGID_MISTYTERRAINPREVENTS
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
orhalfword gMoveResultFlags, MOVE_RESULT_FAILED
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_FlowerVeilProtectsRet::
|
||||
pause B_WAIT_TIME_SHORT
|
||||
@ -2163,18 +2206,21 @@ BattleScript_AlreadyAsleep::
|
||||
pause B_WAIT_TIME_SHORT
|
||||
printstring STRINGID_PKMNALREADYASLEEP
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
orhalfword gMoveResultFlags, MOVE_RESULT_FAILED
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_WasntAffected::
|
||||
pause B_WAIT_TIME_SHORT
|
||||
printstring STRINGID_PKMNWASNTAFFECTED
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
orhalfword gMoveResultFlags, MOVE_RESULT_FAILED
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_CantMakeAsleep::
|
||||
pause B_WAIT_TIME_SHORT
|
||||
printfromtable gUproarAwakeStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
orhalfword gMoveResultFlags, MOVE_RESULT_FAILED
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_EffectPoisonHit:
|
||||
@ -2621,6 +2667,7 @@ BattleScript_EffectToxic::
|
||||
jumpifsubstituteblocks BattleScript_ButItFailed
|
||||
jumpifstatus BS_TARGET, STATUS1_POISON | STATUS1_TOXIC_POISON, BattleScript_AlreadyPoisoned
|
||||
jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_ButItFailed
|
||||
jumpifterrainaffected BS_TARGET, STATUS_FIELD_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents
|
||||
trypoisontype BS_ATTACKER, BS_TARGET, BattleScript_NotAffected
|
||||
accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE
|
||||
jumpifsafeguard BattleScript_SafeguardProtected
|
||||
@ -2845,6 +2892,7 @@ BattleScript_EffectConfuse:
|
||||
jumpifability BS_TARGET, ABILITY_OWN_TEMPO, BattleScript_OwnTempoPrevents
|
||||
jumpifsubstituteblocks BattleScript_ButItFailed
|
||||
jumpifstatus2 BS_TARGET, STATUS2_CONFUSION, BattleScript_AlreadyConfused
|
||||
jumpifterrainaffected BS_TARGET, STATUS_FIELD_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents
|
||||
accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE
|
||||
jumpifsafeguard BattleScript_SafeguardProtected
|
||||
attackanimation
|
||||
@ -2963,6 +3011,7 @@ BattleScript_EffectPoison::
|
||||
jumpifstatus BS_TARGET, STATUS1_TOXIC_POISON, BattleScript_AlreadyPoisoned
|
||||
trypoisontype BS_ATTACKER, BS_TARGET, BattleScript_NotAffected
|
||||
jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_ButItFailed
|
||||
jumpifterrainaffected BS_TARGET, STATUS_FIELD_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents
|
||||
accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE
|
||||
jumpifsafeguard BattleScript_SafeguardProtected
|
||||
attackanimation
|
||||
@ -2988,6 +3037,7 @@ BattleScript_EffectParalyze:
|
||||
jumpifstatus BS_TARGET, STATUS1_PARALYSIS, BattleScript_AlreadyParalyzed
|
||||
tryparalyzetype BS_ATTACKER, BS_TARGET, BattleScript_NotAffected
|
||||
jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_ButItFailed
|
||||
jumpifterrainaffected BS_TARGET, STATUS_FIELD_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents
|
||||
accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE
|
||||
jumpifsafeguard BattleScript_SafeguardProtected
|
||||
bichalfword gMoveResultFlags, MOVE_RESULT_SUPER_EFFECTIVE | MOVE_RESULT_NOT_VERY_EFFECTIVE
|
||||
@ -4302,6 +4352,7 @@ BattleScript_EffectWillOWisp::
|
||||
jumpifleafguard BattleScript_LeafGuardProtects
|
||||
jumpifshieldsdown BS_TARGET, BattleScript_LeafGuardProtects
|
||||
jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_ButItFailed
|
||||
jumpifterrainaffected BS_TARGET, STATUS_FIELD_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents
|
||||
accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE
|
||||
jumpifsafeguard BattleScript_SafeguardProtected
|
||||
attackanimation
|
||||
@ -5557,16 +5608,28 @@ BattleScript_RoarSuccessSwitch::
|
||||
waitstate
|
||||
printstring STRINGID_PKMNWASDRAGGEDOUT
|
||||
switchineffects BS_TARGET
|
||||
jumpifbyte CMP_EQUAL, sSWITCH_CASE, B_SWITCH_RED_CARD, BattleScript_RoarSuccessSwitch_Ret
|
||||
setbyte sSWITCH_CASE, B_SWITCH_NORMAL
|
||||
goto BattleScript_MoveEnd
|
||||
BattleScript_RoarSuccessSwitch_Ret:
|
||||
swapattackerwithtarget @ continuation of RedCardActivates
|
||||
restoretarget
|
||||
removeitem BS_TARGET
|
||||
setbyte sSWITCH_CASE, B_SWITCH_NORMAL
|
||||
return
|
||||
|
||||
BattleScript_RoarSuccessEndBattle::
|
||||
call BattleScript_RoarSuccessRet
|
||||
setbyte sSWITCH_CASE, B_SWITCH_NORMAL
|
||||
setoutcomeonteleport BS_ATTACKER
|
||||
finishaction
|
||||
|
||||
BattleScript_RoarSuccessRet:
|
||||
jumpifbyte CMP_EQUAL, sSWITCH_CASE, B_SWITCH_HIT, BattleScript_RoarSuccessRet_Ret
|
||||
jumpifbyte CMP_EQUAL, sSWITCH_CASE, B_SWITCH_RED_CARD, BattleScript_RoarSuccessRet_Ret
|
||||
attackanimation
|
||||
waitanimation
|
||||
BattleScript_RoarSuccessRet_Ret:
|
||||
switchoutabilities BS_TARGET
|
||||
returntoball BS_TARGET
|
||||
waitstate
|
||||
@ -5611,6 +5674,21 @@ BattleScript_TargetItemStatRaise::
|
||||
removeitem BS_TARGET
|
||||
BattleScript_TargetItemStatRaiseRemoveItemRet:
|
||||
return
|
||||
|
||||
BattleScript_AttackerItemStatRaise::
|
||||
copybyte sBATTLER, gBattlerAttacker
|
||||
statbuffchange MOVE_EFFECT_AFFECTS_USER, BattleScript_AttackerItemStatRaiseRet
|
||||
jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0x2, BattleScript_AttackerItemStatRaiseRet
|
||||
playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT, NULL
|
||||
waitanimation
|
||||
setgraphicalstatchangevalues
|
||||
playanimation BS_ATTACKER, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1
|
||||
waitanimation
|
||||
printstring STRINGID_USINGITEMSTATOFPKMNROSE
|
||||
waitmessage 0x40
|
||||
removeitem BS_ATTACKER
|
||||
BattleScript_AttackerItemStatRaiseRet:
|
||||
return
|
||||
|
||||
BattleScript_MistProtected::
|
||||
pause B_WAIT_TIME_SHORT
|
||||
@ -6894,6 +6972,19 @@ BattleScript_SnowWarningActivates::
|
||||
playanimation BS_BATTLER_0, B_ANIM_HAIL_CONTINUES, NULL
|
||||
call BattleScript_WeatherFormChanges
|
||||
end3
|
||||
|
||||
BattleScript_TerrainSeedLoop:
|
||||
savetarget
|
||||
setbyte gBattlerTarget, 0
|
||||
BattleScript_TerrainSeedLoopIter:
|
||||
copybyte sBATTLER, gBattlerTarget
|
||||
doterrainseed BS_TARGET, BattleScript_TerrainSeedLoop_NextBattler
|
||||
removeitem BS_TARGET
|
||||
BattleScript_TerrainSeedLoop_NextBattler:
|
||||
addbyte gBattlerTarget, 0x1
|
||||
jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_TerrainSeedLoopIter
|
||||
restoretarget
|
||||
return
|
||||
|
||||
BattleScript_ElectricSurgeActivates::
|
||||
pause B_WAIT_TIME_SHORT
|
||||
@ -6901,6 +6992,7 @@ BattleScript_ElectricSurgeActivates::
|
||||
printstring STRINGID_TERRAINBECOMESELECTRIC
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
playanimation BS_SCRIPTING, B_ANIM_RESTORE_BG, NULL
|
||||
call BattleScript_TerrainSeedLoop
|
||||
end3
|
||||
|
||||
BattleScript_MistySurgeActivates::
|
||||
@ -6909,6 +7001,7 @@ BattleScript_MistySurgeActivates::
|
||||
printstring STRINGID_TERRAINBECOMESMISTY
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
playanimation BS_SCRIPTING, B_ANIM_RESTORE_BG, NULL
|
||||
call BattleScript_TerrainSeedLoop
|
||||
end3
|
||||
|
||||
BattleScript_GrassySurgeActivates::
|
||||
@ -6917,6 +7010,7 @@ BattleScript_GrassySurgeActivates::
|
||||
printstring STRINGID_TERRAINBECOMESGRASSY
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
playanimation BS_SCRIPTING, B_ANIM_RESTORE_BG, NULL
|
||||
call BattleScript_TerrainSeedLoop
|
||||
end3
|
||||
|
||||
BattleScript_PsychicSurgeActivates::
|
||||
@ -6925,6 +7019,7 @@ BattleScript_PsychicSurgeActivates::
|
||||
printstring STRINGID_TERRAINBECOMESPSYCHIC
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
playanimation BS_SCRIPTING, B_ANIM_RESTORE_BG, NULL
|
||||
call BattleScript_TerrainSeedLoop
|
||||
end3
|
||||
|
||||
BattleScript_BadDreamsActivates::
|
||||
@ -7076,6 +7171,7 @@ BattleScript_SoundproofProtected::
|
||||
call BattleScript_AbilityPopUp
|
||||
printstring STRINGID_PKMNSXBLOCKSY
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
orhalfword gMoveResultFlags, MOVE_RESULT_DOESNT_AFFECT_FOE
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_DazzlingProtected::
|
||||
@ -7119,6 +7215,7 @@ BattleScript_AbilityNoSpecificStatLoss::
|
||||
printstring STRINGID_PKMNSXPREVENTSYLOSS
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
setbyte cMULTISTRING_CHOOSER, B_MSG_STAT_FELL_EMPTY
|
||||
orhalfword gMoveResultFlags, MOVE_RESULT_NO_EFFECT
|
||||
return
|
||||
|
||||
BattleScript_StickyHoldActivates::
|
||||
@ -7554,6 +7651,19 @@ BattleScript_BerryCureChosenStatusRet::
|
||||
removeitem BS_SCRIPTING
|
||||
return
|
||||
|
||||
BattleScript_MentalHerbCureRet::
|
||||
playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT, NULL
|
||||
printfromtable gMentalHerbCureStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
updatestatusicon BS_SCRIPTING
|
||||
removeitem BS_SCRIPTING
|
||||
copybyte gBattlerAttacker, sSAVED_BATTLER @ restore the original attacker just to be safe
|
||||
return
|
||||
|
||||
BattleScript_MentalHerbCureEnd2::
|
||||
call BattleScript_MentalHerbCureRet
|
||||
end2
|
||||
|
||||
BattleScript_WhiteHerbEnd2::
|
||||
call BattleScript_WhiteHerbRet
|
||||
end2
|
||||
@ -7707,12 +7817,13 @@ BattleScript_BerryStatRaiseEnd2::
|
||||
BattleScript_BerryStatRaiseEnd2_AbilityPopup:
|
||||
call BattleScript_AbilityPopUp
|
||||
BattleScript_BerryStatRaiseEnd2_Anim:
|
||||
playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT, NULL
|
||||
statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_BUFF_ALLOW_PTR, BattleScript_BerryStatRaiseDoStatUp
|
||||
BattleScript_BerryStatRaiseDoStatUp::
|
||||
statbuffchange STAT_BUFF_ALLOW_PTR, BattleScript_BerryStatRaiseEnd2_End
|
||||
setgraphicalstatchangevalues
|
||||
playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT, sB_ANIM_ARG1
|
||||
setbyte cMULTISTRING_CHOOSER, B_MSG_STAT_ROSE_ITEM
|
||||
call BattleScript_StatUp
|
||||
removeitem BS_ATTACKER
|
||||
BattleScript_BerryStatRaiseEnd2_End::
|
||||
end2
|
||||
|
||||
BattleScript_BerryStatRaiseRet::
|
||||
@ -7721,12 +7832,13 @@ BattleScript_BerryStatRaiseRet::
|
||||
BattleScript_BerryStatRaiseRet_AbilityPopup:
|
||||
call BattleScript_AbilityPopUp
|
||||
BattleScript_BerryStatRaiseRet_Anim:
|
||||
playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT, NULL
|
||||
statbuffchange STAT_BUFF_ALLOW_PTR, BattleScript_BerryStatRaiseRet_End
|
||||
BattleScript_BerryStatRaiseRet_End:
|
||||
setgraphicalstatchangevalues
|
||||
playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT, sB_ANIM_ARG1
|
||||
setbyte cMULTISTRING_CHOOSER, B_MSG_STAT_ROSE_ITEM
|
||||
call BattleScript_StatUp
|
||||
removeitem BS_SCRIPTING
|
||||
BattleScript_BerryStatRaiseRet_End:
|
||||
return
|
||||
|
||||
BattleScript_BerryFocusEnergyEnd2::
|
||||
@ -7980,6 +8092,64 @@ BattleScript_StickyBarbTransfer::
|
||||
removeitem BS_TARGET
|
||||
return
|
||||
|
||||
BattleScript_RedCardActivates::
|
||||
playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT, NULL
|
||||
printstring STRINGID_REDCARDACTIVATE
|
||||
waitmessage 0x40
|
||||
swapattackerwithtarget
|
||||
jumpifstatus3 BS_EFFECT_BATTLER, STATUS3_ROOTED, BattleScript_RedCardIngrain
|
||||
jumpifability BS_EFFECT_BATTLER, ABILITY_SUCTION_CUPS, BattleScript_RedCardSuctionCups
|
||||
setbyte sSWITCH_CASE, B_SWITCH_RED_CARD
|
||||
forcerandomswitch BattleScript_RedCardEnd
|
||||
@ changes the current battle script. the rest happens in BattleScript_RoarSuccessSwitch_Ret, if switch is successful
|
||||
BattleScript_RedCardEnd:
|
||||
return
|
||||
BattleScript_RedCardIngrain:
|
||||
printstring STRINGID_PKMNANCHOREDITSELF
|
||||
waitmessage 0x40
|
||||
removeitem BS_SCRIPTING
|
||||
swapattackerwithtarget
|
||||
return
|
||||
BattleScript_RedCardSuctionCups:
|
||||
printstring STRINGID_PKMNANCHORSITSELFWITH
|
||||
waitmessage 0x40
|
||||
removeitem BS_SCRIPTING
|
||||
swapattackerwithtarget
|
||||
return
|
||||
|
||||
BattleScript_EjectButtonActivates::
|
||||
makevisible BS_ATTACKER
|
||||
playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT, NULL
|
||||
printstring STRINGID_EJECTBUTTONACTIVATE
|
||||
waitmessage 0x40
|
||||
removeitem BS_SCRIPTING
|
||||
makeinvisible BS_SCRIPTING
|
||||
openpartyscreen BS_SCRIPTING, BattleScript_EjectButtonEnd
|
||||
switchoutabilities BS_SCRIPTING
|
||||
waitstate
|
||||
switchhandleorder BS_SCRIPTING 0x2
|
||||
returntoball BS_SCRIPTING
|
||||
getswitchedmondata BS_SCRIPTING
|
||||
switchindataupdate BS_SCRIPTING
|
||||
hpthresholds BS_SCRIPTING
|
||||
printstring 0x3
|
||||
switchinanim BS_SCRIPTING 0x1
|
||||
waitstate
|
||||
switchineffects BS_SCRIPTING
|
||||
BattleScript_EjectButtonEnd:
|
||||
return
|
||||
|
||||
BattleScript_EjectPackActivate_Ret::
|
||||
goto BattleScript_EjectButtonActivates
|
||||
|
||||
BattleScript_EjectPackActivate_End2::
|
||||
call BattleScript_EjectPackActivate_Ret
|
||||
end2
|
||||
|
||||
BattleScript_EjectPackActivates::
|
||||
jumpifcantswitch BS_SCRIPTING, BattleScript_EjectButtonEnd
|
||||
goto BattleScript_EjectPackActivate_Ret
|
||||
|
||||
BattleScript_DarkTypePreventsPrankster::
|
||||
attackstring
|
||||
ppreduce
|
||||
@ -7988,4 +8158,3 @@ BattleScript_DarkTypePreventsPrankster::
|
||||
waitmessage 0x40
|
||||
orhalfword gMoveResultFlags, MOVE_RESULT_NO_EFFECT
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
|
@ -126,7 +126,7 @@ struct ProtectStruct
|
||||
u32 stealMove:1;
|
||||
u32 prlzImmobility:1;
|
||||
u32 confusionSelfDmg:1;
|
||||
u32 targetNotAffected:1;
|
||||
u32 targetAffected:1;
|
||||
u32 chargingTurn:1;
|
||||
u32 fleeFlag:2; // For RunAway and Smoke Ball.
|
||||
u32 usedImprisonedMove:1;
|
||||
@ -145,6 +145,7 @@ struct ProtectStruct
|
||||
u32 micle:1;
|
||||
u32 custap:1; // also quick claw
|
||||
u32 touchedProtectLike:1;
|
||||
u32 disableEjectPack:1;
|
||||
u32 physicalDmg;
|
||||
u32 specialDmg;
|
||||
u8 physicalBattlerId;
|
||||
@ -153,6 +154,7 @@ struct ProtectStruct
|
||||
|
||||
struct SpecialStatus
|
||||
{
|
||||
u8 statFell:1;
|
||||
u8 statLowered:1;
|
||||
u8 lightningRodRedirected:1;
|
||||
u8 restoredBattlerSprite: 1;
|
||||
@ -596,6 +598,7 @@ struct BattleStruct
|
||||
u16 changedSpecies[PARTY_SIZE]; // For Zygarde or future forms when multiple mons can change into the same pokemon.
|
||||
u8 quickClawBattlerId;
|
||||
struct StolenItem itemStolen[PARTY_SIZE]; // Player's team that had items stolen (two bytes per party member)
|
||||
u8 blunderPolicy:1; // should blunder policy activate
|
||||
};
|
||||
|
||||
#define GET_MOVE_TYPE(move, typeArg) \
|
||||
@ -667,8 +670,9 @@ struct BattleScripting
|
||||
u16 moveEffect;
|
||||
u16 multihitMoveEffect;
|
||||
u8 illusionNickHack; // To properly display nick in STRINGID_ENEMYABOUTTOSWITCHPKMN.
|
||||
bool8 fixedPopup; // force ability popup to stick until manually called back
|
||||
bool8 fixedPopup; // Force ability popup to stick until manually called back
|
||||
u16 abilityPopupOverwrite;
|
||||
u8 switchCase; // Special switching conditions, eg. red card
|
||||
};
|
||||
|
||||
// rom_80A5C6C
|
||||
|
@ -119,10 +119,10 @@ bool32 IsUngroundingEffect(u16 effect);
|
||||
bool32 IsSemiInvulnerable(u8 battlerDef, u16 move);
|
||||
|
||||
// status checks
|
||||
bool32 CanBeBurned(u8 battler, u16 ability);
|
||||
bool32 CanBePoisoned(u8 battler, u16 ability);
|
||||
bool32 CanBeConfused(u8 battler, u16 ability);
|
||||
bool32 CanSleep(u8 battler, u16 ability);
|
||||
bool32 AI_CanBeBurned(u8 battler, u16 ability);
|
||||
bool32 AI_CanBePoisoned(u8 battler, u16 ability);
|
||||
bool32 AI_CanBeConfused(u8 battler, u16 ability);
|
||||
bool32 AI_CanSleep(u8 battler, u16 ability);
|
||||
bool32 IsBattlerIncapacitated(u8 battler, u16 ability);
|
||||
bool32 AI_CanPutToSleep(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16 partnerMove);
|
||||
bool32 ShouldPoisonSelf(u8 battler, u16 ability);
|
||||
|
@ -373,6 +373,17 @@ extern const u8 BattleScript_BattlerShookOffTaunt[];
|
||||
extern const u8 BattleScript_BattlerGotOverItsInfatuation[];
|
||||
extern const u8 BattleScript_Pickpocket[];
|
||||
extern const u8 BattleScript_StickyBarbTransfer[];
|
||||
extern const u8 BattleScript_AttackerItemStatRaise[];
|
||||
extern const u8 BattleScript_RedCardActivates[];
|
||||
extern const u8 BattleScript_EjectButtonActivates[];
|
||||
extern const u8 BattleScript_EjectPackActivate_Ret[];
|
||||
extern const u8 BattleScript_EjectPackActivate_End2[];
|
||||
extern const u8 BattleScript_EjectPackActivates[];
|
||||
extern const u8 BattleScript_MentalHerbCureRet[];
|
||||
extern const u8 BattleScript_MentalHerbCureEnd2[];
|
||||
extern const u8 BattleScript_TerrainPreventsEnd2[];
|
||||
extern const u8 BattleScript_MistyTerrainPrevents[];
|
||||
extern const u8 BattleScript_ElectricTerrainPrevents[];
|
||||
extern const u8 BattleScript_DarkTypePreventsPrankster[];
|
||||
|
||||
#endif // GUARD_BATTLE_SCRIPTS_H
|
||||
|
@ -28,9 +28,10 @@
|
||||
|
||||
#define ITEMEFFECT_ON_SWITCH_IN 0x0
|
||||
#define ITEMEFFECT_MOVE_END 0x3
|
||||
#define ITEMEFFECT_KINGSROCK_SHELLBELL 0x4
|
||||
#define ITEMEFFECT_KINGSROCK 0x4
|
||||
#define ITEMEFFECT_TARGET 0x5
|
||||
#define ITEMEFFECT_ORBS 0x6
|
||||
#define ITEMEFFECT_LIFEORB_SHELLBELL 0x7
|
||||
|
||||
#define WEATHER_HAS_EFFECT ((!IsAbilityOnField(ABILITY_CLOUD_NINE) && !IsAbilityOnField(ABILITY_AIR_LOCK)))
|
||||
|
||||
@ -144,7 +145,12 @@ void TryRestoreStolenItems(void);
|
||||
bool32 CanStealItem(u8 battlerStealing, u8 battlerItem, u16 item);
|
||||
void TrySaveExchangedItem(u8 battlerId, u16 stolenItem);
|
||||
bool32 IsPartnerMonFromSameTrainer(u8 battlerId);
|
||||
|
||||
u8 TryHandleSeed(u8 battler, u32 terrainFlag, u8 statId, u16 itemId, bool32 execute);
|
||||
bool32 IsBattlerAffectedByHazards(u8 battlerId, bool32 toxicSpikes);
|
||||
void SortBattlersBySpeed(u8 *battlers, bool8 slowToFast);
|
||||
bool32 CompareStat(u8 battlerId, u8 statId, u8 cmpTo, u8 cmpKind);
|
||||
bool32 TryRoomService(u8 battlerId);
|
||||
void BufferStatChange(u8 battlerId, u8 statId, u8 stringId);
|
||||
|
||||
// ability checks
|
||||
bool32 IsRolePlayBannedAbilityAtk(u16 ability);
|
||||
@ -155,4 +161,12 @@ bool32 IsGastroAcidBannedAbility(u16 ability);
|
||||
bool32 IsEntrainmentBannedAbilityAttacker(u16 ability);
|
||||
bool32 IsEntrainmentTargetOrSimpleBeamBannedAbility(u16 ability);
|
||||
|
||||
bool32 CanSleep(u8 battlerId);
|
||||
bool32 CanBePoisoned(u8 battlerId);
|
||||
bool32 CanBeBurned(u8 battlerId);
|
||||
bool32 CanBeParalyzed(u8 battlerId);
|
||||
bool32 CanBeFrozen(u8 battlerId);
|
||||
bool32 CanBeConfused(u8 battlerId);
|
||||
bool32 IsBattlerTerrainAffected(u8 battlerId, u32 terrainFlag);
|
||||
|
||||
#endif // GUARD_BATTLE_UTIL_H
|
||||
|
@ -131,7 +131,7 @@
|
||||
#define B_HP_BERRIES GEN_7 // In Gen4+, berries which restore hp activate immediately after HP drops to half. In Gen3, the effect occurs at the end of the turn.
|
||||
#define B_BERRIES_INSTANT GEN_7 // In Gen4+, most berries activate on battle start/switch-in if applicable. In Gen3, they only activate either at the move end or turn end.
|
||||
#define B_X_ITEMS_BUFF GEN_7 // In Gen7+, the X Items raise a stat by 2 stages instead of 1.
|
||||
#define B_MENTAL_HERB GEN_5 // In Gen5+, mental herb cures Taunt, Encore, Heal Block, and Disable
|
||||
#define B_MENTAL_HERB GEN_5 // In Gen5+, the Mental Herb cures Infatuation, Taunt, Encore, Torment, Heal Block, and Disable
|
||||
|
||||
// Flag settings
|
||||
// To use the following features in scripting, replace the 0s with the flag ID you're assigning it to.
|
||||
|
@ -37,6 +37,7 @@
|
||||
#define sILLUSION_NICK_HACK gBattleScripting + 0x32
|
||||
#define sFIXED_ABILITY_POPUP gBattleScripting + 0x33
|
||||
#define sABILITY_OVERWRITE gBattleScripting + 0x34
|
||||
#define sSWITCH_CASE gBattleScripting + 0x36
|
||||
|
||||
#define cMULTISTRING_CHOOSER gBattleCommunication + 5
|
||||
#define cMISS_TYPE gBattleCommunication + 6
|
||||
@ -174,6 +175,10 @@
|
||||
#define VARIOUS_TOTEM_BOOST 103
|
||||
#define VARIOUS_TRY_ACTIVATE_GRIM_NEIGH 104
|
||||
#define VARIOUS_MOVEEND_ITEM_EFFECTS 105
|
||||
#define VARIOUS_TERRAIN_SEED 106
|
||||
#define VARIOUS_MAKE_INVISIBLE 107
|
||||
#define VARIOUS_ROOM_SERVICE 108
|
||||
#define VARIOUS_JUMP_IF_TERRAIN_AFFECTED 109
|
||||
|
||||
// Cmd_manipulatedamage
|
||||
#define DMG_CHANGE_SIGN 0
|
||||
@ -228,16 +233,24 @@
|
||||
#define MOVEEND_ITEM_EFFECTS_TARGET 13
|
||||
#define MOVEEND_MOVE_EFFECTS2 14
|
||||
#define MOVEEND_ITEM_EFFECTS_ALL 15
|
||||
#define MOVEEND_KINGSROCK_SHELLBELL 16
|
||||
#define MOVEEND_KINGSROCK 16 // These item effects will occur each strike of a multi-hit move
|
||||
#define MOVEEND_SUBSTITUTE 17
|
||||
#define MOVEEND_UPDATE_LAST_MOVES 18
|
||||
#define MOVEEND_MIRROR_MOVE 19
|
||||
#define MOVEEND_NEXT_TARGET 20
|
||||
#define MOVEEND_LIFE_ORB 21
|
||||
#define MOVEEND_PICKPOCKET 22
|
||||
#define MOVEEND_DANCER 23
|
||||
#define MOVEEND_EMERGENCY_EXIT 24
|
||||
#define MOVEEND_CLEAR_BITS 25
|
||||
#define MOVEEND_COUNT 26
|
||||
#define MOVEEND_NEXT_TARGET 20 // Everything up until here is handled for each strike of a multi-hit move
|
||||
#define MOVEEND_EJECT_BUTTON 21
|
||||
#define MOVEEND_RED_CARD 22
|
||||
#define MOVEEND_EJECT_PACK 23
|
||||
#define MOVEEND_LIFEORB_SHELLBELL 24 // Includes shell bell, throat spray, etc
|
||||
#define MOVEEND_PICKPOCKET 25
|
||||
#define MOVEEND_DANCER 26
|
||||
#define MOVEEND_EMERGENCY_EXIT 27
|
||||
#define MOVEEND_CLEAR_BITS 28
|
||||
#define MOVEEND_COUNT 29
|
||||
|
||||
// switch cases
|
||||
#define B_SWITCH_NORMAL 0
|
||||
#define B_SWITCH_HIT 1 // dragon tail, circle throw
|
||||
#define B_SWITCH_RED_CARD 2
|
||||
|
||||
#endif // GUARD_CONSTANTS_BATTLE_SCRIPT_COMMANDS_H
|
||||
|
@ -573,8 +573,13 @@
|
||||
#define STRINGID_ITEMCANNOTBEREMOVED 569
|
||||
#define STRINGID_STICKYBARBTRANSFER 570
|
||||
#define STRINGID_PKMNBURNHEALED 571
|
||||
#define STRINGID_REDCARDACTIVATE 572
|
||||
#define STRINGID_EJECTBUTTONACTIVATE 573
|
||||
#define STRINGID_ATKGOTOVERINFATUATION 574
|
||||
#define STRINGID_TORMENTEDNOMORE 575
|
||||
#define STRINGID_HEALBLOCKEDNOMORE 576
|
||||
|
||||
#define BATTLESTRINGS_COUNT 572
|
||||
#define BATTLESTRINGS_COUNT 577
|
||||
|
||||
// The below IDs are all indexes into battle message tables,
|
||||
// used to determine which of a set of messages to print.
|
||||
@ -810,4 +815,17 @@
|
||||
#define B_MSG_SWITCHIN_ASONE 13
|
||||
#define B_MSG_SWITCHIN_CURIOUS_MEDICINE 14
|
||||
|
||||
// gMentalHerbCureStringIds
|
||||
#define B_MSG_MENTALHERBCURE_INFATUATION 0
|
||||
#define B_MSG_MENTALHERBCURE_TAUNT 1
|
||||
#define B_MSG_MENTALHERBCURE_ENCORE 2
|
||||
#define B_MSG_MENTALHERBCURE_TORMENT 3
|
||||
#define B_MSG_MENTALHERBCURE_HEALBLOCK 4
|
||||
#define B_MSG_MENTALHERBCURE_DISABLE 5
|
||||
|
||||
// gTerrainPreventsStringIds
|
||||
#define B_MSG_TERRAINPREVENTS_MISTY 0
|
||||
#define B_MSG_TERRAINPREVENTS_ELECTRIC 1
|
||||
#define B_MSG_TERRAINPREVENTS_PSYCHIC 2
|
||||
|
||||
#endif // GUARD_CONSTANTS_BATTLE_STRING_IDS_H
|
||||
|
@ -29,7 +29,7 @@
|
||||
#define HOLD_EFFECT_EXP_SHARE 25
|
||||
#define HOLD_EFFECT_QUICK_CLAW 26
|
||||
#define HOLD_EFFECT_FRIENDSHIP_UP 27
|
||||
#define HOLD_EFFECT_CURE_ATTRACT 28
|
||||
#define HOLD_EFFECT_MENTAL_HERB 28
|
||||
#define HOLD_EFFECT_CHOICE_BAND 29
|
||||
#define HOLD_EFFECT_FLINCH 30
|
||||
#define HOLD_EFFECT_BUG_POWER 31
|
||||
@ -154,4 +154,10 @@
|
||||
|
||||
#define HOLD_EFFECT_CHOICE(holdEffect)((holdEffect == HOLD_EFFECT_CHOICE_BAND || holdEffect == HOLD_EFFECT_CHOICE_SCARF || holdEffect == HOLD_EFFECT_CHOICE_SPECS))
|
||||
|
||||
// Terrain seed params
|
||||
#define HOLD_EFFECT_PARAM_ELECTRIC_TERRAIN 0
|
||||
#define HOLD_EFFECT_PARAM_GRASSY_TERRAIN 1
|
||||
#define HOLD_EFFECT_PARAM_MISTY_TERRAIN 2
|
||||
#define HOLD_EFFECT_PARAM_PSYCHIC_TERRAIN 3
|
||||
|
||||
#endif // GUARD_HOLD_EFFECTS_H
|
||||
|
@ -1204,7 +1204,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|
||||
break;
|
||||
case EFFECT_DISABLE:
|
||||
if (gDisableStructs[battlerDef].disableTimer == 0
|
||||
&& (B_MENTAL_HERB >= GEN_5 && AI_DATA->defHoldEffect != HOLD_EFFECT_CURE_ATTRACT)
|
||||
&& (B_MENTAL_HERB >= GEN_5 && AI_DATA->defHoldEffect != HOLD_EFFECT_MENTAL_HERB)
|
||||
&& !PartnerHasSameMoveEffectWithoutTarget(AI_DATA->battlerAtkPartner, move, AI_DATA->partnerMove))
|
||||
{
|
||||
if (GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 0) // attacker should go first
|
||||
@ -1224,7 +1224,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|
||||
break;
|
||||
case EFFECT_ENCORE:
|
||||
if (gDisableStructs[battlerDef].encoreTimer == 0
|
||||
&& (B_MENTAL_HERB >= GEN_5 && AI_DATA->defHoldEffect != HOLD_EFFECT_CURE_ATTRACT)
|
||||
&& (B_MENTAL_HERB >= GEN_5 && AI_DATA->defHoldEffect != HOLD_EFFECT_MENTAL_HERB)
|
||||
&& !DoesPartnerHaveSameMoveEffect(AI_DATA->battlerAtkPartner, battlerDef, move, AI_DATA->partnerMove))
|
||||
{
|
||||
if (GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 0) // attacker should go first
|
||||
@ -1458,7 +1458,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|
||||
break;
|
||||
}
|
||||
|
||||
if (B_MENTAL_HERB >= GEN_5 && AI_DATA->defHoldEffect == HOLD_EFFECT_CURE_ATTRACT)
|
||||
if (B_MENTAL_HERB >= GEN_5 && AI_DATA->defHoldEffect == HOLD_EFFECT_MENTAL_HERB)
|
||||
score -= 6;
|
||||
break;
|
||||
case EFFECT_WILL_O_WISP:
|
||||
@ -1570,7 +1570,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|
||||
score -= 10;
|
||||
break;
|
||||
case EFFECT_REST:
|
||||
if (!CanSleep(battlerAtk, AI_DATA->atkAbility))
|
||||
if (!AI_CanSleep(battlerAtk, AI_DATA->atkAbility))
|
||||
score -= 10;
|
||||
//fallthrough
|
||||
case EFFECT_RESTORE_HP:
|
||||
@ -2686,7 +2686,7 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|
||||
case EFFECT_SWAGGER:
|
||||
if (gBattleMons[battlerAtkPartner].statStages[STAT_ATK] < MAX_STAT_STAGE
|
||||
&& HasMoveWithSplit(battlerAtkPartner, SPLIT_PHYSICAL)
|
||||
&& (!CanBeConfused(battlerAtkPartner, TRUE)
|
||||
&& (!AI_CanBeConfused(battlerAtkPartner, TRUE)
|
||||
|| atkPartnerHoldEffect == HOLD_EFFECT_CURE_CONFUSION
|
||||
|| atkPartnerHoldEffect == HOLD_EFFECT_CURE_STATUS))
|
||||
{
|
||||
@ -2696,7 +2696,7 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|
||||
case EFFECT_FLATTER:
|
||||
if (gBattleMons[battlerAtkPartner].statStages[STAT_SPATK] < MAX_STAT_STAGE
|
||||
&& HasMoveWithSplit(battlerAtkPartner, SPLIT_SPECIAL)
|
||||
&& (!CanBeConfused(battlerAtkPartner, TRUE)
|
||||
&& (!AI_CanBeConfused(battlerAtkPartner, TRUE)
|
||||
|| atkPartnerHoldEffect == HOLD_EFFECT_CURE_CONFUSION
|
||||
|| atkPartnerHoldEffect == HOLD_EFFECT_CURE_STATUS))
|
||||
{
|
||||
@ -3248,7 +3248,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|
||||
}
|
||||
break;
|
||||
case EFFECT_REST:
|
||||
if (!(CanSleep(battlerAtk, AI_DATA->atkAbility)))
|
||||
if (!(AI_CanSleep(battlerAtk, AI_DATA->atkAbility)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
@ -3408,7 +3408,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|
||||
break;
|
||||
case EFFECT_DISABLE:
|
||||
if (gDisableStructs[battlerDef].disableTimer == 0
|
||||
&& (B_MENTAL_HERB >= GEN_5 && AI_DATA->defHoldEffect != HOLD_EFFECT_CURE_ATTRACT)) // mental herb
|
||||
&& (B_MENTAL_HERB >= GEN_5 && AI_DATA->defHoldEffect != HOLD_EFFECT_MENTAL_HERB)) // mental herb
|
||||
{
|
||||
if (GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 0) // AI goes first
|
||||
{
|
||||
@ -3430,7 +3430,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|
||||
break;
|
||||
case EFFECT_ENCORE:
|
||||
if (gDisableStructs[battlerDef].encoreTimer == 0
|
||||
&& (B_MENTAL_HERB >= GEN_5 && AI_DATA->defHoldEffect != HOLD_EFFECT_CURE_ATTRACT)) // mental herb
|
||||
&& (B_MENTAL_HERB >= GEN_5 && AI_DATA->defHoldEffect != HOLD_EFFECT_MENTAL_HERB)) // mental herb
|
||||
{
|
||||
if (IsEncoreEncouragedEffect(gBattleMoves[gLastMoves[battlerDef]].effect))
|
||||
score += 3;
|
||||
@ -3937,11 +3937,11 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|
||||
score += 2;
|
||||
break;
|
||||
case HOLD_EFFECT_TOXIC_ORB:
|
||||
if (!ShouldPoisonSelf(battlerAtk, AI_DATA->atkAbility) && CanBePoisoned(battlerDef, AI_DATA->defAbility))
|
||||
if (!ShouldPoisonSelf(battlerAtk, AI_DATA->atkAbility) && AI_CanBePoisoned(battlerDef, AI_DATA->defAbility))
|
||||
score += 2;
|
||||
break;
|
||||
case HOLD_EFFECT_FLAME_ORB:
|
||||
if (!ShouldBurnSelf(battlerAtk, AI_DATA->atkAbility) && CanBeBurned(battlerAtk, AI_DATA->defAbility))
|
||||
if (!ShouldBurnSelf(battlerAtk, AI_DATA->atkAbility) && AI_CanBeBurned(battlerAtk, AI_DATA->defAbility))
|
||||
score += 2;
|
||||
break;
|
||||
case HOLD_EFFECT_BLACK_SLUDGE:
|
||||
|
@ -2589,7 +2589,7 @@ bool32 IsBattlerIncapacitated(u8 battler, u16 ability)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool32 CanSleep(u8 battler, u16 ability)
|
||||
bool32 AI_CanSleep(u8 battler, u16 ability)
|
||||
{
|
||||
if (ability == ABILITY_INSOMNIA
|
||||
|| ability == ABILITY_VITAL_SPIRIT
|
||||
@ -2603,7 +2603,7 @@ bool32 CanSleep(u8 battler, u16 ability)
|
||||
|
||||
bool32 AI_CanPutToSleep(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16 partnerMove)
|
||||
{
|
||||
if (!CanSleep(battlerDef, defAbility)
|
||||
if (!AI_CanSleep(battlerDef, defAbility)
|
||||
|| AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0
|
||||
|| DoesSubstituteBlockMove(battlerAtk, battlerDef, move)
|
||||
|| PartnerMoveEffectIsStatusSameTarget(BATTLE_PARTNER(battlerAtk), battlerDef, partnerMove)) // shouldn't try to sleep mon that partner is trying to make sleep
|
||||
@ -2611,7 +2611,7 @@ bool32 AI_CanPutToSleep(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool32 CanBePoisoned(u8 battler, u16 ability)
|
||||
bool32 AI_CanBePoisoned(u8 battler, u16 ability)
|
||||
{
|
||||
if (ability == ABILITY_IMMUNITY
|
||||
|| ability == ABILITY_PASTEL_VEIL
|
||||
@ -2624,7 +2624,7 @@ bool32 CanBePoisoned(u8 battler, u16 ability)
|
||||
|
||||
bool32 ShouldPoisonSelf(u8 battler, u16 ability)
|
||||
{
|
||||
if (CanBePoisoned(battler, ability) && (
|
||||
if (AI_CanBePoisoned(battler, ability) && (
|
||||
ability == ABILITY_MARVEL_SCALE
|
||||
|| ability == ABILITY_POISON_HEAL
|
||||
|| ability == ABILITY_QUICK_FEET
|
||||
@ -2639,7 +2639,7 @@ bool32 ShouldPoisonSelf(u8 battler, u16 ability)
|
||||
|
||||
bool32 AI_CanPoison(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16 partnerMove)
|
||||
{
|
||||
if (!CanBePoisoned(battlerDef, defAbility)
|
||||
if (!AI_CanBePoisoned(battlerDef, defAbility)
|
||||
|| AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0
|
||||
|| DoesSubstituteBlockMove(battlerAtk, battlerDef, move)
|
||||
|| PartnerMoveEffectIsStatusSameTarget(BATTLE_PARTNER(battlerAtk), battlerDef, partnerMove))
|
||||
@ -2673,7 +2673,7 @@ bool32 AI_CanParalyze(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u1
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool32 CanBeConfused(u8 battler, u16 ability)
|
||||
bool32 AI_CanBeConfused(u8 battler, u16 ability)
|
||||
{
|
||||
if ((gBattleMons[battler].status2 & STATUS2_CONFUSION)
|
||||
|| (ability == ABILITY_OWN_TEMPO)
|
||||
@ -2684,7 +2684,7 @@ bool32 CanBeConfused(u8 battler, u16 ability)
|
||||
|
||||
bool32 AI_CanConfuse(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 battlerAtkPartner, u16 move, u16 partnerMove)
|
||||
{
|
||||
if (!CanBeConfused(battlerDef, defAbility)
|
||||
if (!AI_CanBeConfused(battlerDef, defAbility)
|
||||
|| AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0
|
||||
|| gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_SAFEGUARD
|
||||
|| DoesSubstituteBlockMove(battlerAtk, battlerDef, move)
|
||||
@ -2696,7 +2696,7 @@ bool32 AI_CanConfuse(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 battlerAtk
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool32 CanBeBurned(u8 battler, u16 ability)
|
||||
bool32 AI_CanBeBurned(u8 battler, u16 ability)
|
||||
{
|
||||
if (ability == ABILITY_WATER_VEIL
|
||||
|| ability == ABILITY_WATER_BUBBLE
|
||||
@ -2710,7 +2710,7 @@ bool32 CanBeBurned(u8 battler, u16 ability)
|
||||
|
||||
bool32 ShouldBurnSelf(u8 battler, u16 ability)
|
||||
{
|
||||
if (CanBeBurned(battler, ability) && (
|
||||
if (AI_CanBeBurned(battler, ability) && (
|
||||
ability == ABILITY_QUICK_FEET
|
||||
|| ability == ABILITY_HEATPROOF
|
||||
|| ability == ABILITY_MAGIC_GUARD
|
||||
@ -2724,7 +2724,7 @@ bool32 ShouldBurnSelf(u8 battler, u16 ability)
|
||||
|
||||
bool32 AI_CanBurn(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 battlerAtkPartner, u16 move, u16 partnerMove)
|
||||
{
|
||||
if (!CanBeBurned(battlerDef, defAbility)
|
||||
if (!AI_CanBeBurned(battlerDef, defAbility)
|
||||
|| AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0
|
||||
|| DoesSubstituteBlockMove(battlerAtk, battlerDef, move)
|
||||
|| PartnerMoveEffectIsStatusSameTarget(battlerAtkPartner, battlerDef, partnerMove))
|
||||
|
@ -3032,6 +3032,10 @@ void SwitchInClearSetData(void)
|
||||
gBattleResources->flags->flags[gActiveBattler] = 0;
|
||||
gCurrentMove = 0;
|
||||
gBattleStruct->arenaTurnCounter = 0xFF;
|
||||
|
||||
// Reset damage to prevent things like red card activating if the switched-in mon is holding it
|
||||
gSpecialStatuses[gActiveBattler].physicalDmg = 0;
|
||||
gSpecialStatuses[gActiveBattler].specialDmg = 0;
|
||||
|
||||
ClearBattlerMoveHistory(gActiveBattler);
|
||||
ClearBattlerAbilityHistory(gActiveBattler);
|
||||
@ -3074,7 +3078,7 @@ void FaintClearSetData(void)
|
||||
gProtectStructs[gActiveBattler].stealMove = 0;
|
||||
gProtectStructs[gActiveBattler].prlzImmobility = 0;
|
||||
gProtectStructs[gActiveBattler].confusionSelfDmg = 0;
|
||||
gProtectStructs[gActiveBattler].targetNotAffected = 0;
|
||||
gProtectStructs[gActiveBattler].targetAffected = 0;
|
||||
gProtectStructs[gActiveBattler].chargingTurn = 0;
|
||||
gProtectStructs[gActiveBattler].fleeFlag = 0;
|
||||
gProtectStructs[gActiveBattler].usedImprisonedMove = 0;
|
||||
|
@ -699,9 +699,20 @@ static const u8 sText_PkmnGotOverItsInfatuation[] = _("{B_SCR_ACTIVE_NAME_WITH_P
|
||||
static const u8 sText_ItemCannotBeRemoved[] = _("{B_ATK_NAME_WITH_PREFIX}'s item cannot be removed!");
|
||||
static const u8 sText_StickyBarbTransfer[] = _("The {B_LAST_ITEM} attached itself to\n{B_ATK_NAME_WITH_PREFIX}!");
|
||||
static const u8 sText_PkmnBurnHealed[] = _("{B_DEF_NAME_WITH_PREFIX}'s\nburn was healed.");
|
||||
static const u8 sText_RedCardActivate[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} held up its {B_LAST_ITEM}\nagainst {B_ATK_NAME_WITH_PREFIX}!");
|
||||
static const u8 sText_EjectButtonActivate[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} is switched\nout with the {B_LAST_ITEM}!");
|
||||
static const u8 sText_AttackerGotOverInfatuation[] =_("{B_ATK_NAME_WITH_PREFIX} got over\nits infatuation!");
|
||||
static const u8 sText_TormentedNoMore[] = _("{B_ATK_NAME_WITH_PREFIX} is\ntormented no more!");
|
||||
static const u8 sText_HealBlockedNoMore[] = _("{B_ATK_NAME_WITH_PREFIX} is cured of\nits heal block!");
|
||||
|
||||
|
||||
const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
|
||||
{
|
||||
[STRINGID_HEALBLOCKEDNOMORE - 12] = sText_HealBlockedNoMore,
|
||||
[STRINGID_TORMENTEDNOMORE - 12] = sText_TormentedNoMore,
|
||||
[STRINGID_ATKGOTOVERINFATUATION - 12] = sText_AttackerGotOverInfatuation,
|
||||
[STRINGID_EJECTBUTTONACTIVATE - 12] = sText_EjectButtonActivate,
|
||||
[STRINGID_REDCARDACTIVATE - 12] = sText_RedCardActivate,
|
||||
[STRINGID_PKMNBURNHEALED - 12] = sText_PkmnBurnHealed,
|
||||
[STRINGID_STICKYBARBTRANSFER - 12] = sText_StickyBarbTransfer,
|
||||
[STRINGID_ITEMCANNOTBEREMOVED - 12] = sText_ItemCannotBeRemoved,
|
||||
@ -1264,6 +1275,16 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
|
||||
[STRINGID_SCREENCLEANERENTERS - 12] = sText_ScreenCleanerActivates,
|
||||
};
|
||||
|
||||
const u16 gMentalHerbCureStringIds[] =
|
||||
{
|
||||
[B_MSG_MENTALHERBCURE_INFATUATION] = STRINGID_ATKGOTOVERINFATUATION,
|
||||
[B_MSG_MENTALHERBCURE_TAUNT] = STRINGID_BUFFERENDS,
|
||||
[B_MSG_MENTALHERBCURE_ENCORE] = STRINGID_PKMNENCOREENDED,
|
||||
[B_MSG_MENTALHERBCURE_TORMENT] = STRINGID_TORMENTEDNOMORE,
|
||||
[B_MSG_MENTALHERBCURE_HEALBLOCK] = STRINGID_HEALBLOCKEDNOMORE,
|
||||
[B_MSG_MENTALHERBCURE_DISABLE] = STRINGID_PKMNMOVEDISABLEDNOMORE,
|
||||
};
|
||||
|
||||
const u16 gTerrainStringIds[] =
|
||||
{
|
||||
STRINGID_TERRAINBECOMESMISTY, STRINGID_TERRAINBECOMESGRASSY, STRINGID_TERRAINBECOMESELECTRIC, STRINGID_TERRAINBECOMESPSYCHIC
|
||||
@ -1271,7 +1292,9 @@ const u16 gTerrainStringIds[] =
|
||||
|
||||
const u16 gTerrainPreventsStringIds[] =
|
||||
{
|
||||
STRINGID_MISTYTERRAINPREVENTS, STRINGID_ELECTRICTERRAINPREVENTS, STRINGID_PSYCHICTERRAINPREVENTS
|
||||
[B_MSG_TERRAINPREVENTS_MISTY] = STRINGID_MISTYTERRAINPREVENTS,
|
||||
[B_MSG_TERRAINPREVENTS_ELECTRIC] = STRINGID_ELECTRICTERRAINPREVENTS,
|
||||
[B_MSG_TERRAINPREVENTS_PSYCHIC] = STRINGID_PSYCHICTERRAINPREVENTS
|
||||
};
|
||||
|
||||
const u16 gMagicCoatBounceStringIds[] =
|
||||
|
@ -1681,6 +1681,9 @@ static void Cmd_accuracycheck(void)
|
||||
if ((Random() % 100 + 1) > GetTotalAccuracy(gBattlerAttacker, gBattlerTarget, move))
|
||||
{
|
||||
gMoveResultFlags |= MOVE_RESULT_MISSED;
|
||||
if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_BLUNDER_POLICY)
|
||||
gBattleStruct->blunderPolicy = TRUE; // Only activates from missing through acc/evasion checks
|
||||
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE &&
|
||||
(gBattleMoves[move].target == MOVE_TARGET_BOTH || gBattleMoves[move].target == MOVE_TARGET_FOES_AND_ALLY))
|
||||
gBattleCommunication[MISS_TYPE] = B_MSG_AVOIDED_ATK;
|
||||
@ -2499,8 +2502,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
|
||||
{
|
||||
s32 i, byTwo, affectsUser = 0;
|
||||
bool32 statusChanged = FALSE;
|
||||
bool32 noSunCanFreeze = TRUE;
|
||||
|
||||
|
||||
switch (gBattleScripting.moveEffect) // Set move effects which happen later on
|
||||
{
|
||||
case MOVE_EFFECT_KNOCK_OFF:
|
||||
@ -2559,15 +2561,9 @@ void SetMoveEffect(bool32 primary, u32 certain)
|
||||
else
|
||||
gActiveBattler = gBattlersCount;
|
||||
|
||||
if (gBattleMons[gEffectBattler].status1)
|
||||
break;
|
||||
if (gActiveBattler != gBattlersCount)
|
||||
break;
|
||||
if (GetBattlerAbility(gEffectBattler) == ABILITY_VITAL_SPIRIT
|
||||
|| GetBattlerAbility(gEffectBattler) == ABILITY_INSOMNIA
|
||||
|| GetBattlerAbility(gEffectBattler) == ABILITY_COMATOSE
|
||||
|| IsAbilityOnSide(gEffectBattler, ABILITY_SWEET_VEIL)
|
||||
|| IsAbilityStatusProtected(gEffectBattler))
|
||||
if (!CanSleep(gEffectBattler))
|
||||
break;
|
||||
|
||||
CancelMultiTurnMoves(gEffectBattler);
|
||||
@ -2606,11 +2602,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
|
||||
}
|
||||
if (!CanPoisonType(gBattleScripting.battler, gEffectBattler))
|
||||
break;
|
||||
if (gBattleMons[gEffectBattler].status1)
|
||||
break;
|
||||
if (GetBattlerAbility(gEffectBattler) == ABILITY_IMMUNITY
|
||||
|| GetBattlerAbility(gEffectBattler) == ABILITY_COMATOSE
|
||||
|| IsAbilityStatusProtected(gEffectBattler))
|
||||
if (!CanBePoisoned(gEffectBattler))
|
||||
break;
|
||||
|
||||
statusChanged = TRUE;
|
||||
@ -2645,30 +2637,14 @@ void SetMoveEffect(bool32 primary, u32 certain)
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STATUS_HAD_NO_EFFECT;
|
||||
RESET_RETURN
|
||||
}
|
||||
if (IS_BATTLER_OF_TYPE(gEffectBattler, TYPE_FIRE))
|
||||
break;
|
||||
if (GetBattlerAbility(gEffectBattler) == ABILITY_WATER_VEIL
|
||||
|| GetBattlerAbility(gEffectBattler) == ABILITY_COMATOSE
|
||||
|| GetBattlerAbility(gEffectBattler) == ABILITY_WATER_BUBBLE
|
||||
|| IsAbilityStatusProtected(gEffectBattler))
|
||||
break;
|
||||
if (gBattleMons[gEffectBattler].status1)
|
||||
|
||||
if (!CanBeBurned(gEffectBattler))
|
||||
break;
|
||||
|
||||
statusChanged = TRUE;
|
||||
break;
|
||||
case STATUS1_FREEZE:
|
||||
if (WEATHER_HAS_EFFECT && gBattleWeather & WEATHER_SUN_ANY)
|
||||
noSunCanFreeze = FALSE;
|
||||
if (IS_BATTLER_OF_TYPE(gEffectBattler, TYPE_ICE))
|
||||
break;
|
||||
if (gBattleMons[gEffectBattler].status1)
|
||||
break;
|
||||
if (noSunCanFreeze == 0)
|
||||
break;
|
||||
if (GetBattlerAbility(gEffectBattler) == ABILITY_MAGMA_ARMOR
|
||||
|| GetBattlerAbility(gEffectBattler) == ABILITY_COMATOSE
|
||||
|| IsAbilityStatusProtected(gEffectBattler))
|
||||
if (!CanBeFrozen(gEffectBattler))
|
||||
break;
|
||||
|
||||
CancelMultiTurnMoves(gEffectBattler);
|
||||
@ -2711,11 +2687,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
|
||||
}
|
||||
if (!CanParalyzeType(gBattleScripting.battler, gEffectBattler))
|
||||
break;
|
||||
if (GetBattlerAbility(gEffectBattler) == ABILITY_LIMBER
|
||||
|| GetBattlerAbility(gEffectBattler) == ABILITY_COMATOSE
|
||||
|| IsAbilityStatusProtected(gEffectBattler))
|
||||
break;
|
||||
if (gBattleMons[gEffectBattler].status1)
|
||||
if (!CanBeParalyzed(gEffectBattler))
|
||||
break;
|
||||
|
||||
statusChanged = TRUE;
|
||||
@ -2754,9 +2726,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
|
||||
break;
|
||||
if (CanPoisonType(gBattleScripting.battler, gEffectBattler))
|
||||
{
|
||||
if (GetBattlerAbility(gEffectBattler) == ABILITY_IMMUNITY
|
||||
|| GetBattlerAbility(gEffectBattler) == ABILITY_COMATOSE
|
||||
|| IsAbilityStatusProtected(gEffectBattler))
|
||||
if (!CanBePoisoned(gEffectBattler))
|
||||
break;
|
||||
|
||||
// It's redundant, because at this point we know the status1 value is 0.
|
||||
@ -2828,8 +2798,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
|
||||
switch (gBattleScripting.moveEffect)
|
||||
{
|
||||
case MOVE_EFFECT_CONFUSION:
|
||||
if (GetBattlerAbility(gEffectBattler) == ABILITY_OWN_TEMPO
|
||||
|| gBattleMons[gEffectBattler].status2 & STATUS2_CONFUSION)
|
||||
if (!CanBeConfused(gEffectBattler))
|
||||
{
|
||||
gBattlescriptCurrInstr++;
|
||||
}
|
||||
@ -3597,52 +3566,11 @@ static void Cmd_jumpifstat(void)
|
||||
{
|
||||
bool32 ret = 0;
|
||||
u8 battlerId = GetBattlerForBattleScript(gBattlescriptCurrInstr[1]);
|
||||
u8 statValue = gBattleMons[battlerId].statStages[gBattlescriptCurrInstr[3]];
|
||||
u8 statId = gBattlescriptCurrInstr[3];
|
||||
u8 cmpTo = gBattlescriptCurrInstr[4];
|
||||
u8 cmpKind = gBattlescriptCurrInstr[2];
|
||||
|
||||
// Because this command is used as a way of checking if a stat can be lowered/raised,
|
||||
// we need to do some modification at run-time.
|
||||
if (GetBattlerAbility(battlerId) == ABILITY_CONTRARY)
|
||||
{
|
||||
if (cmpKind == CMP_GREATER_THAN)
|
||||
cmpKind = CMP_LESS_THAN;
|
||||
else if (cmpKind == CMP_LESS_THAN)
|
||||
cmpKind = CMP_GREATER_THAN;
|
||||
|
||||
if (cmpTo == 0)
|
||||
cmpTo = 0xC;
|
||||
else if (cmpTo == 0xC)
|
||||
cmpTo = 0;
|
||||
}
|
||||
|
||||
switch (cmpKind)
|
||||
{
|
||||
case CMP_EQUAL:
|
||||
if (statValue == cmpTo)
|
||||
ret++;
|
||||
break;
|
||||
case CMP_NOT_EQUAL:
|
||||
if (statValue != cmpTo)
|
||||
ret++;
|
||||
break;
|
||||
case CMP_GREATER_THAN:
|
||||
if (statValue > cmpTo)
|
||||
ret++;
|
||||
break;
|
||||
case CMP_LESS_THAN:
|
||||
if (statValue < cmpTo)
|
||||
ret++;
|
||||
break;
|
||||
case CMP_COMMON_BITS:
|
||||
if (statValue & cmpTo)
|
||||
ret++;
|
||||
break;
|
||||
case CMP_NO_COMMON_BITS:
|
||||
if (!(statValue & cmpTo))
|
||||
ret++;
|
||||
break;
|
||||
}
|
||||
ret = CompareStat(battlerId, statId, cmpTo, cmpKind);
|
||||
|
||||
if (ret)
|
||||
gBattlescriptCurrInstr = T2_READ_PTR(gBattlescriptCurrInstr + 5);
|
||||
@ -4844,7 +4772,7 @@ static void Cmd_moveend(void)
|
||||
&& gBattleMons[gBattlerTarget].hp != 0 && gBattlerAttacker != gBattlerTarget
|
||||
&& GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gBattlerTarget)
|
||||
&& !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) && TARGET_TURN_DAMAGED
|
||||
&& gBattleMoves[gCurrentMove].power && gBattleMons[gBattlerTarget].statStages[STAT_ATK] < MAX_STAT_STAGE)
|
||||
&& gBattleMoves[gCurrentMove].power && CompareStat(gBattlerTarget, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
{
|
||||
gBattleMons[gBattlerTarget].statStages[STAT_ATK]++;
|
||||
BattleScriptPushCursor();
|
||||
@ -4951,8 +4879,9 @@ static void Cmd_moveend(void)
|
||||
else
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
case MOVEEND_KINGSROCK_SHELLBELL: // king's rock and shell bell
|
||||
if (ItemBattleEffects(ITEMEFFECT_KINGSROCK_SHELLBELL, 0, FALSE))
|
||||
case MOVEEND_KINGSROCK: // King's rock
|
||||
// These effects will occur at each hit in a multi-strike move
|
||||
if (ItemBattleEffects(ITEMEFFECT_KINGSROCK, 0, FALSE))
|
||||
effect = TRUE;
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
@ -5080,6 +5009,11 @@ static void Cmd_moveend(void)
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
case MOVEEND_NEXT_TARGET: // For moves hitting two opposing Pokemon.
|
||||
// Set a flag if move hits either target (for throat spray that can't check damage)
|
||||
if (!(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE)
|
||||
&& !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT))
|
||||
gProtectStructs[gBattlerAttacker].targetAffected = 1;
|
||||
|
||||
if (!(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE)
|
||||
&& gBattleTypeFlags & BATTLE_TYPE_DOUBLE
|
||||
&& !gProtectStructs[gBattlerAttacker].chargingTurn
|
||||
@ -5125,23 +5059,106 @@ static void Cmd_moveend(void)
|
||||
RecordLastUsedMoveBy(gBattlerAttacker, gCurrentMove);
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
case MOVEEND_LIFE_ORB:
|
||||
if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_LIFE_ORB
|
||||
&& IsBattlerAlive(gBattlerAttacker)
|
||||
&& !(TestSheerForceFlag(gBattlerAttacker, gCurrentMove))
|
||||
&& GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD
|
||||
&& gSpecialStatuses[gBattlerAttacker].damagedMons)
|
||||
case MOVEEND_EJECT_BUTTON:
|
||||
if (gCurrentMove != MOVE_DRAGON_TAIL
|
||||
&& gCurrentMove != MOVE_CIRCLE_THROW
|
||||
&& IsBattlerAlive(gBattlerAttacker)
|
||||
&& !TestSheerForceFlag(gBattlerAttacker, gCurrentMove)
|
||||
&& (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER || (gBattleTypeFlags & BATTLE_TYPE_TRAINER)))
|
||||
{
|
||||
gBattleMoveDamage = gBattleMons[gBattlerAttacker].maxHP / 10;
|
||||
if (gBattleMoveDamage == 0)
|
||||
gBattleMoveDamage = 1;
|
||||
effect = TRUE;
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_ItemHurtRet;
|
||||
gLastUsedItem = gBattleMons[gBattlerAttacker].item;
|
||||
// Since we check if battler was damaged, we don't need to check move result.
|
||||
// In fact, doing so actually prevents multi-target moves from activating eject button properly
|
||||
u8 battlers[4] = {0, 1, 2, 3};
|
||||
SortBattlersBySpeed(battlers, FALSE);
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
u8 battler = battlers[i];
|
||||
// Attacker is the damage-dealer, battler is mon to be switched out
|
||||
if (IsBattlerAlive(battler)
|
||||
&& GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_EJECT_BUTTON
|
||||
&& !DoesSubstituteBlockMove(gCurrentMove, gBattlerAttacker, battler)
|
||||
&& (gSpecialStatuses[battler].physicalDmg != 0 || gSpecialStatuses[battler].specialDmg != 0)
|
||||
&& CountUsablePartyMons(battler) > 0) // Has mon to switch into
|
||||
{
|
||||
gActiveBattler = gBattleScripting.battler = battler;
|
||||
gLastUsedItem = gBattleMons[battler].item;
|
||||
if (gBattleMoves[gCurrentMove].effect == EFFECT_HIT_ESCAPE)
|
||||
gBattlescriptCurrInstr = BattleScript_MoveEnd; // Prevent user switch-in selection
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_EjectButtonActivates;
|
||||
effect = TRUE;
|
||||
break; // Only the fastest Eject Button activates
|
||||
}
|
||||
}
|
||||
}
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
case MOVEEND_RED_CARD:
|
||||
if (gCurrentMove != MOVE_DRAGON_TAIL
|
||||
&& gCurrentMove != MOVE_CIRCLE_THROW
|
||||
&& IsBattlerAlive(gBattlerAttacker)
|
||||
&& !TestSheerForceFlag(gBattlerAttacker, gCurrentMove))
|
||||
{
|
||||
// Since we check if battler was damaged, we don't need to check move result.
|
||||
// In fact, doing so actually prevents multi-target moves from activating red card properly
|
||||
u8 battlers[4] = {0, 1, 2, 3};
|
||||
SortBattlersBySpeed(battlers, FALSE);
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
u8 battler = battlers[i];
|
||||
// Search for fastest hit pokemon with a red card
|
||||
// Attacker is the one to be switched out, battler is one with red card
|
||||
if (battler != gBattlerAttacker
|
||||
&& IsBattlerAlive(battler)
|
||||
&& !DoesSubstituteBlockMove(gCurrentMove, gBattlerAttacker, battler)
|
||||
&& GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_RED_CARD
|
||||
&& (gSpecialStatuses[battler].physicalDmg != 0 || gSpecialStatuses[battler].specialDmg != 0)
|
||||
&& CanBattlerSwitch(gBattlerAttacker))
|
||||
{
|
||||
gLastUsedItem = gBattleMons[battler].item;
|
||||
gActiveBattler = gBattleStruct->savedBattlerTarget = gBattleScripting.battler = battler; // Battler with red card
|
||||
gEffectBattler = gBattlerAttacker;
|
||||
if (gBattleMoves[gCurrentMove].effect == EFFECT_HIT_ESCAPE)
|
||||
gBattlescriptCurrInstr = BattleScript_MoveEnd; // Prevent user switch-in selection
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_RedCardActivates;
|
||||
effect = TRUE;
|
||||
break; // Only fastest red card activates
|
||||
}
|
||||
}
|
||||
}
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
case MOVEEND_EJECT_PACK:
|
||||
{
|
||||
u8 battlers[4] = {0, 1, 2, 3};
|
||||
SortBattlersBySpeed(battlers, FALSE);
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
u8 battler = battlers[i];
|
||||
if (IsBattlerAlive(battler)
|
||||
&& gSpecialStatuses[battler].statFell
|
||||
&& GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_EJECT_PACK
|
||||
&& !(gCurrentMove == MOVE_PARTING_SHOT && CanBattlerSwitch(gBattlerAttacker)) // Does not activate if attacker used Parting Shot and can switch out
|
||||
&& CountUsablePartyMons(battler) > 0) // Has mon to switch into
|
||||
{
|
||||
gSpecialStatuses[battler].statFell = FALSE;
|
||||
gActiveBattler = gBattleScripting.battler = battler;
|
||||
gLastUsedItem = gBattleMons[battler].item;
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_EjectPackActivates;
|
||||
effect = TRUE;
|
||||
break; // Only fastest eject pack activates
|
||||
}
|
||||
}
|
||||
}
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
case MOVEEND_LIFEORB_SHELLBELL:
|
||||
if (ItemBattleEffects(ITEMEFFECT_LIFEORB_SHELLBELL, 0, FALSE))
|
||||
effect = TRUE;
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
case MOVEEND_PICKPOCKET:
|
||||
if (IsBattlerAlive(gBattlerAttacker)
|
||||
&& gBattleMons[gBattlerAttacker].item != ITEM_NONE // Attacker must be holding an item
|
||||
@ -5242,6 +5259,7 @@ static void Cmd_moveend(void)
|
||||
if (gSpecialStatuses[gBattlerAttacker].dancerOriginalTarget)
|
||||
*(gBattleStruct->moveTarget + gBattlerAttacker) = gSpecialStatuses[gBattlerAttacker].dancerOriginalTarget & 0x3;
|
||||
gProtectStructs[gBattlerAttacker].usesBouncedMove = 0;
|
||||
gProtectStructs[gBattlerAttacker].targetAffected = 0;
|
||||
gBattleStruct->ateBoost[gBattlerAttacker] = 0;
|
||||
gStatuses3[gBattlerAttacker] &= ~(STATUS3_ME_FIRST);
|
||||
gSpecialStatuses[gBattlerAttacker].gemBoost = 0;
|
||||
@ -5511,6 +5529,7 @@ bool32 CanBattlerSwitch(u32 battlerId)
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check if attacker side has mon to switch into
|
||||
battlerIn1 = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
|
||||
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
|
||||
@ -5945,6 +5964,7 @@ static void Cmd_switchineffects(void)
|
||||
if (!(gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_SPIKES_DAMAGED)
|
||||
&& (gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_SPIKES)
|
||||
&& GetBattlerAbility(gActiveBattler) != ABILITY_MAGIC_GUARD
|
||||
&& IsBattlerAffectedByHazards(gActiveBattler, FALSE)
|
||||
&& IsBattlerGrounded(gActiveBattler))
|
||||
{
|
||||
u8 spikesDmg = (5 - gSideTimers[GetBattlerSide(gActiveBattler)].spikesAmount) * 2;
|
||||
@ -5957,6 +5977,7 @@ static void Cmd_switchineffects(void)
|
||||
}
|
||||
else if (!(gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_STEALTH_ROCK_DAMAGED)
|
||||
&& (gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_STEALTH_ROCK)
|
||||
&& IsBattlerAffectedByHazards(gActiveBattler, FALSE)
|
||||
&& GetBattlerAbility(gActiveBattler) != ABILITY_MAGIC_GUARD)
|
||||
{
|
||||
gSideStatuses[GetBattlerSide(gActiveBattler)] |= SIDE_STATUS_STEALTH_ROCK_DAMAGED;
|
||||
@ -5978,12 +5999,13 @@ static void Cmd_switchineffects(void)
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_ToxicSpikesAbsorbed;
|
||||
}
|
||||
else
|
||||
else if (IsBattlerAffectedByHazards(gActiveBattler, TRUE))
|
||||
{
|
||||
if (!(gBattleMons[gActiveBattler].status1 & STATUS1_ANY)
|
||||
&& !IS_BATTLER_OF_TYPE(gActiveBattler, TYPE_STEEL)
|
||||
&& GetBattlerAbility(gActiveBattler) != ABILITY_IMMUNITY
|
||||
&& !(gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_SAFEGUARD))
|
||||
&& !(gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_SAFEGUARD)
|
||||
&& !(gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN))
|
||||
{
|
||||
if (gSideTimers[GetBattlerSide(gActiveBattler)].toxicSpikesAmount >= 2)
|
||||
gBattleMons[gActiveBattler].status1 |= STATUS1_TOXIC_POISON;
|
||||
@ -6000,6 +6022,7 @@ static void Cmd_switchineffects(void)
|
||||
}
|
||||
else if (!(gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_STICKY_WEB_DAMAGED)
|
||||
&& (gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_STICKY_WEB)
|
||||
&& IsBattlerAffectedByHazards(gActiveBattler, FALSE)
|
||||
&& IsBattlerGrounded(gActiveBattler))
|
||||
{
|
||||
gSideStatuses[GetBattlerSide(gActiveBattler)] |= SIDE_STATUS_STICKY_WEB_DAMAGED;
|
||||
@ -7456,7 +7479,7 @@ static void Cmd_various(void)
|
||||
bits = 0;
|
||||
for (i = STAT_ATK; i < NUM_BATTLE_STATS; i++)
|
||||
{
|
||||
if (gBattleMons[gActiveBattler].statStages[i] != 12)
|
||||
if (CompareStat(gActiveBattler, i, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
bits |= gBitTable[i];
|
||||
}
|
||||
if (bits)
|
||||
@ -7693,7 +7716,7 @@ static void Cmd_various(void)
|
||||
|| GetBattlerAbility(gActiveBattler) == ABILITY_AS_ONE_ICE_RIDER)
|
||||
&& HasAttackerFaintedTarget()
|
||||
&& !NoAliveMonsForEitherParty()
|
||||
&& gBattleMons[gBattlerAttacker].statStages[STAT_ATK] != 12)
|
||||
&& CompareStat(gBattlerAttacker, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
{
|
||||
gBattleMons[gBattlerAttacker].statStages[STAT_ATK]++;
|
||||
SET_STATCHANGER(STAT_ATK, 1, FALSE);
|
||||
@ -7711,7 +7734,7 @@ static void Cmd_various(void)
|
||||
|| GetBattlerAbility(gActiveBattler) == ABILITY_AS_ONE_SHADOW_RIDER)
|
||||
&& HasAttackerFaintedTarget()
|
||||
&& !NoAliveMonsForEitherParty()
|
||||
&& gBattleMons[gBattlerAttacker].statStages[STAT_SPATK] != 12)
|
||||
&& CompareStat(gBattlerAttacker, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
{
|
||||
gBattleMons[gBattlerAttacker].statStages[STAT_SPATK]++;
|
||||
SET_STATCHANGER(STAT_SPATK, 1, FALSE);
|
||||
@ -7756,7 +7779,7 @@ static void Cmd_various(void)
|
||||
if (GetBattlerAbility(gActiveBattler) == ABILITY_BEAST_BOOST
|
||||
&& HasAttackerFaintedTarget()
|
||||
&& !NoAliveMonsForEitherParty()
|
||||
&& gBattleMons[gBattlerAttacker].statStages[i] != 12)
|
||||
&& CompareStat(gBattlerAttacker, i, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
{
|
||||
gBattleMons[gBattlerAttacker].statStages[i]++;
|
||||
SET_STATCHANGER(i, 1, FALSE);
|
||||
@ -7773,7 +7796,7 @@ static void Cmd_various(void)
|
||||
if (GetBattlerAbility(gBattleScripting.battler) == ABILITY_SOUL_HEART
|
||||
&& IsBattlerAlive(gBattleScripting.battler)
|
||||
&& !NoAliveMonsForEitherParty()
|
||||
&& gBattleMons[gBattleScripting.battler].statStages[STAT_SPATK] != 12)
|
||||
&& CompareStat(gBattleScripting.battler, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
{
|
||||
gBattleMons[gBattleScripting.battler].statStages[STAT_SPATK]++;
|
||||
SET_STATCHANGER(STAT_SPATK, 1, FALSE);
|
||||
@ -7789,7 +7812,7 @@ static void Cmd_various(void)
|
||||
if (gBattleMoves[gCurrentMove].effect == EFFECT_FELL_STINGER
|
||||
&& HasAttackerFaintedTarget()
|
||||
&& !NoAliveMonsForEitherParty()
|
||||
&& gBattleMons[gBattlerAttacker].statStages[STAT_ATK] != 12)
|
||||
&& CompareStat(gBattlerAttacker, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
{
|
||||
if (B_FELL_STINGER_STAT_RAISE >= GEN_7)
|
||||
SET_STATCHANGER(STAT_ATK, 3, FALSE);
|
||||
@ -8115,6 +8138,7 @@ static void Cmd_various(void)
|
||||
&& !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
|
||||
&& TARGET_TURN_DAMAGED)
|
||||
{
|
||||
gBattleScripting.switchCase = B_SWITCH_HIT;
|
||||
gBattlescriptCurrInstr = BattleScript_ForceRandomSwitch;
|
||||
}
|
||||
else
|
||||
@ -8500,6 +8524,59 @@ static void Cmd_various(void)
|
||||
if (ItemBattleEffects(1, gActiveBattler, FALSE))
|
||||
return;
|
||||
break;
|
||||
case VARIOUS_ROOM_SERVICE:
|
||||
if (GetBattlerHoldEffect(gActiveBattler, TRUE) == HOLD_EFFECT_ROOM_SERVICE && TryRoomService(gActiveBattler))
|
||||
{
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_BerryStatRaiseRet;
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3);
|
||||
}
|
||||
return;
|
||||
case VARIOUS_TERRAIN_SEED:
|
||||
if (GetBattlerHoldEffect(gActiveBattler, TRUE) == HOLD_EFFECT_SEEDS)
|
||||
{
|
||||
u8 effect = 0;
|
||||
u16 item = gBattleMons[gActiveBattler].item;
|
||||
switch (GetBattlerHoldEffectParam(gActiveBattler))
|
||||
{
|
||||
case HOLD_EFFECT_PARAM_ELECTRIC_TERRAIN:
|
||||
effect = TryHandleSeed(gActiveBattler, STATUS_FIELD_ELECTRIC_TERRAIN, STAT_DEF, item, FALSE);
|
||||
break;
|
||||
case HOLD_EFFECT_PARAM_GRASSY_TERRAIN:
|
||||
effect = TryHandleSeed(gActiveBattler, STATUS_FIELD_GRASSY_TERRAIN, STAT_DEF, item, FALSE);
|
||||
break;
|
||||
case HOLD_EFFECT_PARAM_MISTY_TERRAIN:
|
||||
effect = TryHandleSeed(gActiveBattler, STATUS_FIELD_MISTY_TERRAIN, STAT_SPDEF, item, FALSE);
|
||||
break;
|
||||
case HOLD_EFFECT_PARAM_PSYCHIC_TERRAIN:
|
||||
effect = TryHandleSeed(gActiveBattler, STATUS_FIELD_PSYCHIC_TERRAIN, STAT_SPDEF, item, FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
if (effect)
|
||||
return;
|
||||
}
|
||||
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3);
|
||||
return;
|
||||
case VARIOUS_MAKE_INVISIBLE:
|
||||
if (gBattleControllerExecFlags)
|
||||
break;
|
||||
|
||||
BtlController_EmitSpriteInvisibility(0, TRUE);
|
||||
MarkBattlerForControllerExec(gActiveBattler);
|
||||
break;
|
||||
case VARIOUS_JUMP_IF_TERRAIN_AFFECTED:
|
||||
{
|
||||
u32 flags = T1_READ_32(gBattlescriptCurrInstr + 3);
|
||||
if (IsBattlerTerrainAffected(gActiveBattler, flags))
|
||||
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 7);
|
||||
else
|
||||
gBattlescriptCurrInstr += 11;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
gBattlescriptCurrInstr += 3;
|
||||
@ -8826,6 +8903,14 @@ static void Cmd_trysetrest(void)
|
||||
{
|
||||
gBattlescriptCurrInstr = failJump;
|
||||
}
|
||||
else if (IsBattlerTerrainAffected(gBattlerTarget, STATUS_FIELD_ELECTRIC_TERRAIN))
|
||||
{
|
||||
gBattlescriptCurrInstr = BattleScript_ElectricTerrainPrevents;
|
||||
}
|
||||
else if (IsBattlerTerrainAffected(gBattlerTarget, STATUS_FIELD_MISTY_TERRAIN))
|
||||
{
|
||||
gBattlescriptCurrInstr = BattleScript_MistyTerrainPrevents;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gBattleMons[gBattlerTarget].status1 & ((u8)(~STATUS1_SLEEP)))
|
||||
@ -9184,11 +9269,18 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr
|
||||
gBattleTextBuff2[index] = STRINGID_STATFELL >> 8;
|
||||
index++;
|
||||
gBattleTextBuff2[index] = B_BUFF_EOS;
|
||||
|
||||
|
||||
if (gBattleMons[gActiveBattler].statStages[statId] == MIN_STAT_STAGE)
|
||||
{
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STAT_WONT_DECREASE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check eject pack. disableEjectPack set for edge cases (e.g. attacking weak armor'd eject pack holder with u-turn)
|
||||
if (gProtectStructs[gActiveBattler].disableEjectPack == 0)
|
||||
gSpecialStatuses[gActiveBattler].statFell = TRUE;
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = (gBattlerTarget == gActiveBattler); // B_MSG_ATTACKER_STAT_FELL or B_MSG_DEFENDER_STAT_FELL
|
||||
}
|
||||
}
|
||||
}
|
||||
else // stat increase
|
||||
@ -9363,6 +9455,36 @@ static void Cmd_forcerandomswitch(void)
|
||||
struct Pokemon* party = NULL;
|
||||
s32 validMons = 0;
|
||||
s32 minNeeded;
|
||||
|
||||
bool32 redCardForcedSwitch = FALSE;
|
||||
|
||||
// Red card checks against wild pokemon. If we have reached here, the player has a mon to switch into
|
||||
// Red card swaps attacker with target to get the animation correct, so here we check attacker which is really the target. Thanks GF...
|
||||
if (gBattleScripting.switchCase == B_SWITCH_RED_CARD
|
||||
&& !(gBattleTypeFlags & BATTLE_TYPE_TRAINER)
|
||||
&& GetBattlerSide(gBattlerAttacker) == B_SIDE_OPPONENT) // Check opponent's red card activating
|
||||
{
|
||||
if (!WILD_DOUBLE_BATTLE)
|
||||
{
|
||||
// Wild mon with red card will end single battle
|
||||
gBattlescriptCurrInstr = BattleScript_RoarSuccessEndBattle;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Wild double battle, wild mon red card activation on player
|
||||
if (IS_WHOLE_SIDE_ALIVE(gBattlerTarget))
|
||||
{
|
||||
// Both player's battlers are alive
|
||||
redCardForcedSwitch = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Player has only one mon alive -> force red card switch before manually switching to other mon
|
||||
redCardForcedSwitch = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Swapping pokemon happens in:
|
||||
// trainer battles
|
||||
@ -9376,8 +9498,9 @@ static void Cmd_forcerandomswitch(void)
|
||||
|| (WILD_DOUBLE_BATTLE
|
||||
&& GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER
|
||||
&& GetBattlerSide(gBattlerTarget) == B_SIDE_PLAYER)
|
||||
|| redCardForcedSwitch
|
||||
)
|
||||
{
|
||||
{
|
||||
if (GetBattlerSide(gBattlerTarget) == B_SIDE_PLAYER)
|
||||
party = gPlayerParty;
|
||||
else
|
||||
@ -9485,7 +9608,7 @@ static void Cmd_forcerandomswitch(void)
|
||||
}
|
||||
}
|
||||
|
||||
if (validMons <= minNeeded)
|
||||
if (!redCardForcedSwitch && validMons <= minNeeded)
|
||||
{
|
||||
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1);
|
||||
}
|
||||
@ -10655,8 +10778,8 @@ static void Cmd_handlerollout(void)
|
||||
static void Cmd_jumpifconfusedandstatmaxed(void)
|
||||
{
|
||||
if (gBattleMons[gBattlerTarget].status2 & STATUS2_CONFUSION
|
||||
&& gBattleMons[gBattlerTarget].statStages[gBattlescriptCurrInstr[1]] == MAX_STAT_STAGE)
|
||||
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 2);
|
||||
&& !CompareStat(gBattlerTarget, gBattlescriptCurrInstr[1], MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 2); // Fails if we're confused AND stat cannot be raised
|
||||
else
|
||||
gBattlescriptCurrInstr += 6;
|
||||
}
|
||||
@ -10865,7 +10988,8 @@ static void Cmd_maxattackhalvehp(void) // belly drum
|
||||
|
||||
if (!(gBattleMons[gBattlerAttacker].maxHP / 2))
|
||||
halfHp = 1;
|
||||
|
||||
|
||||
// Belly Drum fails if the user's current HP is less than half its maximum, or if the user's Attack is already at +6 (even if the user has Contrary).
|
||||
if (gBattleMons[gBattlerAttacker].statStages[STAT_ATK] < MAX_STAT_STAGE
|
||||
&& gBattleMons[gBattlerAttacker].hp > halfHp)
|
||||
{
|
||||
@ -11465,6 +11589,18 @@ static void Cmd_setyawn(void)
|
||||
{
|
||||
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1);
|
||||
}
|
||||
else if (IsBattlerTerrainAffected(gBattlerTarget, STATUS_FIELD_ELECTRIC_TERRAIN))
|
||||
{
|
||||
// When Yawn is used while Electric Terrain is set and drowsiness is set from Yawn being used against target in the previous turn:
|
||||
// "But it failed" will display first.
|
||||
gBattlescriptCurrInstr = BattleScript_ElectricTerrainPrevents;
|
||||
}
|
||||
else if (IsBattlerTerrainAffected(gBattlerTarget, STATUS_FIELD_MISTY_TERRAIN))
|
||||
{
|
||||
// When Yawn is used while Misty Terrain is set and drowsiness is set from Yawn being used against target in the previous turn:
|
||||
// "But it failed" will display first.
|
||||
gBattlescriptCurrInstr = BattleScript_MistyTerrainPrevents;
|
||||
}
|
||||
else
|
||||
{
|
||||
gStatuses3[gBattlerTarget] |= STATUS3_YAWN_TURN(2);
|
||||
@ -12538,14 +12674,14 @@ static void Cmd_trainerslideout(void)
|
||||
|
||||
static const u16 sTelekinesisBanList[] =
|
||||
{
|
||||
SPECIES_DIGLETT,
|
||||
SPECIES_DUGTRIO,
|
||||
SPECIES_DIGLETT,
|
||||
SPECIES_DUGTRIO,
|
||||
#ifdef POKEMON_EXPANSION
|
||||
SPECIES_DIGLETT_ALOLAN,
|
||||
SPECIES_DUGTRIO_ALOLAN,
|
||||
SPECIES_SANDYGAST,
|
||||
SPECIES_PALOSSAND,
|
||||
SPECIES_GENGAR_MEGA,
|
||||
SPECIES_DIGLETT_ALOLAN,
|
||||
SPECIES_DUGTRIO_ALOLAN,
|
||||
SPECIES_SANDYGAST,
|
||||
SPECIES_PALOSSAND,
|
||||
SPECIES_GENGAR_MEGA,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -1410,7 +1410,6 @@ void CancelMultiTurnMoves(u8 battler)
|
||||
bool8 WasUnableToUseMove(u8 battler)
|
||||
{
|
||||
if (gProtectStructs[battler].prlzImmobility
|
||||
|| gProtectStructs[battler].targetNotAffected
|
||||
|| gProtectStructs[battler].usedImprisonedMove
|
||||
|| gProtectStructs[battler].loveImmobility
|
||||
|| gProtectStructs[battler].usedDisabledMove
|
||||
@ -1444,8 +1443,8 @@ void PrepareStringBattle(u16 stringId, u8 battler)
|
||||
|
||||
// Check Defiant and Competitive stat raise whenever a stat is lowered.
|
||||
else if ((stringId == STRINGID_DEFENDERSSTATFELL || stringId == STRINGID_PKMNCUTSATTACKWITH)
|
||||
&& ((GetBattlerAbility(gBattlerTarget) == ABILITY_DEFIANT && gBattleMons[gBattlerTarget].statStages[STAT_ATK] != MAX_STAT_STAGE)
|
||||
|| (GetBattlerAbility(gBattlerTarget) == ABILITY_COMPETITIVE && gBattleMons[gBattlerTarget].statStages[STAT_SPATK] != MAX_STAT_STAGE))
|
||||
&& ((GetBattlerAbility(gBattlerTarget) == ABILITY_DEFIANT && CompareStat(gBattlerTarget, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
|| (GetBattlerAbility(gBattlerTarget) == ABILITY_COMPETITIVE && CompareStat(gBattlerTarget, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN)))
|
||||
&& gSpecialStatuses[gBattlerTarget].changedStatsBattlerId != BATTLE_PARTNER(gBattlerTarget)
|
||||
&& gSpecialStatuses[gBattlerTarget].changedStatsBattlerId != gBattlerTarget)
|
||||
{
|
||||
@ -2727,11 +2726,24 @@ u8 DoBattlerEndTurnEffects(void)
|
||||
&& !IsLeafGuardProtected(gActiveBattler))
|
||||
{
|
||||
CancelMultiTurnMoves(gActiveBattler);
|
||||
gBattleMons[gActiveBattler].status1 |= (Random() & 3) + 2;
|
||||
BtlController_EmitSetMonData(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBattler].status1);
|
||||
MarkBattlerForControllerExec(gActiveBattler);
|
||||
gEffectBattler = gActiveBattler;
|
||||
BattleScriptExecute(BattleScript_YawnMakesAsleep);
|
||||
if (IsBattlerTerrainAffected(gActiveBattler, STATUS_FIELD_ELECTRIC_TERRAIN))
|
||||
{
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAINPREVENTS_ELECTRIC;
|
||||
BattleScriptExecute(BattleScript_TerrainPreventsEnd2);
|
||||
}
|
||||
else if (IsBattlerTerrainAffected(gActiveBattler, STATUS_FIELD_MISTY_TERRAIN))
|
||||
{
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAINPREVENTS_MISTY;
|
||||
BattleScriptExecute(BattleScript_TerrainPreventsEnd2);
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattleMons[gActiveBattler].status1 |= (Random() & 3) + 2;
|
||||
BtlController_EmitSetMonData(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBattler].status1);
|
||||
MarkBattlerForControllerExec(gActiveBattler);
|
||||
BattleScriptExecute(BattleScript_YawnMakesAsleep);
|
||||
}
|
||||
effect++;
|
||||
}
|
||||
}
|
||||
@ -4073,7 +4085,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
|
||||
|
||||
gSpecialStatuses[battler].switchInAbilityDone = 1;
|
||||
|
||||
if (gBattleMons[battler].statStages[statId] != MAX_STAT_STAGE)
|
||||
if (CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
{
|
||||
gBattleMons[battler].statStages[statId]++;
|
||||
SET_STATCHANGER(statId, 1, FALSE);
|
||||
@ -4324,7 +4336,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
|
||||
}
|
||||
break;
|
||||
case ABILITY_SPEED_BOOST:
|
||||
if (gBattleMons[battler].statStages[STAT_SPEED] < MAX_STAT_STAGE && gDisableStructs[battler].isFirstTurn != 2)
|
||||
if (CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN) && gDisableStructs[battler].isFirstTurn != 2)
|
||||
{
|
||||
gBattleMons[battler].statStages[STAT_SPEED]++;
|
||||
gBattleScripting.animArg1 = 14 + STAT_SPEED;
|
||||
@ -4342,9 +4354,9 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
|
||||
|
||||
for (i = STAT_ATK; i < statsNum; i++)
|
||||
{
|
||||
if (gBattleMons[battler].statStages[i] != MIN_STAT_STAGE)
|
||||
if (CompareStat(battler, i, MIN_STAT_STAGE, CMP_GREATER_THAN))
|
||||
validToLower |= gBitTable[i];
|
||||
if (gBattleMons[battler].statStages[i] != MAX_STAT_STAGE)
|
||||
if (CompareStat(battler, i, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
validToRaise |= gBitTable[i];
|
||||
}
|
||||
|
||||
@ -4547,7 +4559,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
|
||||
}
|
||||
else if (effect == 2) // Boost Stat ability;
|
||||
{
|
||||
if (gBattleMons[battler].statStages[statId] == MAX_STAT_STAGE)
|
||||
if (!CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
{
|
||||
if ((gProtectStructs[gBattlerAttacker].notFirstStrike))
|
||||
gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless;
|
||||
@ -4576,7 +4588,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
|
||||
&& TARGET_TURN_DAMAGED
|
||||
&& IsBattlerAlive(battler)
|
||||
&& moveType == TYPE_DARK
|
||||
&& gBattleMons[battler].statStages[STAT_ATK] != MAX_STAT_STAGE)
|
||||
&& CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
{
|
||||
SET_STATCHANGER(STAT_ATK, 1, FALSE);
|
||||
BattleScriptPushCursor();
|
||||
@ -4589,7 +4601,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
|
||||
&& TARGET_TURN_DAMAGED
|
||||
&& IsBattlerAlive(battler)
|
||||
&& (moveType == TYPE_DARK || moveType == TYPE_BUG || moveType == TYPE_GHOST)
|
||||
&& gBattleMons[battler].statStages[STAT_SPEED] != MAX_STAT_STAGE)
|
||||
&& CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
{
|
||||
SET_STATCHANGER(STAT_SPEED, 1, FALSE);
|
||||
BattleScriptPushCursor();
|
||||
@ -4602,7 +4614,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
|
||||
&& TARGET_TURN_DAMAGED
|
||||
&& IsBattlerAlive(battler)
|
||||
&& moveType == TYPE_WATER
|
||||
&& gBattleMons[battler].statStages[STAT_DEF] != MAX_STAT_STAGE)
|
||||
&& CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
{
|
||||
SET_STATCHANGER(STAT_DEF, 2, FALSE);
|
||||
BattleScriptPushCursor();
|
||||
@ -4614,7 +4626,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
|
||||
if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
|
||||
&& TARGET_TURN_DAMAGED
|
||||
&& IsBattlerAlive(battler)
|
||||
&& gBattleMons[battler].statStages[STAT_DEF] != MAX_STAT_STAGE)
|
||||
&& CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
{
|
||||
SET_STATCHANGER(STAT_DEF, 1, FALSE);
|
||||
BattleScriptPushCursor();
|
||||
@ -4631,7 +4643,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
|
||||
&& gBattleMons[battler].hp < gBattleMons[battler].maxHP / 2
|
||||
&& (gMultiHitCounter == 0 || gMultiHitCounter == 1)
|
||||
&& !(TestSheerForceFlag(gBattlerAttacker, gCurrentMove))
|
||||
&& gBattleMons[battler].statStages[STAT_SPATK] != MAX_STAT_STAGE)
|
||||
&& CompareStat(battler, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
{
|
||||
SET_STATCHANGER(STAT_SPATK, 1, FALSE);
|
||||
BattleScriptPushCursor();
|
||||
@ -4662,8 +4674,12 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
|
||||
&& TARGET_TURN_DAMAGED
|
||||
&& IsBattlerAlive(battler)
|
||||
&& IS_MOVE_PHYSICAL(gCurrentMove)
|
||||
&& (gBattleMons[battler].statStages[STAT_SPEED] != MAX_STAT_STAGE || gBattleMons[battler].statStages[STAT_DEF] != MIN_STAT_STAGE))
|
||||
&& (CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN) // Don't activate if speed cannot be raised
|
||||
|| CompareStat(battler, STAT_DEF, MIN_STAT_STAGE, CMP_GREATER_THAN))) // Don't activate if defense cannot be lowered
|
||||
{
|
||||
if (gBattleMoves[gCurrentMove].effect == EFFECT_HIT_ESCAPE && CanBattlerSwitch(gBattlerAttacker))
|
||||
gProtectStructs[battler].disableEjectPack = 1; // Set flag for target
|
||||
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_WeakArmorActivates;
|
||||
effect++;
|
||||
@ -4719,7 +4735,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
|
||||
&& gIsCriticalHit
|
||||
&& TARGET_TURN_DAMAGED
|
||||
&& IsBattlerAlive(battler)
|
||||
&& gBattleMons[battler].statStages[STAT_ATK] != MAX_STAT_STAGE)
|
||||
&& CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
{
|
||||
SET_STATCHANGER(STAT_ATK, MAX_STAT_STAGE - gBattleMons[battler].statStages[STAT_ATK], FALSE);
|
||||
BattleScriptPushCursor();
|
||||
@ -4746,7 +4762,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
|
||||
case ABILITY_TANGLING_HAIR:
|
||||
if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
|
||||
&& gBattleMons[gBattlerAttacker].hp != 0
|
||||
&& gBattleMons[gBattlerAttacker].statStages[STAT_SPEED] != MIN_STAT_STAGE
|
||||
&& CompareStat(gBattlerAttacker, STAT_SPEED, MIN_STAT_STAGE, CMP_GREATER_THAN)
|
||||
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
|
||||
&& TARGET_TURN_DAMAGED
|
||||
&& IsMoveMakingContact(move, gBattlerAttacker))
|
||||
@ -4817,10 +4833,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
|
||||
&& gBattleMons[gBattlerAttacker].hp != 0
|
||||
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
|
||||
&& TARGET_TURN_DAMAGED
|
||||
&& GetBattlerAbility(gBattlerAttacker) != ABILITY_INSOMNIA
|
||||
&& GetBattlerAbility(gBattlerAttacker) != ABILITY_VITAL_SPIRIT
|
||||
&& !(gBattleMons[gBattlerAttacker].status1 & STATUS1_ANY)
|
||||
&& !IsAbilityStatusProtected(gBattlerAttacker)
|
||||
&& CanSleep(gBattlerAttacker)
|
||||
&& IsMoveMakingContact(move, gBattlerAttacker)
|
||||
&& (Random() % 3) == 0)
|
||||
{
|
||||
@ -4839,11 +4852,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
|
||||
&& gBattleMons[gBattlerAttacker].hp != 0
|
||||
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
|
||||
&& TARGET_TURN_DAMAGED
|
||||
&& !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_POISON)
|
||||
&& !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_STEEL)
|
||||
&& GetBattlerAbility(gBattlerAttacker) != ABILITY_IMMUNITY
|
||||
&& !(gBattleMons[gBattlerAttacker].status1 & STATUS1_ANY)
|
||||
&& !IsAbilityStatusProtected(gBattlerAttacker)
|
||||
&& CanBePoisoned(gBattlerAttacker)
|
||||
&& IsMoveMakingContact(move, gBattlerAttacker)
|
||||
&& (Random() % 3) == 0)
|
||||
{
|
||||
@ -4861,10 +4870,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
|
||||
&& gBattleMons[gBattlerAttacker].hp != 0
|
||||
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
|
||||
&& TARGET_TURN_DAMAGED
|
||||
&& CanParalyzeType(gBattlerTarget, gBattlerAttacker)
|
||||
&& GetBattlerAbility(gBattlerAttacker) != ABILITY_LIMBER
|
||||
&& !(gBattleMons[gBattlerAttacker].status1 & STATUS1_ANY)
|
||||
&& !IsAbilityStatusProtected(gBattlerAttacker)
|
||||
&& CanBeParalyzed(gBattlerAttacker)
|
||||
&& IsMoveMakingContact(move, gBattlerAttacker)
|
||||
&& (Random() % 3) == 0)
|
||||
{
|
||||
@ -4881,11 +4887,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
|
||||
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
|
||||
&& (gBattleMoves[move].flags & FLAG_MAKES_CONTACT)
|
||||
&& TARGET_TURN_DAMAGED
|
||||
&& !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_FIRE)
|
||||
&& GetBattlerAbility(gBattlerAttacker) != ABILITY_WATER_VEIL
|
||||
&& GetBattlerAbility(gBattlerAttacker) != ABILITY_WATER_BUBBLE
|
||||
&& !(gBattleMons[gBattlerAttacker].status1 & STATUS1_ANY)
|
||||
&& !IsAbilityStatusProtected(gBattlerAttacker)
|
||||
&& CanBeBurned(gBattlerAttacker)
|
||||
&& (Random() % 3) == 0)
|
||||
{
|
||||
gBattleScripting.moveEffect = MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_BURN;
|
||||
@ -4940,7 +4942,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
|
||||
if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
|
||||
&& TARGET_TURN_DAMAGED
|
||||
&& IsBattlerAlive(battler)
|
||||
&& gBattleMons[battler].statStages[STAT_SPEED] != MAX_STAT_STAGE
|
||||
&& CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN)
|
||||
&& (moveType == TYPE_FIRE || moveType == TYPE_WATER))
|
||||
{
|
||||
SET_STATCHANGER(STAT_SPEED, 6, FALSE);
|
||||
@ -4993,11 +4995,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
|
||||
if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
|
||||
&& gBattleMons[gBattlerTarget].hp != 0
|
||||
&& !gProtectStructs[gBattlerTarget].confusionSelfDmg
|
||||
&& !IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_POISON)
|
||||
&& !IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_STEEL)
|
||||
&& GetBattlerAbility(gBattlerTarget) != ABILITY_IMMUNITY
|
||||
&& !(gBattleMons[gBattlerTarget].status1 & STATUS1_ANY)
|
||||
&& !IsAbilityStatusProtected(gBattlerTarget)
|
||||
&& CanBePoisoned(gBattlerTarget)
|
||||
&& IsMoveMakingContact(move, gBattlerAttacker)
|
||||
&& (Random() % 3) == 0)
|
||||
{
|
||||
@ -5400,6 +5398,100 @@ enum
|
||||
ITEM_STATS_CHANGE, // 5
|
||||
};
|
||||
|
||||
bool32 IsBattlerTerrainAffected(u8 battlerId, u32 terrainFlag)
|
||||
{
|
||||
if (!(gFieldStatuses & terrainFlag))
|
||||
return FALSE;
|
||||
else if (gStatuses3[battlerId] & STATUS3_SEMI_INVULNERABLE)
|
||||
return FALSE;
|
||||
|
||||
return IsBattlerGrounded(battlerId);
|
||||
}
|
||||
|
||||
bool32 CanSleep(u8 battlerId)
|
||||
{
|
||||
u16 ability = GetBattlerAbility(battlerId);
|
||||
if (ability == ABILITY_INSOMNIA
|
||||
|| ability == ABILITY_VITAL_SPIRIT
|
||||
|| ability == ABILITY_COMATOSE
|
||||
|| gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_SAFEGUARD
|
||||
|| gBattleMons[battlerId].status1 & STATUS1_ANY
|
||||
|| IsAbilityOnSide(battlerId, ABILITY_SWEET_VEIL)
|
||||
|| IsAbilityStatusProtected(battlerId)
|
||||
|| IsBattlerTerrainAffected(battlerId, STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_MISTY_TERRAIN))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool32 CanBePoisoned(u8 battlerId)
|
||||
{
|
||||
u16 ability = GetBattlerAbility(battlerId);
|
||||
if (IS_BATTLER_OF_TYPE(battlerId, TYPE_POISON)
|
||||
|| IS_BATTLER_OF_TYPE(battlerId, TYPE_STEEL)
|
||||
|| gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_SAFEGUARD
|
||||
|| gBattleMons[battlerId].status1 & STATUS1_ANY
|
||||
|| ability == ABILITY_IMMUNITY
|
||||
|| ability == ABILITY_COMATOSE
|
||||
|| gBattleMons[battlerId].status1 & STATUS1_ANY
|
||||
|| IsAbilityStatusProtected(battlerId)
|
||||
|| IsBattlerTerrainAffected(battlerId, STATUS_FIELD_MISTY_TERRAIN))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool32 CanBeBurned(u8 battlerId)
|
||||
{
|
||||
u16 ability = GetBattlerAbility(battlerId);
|
||||
if (IS_BATTLER_OF_TYPE(battlerId, TYPE_FIRE)
|
||||
|| gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_SAFEGUARD
|
||||
|| gBattleMons[battlerId].status1 & STATUS1_ANY
|
||||
|| ability == ABILITY_WATER_VEIL
|
||||
|| ability == ABILITY_WATER_BUBBLE
|
||||
|| ability == ABILITY_COMATOSE
|
||||
|| IsAbilityStatusProtected(battlerId)
|
||||
|| IsBattlerTerrainAffected(battlerId, STATUS_FIELD_MISTY_TERRAIN))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool32 CanBeParalyzed(u8 battlerId)
|
||||
{
|
||||
u16 ability = GetBattlerAbility(battlerId);
|
||||
if ((B_PARALYZE_ELECTRIC >= GEN_6 && IS_BATTLER_OF_TYPE(battlerId, TYPE_ELECTRIC))
|
||||
|| gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_SAFEGUARD
|
||||
|| ability == ABILITY_LIMBER
|
||||
|| ability == ABILITY_COMATOSE
|
||||
|| gBattleMons[battlerId].status1 & STATUS1_ANY
|
||||
|| IsAbilityStatusProtected(battlerId)
|
||||
|| IsBattlerTerrainAffected(battlerId, STATUS_FIELD_MISTY_TERRAIN))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool32 CanBeFrozen(u8 battlerId)
|
||||
{
|
||||
u16 ability = GetBattlerAbility(battlerId);
|
||||
if (IS_BATTLER_OF_TYPE(battlerId, TYPE_ICE)
|
||||
|| (WEATHER_HAS_EFFECT && gBattleWeather & WEATHER_SUN_ANY)
|
||||
|| gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_SAFEGUARD
|
||||
|| ability == ABILITY_MAGMA_ARMOR
|
||||
|| ability == ABILITY_COMATOSE
|
||||
|| gBattleMons[battlerId].status1 & STATUS1_ANY
|
||||
|| IsAbilityStatusProtected(battlerId)
|
||||
|| IsBattlerTerrainAffected(battlerId, STATUS_FIELD_MISTY_TERRAIN))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool32 CanBeConfused(u8 battlerId)
|
||||
{
|
||||
if (GetBattlerAbility(gEffectBattler) == ABILITY_OWN_TEMPO
|
||||
|| gBattleMons[gEffectBattler].status2 & STATUS2_CONFUSION
|
||||
|| IsBattlerTerrainAffected(battlerId, STATUS_FIELD_MISTY_TERRAIN))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// second argument is 1/X of current hp compared to max hp
|
||||
bool32 HasEnoughHpToEatBerry(u32 battlerId, u32 hpFraction, u32 itemId)
|
||||
{
|
||||
@ -5463,11 +5555,9 @@ static u8 HealConfuseBerry(u32 battlerId, u32 itemId, u8 flavorId, bool32 end2)
|
||||
|
||||
static u8 StatRaiseBerry(u32 battlerId, u32 itemId, u32 statId, bool32 end2)
|
||||
{
|
||||
if (gBattleMons[battlerId].statStages[statId] < MAX_STAT_STAGE && HasEnoughHpToEatBerry(battlerId, GetBattlerHoldEffectParam(battlerId), itemId))
|
||||
if (CompareStat(battlerId, statId, MAX_STAT_STAGE, CMP_LESS_THAN) && HasEnoughHpToEatBerry(battlerId, GetBattlerHoldEffectParam(battlerId), itemId))
|
||||
{
|
||||
PREPARE_STAT_BUFFER(gBattleTextBuff1, statId);
|
||||
PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATROSE);
|
||||
|
||||
BufferStatChange(battlerId, statId, STRINGID_STATROSE);
|
||||
gEffectBattler = battlerId;
|
||||
if (GetBattlerAbility(battlerId) == ABILITY_RIPEN)
|
||||
SET_STATCHANGER(statId, 2, FALSE);
|
||||
@ -5494,10 +5584,11 @@ static u8 StatRaiseBerry(u32 battlerId, u32 itemId, u32 statId, bool32 end2)
|
||||
static u8 RandomStatRaiseBerry(u32 battlerId, u32 itemId, bool32 end2)
|
||||
{
|
||||
s32 i;
|
||||
u16 stringId;
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
if (gBattleMons[battlerId].statStages[STAT_ATK + i] < MAX_STAT_STAGE)
|
||||
if (CompareStat(battlerId, STAT_ATK + i, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
break;
|
||||
}
|
||||
if (i != 5 && HasEnoughHpToEatBerry(battlerId, GetBattlerHoldEffectParam(battlerId), itemId))
|
||||
@ -5505,21 +5596,19 @@ static u8 RandomStatRaiseBerry(u32 battlerId, u32 itemId, bool32 end2)
|
||||
do
|
||||
{
|
||||
i = Random() % 5;
|
||||
} while (gBattleMons[battlerId].statStages[STAT_ATK + i] == MAX_STAT_STAGE);
|
||||
} while (!CompareStat(battlerId, STAT_ATK + i, MAX_STAT_STAGE, CMP_LESS_THAN));
|
||||
|
||||
PREPARE_STAT_BUFFER(gBattleTextBuff1, i + 1);
|
||||
|
||||
stringId = (GetBattlerAbility(battlerId) == ABILITY_CONTRARY) ? STRINGID_STATFELL : STRINGID_STATROSE;
|
||||
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;
|
||||
gBattleTextBuff2[5] = stringId;
|
||||
gBattleTextBuff2[6] = stringId >> 8;
|
||||
gBattleTextBuff2[7] = EOS;
|
||||
|
||||
gEffectBattler = battlerId;
|
||||
|
||||
if (GetBattlerAbility(battlerId) == ABILITY_RIPEN)
|
||||
SET_STATCHANGER(i + 1, 4, FALSE);
|
||||
else
|
||||
@ -5527,7 +5616,6 @@ static u8 RandomStatRaiseBerry(u32 battlerId, u32 itemId, bool32 end2)
|
||||
|
||||
gBattleScripting.animArg1 = 0x21 + i + 6;
|
||||
gBattleScripting.animArg2 = 0;
|
||||
|
||||
if (end2)
|
||||
{
|
||||
BattleScriptExecute(BattleScript_BerryStatRaiseEnd2);
|
||||
@ -5537,6 +5625,7 @@ static u8 RandomStatRaiseBerry(u32 battlerId, u32 itemId, bool32 end2)
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_BerryStatRaiseRet;
|
||||
}
|
||||
|
||||
return ITEM_STATS_CHANGE;
|
||||
}
|
||||
return 0;
|
||||
@ -5566,13 +5655,11 @@ static u8 DamagedStatBoostBerryEffect(u8 battlerId, u8 statId, u8 split)
|
||||
{
|
||||
if (IsBattlerAlive(battlerId)
|
||||
&& TARGET_TURN_DAMAGED
|
||||
&& gBattleMons[battlerId].statStages[statId] < MAX_STAT_STAGE
|
||||
&& CompareStat(battlerId, statId, MAX_STAT_STAGE, CMP_LESS_THAN)
|
||||
&& !DoesSubstituteBlockMove(gBattlerAttacker, battlerId, gCurrentMove)
|
||||
&& GetBattleMoveSplit(gCurrentMove) == split)
|
||||
{
|
||||
|
||||
PREPARE_STAT_BUFFER(gBattleTextBuff1, statId);
|
||||
PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATROSE);
|
||||
BufferStatChange(battlerId, statId, STRINGID_STATROSE);
|
||||
|
||||
gEffectBattler = battlerId;
|
||||
if (GetBattlerAbility(battlerId) == ABILITY_RIPEN)
|
||||
@ -5589,6 +5676,30 @@ static u8 DamagedStatBoostBerryEffect(u8 battlerId, u8 statId, u8 split)
|
||||
return 0;
|
||||
}
|
||||
|
||||
u8 TryHandleSeed(u8 battler, u32 terrainFlag, u8 statId, u16 itemId, bool32 execute)
|
||||
{
|
||||
if (gFieldStatuses & terrainFlag && CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
{
|
||||
BufferStatChange(battler, statId, STRINGID_STATROSE);
|
||||
gLastUsedItem = itemId; // For surge abilities
|
||||
gEffectBattler = gBattleScripting.battler = battler;
|
||||
SET_STATCHANGER(statId, 1, FALSE);
|
||||
gBattleScripting.animArg1 = 0xE + statId;
|
||||
gBattleScripting.animArg2 = 0;
|
||||
if (execute)
|
||||
{
|
||||
BattleScriptExecute(BattleScript_BerryStatRaiseEnd2);
|
||||
}
|
||||
else
|
||||
{
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_BerryStatRaiseRet;
|
||||
}
|
||||
return ITEM_STATS_CHANGE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8 ItemHealHp(u32 battlerId, u32 itemId, bool32 end2, bool32 percentHeal)
|
||||
{
|
||||
if (HasEnoughHpToEatBerry(battlerId, 2, itemId))
|
||||
@ -5624,6 +5735,61 @@ static bool32 UnnerveOn(u32 battlerId, u32 itemId)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static bool32 GetMentalHerbEffect(u8 battlerId)
|
||||
{
|
||||
bool32 ret = FALSE;
|
||||
|
||||
// Check infatuation
|
||||
if (gBattleMons[battlerId].status2 & STATUS2_INFATUATION)
|
||||
{
|
||||
gBattleMons[battlerId].status2 &= ~(STATUS2_INFATUATION);
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_INFATUATION; // STRINGID_TARGETGOTOVERINFATUATION
|
||||
StringCopy(gBattleTextBuff1, gStatusConditionString_LoveJpn);
|
||||
ret = TRUE;
|
||||
}
|
||||
#if B_MENTAL_HERB >= GEN_5
|
||||
// Check taunt
|
||||
if (gDisableStructs[battlerId].tauntTimer != 0)
|
||||
{
|
||||
gDisableStructs[battlerId].tauntTimer = gDisableStructs[battlerId].tauntTimer2 = 0;
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_TAUNT;
|
||||
PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_TAUNT);
|
||||
ret = TRUE;
|
||||
}
|
||||
// Check encore
|
||||
if (gDisableStructs[battlerId].encoreTimer != 0)
|
||||
{
|
||||
gDisableStructs[battlerId].encoredMove = 0;
|
||||
gDisableStructs[battlerId].encoreTimerStartValue = gDisableStructs[battlerId].encoreTimer = 0;
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_ENCORE; // STRINGID_PKMNENCOREENDED
|
||||
ret = TRUE;
|
||||
}
|
||||
// Check torment
|
||||
if (gBattleMons[battlerId].status2 & STATUS2_TORMENT)
|
||||
{
|
||||
gBattleMons[battlerId].status2 &= ~(STATUS2_TORMENT);
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_TORMENT;
|
||||
ret = TRUE;
|
||||
}
|
||||
// Check heal block
|
||||
if (gStatuses3[battlerId] & STATUS3_HEAL_BLOCK)
|
||||
{
|
||||
gStatuses3[battlerId] &= ~(STATUS3_HEAL_BLOCK);
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_HEALBLOCK;
|
||||
ret = TRUE;
|
||||
}
|
||||
// Check disable
|
||||
if (gDisableStructs[battlerId].disableTimer != 0)
|
||||
{
|
||||
gDisableStructs[battlerId].disableTimer = gDisableStructs[battlerId].disableTimerStartValue = 0;
|
||||
gDisableStructs[battlerId].disabledMove = 0;
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_DISABLE;
|
||||
ret = TRUE;
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn)
|
||||
{
|
||||
int i = 0, moveType;
|
||||
@ -5823,6 +5989,48 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn)
|
||||
BattleScriptPushCursorAndCallback(BattleScript_AirBaloonMsgIn);
|
||||
RecordItemEffectBattle(battlerId, HOLD_EFFECT_AIR_BALLOON);
|
||||
break;
|
||||
case HOLD_EFFECT_ROOM_SERVICE:
|
||||
if (TryRoomService(battlerId))
|
||||
{
|
||||
BattleScriptExecute(BattleScript_BerryStatRaiseEnd2);
|
||||
effect = ITEM_STATS_CHANGE;
|
||||
}
|
||||
break;
|
||||
case HOLD_EFFECT_SEEDS:
|
||||
switch (GetBattlerHoldEffectParam(battlerId))
|
||||
{
|
||||
case HOLD_EFFECT_PARAM_ELECTRIC_TERRAIN:
|
||||
effect = TryHandleSeed(battlerId, STATUS_FIELD_ELECTRIC_TERRAIN, STAT_DEF, gLastUsedItem, TRUE);
|
||||
break;
|
||||
case HOLD_EFFECT_PARAM_GRASSY_TERRAIN:
|
||||
effect = TryHandleSeed(battlerId, STATUS_FIELD_GRASSY_TERRAIN, STAT_DEF, gLastUsedItem, TRUE);
|
||||
break;
|
||||
case HOLD_EFFECT_PARAM_MISTY_TERRAIN:
|
||||
effect = TryHandleSeed(battlerId, STATUS_FIELD_MISTY_TERRAIN, STAT_SPDEF, gLastUsedItem, TRUE);
|
||||
break;
|
||||
case HOLD_EFFECT_PARAM_PSYCHIC_TERRAIN:
|
||||
effect = TryHandleSeed(battlerId, STATUS_FIELD_PSYCHIC_TERRAIN, STAT_SPDEF, gLastUsedItem, TRUE);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case HOLD_EFFECT_EJECT_PACK:
|
||||
if (gSpecialStatuses[battlerId].statFell
|
||||
&& !(gCurrentMove == MOVE_PARTING_SHOT && CanBattlerSwitch(gBattlerAttacker))) // Does not activate if attacker used Parting Shot and can switch out
|
||||
{
|
||||
gSpecialStatuses[battlerId].statFell = FALSE;
|
||||
gActiveBattler = gBattleScripting.battler = battlerId;
|
||||
effect = ITEM_STATS_CHANGE;
|
||||
if (moveTurn)
|
||||
{
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_EjectPackActivate_Ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
BattleScriptExecute(BattleScript_EjectPackActivate_End2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (effect)
|
||||
@ -6075,13 +6283,12 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn)
|
||||
effect = ITEM_STATUS_CHANGE;
|
||||
}
|
||||
break;
|
||||
case HOLD_EFFECT_CURE_ATTRACT:
|
||||
if (gBattleMons[battlerId].status2 & STATUS2_INFATUATION)
|
||||
case HOLD_EFFECT_MENTAL_HERB:
|
||||
if (GetMentalHerbEffect(battlerId))
|
||||
{
|
||||
gBattleMons[battlerId].status2 &= ~(STATUS2_INFATUATION);
|
||||
StringCopy(gBattleTextBuff1, gStatusConditionString_LoveJpn);
|
||||
BattleScriptExecute(BattleScript_BerryCureChosenStatusEnd2);
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_CURED_PROBLEM;
|
||||
gBattleScripting.savedBattler = gBattlerAttacker;
|
||||
gBattlerAttacker = battlerId;
|
||||
BattleScriptExecute(BattleScript_MentalHerbCureEnd2);
|
||||
effect = ITEM_EFFECT_OTHER;
|
||||
}
|
||||
break;
|
||||
@ -6226,14 +6433,13 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn)
|
||||
effect = ITEM_EFFECT_OTHER;
|
||||
}
|
||||
break;
|
||||
case HOLD_EFFECT_CURE_ATTRACT:
|
||||
if (gBattleMons[battlerId].status2 & STATUS2_INFATUATION)
|
||||
case HOLD_EFFECT_MENTAL_HERB:
|
||||
if (GetMentalHerbEffect(battlerId))
|
||||
{
|
||||
gBattleMons[battlerId].status2 &= ~(STATUS2_INFATUATION);
|
||||
StringCopy(gBattleTextBuff1, gStatusConditionString_LoveJpn);
|
||||
gBattleScripting.savedBattler = gBattlerAttacker;
|
||||
gBattlerAttacker = battlerId;
|
||||
BattleScriptPushCursor();
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_CURED_PROBLEM;
|
||||
gBattlescriptCurrInstr = BattleScript_BerryCureChosenStatusRet;
|
||||
gBattlescriptCurrInstr = BattleScript_MentalHerbCureRet;
|
||||
effect = ITEM_EFFECT_OTHER;
|
||||
}
|
||||
break;
|
||||
@ -6305,45 +6511,91 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ITEMEFFECT_KINGSROCK_SHELLBELL:
|
||||
if (gBattleMoveDamage)
|
||||
case ITEMEFFECT_KINGSROCK:
|
||||
// Occur on each hit of a multi-strike move
|
||||
switch (atkHoldEffect)
|
||||
{
|
||||
switch (atkHoldEffect)
|
||||
case HOLD_EFFECT_FLINCH:
|
||||
if (gBattleMoveDamage != 0 // Need to have done damage
|
||||
&& !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
|
||||
&& TARGET_TURN_DAMAGED
|
||||
&& (Random() % 100) < atkHoldEffectParam
|
||||
&& gBattleMoves[gCurrentMove].flags & FLAG_KINGS_ROCK_AFFECTED
|
||||
&& gBattleMons[gBattlerTarget].hp)
|
||||
{
|
||||
case HOLD_EFFECT_FLINCH:
|
||||
if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
|
||||
&& TARGET_TURN_DAMAGED
|
||||
&& (Random() % 100) < atkHoldEffectParam
|
||||
&& gBattleMoves[gCurrentMove].flags & FLAG_KINGS_ROCK_AFFECTED
|
||||
&& gBattleMons[gBattlerTarget].hp)
|
||||
{
|
||||
gBattleScripting.moveEffect = MOVE_EFFECT_FLINCH;
|
||||
BattleScriptPushCursor();
|
||||
SetMoveEffect(FALSE, 0);
|
||||
BattleScriptPop();
|
||||
}
|
||||
break;
|
||||
case HOLD_EFFECT_SHELL_BELL:
|
||||
if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
|
||||
&& gSpecialStatuses[gBattlerTarget].dmg != 0
|
||||
&& gSpecialStatuses[gBattlerTarget].dmg != 0xFFFF
|
||||
&& gBattlerAttacker != gBattlerTarget
|
||||
&& gBattleMons[gBattlerAttacker].hp != gBattleMons[gBattlerAttacker].maxHP
|
||||
&& gBattleMons[gBattlerAttacker].hp != 0)
|
||||
{
|
||||
gLastUsedItem = atkItem;
|
||||
gPotentialItemEffectBattler = gBattlerAttacker;
|
||||
gBattleScripting.battler = gBattlerAttacker;
|
||||
gBattleMoveDamage = (gSpecialStatuses[gBattlerTarget].dmg / atkHoldEffectParam) * -1;
|
||||
if (gBattleMoveDamage == 0)
|
||||
gBattleMoveDamage = -1;
|
||||
gSpecialStatuses[gBattlerTarget].dmg = 0;
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_ItemHealHP_Ret;
|
||||
effect++;
|
||||
}
|
||||
break;
|
||||
gBattleScripting.moveEffect = MOVE_EFFECT_FLINCH;
|
||||
BattleScriptPushCursor();
|
||||
SetMoveEffect(FALSE, 0);
|
||||
BattleScriptPop();
|
||||
}
|
||||
break;
|
||||
case HOLD_EFFECT_BLUNDER_POLICY:
|
||||
if (gBattleStruct->blunderPolicy
|
||||
&& gBattleMons[gBattlerAttacker].hp != 0
|
||||
&& CompareStat(gBattlerAttacker, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
{
|
||||
gBattleStruct->blunderPolicy = FALSE;
|
||||
gLastUsedItem = atkItem;
|
||||
gBattleScripting.statChanger = SET_STATCHANGER(STAT_SPEED, 2, FALSE);
|
||||
effect = ITEM_STATS_CHANGE;
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_AttackerItemStatRaise;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ITEMEFFECT_LIFEORB_SHELLBELL:
|
||||
// Occur after the final hit of a multi-strike move
|
||||
switch (atkHoldEffect)
|
||||
{
|
||||
case HOLD_EFFECT_SHELL_BELL:
|
||||
if (gSpecialStatuses[gBattlerAttacker].damagedMons // Need to have done damage
|
||||
&& gBattlerAttacker != gBattlerTarget
|
||||
&& gBattleMons[gBattlerAttacker].hp != gBattleMons[gBattlerAttacker].maxHP
|
||||
&& gBattleMons[gBattlerAttacker].hp != 0)
|
||||
{
|
||||
gLastUsedItem = atkItem;
|
||||
gPotentialItemEffectBattler = gBattlerAttacker;
|
||||
gBattleScripting.battler = gBattlerAttacker;
|
||||
gBattleMoveDamage = (gSpecialStatuses[gBattlerTarget].dmg / atkHoldEffectParam) * -1;
|
||||
if (gBattleMoveDamage == 0)
|
||||
gBattleMoveDamage = -1;
|
||||
gSpecialStatuses[gBattlerTarget].dmg = 0;
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_ItemHealHP_Ret;
|
||||
effect = ITEM_HP_CHANGE;
|
||||
}
|
||||
break;
|
||||
case HOLD_EFFECT_LIFE_ORB:
|
||||
if (IsBattlerAlive(gBattlerAttacker)
|
||||
&& !(TestSheerForceFlag(gBattlerAttacker, gCurrentMove))
|
||||
&& GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD
|
||||
&& gSpecialStatuses[gBattlerAttacker].damagedMons)
|
||||
{
|
||||
gBattleMoveDamage = gBattleMons[gBattlerAttacker].maxHP / 10;
|
||||
if (gBattleMoveDamage == 0)
|
||||
gBattleMoveDamage = 1;
|
||||
effect = ITEM_HP_CHANGE;
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_ItemHurtRet;
|
||||
gLastUsedItem = gBattleMons[gBattlerAttacker].item;
|
||||
}
|
||||
break;
|
||||
case HOLD_EFFECT_THROAT_SPRAY: // Does NOT need to be a damaging move
|
||||
if (gProtectStructs[gBattlerAttacker].targetAffected
|
||||
&& gBattleMons[gBattlerAttacker].hp != 0
|
||||
&& gBattleMoves[gCurrentMove].flags & FLAG_SOUND
|
||||
&& CompareStat(gBattlerAttacker, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN)
|
||||
&& !NoAliveMonsForEitherParty()) // Don't activate if battle will end
|
||||
{
|
||||
gLastUsedItem = atkItem;
|
||||
gBattleScripting.battler = gBattlerAttacker;
|
||||
gBattleScripting.statChanger = SET_STATCHANGER(STAT_SPATK, 1, FALSE);
|
||||
effect = ITEM_STATS_CHANGE;
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_AttackerItemStatRaise;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ITEMEFFECT_TARGET:
|
||||
@ -6758,7 +7010,7 @@ u8 IsMonDisobedient(void)
|
||||
obedienceLevel = gBattleMons[gBattlerAttacker].level - obedienceLevel;
|
||||
|
||||
calc = (Random() & 255);
|
||||
if (calc < obedienceLevel && !(gBattleMons[gBattlerAttacker].status1 & STATUS1_ANY) && gBattleMons[gBattlerAttacker].ability != ABILITY_VITAL_SPIRIT && gBattleMons[gBattlerAttacker].ability != ABILITY_INSOMNIA)
|
||||
if (calc < obedienceLevel && CanSleep(gBattlerAttacker))
|
||||
{
|
||||
// try putting asleep
|
||||
int i;
|
||||
@ -8749,14 +9001,6 @@ void SortBattlersBySpeed(u8 *battlers, bool8 slowToFast)
|
||||
}
|
||||
}
|
||||
|
||||
bool32 TestSheerForceFlag(u8 battler, u16 move)
|
||||
{
|
||||
if (GetBattlerAbility(battler) == ABILITY_SHEER_FORCE && gBattleMoves[move].flags & FLAG_SHEER_FORCE_BOOST)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void TryRestoreStolenItems(void)
|
||||
{
|
||||
u32 i;
|
||||
@ -8827,3 +9071,122 @@ void TrySaveExchangedItem(u8 battlerId, u16 stolenItem)
|
||||
#endif
|
||||
}
|
||||
|
||||
bool32 IsBattlerAffectedByHazards(u8 battlerId, bool32 toxicSpikes)
|
||||
{
|
||||
bool32 ret = TRUE;
|
||||
u32 holdEffect = GetBattlerHoldEffect(gActiveBattler, TRUE);
|
||||
if (toxicSpikes && holdEffect == HOLD_EFFECT_HEAVY_DUTY_BOOTS && !IS_BATTLER_OF_TYPE(battlerId, TYPE_POISON))
|
||||
{
|
||||
ret = FALSE;
|
||||
RecordItemEffectBattle(battlerId, holdEffect);
|
||||
}
|
||||
else if (holdEffect == HOLD_EFFECT_HEAVY_DUTY_BOOTS)
|
||||
{
|
||||
ret = FALSE;
|
||||
RecordItemEffectBattle(battlerId, holdEffect);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool32 TestSheerForceFlag(u8 battler, u16 move)
|
||||
{
|
||||
if (GetBattlerAbility(battler) == ABILITY_SHEER_FORCE && gBattleMoves[move].flags & FLAG_SHEER_FORCE_BOOST)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// This function is the body of "jumpifstat", but can be used dynamically in a function
|
||||
bool32 CompareStat(u8 battlerId, u8 statId, u8 cmpTo, u8 cmpKind)
|
||||
{
|
||||
bool8 ret = FALSE;
|
||||
u8 statValue = gBattleMons[battlerId].statStages[statId];
|
||||
|
||||
// Because this command is used as a way of checking if a stat can be lowered/raised,
|
||||
// we need to do some modification at run-time.
|
||||
if (GetBattlerAbility(battlerId) == ABILITY_CONTRARY)
|
||||
{
|
||||
if (cmpKind == CMP_GREATER_THAN)
|
||||
cmpKind = CMP_LESS_THAN;
|
||||
else if (cmpKind == CMP_LESS_THAN)
|
||||
cmpKind = CMP_GREATER_THAN;
|
||||
|
||||
if (cmpTo == MIN_STAT_STAGE)
|
||||
cmpTo = MAX_STAT_STAGE;
|
||||
else if (cmpTo == MAX_STAT_STAGE)
|
||||
cmpTo = MIN_STAT_STAGE;
|
||||
}
|
||||
|
||||
switch (cmpKind)
|
||||
{
|
||||
case CMP_EQUAL:
|
||||
if (statValue == cmpTo)
|
||||
ret = TRUE;
|
||||
break;
|
||||
case CMP_NOT_EQUAL:
|
||||
if (statValue != cmpTo)
|
||||
ret = TRUE;
|
||||
break;
|
||||
case CMP_GREATER_THAN:
|
||||
if (statValue > cmpTo)
|
||||
ret = TRUE;
|
||||
break;
|
||||
case CMP_LESS_THAN:
|
||||
if (statValue < cmpTo)
|
||||
ret = TRUE;
|
||||
break;
|
||||
case CMP_COMMON_BITS:
|
||||
if (statValue & cmpTo)
|
||||
ret = TRUE;
|
||||
break;
|
||||
case CMP_NO_COMMON_BITS:
|
||||
if (!(statValue & cmpTo))
|
||||
ret = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void BufferStatChange(u8 battlerId, u8 statId, u8 stringId)
|
||||
{
|
||||
bool8 hasContrary = (GetBattlerAbility(battlerId) == ABILITY_CONTRARY);
|
||||
|
||||
PREPARE_STAT_BUFFER(gBattleTextBuff1, statId);
|
||||
if (stringId == STRINGID_STATFELL)
|
||||
{
|
||||
if (hasContrary)
|
||||
PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATROSE)
|
||||
else
|
||||
PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATFELL)
|
||||
}
|
||||
else if (stringId == STRINGID_STATROSE)
|
||||
{
|
||||
if (hasContrary)
|
||||
PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATFELL)
|
||||
else
|
||||
PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATROSE)
|
||||
}
|
||||
else
|
||||
{
|
||||
PREPARE_STRING_BUFFER(gBattleTextBuff2, stringId)
|
||||
}
|
||||
}
|
||||
|
||||
bool32 TryRoomService(u8 battlerId)
|
||||
{
|
||||
if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && CompareStat(battlerId, STAT_SPEED, MIN_STAT_STAGE, CMP_GREATER_THAN))
|
||||
{
|
||||
BufferStatChange(battlerId, STAT_SPEED, STRINGID_STATFELL);
|
||||
gEffectBattler = gBattleScripting.battler = battlerId;
|
||||
SET_STATCHANGER(STAT_SPEED, 1, TRUE);
|
||||
gBattleScripting.animArg1 = 0xE + STAT_SPEED;
|
||||
gBattleScripting.animArg2 = 0;
|
||||
gLastUsedItem = gBattleMons[battlerId].item;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
@ -2262,7 +2262,7 @@ const struct Item gItems[] =
|
||||
.name = _("MENTAL HERB"),
|
||||
.itemId = ITEM_MENTAL_HERB,
|
||||
.price = 100,
|
||||
.holdEffect = HOLD_EFFECT_CURE_ATTRACT,
|
||||
.holdEffect = HOLD_EFFECT_MENTAL_HERB,
|
||||
.description = sMentalHerbDesc,
|
||||
.pocket = POCKET_ITEMS,
|
||||
.type = ITEM_USE_BAG_MENU,
|
||||
|
Loading…
Reference in New Issue
Block a user