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

This commit is contained in:
Bassoonian 2023-04-27 10:50:32 +02:00
commit c279830892
103 changed files with 2240 additions and 1402 deletions

View File

@ -1330,6 +1330,22 @@
.4byte \jumpInstr
.endm
.macro itemrestorehp
callnative BS_ItemRestoreHP
.endm
.macro itemcurestatus
callnative BS_ItemCureStatus
.endm
.macro itemincreasestat
callnative BS_ItemIncreaseStat
.endm
.macro itemrestorepp
callnative BS_ItemRestorePP
.endm
@ various command changed to more readable macros
.macro cancelmultiturnmoves battler:req
various \battler, VARIOUS_CANCEL_MULTI_TURN_MOVES
@ -2061,6 +2077,14 @@
various \battler, VARIOUS_ACTIVATE_TERRAIN_CHANGE_ABILITIES
.endm
.macro trytrainerslidezmovemsg battler:req
various \battler, VARIOUS_TRY_TRAINER_SLIDE_MSG_Z_MOVE
.endm
.macro trytrainerslidemegaevolutionmsg battler:req
various \battler, VARIOUS_TRY_TRAINER_SLIDE_MSG_MEGA_EVOLUTION
.endm
@ helpful macros
.macro setstatchanger stat:req, stages:req, down:req
setbyte sSTATCHANGER, \stat | \stages << 3 | \down << 7

View File

@ -24463,6 +24463,7 @@ General_TurnTrap:
jumpargeq 0, TRAP_ANIM_MAGMA_STORM, Status_MagmaStorm
jumpargeq 0, TRAP_ANIM_INFESTATION, Status_Infestation
jumpargeq 0, TRAP_ANIM_SNAP_TRAP, Status_Snap_Trap
jumpargeq 0, TRAP_ANIM_THUNDER_CAGE, Status_Thunder_Cage
goto Status_BindWrap
Status_BindWrap:
loadspritegfx ANIM_TAG_TENDRILS
@ -24549,6 +24550,10 @@ Status_Clamp:
waitforvisualfinish
end
Status_Thunder_Cage:
@ TODO
goto Move_THUNDER_CAGE
Status_Snap_Trap: @ placeholder
goto Move_BITE

View File

@ -5612,7 +5612,7 @@ BattleScript_EffectStockpileSpDef::
BattleScript_EffectStockpileEnd:
stockpile 1
goto BattleScript_MoveEnd
BattleScript_MoveEffectStockpileWoreOff::
.if B_STOCKPILE_RAISES_DEFS >= GEN_4
dostockpilestatchangeswearoff BS_ATTACKER, BattleScript_StockpileStatChangeDown
@ -5620,7 +5620,7 @@ BattleScript_MoveEffectStockpileWoreOff::
waitmessage B_WAIT_TIME_SHORT
.endif
return
BattleScript_StockpileStatChangeDown:
statbuffchange MOVE_EFFECT_AFFECTS_USER, BattleScript_StockpileStatChangeDown_Ret
setgraphicalstatchangevalues
@ -6943,7 +6943,7 @@ BattleScript_MagicRoomEnds::
printstring STRINGID_MAGICROOMENDS
waitmessage B_WAIT_TIME_LONG
end2
BattleScript_GrassyTerrainEnds:
setbyte cMULTISTRING_CHOOSER, B_MSG_TERRAINENDS_GRASS
BattleScript_TerrainEnds_Ret::
@ -6951,7 +6951,7 @@ BattleScript_TerrainEnds_Ret::
waitmessage B_WAIT_TIME_LONG
playanimation BS_ATTACKER, B_ANIM_RESTORE_BG
return
BattleScript_TerrainEnds::
call BattleScript_TerrainEnds_Ret
end2
@ -7496,7 +7496,7 @@ BattleScript_StealthRockFree::
printstring STRINGID_PKMNBLEWAWAYSTEALTHROCK
waitmessage B_WAIT_TIME_LONG
return
BattleScript_SpikesDefog::
printstring STRINGID_SPIKESDISAPPEAREDFROMTEAM
waitmessage B_WAIT_TIME_LONG
@ -7871,6 +7871,8 @@ BattleScript_FocusPunchSetUp::
end2
BattleScript_MegaEvolution::
printstring STRINGID_EMPTYSTRING3
trytrainerslidemegaevolutionmsg BS_ATTACKER
printstring STRINGID_MEGAEVOREACTING
BattleScript_MegaEvolutionAfterString:
waitmessage B_WAIT_TIME_LONG
@ -7885,6 +7887,8 @@ BattleScript_MegaEvolutionAfterString:
end2
BattleScript_WishMegaEvolution::
printstring STRINGID_EMPTYSTRING3
trytrainerslidemegaevolutionmsg BS_ATTACKER
printstring STRINGID_FERVENTWISHREACHED
goto BattleScript_MegaEvolutionAfterString
@ -9158,7 +9162,7 @@ BattleScript_WanderingSpiritActivates::
pause 20
destroyabilitypopup
pause 40
copybyte gBattlerAbility, gBattlerAttacker
setbyte sFIXED_ABILITY_POPUP, TRUE
copyhword sABILITY_OVERWRITE, gLastUsedAbility
showabilitypopup BS_ATTACKER
@ -10053,6 +10057,8 @@ BattleScript_JabocaRowapBerryActivate_Dmg:
@ z moves / effects
BattleScript_ZMoveActivateDamaging::
printstring STRINGID_EMPTYSTRING3
trytrainerslidezmovemsg BS_ATTACKER
printstring STRINGID_ZPOWERSURROUNDS
playanimation BS_ATTACKER, B_ANIM_ZMOVE_ACTIVATE, NULL
printstring STRINGID_ZMOVEUNLEASHED
@ -10060,6 +10066,8 @@ BattleScript_ZMoveActivateDamaging::
return
BattleScript_ZMoveActivateStatus::
printstring STRINGID_EMPTYSTRING3
trytrainerslidezmovemsg BS_ATTACKER
savetarget
printstring STRINGID_ZPOWERSURROUNDS
playanimation BS_ATTACKER, B_ANIM_ZMOVE_ACTIVATE, NULL
@ -10365,3 +10373,30 @@ BattleScript_CouldntFullyProtect::
printstring STRINGID_COULDNTFULLYPROTECT
waitmessage B_WAIT_TIME_LONG
return
BattleScript_BerserkGeneRet::
BattleScript_BerserkGeneRet_Anim:
statbuffchange STAT_CHANGE_ALLOW_PTR, BattleScript_BerserkGeneRet_TryConfuse
setgraphicalstatchangevalues
playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT, sB_ANIM_ARG1
setbyte cMULTISTRING_CHOOSER, B_MSG_STAT_ROSE_ITEM
call BattleScript_StatUp
BattleScript_BerserkGeneRet_TryConfuse:
jumpifability BS_SCRIPTING, ABILITY_OWN_TEMPO, BattleScript_BerserkGeneRet_OwnTempoPrevents
jumpifsafeguard BattleScript_BerserkGeneRet_SafeguardProtected
setmoveeffect MOVE_EFFECT_CONFUSION
seteffectprimary
goto BattleScript_BerserkGeneRet_End
BattleScript_BerserkGeneRet_SafeguardProtected::
pause B_WAIT_TIME_SHORT
printstring STRINGID_PKMNUSEDSAFEGUARD
waitmessage B_WAIT_TIME_LONG
goto BattleScript_BerserkGeneRet_End
BattleScript_BerserkGeneRet_OwnTempoPrevents:
pause B_WAIT_TIME_SHORT
call BattleScript_AbilityPopUp
printstring STRINGID_PKMNPREVENTSCONFUSIONWITH
waitmessage B_WAIT_TIME_LONG
BattleScript_BerserkGeneRet_End:
removeitem BS_SCRIPTING
end3

View File

@ -3,219 +3,255 @@
#include "constants/battle_script_commands.h"
#include "constants/battle_anim.h"
#include "constants/battle_string_ids.h"
#include "constants/items.h"
#include "constants/moves.h"
#include "constants/songs.h"
#include "constants/game_stat.h"
.include "asm/macros.inc"
.include "asm/macros/battle_script.inc"
.include "constants/constants.inc"
.include "asm/macros.inc"
.include "asm/macros/battle_script.inc"
.include "constants/constants.inc"
.section script_data, "aw", %progbits
.section script_data, "aw", %progbits
.align 2
.align 2
gBattlescriptsForUsingItem::
.4byte BattleScript_PlayerUsesItem
.4byte BattleScript_OpponentUsesHealItem @ AI_ITEM_FULL_RESTORE
.4byte BattleScript_OpponentUsesHealItem @ AI_ITEM_HEAL_HP
.4byte BattleScript_OpponentUsesStatusCureItem @ AI_ITEM_CURE_CONDITION
.4byte BattleScript_OpponentUsesXItem @ AI_ITEM_X_STAT
.4byte BattleScript_OpponentUsesGuardSpec @ AI_ITEM_GUARD_SPEC
.4byte BattleScript_ItemRestoreHP @ EFFECT_ITEM_RESTORE_HP
.4byte BattleScript_ItemCureStatus @ EFFECT_ITEM_CURE_STATUS
.4byte BattleScript_ItemHealAndCureStatus @ EFFECT_ITEM_HEAL_AND_CURE_STATUS
.4byte BattleScript_ItemIncreaseStat @ EFFECT_ITEM_INCREASE_STAT
.4byte BattleScript_ItemSetMist @ EFFECT_ITEM_SET_MIST
.4byte BattleScript_ItemSetFocusEnergy @ EFFECT_ITEM_SET_FOCUS_ENERGY
.4byte BattleScript_RunByUsingItem @ EFFECT_ITEM_ESCAPE
.4byte BattleScript_BallThrow @ EFFECT_ITEM_THROW_BALL
.4byte BattleScript_ItemRestoreHP @ EFFECT_ITEM_REVIVE
.4byte BattleScript_ItemRestorePP @ EFFECT_ITEM_RESTORE_PP
.4byte BattleScript_ItemIncreaseAllStats @ EFFECT_ITEM_INCREASE_ALL_STATS
.align 2
gBattlescriptsForRunningByItem::
.4byte BattleScript_RunByUsingItem
.align 2
.align 2
gBattlescriptsForSafariActions::
.4byte BattleScript_ActionWatchesCarefully
.4byte BattleScript_ActionGetNear
.4byte BattleScript_ActionThrowPokeblock
.4byte BattleScript_ActionWallyThrow
.4byte BattleScript_ActionWatchesCarefully
.4byte BattleScript_ActionGetNear
.4byte BattleScript_ActionThrowPokeblock
.4byte BattleScript_ActionWallyThrow
BattleScript_ItemEnd:
end
BattleScript_UseItemMessage:
printstring STRINGID_EMPTYSTRING3
pause B_WAIT_TIME_MED
playse SE_USE_ITEM
getbattlerside BS_ATTACKER
copybyte cMULTISTRING_CHOOSER, gBattleCommunication
printfromtable gTrainerUsedItemStringIds
waitmessage B_WAIT_TIME_LONG
return
BattleScript_ItemRestoreHP::
call BattleScript_UseItemMessage
itemrestorehp
jumpifbyte CMP_EQUAL, gBattleCommunication, TRUE, BattleScript_ItemRestoreHP_SendOutRevivedBattler
bichalfword gMoveResultFlags, MOVE_RESULT_NO_EFFECT
orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE
healthbarupdate BS_ATTACKER
datahpupdate BS_ATTACKER
printstring STRINGID_ITEMRESTOREDSPECIESHEALTH
waitmessage B_WAIT_TIME_LONG
end
BattleScript_ItemRestoreHP_SendOutRevivedBattler:
switchinanim BS_ATTACKER, FALSE
waitstate
switchineffects BS_ATTACKER
end
BattleScript_ItemCureStatus::
call BattleScript_UseItemMessage
itemcurestatus
updatestatusicon BS_ATTACKER
printstring STRINGID_ITEMCUREDSPECIESSTATUS
waitmessage B_WAIT_TIME_LONG
end
BattleScript_ItemHealAndCureStatus::
call BattleScript_UseItemMessage
itemrestorehp
curestatus BS_ATTACKER
bichalfword gMoveResultFlags, MOVE_RESULT_NO_EFFECT
orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE
healthbarupdate BS_ATTACKER
datahpupdate BS_ATTACKER
updatestatusicon BS_ATTACKER
printstring STRINGID_ITEMRESTOREDSPECIESHEALTH
waitmessage B_WAIT_TIME_LONG
end
BattleScript_ItemIncreaseStat::
call BattleScript_UseItemMessage
itemincreasestat
statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_CHANGE_NOT_PROTECT_AFFECTED | STAT_CHANGE_ALLOW_PTR, BattleScript_ItemEnd
setgraphicalstatchangevalues
playanimation BS_ATTACKER, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1
printfromtable gStatUpStringIds
waitmessage B_WAIT_TIME_LONG
end
BattleScript_ItemSetMist::
call BattleScript_UseItemMessage
setmist
playmoveanimation BS_ATTACKER, MOVE_MIST
waitanimation
printfromtable gMistUsedStringIds
waitmessage B_WAIT_TIME_LONG
end
BattleScript_ItemSetFocusEnergy::
call BattleScript_UseItemMessage
jumpifstatus2 BS_ATTACKER, STATUS2_FOCUS_ENERGY, BattleScript_ButItFailed
setfocusenergy
playmoveanimation BS_ATTACKER, MOVE_FOCUS_ENERGY
waitanimation
printstring STRINGID_PKMNUSEDXTOGETPUMPED
waitmessage B_WAIT_TIME_LONG
end
BattleScript_ItemRestorePP::
call BattleScript_UseItemMessage
itemrestorepp
printstring STRINGID_ITEMRESTOREDSPECIESPP
waitmessage B_WAIT_TIME_LONG
end
BattleScript_ItemIncreaseAllStats::
call BattleScript_UseItemMessage
call BattleScript_AllStatsUp
end
BattleScript_BallThrow::
jumpifword CMP_COMMON_BITS, gBattleTypeFlags, BATTLE_TYPE_WALLY_TUTORIAL, BattleScript_BallThrowByWally
printstring STRINGID_PLAYERUSEDITEM
handleballthrow
jumpifword CMP_COMMON_BITS, gBattleTypeFlags, BATTLE_TYPE_WALLY_TUTORIAL, BattleScript_BallThrowByWally
printstring STRINGID_PLAYERUSEDITEM
handleballthrow
BattleScript_BallThrowByWally::
printstring STRINGID_WALLYUSEDITEM
handleballthrow
printstring STRINGID_WALLYUSEDITEM
handleballthrow
BattleScript_SafariBallThrow::
printstring STRINGID_PLAYERUSEDITEM
updatestatusicon BS_ATTACKER
handleballthrow
printstring STRINGID_PLAYERUSEDITEM
updatestatusicon BS_ATTACKER
handleballthrow
BattleScript_SuccessBallThrow::
setbyte sMON_CAUGHT, TRUE
incrementgamestat GAME_STAT_POKEMON_CAPTURES
setbyte sMON_CAUGHT, TRUE
incrementgamestat GAME_STAT_POKEMON_CAPTURES
BattleScript_PrintCaughtMonInfo::
printstring STRINGID_GOTCHAPKMNCAUGHTPLAYER
jumpifbyte CMP_NOT_EQUAL, sEXP_CATCH, TRUE, BattleScript_TryPrintCaughtMonInfo
setbyte sGIVEEXP_STATE, 0
getexp BS_TARGET
sethword gBattle_BG2_X, 0
printstring STRINGID_GOTCHAPKMNCAUGHTPLAYER
jumpifbyte CMP_NOT_EQUAL, sEXP_CATCH, TRUE, BattleScript_TryPrintCaughtMonInfo
setbyte sGIVEEXP_STATE, 0
getexp BS_TARGET
sethword gBattle_BG2_X, 0
BattleScript_TryPrintCaughtMonInfo:
trysetcaughtmondexflags BattleScript_TryNicknameCaughtMon
printstring STRINGID_PKMNDATAADDEDTODEX
waitstate
setbyte gBattleCommunication, 0
displaydexinfo
trysetcaughtmondexflags BattleScript_TryNicknameCaughtMon
printstring STRINGID_PKMNDATAADDEDTODEX
waitstate
setbyte gBattleCommunication, 0
displaydexinfo
BattleScript_TryNicknameCaughtMon::
printstring STRINGID_GIVENICKNAMECAPTURED
waitstate
setbyte gBattleCommunication, 0
trygivecaughtmonnick BattleScript_GiveCaughtMonEnd
givecaughtmon
printfromtable gCaughtMonStringIds
waitmessage B_WAIT_TIME_LONG
goto BattleScript_SuccessBallThrowEnd
printstring STRINGID_GIVENICKNAMECAPTURED
waitstate
setbyte gBattleCommunication, 0
trygivecaughtmonnick BattleScript_GiveCaughtMonEnd
givecaughtmon
printfromtable gCaughtMonStringIds
waitmessage B_WAIT_TIME_LONG
goto BattleScript_SuccessBallThrowEnd
BattleScript_GiveCaughtMonEnd::
givecaughtmon
givecaughtmon
BattleScript_SuccessBallThrowEnd::
setbyte gBattleOutcome, B_OUTCOME_CAUGHT
finishturn
setbyte gBattleOutcome, B_OUTCOME_CAUGHT
finishturn
BattleScript_WallyBallThrow::
printstring STRINGID_GOTCHAPKMNCAUGHTWALLY
setbyte gBattleOutcome, B_OUTCOME_CAUGHT
finishturn
printstring STRINGID_GOTCHAPKMNCAUGHTWALLY
setbyte gBattleOutcome, B_OUTCOME_CAUGHT
finishturn
BattleScript_ShakeBallThrow::
printfromtable gBallEscapeStringIds
waitmessage B_WAIT_TIME_LONG
jumpifword CMP_NO_COMMON_BITS, gBattleTypeFlags, BATTLE_TYPE_SAFARI, BattleScript_ShakeBallThrowEnd
jumpifbyte CMP_NOT_EQUAL, gNumSafariBalls, 0, BattleScript_ShakeBallThrowEnd
printstring STRINGID_OUTOFSAFARIBALLS
waitmessage B_WAIT_TIME_LONG
setbyte gBattleOutcome, B_OUTCOME_NO_SAFARI_BALLS
printfromtable gBallEscapeStringIds
waitmessage B_WAIT_TIME_LONG
jumpifword CMP_NO_COMMON_BITS, gBattleTypeFlags, BATTLE_TYPE_SAFARI, BattleScript_ShakeBallThrowEnd
jumpifbyte CMP_NOT_EQUAL, gNumSafariBalls, 0, BattleScript_ShakeBallThrowEnd
printstring STRINGID_OUTOFSAFARIBALLS
waitmessage B_WAIT_TIME_LONG
setbyte gBattleOutcome, B_OUTCOME_NO_SAFARI_BALLS
BattleScript_ShakeBallThrowEnd::
finishaction
finishaction
BattleScript_TrainerBallBlock::
waitmessage B_WAIT_TIME_LONG
printstring STRINGID_TRAINERBLOCKEDBALL
waitmessage B_WAIT_TIME_LONG
printstring STRINGID_DONTBEATHIEF
waitmessage B_WAIT_TIME_LONG
finishaction
BattleScript_PlayerUsesItem::
moveendcase MOVEEND_MIRROR_MOVE
end
BattleScript_OpponentUsesHealItem::
printstring STRINGID_EMPTYSTRING3
pause B_WAIT_TIME_MED
playse SE_USE_ITEM
printstring STRINGID_TRAINER1USEDITEM
waitmessage B_WAIT_TIME_LONG
bichalfword gMoveResultFlags, MOVE_RESULT_NO_EFFECT
useitemonopponent
orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE
healthbarupdate BS_ATTACKER
datahpupdate BS_ATTACKER
printstring STRINGID_PKMNSITEMRESTOREDHEALTH
waitmessage B_WAIT_TIME_LONG
updatestatusicon BS_ATTACKER
moveendcase MOVEEND_MIRROR_MOVE
finishaction
BattleScript_OpponentUsesStatusCureItem::
printstring STRINGID_EMPTYSTRING3
pause B_WAIT_TIME_MED
playse SE_USE_ITEM
printstring STRINGID_TRAINER1USEDITEM
waitmessage B_WAIT_TIME_LONG
useitemonopponent
printfromtable gTrainerItemCuredStatusStringIds
waitmessage B_WAIT_TIME_LONG
updatestatusicon BS_ATTACKER
moveendcase MOVEEND_MIRROR_MOVE
finishaction
BattleScript_OpponentUsesXItem::
printstring STRINGID_EMPTYSTRING3
pause B_WAIT_TIME_MED
playse SE_USE_ITEM
printstring STRINGID_TRAINER1USEDITEM
waitmessage B_WAIT_TIME_LONG
useitemonopponent
printfromtable gStatUpStringIds
waitmessage B_WAIT_TIME_LONG
moveendcase MOVEEND_MIRROR_MOVE
finishaction
BattleScript_OpponentUsesGuardSpec::
printstring STRINGID_EMPTYSTRING3
pause B_WAIT_TIME_MED
playse SE_USE_ITEM
printstring STRINGID_TRAINER1USEDITEM
waitmessage B_WAIT_TIME_LONG
useitemonopponent
printfromtable gMistUsedStringIds
waitmessage B_WAIT_TIME_LONG
moveendcase MOVEEND_MIRROR_MOVE
finishaction
waitmessage B_WAIT_TIME_LONG
printstring STRINGID_TRAINERBLOCKEDBALL
waitmessage B_WAIT_TIME_LONG
printstring STRINGID_DONTBEATHIEF
waitmessage B_WAIT_TIME_LONG
finishaction
BattleScript_RunByUsingItem::
playse SE_FLEE
setbyte gBattleOutcome, B_OUTCOME_RAN
finishturn
playse SE_FLEE
setbyte gBattleOutcome, B_OUTCOME_RAN
finishturn
BattleScript_ActionWatchesCarefully:
printstring STRINGID_PKMNWATCHINGCAREFULLY
waitmessage B_WAIT_TIME_LONG
end2
printstring STRINGID_PKMNWATCHINGCAREFULLY
waitmessage B_WAIT_TIME_LONG
end2
BattleScript_ActionGetNear:
printfromtable gSafariGetNearStringIds
waitmessage B_WAIT_TIME_LONG
end2
printfromtable gSafariGetNearStringIds
waitmessage B_WAIT_TIME_LONG
end2
BattleScript_ActionThrowPokeblock:
printstring STRINGID_THREWPOKEBLOCKATPKMN
waitmessage B_WAIT_TIME_LONG
playanimation BS_ATTACKER, B_ANIM_POKEBLOCK_THROW, NULL
printfromtable gSafariPokeblockResultStringIds
waitmessage B_WAIT_TIME_LONG
end2
printstring STRINGID_THREWPOKEBLOCKATPKMN
waitmessage B_WAIT_TIME_LONG
playanimation BS_ATTACKER, B_ANIM_POKEBLOCK_THROW, NULL
printfromtable gSafariPokeblockResultStringIds
waitmessage B_WAIT_TIME_LONG
end2
BattleScript_ActionWallyThrow:
printstring STRINGID_RETURNMON
waitmessage B_WAIT_TIME_LONG
returnatktoball
waitstate
trainerslidein BS_TARGET
waitstate
printstring STRINGID_YOUTHROWABALLNOWRIGHT
waitmessage B_WAIT_TIME_LONG
end2
printstring STRINGID_RETURNMON
waitmessage B_WAIT_TIME_LONG
returnatktoball
waitstate
trainerslidein BS_TARGET
waitstate
printstring STRINGID_YOUTHROWABALLNOWRIGHT
waitmessage B_WAIT_TIME_LONG
end2
BattleScript_TrainerASlideMsgRet::
handletrainerslidemsg BS_SCRIPTING, 0
trainerslidein B_POSITION_OPPONENT_LEFT
handletrainerslidemsg BS_SCRIPTING, 1
waitstate
trainerslideout B_POSITION_OPPONENT_LEFT
waitstate
handletrainerslidemsg BS_SCRIPTING, 2
return
handletrainerslidemsg BS_SCRIPTING, 0
trainerslidein B_POSITION_OPPONENT_LEFT
handletrainerslidemsg BS_SCRIPTING, 1
waitstate
trainerslideout B_POSITION_OPPONENT_LEFT
waitstate
handletrainerslidemsg BS_SCRIPTING, 2
return
BattleScript_TrainerASlideMsgEnd2::
call BattleScript_TrainerASlideMsgRet
end2
call BattleScript_TrainerASlideMsgRet
end2
BattleScript_TrainerBSlideMsgRet::
handletrainerslidemsg BS_SCRIPTING, 0
trainerslidein B_POSITION_OPPONENT_RIGHT
handletrainerslidemsg BS_SCRIPTING, 1
waitstate
trainerslideout B_POSITION_OPPONENT_RIGHT
waitstate
handletrainerslidemsg BS_SCRIPTING, 2
return
handletrainerslidemsg BS_SCRIPTING, 0
trainerslidein B_POSITION_OPPONENT_RIGHT
handletrainerslidemsg BS_SCRIPTING, 1
waitstate
trainerslideout B_POSITION_OPPONENT_RIGHT
waitstate
handletrainerslidemsg BS_SCRIPTING, 2
return
BattleScript_TrainerBSlideMsgEnd2::
call BattleScript_TrainerBSlideMsgRet
end2
call BattleScript_TrainerBSlideMsgRet
end2

View File

@ -0,0 +1,19 @@
JASC-PAL
0100
16
212 146 75
49 49 49
131 123 131
98 90 98
74 65 74
164 90 222
230 180 255
255 230 238
255 230 106
255 189 74
255 171 32
238 148 0
255 246 189
123 82 32
0 0 0
0 0 0

Binary file not shown.

After

Width:  |  Height:  |  Size: 356 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 802 B

After

Width:  |  Height:  |  Size: 738 B

View File

@ -11,8 +11,8 @@ JASC-PAL
16 16 16
128 216 160
224 248 216
112 56 56
176 64 64
112 56 56
128 216 160
0 0 0
0 0 0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 725 B

After

Width:  |  Height:  |  Size: 737 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 562 B

After

Width:  |  Height:  |  Size: 524 B

View File

@ -14,6 +14,6 @@ JASC-PAL
248 232 176
248 120 88
152 40 72
104 88 80
248 120 88
0 0 0
0 0 0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -13,7 +13,7 @@ JASC-PAL
248 232 144
192 168 64
248 248 248
88 72 64
104 104 104
176 176 192
0 0 0
0 0 0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -11,8 +11,8 @@ JASC-PAL
246 230 197
230 213 164
57 65 106
139 106 82
98 98 148
139 106 82
255 255 255
172 123 74
255 213 123

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -14,6 +14,6 @@ JASC-PAL
136 32 72
136 160 200
192 200 224
16 16 16
224 104 40
248 144 96
16 16 16

Binary file not shown.

Before

Width:  |  Height:  |  Size: 966 B

After

Width:  |  Height:  |  Size: 897 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -11,7 +11,7 @@ JASC-PAL
128 104 168
56 44 88
160 136 72
255 255 255
248 236 144
16 16 16
208 196 112
104 80 40

View File

@ -1,19 +0,0 @@
JASC-PAL
0100
16
152 208 160
160 28 200
216 60 224
224 76 144
216 52 48
88 72 128
40 28 72
128 104 168
56 44 88
160 136 72
248 236 144
16 16 16
208 196 112
104 80 40
0 0 0
0 0 0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -512,7 +512,7 @@ struct ZMoveData
u8 splits[MAX_BATTLERS_COUNT];
};
struct StolenItem
struct LostItem
{
u16 originalItem:15;
u16 stolen:1;
@ -576,8 +576,6 @@ struct BattleStruct
void (*savedCallback)(void);
u16 usedHeldItems[PARTY_SIZE][NUM_BATTLE_SIDES]; // For each party member and side. For harvest, recycle
u16 chosenItem[MAX_BATTLERS_COUNT];
u8 AI_itemType[2];
u8 AI_itemFlags[2];
u16 choicedMove[MAX_BATTLERS_COUNT];
u16 changedItems[MAX_BATTLERS_COUNT];
u8 switchInItemsCounter;
@ -637,7 +635,7 @@ struct BattleStruct
u16 moveEffect2; // For Knock Off
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)
struct LostItem itemLost[PARTY_SIZE]; // Player's team that had items consumed or stolen (two bytes per party member)
u8 blunderPolicy:1; // should blunder policy activate
u8 swapDamageCategory:1; // Photon Geyser, Shell Side Arm, Light That Burns the Sky
u8 forcedSwitch:4; // For each battler
@ -657,6 +655,15 @@ struct BattleStruct
u8 storedHealingWish:4; // Each battler as a bit.
u8 storedLunarDance:4; // Each battler as a bit.
u16 supremeOverlordModifier[MAX_BATTLERS_COUNT];
u8 itemPartyIndex[MAX_BATTLERS_COUNT];
bool8 trainerSlideHalfHpMsgDone;
u8 trainerSlideFirstCriticalHitMsgState:2;
u8 trainerSlideFirstSuperEffectiveHitMsgState:2;
u8 trainerSlideFirstSTABMoveMsgState:2;
u8 trainerSlidePlayerMonUnaffectedMsgState:2;
bool8 trainerSlideMegaEvolutionMsgDone;
bool8 trainerSlideZMoveMsgDone;
bool8 trainerSlideBeforeFirstTurnMsgDone;
};
#define F_DYNAMIC_TYPE_1 (1 << 6)
@ -715,6 +722,17 @@ struct BattleStruct
#define SET_STATCHANGER(statId, stage, goesDown)(gBattleScripting.statChanger = (statId) + ((stage) << 3) + (goesDown << 7))
#define SET_STATCHANGER2(dst, statId, stage, goesDown)(dst = (statId) + ((stage) << 3) + (goesDown << 7))
static inline struct Pokemon *GetSideParty(u32 side)
{
return side == B_SIDE_PLAYER ? gPlayerParty : gEnemyParty;
}
static inline struct Pokemon *GetBattlerParty(u32 battlerId)
{
extern u8 GetBattlerSide(u8 battler);
return GetSideParty(GetBattlerSide(battlerId));
}
// NOTE: The members of this struct have hard-coded offsets
// in include/constants/battle_script_commands.h
struct BattleScripting

View File

@ -1,36 +1,6 @@
#ifndef GUARD_BATTLE_AI_SWITCH_ITEMS_H
#define GUARD_BATTLE_AI_SWITCH_ITEMS_H
enum
{
AI_ITEM_FULL_RESTORE = 1,
AI_ITEM_HEAL_HP,
AI_ITEM_CURE_CONDITION,
AI_ITEM_X_STAT,
AI_ITEM_GUARD_SPEC,
AI_ITEM_NOT_RECOGNIZABLE
};
enum {
AI_HEAL_CONFUSION,
AI_HEAL_PARALYSIS,
AI_HEAL_FREEZE,
AI_HEAL_BURN,
AI_HEAL_POISON,
AI_HEAL_SLEEP,
};
enum {
AI_X_ATTACK,
AI_X_DEFEND,
AI_X_SPEED,
AI_X_SPATK,
AI_X_SPDEF, // Unused
AI_X_ACCURACY,
AI_X_EVASION, // Unused
AI_DIRE_HIT,
};
void GetAIPartyIndexes(u32 battlerId, s32 *firstId, s32 *lastId);
void AI_TrySwitchOrUseItem(void);
u8 GetMostSuitableMonToSwitchInto(void);

View File

@ -229,6 +229,14 @@ enum
TRAINER_SLIDE_LAST_SWITCHIN,
TRAINER_SLIDE_LAST_LOW_HP,
TRAINER_SLIDE_FIRST_DOWN,
TRAINER_SLIDE_LAST_HALF_HP,
TRAINER_SLIDE_FIRST_CRITICAL_HIT,
TRAINER_SLIDE_FIRST_SUPER_EFFECTIVE_HIT,
TRAINER_SLIDE_FIRST_STAB_MOVE,
TRAINER_SLIDE_PLAYER_MON_UNAFFECTED,
TRAINER_SLIDE_MEGA_EVOLUTION,
TRAINER_SLIDE_Z_MOVE,
TRAINER_SLIDE_BEFORE_FIRST_TURN,
};
void BufferStringBattle(u16 stringID);

View File

@ -458,6 +458,7 @@ extern const u8 BattleScript_CouldntFullyProtect[];
extern const u8 BattleScript_MoveEffectStockpileWoreOff[];
extern const u8 BattleScript_StealthRockActivates[];
extern const u8 BattleScript_SpikesActivates[];
extern const u8 BattleScript_BerserkGeneRet[];
// zmoves
extern const u8 BattleScript_ZMoveActivateDamaging[];

View File

@ -187,7 +187,6 @@ bool32 SetIllusionMon(struct Pokemon *mon, u32 battlerId);
bool8 ShouldGetStatBadgeBoost(u16 flagId, u8 battlerId);
u8 GetBattleMoveSplit(u32 moveId);
bool32 TestMoveFlags(u16 move, u32 flag);
struct Pokemon *GetBattlerPartyData(u8 battlerId);
bool32 CanFling(u8 battlerId);
bool32 IsTelekinesisBannedSpecies(u16 species);
bool32 IsHealBlockPreventingMove(u32 battler, u32 move);
@ -196,7 +195,7 @@ bool32 IsPartnerMonFromSameTrainer(u8 battlerId);
u8 GetSplitBasedOnStats(u8 battlerId);
void SortBattlersBySpeed(u8 *battlers, bool8 slowToFast);
bool32 TestSheerForceFlag(u8 battler, u16 move);
void TryRestoreStolenItems(void);
void TryRestoreHeldItems(void);
bool32 CanStealItem(u8 battlerStealing, u8 battlerItem, u16 item);
void TrySaveExchangedItem(u8 battlerId, u16 stolenItem);
bool32 IsPartnerMonFromSameTrainer(u8 battlerId);
@ -235,5 +234,6 @@ u32 GetBattlerFriendshipScore(u8 battlerId);
u32 CountBattlerStatIncreases(u8 battlerId, bool32 countEvasionAcc);
bool32 IsMyceliumMightOnField(void);
bool8 ChangeTypeBasedOnTerrain(u8 battlerId);
void RemoveConfusionStatus(u8 battlerId);
#endif // GUARD_BATTLE_UTIL_H

View File

@ -98,7 +98,7 @@
#define B_HEALING_WISH_SWITCH GEN_LATEST // In Gen5+, the mon receiving Healing Wish is sent out at the end of the turn.
// Additionally, in gen8+ the Healing Wish's effect will be stored until the user switches into a statused or hurt mon.
#define B_DEFOG_CLEARS_TERRAIN GEN_LATEST // In Gen8+, Defog also clears active Terrain.
#define B_STOCKPILE_RAISES_DEFS GEN_LATEST // In Gen4+, Stockpile also raises Defense and Sp.Defense stats. Once Spit Up / Swallow is used, these stat changes are lost.
#define B_STOCKPILE_RAISES_DEFS GEN_LATEST // In Gen4+, Stockpile also raises Defense and Sp. Defense stats. Once Spit Up / Swallow is used, these stat changes are lost.
#define B_TRANSFORM_FORM_CHANGES GEN_LATEST // In Gen5+, Transformed Pokemon cannot change forms.
// Ability settings
@ -127,6 +127,7 @@
#define B_X_ITEMS_BUFF GEN_LATEST // In Gen7+, the X Items raise a stat by 2 stages instead of 1.
#define B_MENTAL_HERB GEN_LATEST // In Gen5+, the Mental Herb cures Taunt, Encore, Torment, Heal Block, and Disable in addition to Infatuation from before.
#define B_TRAINERS_KNOCK_OFF_ITEMS TRUE // If TRUE, trainers can steal/swap your items (non-berries are restored after battle). In vanilla games trainers cannot steal items.
#define B_RESTORE_HELD_BATTLE_ITEMS TRUE // In Gen9 all non berry items are restored after battle.
#define B_SOUL_DEW_BOOST GEN_LATEST // In Gens3-6, Soul Dew boosts Lati@s' Sp. Atk and Sp. Def. In Gen7+ it boosts the power of their Psychic and Dragon type moves instead.
#define B_NET_BALL_MODIFIER GEN_LATEST // In Gen7+, Net Ball's catch multiplier is x5 instead of x3.
#define B_DIVE_BALL_MODIFIER GEN_LATEST // In Gen4+, Dive Ball's effectiveness increases by when Surfing or Fishing.
@ -156,6 +157,9 @@
#define VAR_TERRAIN 0 // If this var has a value, assigning a STATUS_FIELD_xx_TERRAIN to it before battle causes the battle to start with that terrain active
#define B_VAR_WILD_AI_FLAGS 0 // If not 0, you can use this var to add to default wild AI flags. NOT usable with flags above (1 << 15)
// Flag and Var settings
#define B_RESET_FLAGS_VARS_AFTER_WHITEOUT TRUE // If TRUE, Overworld_ResetBattleFlagsAndVars will reset battle-related Flags and Vars when the player whites out.
// Terrain settings
#define B_TERRAIN_BG_CHANGE TRUE // If set to TRUE, terrain moves permanently change the default battle background until the effect fades.
#define B_THUNDERSTORM_TERRAIN TRUE // If TRUE, overworld Thunderstorm generates Rain and Electric Terrain as in Gen 8.
@ -184,7 +188,7 @@
// Other settings
#define B_DOUBLE_WILD_CHANCE 0 // % chance of encountering two Pokémon in a Wild Encounter.
#define B_DOUBLE_WILD_REQUIRE_2_MONS FALSE // If set to TRUE, Wild Double Battles will default to Single Battles when the player only has 1 usuable Pokémon, ignoring B_DOUBLE_WILD_CHANCE and B_FLAG_FORCE_DOUBLE_WILD.
#define B_DOUBLE_WILD_REQUIRE_2_MONS FALSE // If set to TRUE, Wild Double Battles will default to Single Battles when the player only has 1 usuable Pokémon, ignoring B_DOUBLE_WILD_CHANCE and B_FLAG_FORCE_DOUBLE_WILD.
#define B_MULTI_BATTLE_WHITEOUT GEN_LATEST // In Gen4+, multi battles end when the Player and also their Partner don't have any more Pokémon to fight.
#define B_EVOLUTION_AFTER_WHITEOUT GEN_LATEST // In Gen6+, Pokemon that qualify for evolution after battle will evolve even if the player loses.
#define B_WILD_NATURAL_ENEMIES TRUE // If set to TRUE, certain wild mon species will attack other species when partnered in double wild battles (eg. Zangoose vs Seviper)
@ -196,6 +200,7 @@
#define B_NEW_SWORD_PARTICLE FALSE // If set to TRUE, it updates Swords Dance's particle.
#define B_NEW_LEECH_SEED_PARTICLE FALSE // If set to TRUE, it updates Leech Seed's animation particle.
#define B_NEW_HORN_ATTACK_PARTICLE FALSE // If set to TRUE, it updates Horn Attack's horn particle.
#define B_NEW_ROCKS_PARTICLE TRUE // If set to TRUE, it updates rock particles.
#define B_NEW_LEAF_PARTICLE FALSE // If set to TRUE, it updates leaf particle.
#define B_NEW_EMBER_PARTICLES FALSE // If set to TRUE, it updates Ember's fire particle.
#define B_NEW_MEAN_LOOK_PARTICLE FALSE // If set to TRUE, it updates Mean Look's eye particle.

View File

@ -2,13 +2,17 @@
#define GUARD_CONFIG_ITEM_H
// Item config
#define I_SHINY_CHARM_REROLLS 3 // Amount of re-rolls if the player has the Shiny Charm. Set to 0 to disable Shiny Charm's effects.
#define I_KEY_FOSSILS GEN_LATEST // In Gen4+, all Gen 3 fossils became regular items.
#define I_KEY_ESCAPE_ROPE GEN_LATEST // In Gen8, Escape Rope became a Key Item. Keep in mind, this will make it free to buy in marts.
#define I_HEALTH_RECOVERY GEN_LATEST // In Gen7+, certain healing items recover a different amount of HP than they used to.
#define I_SITRUS_BERRY_HEAL GEN_LATEST // In Gen4+, Sitrus Berry was changed from healing 30 HP to healing 25% of Max HP.
#define I_VITAMIN_EV_CAP GEN_LATEST // In Gen8+, the Vitamins no longer have a cap of 100 EV per stat.
#define I_GRISEOUS_ORB_FORM_CHANGE GEN_LATEST // In Gen9+, the Griseous Orb no longer changes Giratina's form when held.
#define I_SHINY_CHARM_REROLLS 3 // Amount of re-rolls if the player has the Shiny Charm. Set to 0 to disable Shiny Charm's effects.
#define I_KEY_FOSSILS GEN_LATEST // In Gen4+, all Gen 3 fossils became regular items.
#define I_KEY_ESCAPE_ROPE GEN_LATEST // In Gen8, Escape Rope became a Key Item. Keep in mind, this will make it free to buy in marts.
#define I_HEALTH_RECOVERY GEN_LATEST // In Gen7+, certain healing items recover a different amount of HP than they used to.
#define I_SITRUS_BERRY_HEAL GEN_LATEST // In Gen4+, Sitrus Berry was changed from healing 30 HP to healing 25% of Max HP.
#define I_VITAMIN_EV_CAP GEN_LATEST // In Gen8+, the Vitamins no longer have a cap of 100 EV per stat.
#define I_BERRY_EV_JUMP GEN_LATEST // In Gen4 only, EV-lowering Berries lower a stat's EV to 100 if it is above 100.
#define I_GRISEOUS_ORB_FORM_CHANGE GEN_LATEST // In Gen9+, the Griseous Orb no longer changes Giratina's form when held.
// TM config
#define I_REUSABLE_TMS FALSE // In Gen5-8, TMs are reusable. Setting this to TRUE will make all vanilla TMs reusable, though they can also be cherry-picked by setting their importance to 1.
// Repel/Lure config
// These two settings are both independent and complementary.

View File

@ -21,6 +21,7 @@
// Other settings
#define P_LEGENDARY_PERFECT_IVS GEN_LATEST // Since Gen 6, Legendaries, Mythicals and Ultra Beasts found in the wild or given through gifts have at least 3 perfect IVs.
#define P_EV_CAP GEN_LATEST // Since Gen 6, the max EVs per stat is 252 instead of 255.
// Flag settings
// To use the following features in scripting, replace the 0s with the flag ID you're assigning it to.

View File

@ -185,6 +185,7 @@
#define STATUS4_PLASMA_FISTS (1 << 1)
#define STATUS4_MUD_SPORT (1 << 2) // Only used if B_SPORT_TURNS < GEN_6
#define STATUS4_WATER_SPORT (1 << 3) // Only used if B_SPORT_TURNS < GEN_6
#define STATUS4_INFINITE_CONFUSION (1 << 4) // Used for Berserk Gene
#define HITMARKER_WAKE_UP_CLEAR (1 << 4) // Cleared when waking up. Never set or checked.
#define HITMARKER_SKIP_DMG_TRACK (1 << 5)

View File

@ -583,6 +583,7 @@
#define TRAP_ANIM_MAGMA_STORM 5
#define TRAP_ANIM_INFESTATION 6
#define TRAP_ANIM_SNAP_TRAP 7
#define TRAP_ANIM_THUNDER_CAGE 8
// Weather defines for battle animation scripts.
#define ANIM_WEATHER_NONE 0

View File

@ -89,177 +89,179 @@
#define CMP_NO_COMMON_BITS 5
// Cmd_various
#define VARIOUS_CANCEL_MULTI_TURN_MOVES 0
#define VARIOUS_SET_MAGIC_COAT_TARGET 1
#define VARIOUS_IS_RUNNING_IMPOSSIBLE 2
#define VARIOUS_GET_MOVE_TARGET 3
#define VARIOUS_GET_BATTLER_FAINTED 4
#define VARIOUS_RESET_SWITCH_IN_ABILITY_BITS 5
#define VARIOUS_UPDATE_CHOICE_MOVE_ON_LVL_UP 6
#define VARIOUS_RESET_PLAYER_FAINTED 7
#define VARIOUS_PALACE_FLAVOR_TEXT 8
#define VARIOUS_ARENA_JUDGMENT_WINDOW 9
#define VARIOUS_ARENA_OPPONENT_MON_LOST 10
#define VARIOUS_ARENA_PLAYER_MON_LOST 11
#define VARIOUS_ARENA_BOTH_MONS_LOST 12
#define VARIOUS_EMIT_YESNOBOX 13
#define VARIOUS_DRAW_ARENA_REF_TEXT_BOX 14
#define VARIOUS_ERASE_ARENA_REF_TEXT_BOX 15
#define VARIOUS_ARENA_JUDGMENT_STRING 16
#define VARIOUS_ARENA_WAIT_STRING 17
#define VARIOUS_WAIT_CRY 18
#define VARIOUS_RETURN_OPPONENT_MON1 19
#define VARIOUS_RETURN_OPPONENT_MON2 20
#define VARIOUS_VOLUME_DOWN 21
#define VARIOUS_VOLUME_UP 22
#define VARIOUS_SET_ALREADY_STATUS_MOVE_ATTEMPT 23
#define VARIOUS_PALACE_TRY_ESCAPE_STATUS 24
#define VARIOUS_SET_TELEPORT_OUTCOME 25
#define VARIOUS_PLAY_TRAINER_DEFEATED_MUSIC 26
#define VARIOUS_STAT_TEXT_BUFFER 27
#define VARIOUS_SWITCHIN_ABILITIES 28
#define VARIOUS_SAVE_TARGET 29
#define VARIOUS_RESTORE_TARGET 30
#define VARIOUS_INSTANT_HP_DROP 31
#define VARIOUS_CLEAR_STATUS 32
#define VARIOUS_RESTORE_PP 33
#define VARIOUS_TRY_ACTIVATE_MOXIE 34
#define VARIOUS_TRY_ACTIVATE_FELL_STINGER 35
#define VARIOUS_PLAY_MOVE_ANIMATION 36
#define VARIOUS_SET_LUCKY_CHANT 37
#define VARIOUS_SUCKER_PUNCH_CHECK 38
#define VARIOUS_SET_SIMPLE_BEAM 39
#define VARIOUS_TRY_ENTRAINMENT 40
#define VARIOUS_SET_LAST_USED_ABILITY 41
#define VARIOUS_TRY_HEAL_PULSE 42
#define VARIOUS_TRY_QUASH 43
#define VARIOUS_INVERT_STAT_STAGES 44
#define VARIOUS_SET_TERRAIN 45
#define VARIOUS_TRY_ME_FIRST 46
#define VARIOUS_JUMP_IF_BATTLE_END 47
#define VARIOUS_TRY_ELECTRIFY 48
#define VARIOUS_TRY_REFLECT_TYPE 49
#define VARIOUS_TRY_SOAK 50
#define VARIOUS_HANDLE_MEGA_EVO 51
#define VARIOUS_TRY_LAST_RESORT 52
#define VARIOUS_ARGUMENT_STATUS_EFFECT 53
#define VARIOUS_TRY_HIT_SWITCH_TARGET 54
#define VARIOUS_TRY_AUTOTOMIZE 55
#define VARIOUS_TRY_COPYCAT 56
#define VARIOUS_ABILITY_POPUP 57
#define VARIOUS_DEFOG 58
#define VARIOUS_JUMP_IF_TARGET_ALLY 59
#define VARIOUS_TRY_SYNCHRONOISE 60
#define VARIOUS_PSYCHO_SHIFT 61
#define VARIOUS_CURE_STATUS 62
#define VARIOUS_POWER_TRICK 63
#define VARIOUS_AFTER_YOU 64
#define VARIOUS_BESTOW 65
#define VARIOUS_ARGUMENT_TO_MOVE_EFFECT 66
#define VARIOUS_JUMP_IF_NOT_GROUNDED 67
#define VARIOUS_HANDLE_TRAINER_SLIDE_MSG 68
#define VARIOUS_TRY_TRAINER_SLIDE_MSG_FIRST_OFF 69
#define VARIOUS_TRY_TRAINER_SLIDE_MSG_LAST_ON 70
#define VARIOUS_SET_AURORA_VEIL 71
#define VARIOUS_TRY_THIRD_TYPE 72
#define VARIOUS_ACUPRESSURE 73
#define VARIOUS_SET_POWDER 74
#define VARIOUS_SPECTRAL_THIEF 75
#define VARIOUS_GRAVITY_ON_AIRBORNE_MONS 76
#define VARIOUS_CHECK_IF_GRASSY_TERRAIN_HEALS 77
#define VARIOUS_JUMP_IF_ROAR_FAILS 78
#define VARIOUS_TRY_INSTRUCT 79
#define VARIOUS_JUMP_IF_NOT_BERRY 80
#define VARIOUS_TRACE_ABILITY 81
#define VARIOUS_UPDATE_NICK 82
#define VARIOUS_TRY_ILLUSION_OFF 83
#define VARIOUS_SET_SPRITEIGNORE0HP 84
#define VARIOUS_HANDLE_FORM_CHANGE 85
#define VARIOUS_GET_STAT_VALUE 86
#define VARIOUS_JUMP_IF_FULL_HP 87
#define VARIOUS_LOSE_TYPE 88
#define VARIOUS_TRY_ACTIVATE_SOULHEART 89
#define VARIOUS_TRY_ACTIVATE_RECEIVER 90
#define VARIOUS_TRY_ACTIVATE_BEAST_BOOST 91
#define VARIOUS_TRY_FRISK 92
#define VARIOUS_JUMP_IF_SHIELDS_DOWN_PROTECTED 93
#define VARIOUS_TRY_FAIRY_LOCK 94
#define VARIOUS_JUMP_IF_NO_ALLY 95
#define VARIOUS_POISON_TYPE_IMMUNITY 96
#define VARIOUS_JUMP_IF_NO_HOLD_EFFECT 97
#define VARIOUS_INFATUATE_WITH_BATTLER 98
#define VARIOUS_SET_LAST_USED_ITEM 99
#define VARIOUS_PARALYZE_TYPE_IMMUNITY 100
#define VARIOUS_JUMP_IF_ABSENT 101
#define VARIOUS_DESTROY_ABILITY_POPUP 102
#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
#define VARIOUS_EERIE_SPELL_PP_REDUCE 110
#define VARIOUS_JUMP_IF_TEAM_HEALTHY 111
#define VARIOUS_TRY_HEAL_QUARTER_HP 112
#define VARIOUS_REMOVE_TERRAIN 113
#define VARIOUS_JUMP_IF_PRANKSTER_BLOCKED 114
#define VARIOUS_TRY_TO_CLEAR_PRIMAL_WEATHER 115
#define VARIOUS_GET_ROTOTILLER_TARGETS 116
#define VARIOUS_JUMP_IF_NOT_ROTOTILLER_AFFECTED 117
#define VARIOUS_TRY_ACTIVATE_BATTLE_BOND 118
#define VARIOUS_CONSUME_BERRY 119
#define VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL 120
#define VARIOUS_HANDLE_PRIMAL_REVERSION 121
#define VARIOUS_APPLY_PLASMA_FISTS 122
#define VARIOUS_JUMP_IF_SPECIES 123
#define VARIOUS_UPDATE_ABILITY_POPUP 124
#define VARIOUS_JUMP_IF_WEATHER_AFFECTED 125
#define VARIOUS_JUMP_IF_LEAF_GUARD_PROTECTED 126
#define VARIOUS_SET_ATTACKER_STICKY_WEB_USER 127
#define VARIOUS_PHOTON_GEYSER_CHECK 128
#define VARIOUS_SHELL_SIDE_ARM_CHECK 129
#define VARIOUS_TRY_NO_RETREAT 130
#define VARIOUS_TRY_TAR_SHOT 131
#define VARIOUS_CAN_TAR_SHOT_WORK 132
#define VARIOUS_CHECK_POLTERGEIST 133
#define VARIOUS_SET_OCTOLOCK 134
#define VARIOUS_CUT_1_3_HP_RAISE_STATS 135
#define VARIOUS_TRY_END_NEUTRALIZING_GAS 136
#define VARIOUS_JUMP_IF_UNDER_200 137
#define VARIOUS_SET_SKY_DROP 138
#define VARIOUS_CLEAR_SKY_DROP 139
#define VARIOUS_SKY_DROP_YAWN 140
#define VARIOUS_JUMP_IF_CANT_FLING 141
#define VARIOUS_JUMP_IF_HOLD_EFFECT 142
#define VARIOUS_CURE_CERTAIN_STATUSES 143
#define VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES 144
#define VARIOUS_JUMP_IF_LAST_USED_ITEM_BERRY 145
#define VARIOUS_JUMP_IF_LAST_USED_ITEM_HOLD_EFFECT 146
#define VARIOUS_SAVE_BATTLER_ITEM 147
#define VARIOUS_RESTORE_BATTLER_ITEM 148
#define VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM 149
#define VARIOUS_SET_BEAK_BLAST 150
#define VARIOUS_SWAP_SIDE_STATUSES 151
#define VARIOUS_SET_Z_EFFECT 152
#define VARIOUS_TRY_SYMBIOSIS 153
#define VARIOUS_CAN_TELEPORT 154
#define VARIOUS_GET_BATTLER_SIDE 155
#define VARIOUS_CHECK_PARENTAL_BOND_COUNTER 156
#define VARIOUS_SWAP_STATS 157
#define VARIOUS_JUMP_IF_ROD 158
#define VARIOUS_JUMP_IF_ABSORB 159
#define VARIOUS_JUMP_IF_MOTOR 160
#define VARIOUS_TEATIME_INVUL 161
#define VARIOUS_TEATIME_TARGETS 162
#define VARIOUS_TRY_WIND_RIDER_POWER 163
#define VARIOUS_ACTIVATE_WEATHER_CHANGE_ABILITIES 164
#define VARIOUS_ACTIVATE_TERRAIN_CHANGE_ABILITIES 165
#define VARIOUS_JUMP_IF_EMERGENCY_EXITED 166
#define VARIOUS_STORE_HEALING_WISH 167
#define VARIOUS_HIT_SWITCH_TARGET_FAILED 168
#define VARIOUS_JUMP_IF_SHELL_TRAP 169
#define VARIOUS_TRY_REVIVAL_BLESSING 170
#define VARIOUS_CANCEL_MULTI_TURN_MOVES 0
#define VARIOUS_SET_MAGIC_COAT_TARGET 1
#define VARIOUS_IS_RUNNING_IMPOSSIBLE 2
#define VARIOUS_GET_MOVE_TARGET 3
#define VARIOUS_GET_BATTLER_FAINTED 4
#define VARIOUS_RESET_SWITCH_IN_ABILITY_BITS 5
#define VARIOUS_UPDATE_CHOICE_MOVE_ON_LVL_UP 6
#define VARIOUS_RESET_PLAYER_FAINTED 7
#define VARIOUS_PALACE_FLAVOR_TEXT 8
#define VARIOUS_ARENA_JUDGMENT_WINDOW 9
#define VARIOUS_ARENA_OPPONENT_MON_LOST 10
#define VARIOUS_ARENA_PLAYER_MON_LOST 11
#define VARIOUS_ARENA_BOTH_MONS_LOST 12
#define VARIOUS_EMIT_YESNOBOX 13
#define VARIOUS_DRAW_ARENA_REF_TEXT_BOX 14
#define VARIOUS_ERASE_ARENA_REF_TEXT_BOX 15
#define VARIOUS_ARENA_JUDGMENT_STRING 16
#define VARIOUS_ARENA_WAIT_STRING 17
#define VARIOUS_WAIT_CRY 18
#define VARIOUS_RETURN_OPPONENT_MON1 19
#define VARIOUS_RETURN_OPPONENT_MON2 20
#define VARIOUS_VOLUME_DOWN 21
#define VARIOUS_VOLUME_UP 22
#define VARIOUS_SET_ALREADY_STATUS_MOVE_ATTEMPT 23
#define VARIOUS_PALACE_TRY_ESCAPE_STATUS 24
#define VARIOUS_SET_TELEPORT_OUTCOME 25
#define VARIOUS_PLAY_TRAINER_DEFEATED_MUSIC 26
#define VARIOUS_STAT_TEXT_BUFFER 27
#define VARIOUS_SWITCHIN_ABILITIES 28
#define VARIOUS_SAVE_TARGET 29
#define VARIOUS_RESTORE_TARGET 30
#define VARIOUS_INSTANT_HP_DROP 31
#define VARIOUS_CLEAR_STATUS 32
#define VARIOUS_RESTORE_PP 33
#define VARIOUS_TRY_ACTIVATE_MOXIE 34
#define VARIOUS_TRY_ACTIVATE_FELL_STINGER 35
#define VARIOUS_PLAY_MOVE_ANIMATION 36
#define VARIOUS_SET_LUCKY_CHANT 37
#define VARIOUS_SUCKER_PUNCH_CHECK 38
#define VARIOUS_SET_SIMPLE_BEAM 39
#define VARIOUS_TRY_ENTRAINMENT 40
#define VARIOUS_SET_LAST_USED_ABILITY 41
#define VARIOUS_TRY_HEAL_PULSE 42
#define VARIOUS_TRY_QUASH 43
#define VARIOUS_INVERT_STAT_STAGES 44
#define VARIOUS_SET_TERRAIN 45
#define VARIOUS_TRY_ME_FIRST 46
#define VARIOUS_JUMP_IF_BATTLE_END 47
#define VARIOUS_TRY_ELECTRIFY 48
#define VARIOUS_TRY_REFLECT_TYPE 49
#define VARIOUS_TRY_SOAK 50
#define VARIOUS_HANDLE_MEGA_EVO 51
#define VARIOUS_TRY_LAST_RESORT 52
#define VARIOUS_ARGUMENT_STATUS_EFFECT 53
#define VARIOUS_TRY_HIT_SWITCH_TARGET 54
#define VARIOUS_TRY_AUTOTOMIZE 55
#define VARIOUS_TRY_COPYCAT 56
#define VARIOUS_ABILITY_POPUP 57
#define VARIOUS_DEFOG 58
#define VARIOUS_JUMP_IF_TARGET_ALLY 59
#define VARIOUS_TRY_SYNCHRONOISE 60
#define VARIOUS_PSYCHO_SHIFT 61
#define VARIOUS_CURE_STATUS 62
#define VARIOUS_POWER_TRICK 63
#define VARIOUS_AFTER_YOU 64
#define VARIOUS_BESTOW 65
#define VARIOUS_ARGUMENT_TO_MOVE_EFFECT 66
#define VARIOUS_JUMP_IF_NOT_GROUNDED 67
#define VARIOUS_HANDLE_TRAINER_SLIDE_MSG 68
#define VARIOUS_TRY_TRAINER_SLIDE_MSG_FIRST_OFF 69
#define VARIOUS_TRY_TRAINER_SLIDE_MSG_LAST_ON 70
#define VARIOUS_SET_AURORA_VEIL 71
#define VARIOUS_TRY_THIRD_TYPE 72
#define VARIOUS_ACUPRESSURE 73
#define VARIOUS_SET_POWDER 74
#define VARIOUS_SPECTRAL_THIEF 75
#define VARIOUS_GRAVITY_ON_AIRBORNE_MONS 76
#define VARIOUS_CHECK_IF_GRASSY_TERRAIN_HEALS 77
#define VARIOUS_JUMP_IF_ROAR_FAILS 78
#define VARIOUS_TRY_INSTRUCT 79
#define VARIOUS_JUMP_IF_NOT_BERRY 80
#define VARIOUS_TRACE_ABILITY 81
#define VARIOUS_UPDATE_NICK 82
#define VARIOUS_TRY_ILLUSION_OFF 83
#define VARIOUS_SET_SPRITEIGNORE0HP 84
#define VARIOUS_HANDLE_FORM_CHANGE 85
#define VARIOUS_GET_STAT_VALUE 86
#define VARIOUS_JUMP_IF_FULL_HP 87
#define VARIOUS_LOSE_TYPE 88
#define VARIOUS_TRY_ACTIVATE_SOULHEART 89
#define VARIOUS_TRY_ACTIVATE_RECEIVER 90
#define VARIOUS_TRY_ACTIVATE_BEAST_BOOST 91
#define VARIOUS_TRY_FRISK 92
#define VARIOUS_JUMP_IF_SHIELDS_DOWN_PROTECTED 93
#define VARIOUS_TRY_FAIRY_LOCK 94
#define VARIOUS_JUMP_IF_NO_ALLY 95
#define VARIOUS_POISON_TYPE_IMMUNITY 96
#define VARIOUS_JUMP_IF_NO_HOLD_EFFECT 97
#define VARIOUS_INFATUATE_WITH_BATTLER 98
#define VARIOUS_SET_LAST_USED_ITEM 99
#define VARIOUS_PARALYZE_TYPE_IMMUNITY 100
#define VARIOUS_JUMP_IF_ABSENT 101
#define VARIOUS_DESTROY_ABILITY_POPUP 102
#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
#define VARIOUS_EERIE_SPELL_PP_REDUCE 110
#define VARIOUS_JUMP_IF_TEAM_HEALTHY 111
#define VARIOUS_TRY_HEAL_QUARTER_HP 112
#define VARIOUS_REMOVE_TERRAIN 113
#define VARIOUS_JUMP_IF_PRANKSTER_BLOCKED 114
#define VARIOUS_TRY_TO_CLEAR_PRIMAL_WEATHER 115
#define VARIOUS_GET_ROTOTILLER_TARGETS 116
#define VARIOUS_JUMP_IF_NOT_ROTOTILLER_AFFECTED 117
#define VARIOUS_TRY_ACTIVATE_BATTLE_BOND 118
#define VARIOUS_CONSUME_BERRY 119
#define VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL 120
#define VARIOUS_HANDLE_PRIMAL_REVERSION 121
#define VARIOUS_APPLY_PLASMA_FISTS 122
#define VARIOUS_JUMP_IF_SPECIES 123
#define VARIOUS_UPDATE_ABILITY_POPUP 124
#define VARIOUS_JUMP_IF_WEATHER_AFFECTED 125
#define VARIOUS_JUMP_IF_LEAF_GUARD_PROTECTED 126
#define VARIOUS_SET_ATTACKER_STICKY_WEB_USER 127
#define VARIOUS_PHOTON_GEYSER_CHECK 128
#define VARIOUS_SHELL_SIDE_ARM_CHECK 129
#define VARIOUS_TRY_NO_RETREAT 130
#define VARIOUS_TRY_TAR_SHOT 131
#define VARIOUS_CAN_TAR_SHOT_WORK 132
#define VARIOUS_CHECK_POLTERGEIST 133
#define VARIOUS_SET_OCTOLOCK 134
#define VARIOUS_CUT_1_3_HP_RAISE_STATS 135
#define VARIOUS_TRY_END_NEUTRALIZING_GAS 136
#define VARIOUS_JUMP_IF_UNDER_200 137
#define VARIOUS_SET_SKY_DROP 138
#define VARIOUS_CLEAR_SKY_DROP 139
#define VARIOUS_SKY_DROP_YAWN 140
#define VARIOUS_JUMP_IF_CANT_FLING 141
#define VARIOUS_JUMP_IF_HOLD_EFFECT 142
#define VARIOUS_CURE_CERTAIN_STATUSES 143
#define VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES 144
#define VARIOUS_JUMP_IF_LAST_USED_ITEM_BERRY 145
#define VARIOUS_JUMP_IF_LAST_USED_ITEM_HOLD_EFFECT 146
#define VARIOUS_SAVE_BATTLER_ITEM 147
#define VARIOUS_RESTORE_BATTLER_ITEM 148
#define VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM 149
#define VARIOUS_SET_BEAK_BLAST 150
#define VARIOUS_SWAP_SIDE_STATUSES 151
#define VARIOUS_SET_Z_EFFECT 152
#define VARIOUS_TRY_SYMBIOSIS 153
#define VARIOUS_CAN_TELEPORT 154
#define VARIOUS_GET_BATTLER_SIDE 155
#define VARIOUS_CHECK_PARENTAL_BOND_COUNTER 156
#define VARIOUS_SWAP_STATS 157
#define VARIOUS_JUMP_IF_ROD 158
#define VARIOUS_JUMP_IF_ABSORB 159
#define VARIOUS_JUMP_IF_MOTOR 160
#define VARIOUS_TEATIME_INVUL 161
#define VARIOUS_TEATIME_TARGETS 162
#define VARIOUS_TRY_WIND_RIDER_POWER 163
#define VARIOUS_ACTIVATE_WEATHER_CHANGE_ABILITIES 164
#define VARIOUS_ACTIVATE_TERRAIN_CHANGE_ABILITIES 165
#define VARIOUS_JUMP_IF_EMERGENCY_EXITED 166
#define VARIOUS_STORE_HEALING_WISH 167
#define VARIOUS_HIT_SWITCH_TARGET_FAILED 168
#define VARIOUS_JUMP_IF_SHELL_TRAP 169
#define VARIOUS_TRY_REVIVAL_BLESSING 170
#define VARIOUS_TRY_TRAINER_SLIDE_MSG_Z_MOVE 171
#define VARIOUS_TRY_TRAINER_SLIDE_MSG_MEGA_EVOLUTION 172
// Cmd_manipulatedamage
#define DMG_CHANGE_SIGN 0

View File

@ -648,8 +648,12 @@
#define STRINGID_COULDNTFULLYPROTECT 646
#define STRINGID_STOCKPILEDEFFECTWOREOFF 647
#define STRINGID_PKMNREVIVEDREADYTOFIGHT 648
#define STRINGID_ITEMRESTOREDSPECIESHEALTH 649
#define STRINGID_ITEMCUREDSPECIESSTATUS 650
#define STRINGID_ITEMRESTOREDSPECIESPP 651
#define STRINGID_THUNDERCAGETRAPPED 652
#define BATTLESTRINGS_COUNT 649
#define BATTLESTRINGS_COUNT 653
// This is the string id that gBattleStringsTable starts with.
// String ids before this (e.g. STRINGID_INTROMSG) are not in the table,
@ -914,16 +918,17 @@
#define B_MSG_TERRAINENDS_COUNT 4
// gWrappedStringIds
#define B_MSG_WRAPPED_BIND 0
#define B_MSG_WRAPPED_WRAP 1
#define B_MSG_WRAPPED_FIRE_SPIN 2
#define B_MSG_WRAPPED_CLAMP 3
#define B_MSG_WRAPPED_WHIRLPOOL 4
#define B_MSG_WRAPPED_SAND_TOMB 5
#define B_MSG_WRAPPED_MAGMA_STORM 6
#define B_MSG_WRAPPED_INFESTATION 7
#define B_MSG_WRAPPED_SNAP_TRAP 8
#define NUM_TRAPPING_MOVES 9
#define B_MSG_WRAPPED_BIND 0
#define B_MSG_WRAPPED_WRAP 1
#define B_MSG_WRAPPED_FIRE_SPIN 2
#define B_MSG_WRAPPED_CLAMP 3
#define B_MSG_WRAPPED_WHIRLPOOL 4
#define B_MSG_WRAPPED_SAND_TOMB 5
#define B_MSG_WRAPPED_MAGMA_STORM 6
#define B_MSG_WRAPPED_INFESTATION 7
#define B_MSG_WRAPPED_SNAP_TRAP 8
#define B_MSG_WRAPPED_THUNDER_CAGE 9
#define NUM_TRAPPING_MOVES 10
// z effects
#define B_MSG_Z_RESET_STATS 0

View File

@ -161,6 +161,9 @@
#define HOLD_EFFECT_LOADED_DICE 180
#define HOLD_EFFECT_BOOSTER_ENERGY 181 // Not implemented.
// Gen2 hold effect
#define HOLD_EFFECT_BERSERK_GENE 182
#define HOLD_EFFECT_CHOICE(holdEffect)((holdEffect == HOLD_EFFECT_CHOICE_BAND || holdEffect == HOLD_EFFECT_CHOICE_SCARF || holdEffect == HOLD_EFFECT_CHOICE_SPECS))
// Terrain seed params

View File

@ -7,12 +7,12 @@
#define ITEM0_INFATUATION 0x80
// new field 1 masks
#define ITEM1_X_ATTACK 0x1
#define ITEM1_X_DEFENSE 0x2
#define ITEM1_X_SPEED 0x4
#define ITEM1_X_SPATK 0x8
#define ITEM1_X_SPDEF 0x10
#define ITEM1_X_ACCURACY 0x20
#define ITEM1_X_ATTACK STAT_ATK
#define ITEM1_X_DEFENSE STAT_DEF
#define ITEM1_X_SPEED STAT_SPEED
#define ITEM1_X_SPATK STAT_SPATK
#define ITEM1_X_SPDEF STAT_SPDEF
#define ITEM1_X_ACCURACY STAT_ACC
// field 3 masks
#define ITEM3_CONFUSION 0x1

View File

@ -972,8 +972,9 @@
#define ITEM_BLACK_AUGURITE 795
#define ITEM_LINKING_CORD 796
#define ITEM_PEAT_BLOCK 797
#define ITEM_BERSERK_GENE 798
#define ITEMS_COUNT 798
#define ITEMS_COUNT 799
#define ITEM_FIELD_ARROW ITEMS_COUNT
// A special item id associated with "Cancel"/"Exit" etc. in a list of items or decorations
@ -1030,14 +1031,27 @@
#define EXP_30000 5
// Item type IDs (used to determine the exit callback)
#define ITEM_USE_MAIL 0
#define ITEM_USE_PARTY_MENU 1
#define ITEM_USE_FIELD 2
#define ITEM_USE_PBLOCK_CASE 3
#define ITEM_USE_BAG_MENU 4 // No exit callback, stays in bag menu
#define ITEM_USE_MAIL 0
#define ITEM_USE_PARTY_MENU 1
#define ITEM_USE_FIELD 2
#define ITEM_USE_PBLOCK_CASE 3
#define ITEM_USE_BAG_MENU 4 // No exit callback, stays in bag menu
#define ITEM_USE_PARTY_MENU_MOVES 5
// Item battle usage IDs (only checked to see if nonzero)
#define ITEM_B_USE_MEDICINE 1
#define ITEM_B_USE_OTHER 2
// Item battle script IDs (need to be non-zero)
#define EFFECT_ITEM_RESTORE_HP 1
#define EFFECT_ITEM_CURE_STATUS 2
#define EFFECT_ITEM_HEAL_AND_CURE_STATUS 3
#define EFFECT_ITEM_INCREASE_STAT 4
#define EFFECT_ITEM_SET_MIST 5
#define EFFECT_ITEM_SET_FOCUS_ENERGY 6
#define EFFECT_ITEM_ESCAPE 7
#define EFFECT_ITEM_THROW_BALL 8
#define EFFECT_ITEM_REVIVE 9
#define EFFECT_ITEM_RESTORE_PP 10
#define EFFECT_ITEM_INCREASE_ALL_STATS 11
// Enigma Berry dummy constant
#define EFFECT_ITEM_ENIGMA_BERRY_EREADER 1
#endif // GUARD_CONSTANTS_ITEMS_H

View File

@ -201,7 +201,11 @@
#define MAX_PER_STAT_IVS 31
#define MAX_IV_MASK 31
#define USE_RANDOM_IVS (MAX_PER_STAT_IVS + 1)
#if P_EV_CAP >= GEN_6
#define MAX_PER_STAT_EVS 252
#else
#define MAX_PER_STAT_EVS 255
#endif
#define MAX_TOTAL_EVS 510
#if I_VITAMIN_EV_CAP >= GEN_8
#define EV_ITEM_RAISE_LIMIT MAX_PER_STAT_EVS

View File

@ -8878,6 +8878,8 @@ extern const u32 gItemIcon_GriseousCore[];
extern const u32 gItemIconPalette_GriseousCore[];
extern const u32 gItemIcon_LustrousGlobe[];
extern const u32 gItemIconPalette_LustrousGlobe[];
extern const u32 gItemIcon_BerserkGene[];
extern const u32 gItemIconPalette_BerserkGene[];
extern const u32 gItemIcon_ReturnToFieldArrow[];
extern const u32 gItemIconPalette_ReturnToFieldArrow[];

View File

@ -19,7 +19,6 @@ struct Item
u8 type;
ItemUseFunc fieldUseFunc;
u8 battleUsage;
ItemUseFunc battleUseFunc;
u8 secondaryId;
u8 flingPower;
};
@ -72,8 +71,9 @@ u8 ItemId_GetPocket(u16 itemId);
u8 ItemId_GetType(u16 itemId);
ItemUseFunc ItemId_GetFieldFunc(u16 itemId);
u8 ItemId_GetBattleUsage(u16 itemId);
ItemUseFunc ItemId_GetBattleFunc(u16 itemId);
u8 ItemId_GetSecondaryId(u16 itemId);
u8 ItemId_GetFlingPower(u16 itemId);
u32 GetItemStatus1Mask(u16 itemId);
u32 GetItemStatus2Mask(u16 itemId);
#endif // GUARD_ITEM_H

View File

@ -30,12 +30,9 @@ void ItemUseOutOfBattle_FormChange(u8);
void ItemUseOutOfBattle_FormChange_ConsumedOnUse(u8);
void ItemUseOutOfBattle_Honey(u8);
void ItemUseOutOfBattle_CannotUse(u8);
void ItemUseInBattle_PokeBall(u8);
void ItemUseInBattle_StatIncrease(u8);
void ItemUseInBattle_Medicine(u8);
void ItemUseInBattle_PPRecovery(u8);
void ItemUseInBattle_Escape(u8);
void ItemUseInBattle_EnigmaBerry(u8);
void ItemUseInBattle_BagMenu(u8 taskId);
void ItemUseInBattle_PartyMenu(u8 taskId);
void ItemUseInBattle_PartyMenuChooseMove(u8 taskId);
void Task_UseDigEscapeRopeOnField(u8 taskId);
u8 CanUseDigOrEscapeRopeOnCurMap(void);
u8 CheckIfItemIsTMHMOrEvolutionStone(u16 itemId);

View File

@ -48,6 +48,8 @@ void LoadHeldItemIcons(void);
void DrawHeldItemIconsForTrade(u8 *partyCounts, u8 *partySpriteIds, u8 whichParty);
void LoadPartyMenuAilmentGfx(void);
void CB2_ShowPartyMenuForItemUse(void);
void ItemUseCB_BattleScript(u8 taskId, TaskFunc task);
void ItemUseCB_BattleChooseMove(u8 taskId, TaskFunc task);
void ItemUseCB_Medicine(u8 taskId, TaskFunc task);
void ItemUseCB_AbilityCapsule(u8 taskId, TaskFunc task);
void ItemUseCB_AbilityPatch(u8 taskId, TaskFunc task);
@ -64,6 +66,7 @@ void ItemUseCB_SacredAsh(u8 taskId, TaskFunc task);
void ItemUseCB_EvolutionStone(u8 taskId, TaskFunc task);
void ItemUseCB_FormChange(u8 taskId, TaskFunc task);
void ItemUseCB_FormChange_ConsumedOnUse(u8 taskId, TaskFunc task);
const u8* GetItemEffect(u16 item);
u8 GetItemEffectType(u16 item);
void CB2_PartyMenuFromStartMenu(void);
void CB2_ChooseMonToGiveItem(void);

View File

@ -44,6 +44,7 @@ enum
RECORDED_MOVE_TARGET,
RECORDED_PARTY_INDEX,
RECORDED_BATTLE_PALACE_ACTION,
RECORDED_ITEM_ID,
};
extern u32 gRecordedBattleRngSeed;

View File

@ -1025,6 +1025,8 @@ extern const u8 gText_ThrowInPremierBall[];
extern const u8 gText_ShopBuy[];
extern const u8 gText_ShopSell[];
extern const u8 gText_ShopQuit[];
extern const u8 gText_ThatItemIsSoldOut[];
extern const u8 gText_SoldOut[];
extern const u8 gText_OhABite[];
extern const u8 gText_PokemonOnHook[];

View File

@ -4246,6 +4246,10 @@ Cry_ThundurusTherian::
Cry_LandorusTherian::
.incbin "sound/direct_sound_samples/cries/landorus_therian.bin"
.align 2
Cry_EnamorusTherian::
.incbin "sound/direct_sound_samples/cries/enamorus_therian.bin"
.align 2
Cry_KyuremWhite::
.incbin "sound/direct_sound_samples/cries/kyurem_white.bin"
@ -4360,10 +4364,6 @@ Cry_CalyrexIceRider::
Cry_CalyrexShadowRider::
.incbin "sound/direct_sound_samples/cries/calyrex_shadow_rider.bin"
.align 2
Cry_EnamorusTherian::
.incbin "sound/direct_sound_samples/cries/enamorus_therian.bin"
.endif
.align 2

View File

@ -10,6 +10,8 @@
#include "constants/hold_effects.h"
#include "battle_setup.h"
#include "data.h"
#include "item.h"
#include "party_menu.h"
#include "pokemon.h"
#include "random.h"
#include "util.h"
@ -995,22 +997,6 @@ u8 GetMostSuitableMonToSwitchInto(void)
return PARTY_SIZE;
}
static u8 GetAI_ItemType(u16 itemId, const u8 *itemEffect)
{
if (itemId == ITEM_FULL_RESTORE)
return AI_ITEM_FULL_RESTORE;
else if (itemEffect[4] & ITEM4_HEAL_HP)
return AI_ITEM_HEAL_HP;
else if (itemEffect[3] & ITEM3_STATUS_ALL)
return AI_ITEM_CURE_CONDITION;
else if ((itemEffect[0] & ITEM0_DIRE_HIT) || itemEffect[1])
return AI_ITEM_X_STAT;
else if (itemEffect[3] & ITEM3_GUARD_SPEC)
return AI_ITEM_GUARD_SPEC;
else
return AI_ITEM_NOT_RECOGNIZABLE;
}
static bool32 AiExpectsToFaintPlayer(void)
{
bool32 canFaintPlayer;
@ -1070,96 +1056,70 @@ static bool8 ShouldUseItem(void)
u8 paramOffset;
u8 battlerSide;
if (i != 0 && validMons > (gBattleResources->battleHistory->itemsNo - i) + 1)
continue;
item = gBattleResources->battleHistory->trainerItems[i];
if (item == ITEM_NONE)
continue;
if (gItemEffectTable[item] == NULL)
itemEffects = GetItemEffect(item);
if (itemEffects == NULL)
continue;
if (item == ITEM_ENIGMA_BERRY_E_READER)
itemEffects = gSaveBlock1Ptr->enigmaBerry.itemEffect;
else
itemEffects = gItemEffectTable[item];
*(gBattleStruct->AI_itemType + gActiveBattler / 2) = GetAI_ItemType(item, itemEffects);
switch (*(gBattleStruct->AI_itemType + gActiveBattler / 2))
switch (ItemId_GetBattleUsage(item))
{
case AI_ITEM_FULL_RESTORE:
case EFFECT_ITEM_HEAL_AND_CURE_STATUS:
shouldUse = AI_ShouldHeal(0);
break;
case AI_ITEM_HEAL_HP:
case EFFECT_ITEM_RESTORE_HP:
shouldUse = AI_ShouldHeal(itemEffects[GetItemEffectParamOffset(item, 4, 4)]);
break;
case AI_ITEM_CURE_CONDITION:
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) = 0;
case EFFECT_ITEM_CURE_STATUS:
if (itemEffects[3] & ITEM3_SLEEP && gBattleMons[gActiveBattler].status1 & STATUS1_SLEEP)
{
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= (1 << AI_HEAL_SLEEP);
shouldUse = TRUE;
}
if (itemEffects[3] & ITEM3_POISON && (gBattleMons[gActiveBattler].status1 & STATUS1_POISON
|| gBattleMons[gActiveBattler].status1 & STATUS1_TOXIC_POISON))
{
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= (1 << AI_HEAL_POISON);
shouldUse = TRUE;
}
if (itemEffects[3] & ITEM3_BURN && gBattleMons[gActiveBattler].status1 & STATUS1_BURN)
{
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= (1 << AI_HEAL_BURN);
shouldUse = TRUE;
}
if (itemEffects[3] & ITEM3_FREEZE && gBattleMons[gActiveBattler].status1 & STATUS1_FREEZE)
{
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= (1 << AI_HEAL_FREEZE);
shouldUse = TRUE;
}
if (itemEffects[3] & ITEM3_PARALYSIS && gBattleMons[gActiveBattler].status1 & STATUS1_PARALYSIS)
{
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= (1 << AI_HEAL_PARALYSIS);
shouldUse = TRUE;
}
if (itemEffects[3] & ITEM3_CONFUSION && gBattleMons[gActiveBattler].status2 & STATUS2_CONFUSION)
{
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= (1 << AI_HEAL_CONFUSION);
shouldUse = TRUE;
}
break;
case AI_ITEM_X_STAT:
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) = 0;
if (gDisableStructs[gActiveBattler].isFirstTurn == 0)
case EFFECT_ITEM_INCREASE_STAT:
case EFFECT_ITEM_INCREASE_ALL_STATS:
if (!gDisableStructs[gActiveBattler].isFirstTurn
|| AI_OpponentCanFaintAiWithMod(0))
break;
if (itemEffects[1] & ITEM1_X_ATTACK)
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= (1 << AI_X_ATTACK);
if (itemEffects[1] & ITEM1_X_DEFENSE)
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= (1 << AI_X_DEFEND);
if (itemEffects[1] & ITEM1_X_SPEED)
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= (1 << AI_X_SPEED);
if (itemEffects[1] & ITEM1_X_SPATK)
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= (1 << AI_X_SPATK);
if (itemEffects[1] & ITEM1_X_SPDEF)
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= (1 << AI_X_SPDEF);
if (itemEffects[1] & ITEM1_X_ACCURACY)
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= (1 << AI_X_ACCURACY);
if (itemEffects[0] & ITEM0_DIRE_HIT)
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= (1 << AI_DIRE_HIT);
shouldUse = TRUE;
break;
case AI_ITEM_GUARD_SPEC:
case EFFECT_ITEM_SET_FOCUS_ENERGY:
if (!gDisableStructs[gActiveBattler].isFirstTurn
|| gBattleMons[gActiveBattler].status2 & STATUS2_FOCUS_ENERGY
|| AI_OpponentCanFaintAiWithMod(0))
break;
shouldUse = TRUE;
break;
case EFFECT_ITEM_SET_MIST:
battlerSide = GetBattlerSide(gActiveBattler);
if (gDisableStructs[gActiveBattler].isFirstTurn != 0 && gSideTimers[battlerSide].mistTimer == 0)
if (gDisableStructs[gActiveBattler].isFirstTurn && gSideTimers[battlerSide].mistTimer == 0)
shouldUse = TRUE;
break;
case AI_ITEM_NOT_RECOGNIZABLE:
case EFFECT_ITEM_REVIVE:
gBattleStruct->itemPartyIndex[gActiveBattler] = GetFirstFaintedPartyIndex(gActiveBattler);
if (gBattleStruct->itemPartyIndex[gActiveBattler] != PARTY_SIZE) // Revive if possible.
shouldUse = TRUE;
break;
default:
return FALSE;
}
if (shouldUse)
{
// Set selected party ID to current battler if none chosen.
if (gBattleStruct->itemPartyIndex[gActiveBattler] == PARTY_SIZE)
gBattleStruct->itemPartyIndex[gActiveBattler] = gBattlerPartyIndexes[gActiveBattler];
BtlController_EmitTwoReturnValues(BUFFER_B, B_ACTION_USE_ITEM, 0);
*(gBattleStruct->chosenItem + (gActiveBattler / 2) * 2) = item;
gBattleStruct->chosenItem[gActiveBattler] = item;
gBattleResources->battleHistory->trainerItems[i] = 0;
return shouldUse;
}

View File

@ -477,7 +477,7 @@ bool32 IsAiBattlerAware(u32 battlerId)
{
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_OMNISCIENT)
return TRUE;
return BattlerHasAi(battlerId);
}
@ -1129,7 +1129,7 @@ bool32 CanTargetFaintAi(u8 battlerDef, u8 battlerAtk)
{
s32 i, dmg;
u32 unusable = AI_DATA->moveLimitations[battlerDef];
u16 *moves = gBattleResources->battleHistory->usedMoves[battlerDef];
u16 *moves = GetMovesArray(battlerDef);
for (i = 0; i < MAX_MON_MOVES; i++)
{
@ -3420,7 +3420,7 @@ bool32 IsPartyFullyHealedExceptBattler(u8 battlerId)
bool32 PartyHasMoveSplit(u8 battlerId, u8 split)
{
u8 firstId, lastId;
struct Pokemon* party = GetBattlerPartyData(battlerId);
struct Pokemon *party = GetBattlerParty(battlerId);
u32 i, j;
for (i = 0; i < PARTY_SIZE; i++)

View File

@ -7897,9 +7897,6 @@ void AnimTask_TerrainPulse(u8 taskId)
void AnimTask_AffectionHangedOn(u8 taskId)
{
int side = GetBattlerSide(gBattleAnimTarget);
struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty;
gBattleAnimArgs[0] = GetBattlerFriendshipScore(gBattleAnimTarget);
DestroyAnimVisualTask(taskId);
}

View File

@ -2736,23 +2736,37 @@ void AnimTask_SetAttackerTargetLeftPos(u8 taskId)
void AnimTask_GetTrappedMoveAnimId(u8 taskId)
{
if (gBattleSpritesDataPtr->animationData->animArg == MOVE_FIRE_SPIN)
switch (gBattleSpritesDataPtr->animationData->animArg)
{
case MOVE_FIRE_SPIN:
gBattleAnimArgs[0] = TRAP_ANIM_FIRE_SPIN;
else if (gBattleSpritesDataPtr->animationData->animArg == MOVE_WHIRLPOOL)
break;
case MOVE_WHIRLPOOL:
gBattleAnimArgs[0] = TRAP_ANIM_WHIRLPOOL;
else if (gBattleSpritesDataPtr->animationData->animArg == MOVE_CLAMP)
break;
case MOVE_CLAMP:
gBattleAnimArgs[0] = TRAP_ANIM_CLAMP;
else if (gBattleSpritesDataPtr->animationData->animArg == MOVE_SAND_TOMB)
break;
case MOVE_SAND_TOMB:
gBattleAnimArgs[0] = TRAP_ANIM_SAND_TOMB;
else if (gBattleSpritesDataPtr->animationData->animArg == MOVE_MAGMA_STORM)
break;
case MOVE_MAGMA_STORM:
gBattleAnimArgs[0] = TRAP_ANIM_MAGMA_STORM;
else if (gBattleSpritesDataPtr->animationData->animArg == MOVE_INFESTATION)
break;
case MOVE_INFESTATION:
gBattleAnimArgs[0] = TRAP_ANIM_INFESTATION;
else if (gBattleSpritesDataPtr->animationData->animArg == MOVE_SNAP_TRAP)
break;
case MOVE_SNAP_TRAP:
gBattleAnimArgs[0] = TRAP_ANIM_SNAP_TRAP;
else
break;
case MOVE_THUNDER_CAGE:
gBattleAnimArgs[0] = TRAP_ANIM_THUNDER_CAGE;
break;
default:
gBattleAnimArgs[0] = TRAP_ANIM_BIND;
break;
}
DestroyAnimVisualTask(taskId);
}

View File

@ -228,9 +228,11 @@ static void Intro_DelayAndEnd(void)
}
}
static bool32 TwoIntroMons(u32 battlerId) // Double battle with both player pokemon active.
static bool32 TwoIntroMons(u32 battlerId) // Double battle with both opponent pokemon active.
{
return (IsDoubleBattle() && IsValidForBattle(&gEnemyParty[gBattlerPartyIndexes[BATTLE_PARTNER(battlerId)]]));
return (IsDoubleBattle()
&& IsValidForBattle(&gEnemyParty[gBattlerPartyIndexes[battlerId]])
&& IsValidForBattle(&gEnemyParty[gBattlerPartyIndexes[BATTLE_PARTNER(battlerId)]]));
}
static void Intro_WaitForShinyAnimAndHealthbox(void)
@ -1667,7 +1669,7 @@ static void OpponentHandleChooseMove(void)
static void OpponentHandleChooseItem(void)
{
BtlController_EmitOneReturnValue(BUFFER_B, *(gBattleStruct->chosenItem + (gActiveBattler / 2) * 2));
BtlController_EmitOneReturnValue(BUFFER_B, gBattleStruct->chosenItem[gActiveBattler]);
OpponentBufferExecCompleted();
}
@ -1969,7 +1971,7 @@ static void SpriteCB_FreeOpponentSprite(struct Sprite *sprite)
static void Task_StartSendOutAnim(u8 taskId)
{
u8 savedActiveBank = gActiveBattler;
u8 savedActiveBattler = gActiveBattler;
gActiveBattler = gTasks[taskId].data[0];
if ((!TwoIntroMons(gActiveBattler) || (gBattleTypeFlags & BATTLE_TYPE_MULTI)) && !BATTLE_TWO_VS_ONE_OPPONENT)
@ -1977,7 +1979,7 @@ static void Task_StartSendOutAnim(u8 taskId)
gBattleResources->bufferA[gActiveBattler][1] = gBattlerPartyIndexes[gActiveBattler];
StartSendOutAnim(gActiveBattler, FALSE);
}
else if ((gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS))
else if ((gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) || (BATTLE_TWO_VS_ONE_OPPONENT && !TwoIntroMons(gActiveBattler)))
{
gBattleResources->bufferA[gActiveBattler][1] = gBattlerPartyIndexes[gActiveBattler];
StartSendOutAnim(gActiveBattler, FALSE);
@ -1992,7 +1994,7 @@ static void Task_StartSendOutAnim(u8 taskId)
gActiveBattler ^= BIT_FLANK;
}
gBattlerControllerFuncs[gActiveBattler] = Intro_TryShinyAnimShowHealthbox;
gActiveBattler = savedActiveBank;
gActiveBattler = savedActiveBattler;
DestroyTask(taskId);
}

View File

@ -10,6 +10,7 @@
#include "battle_tv.h"
#include "bg.h"
#include "data.h"
#include "item_menu.h"
#include "item_use.h"
#include "link.h"
#include "main.h"
@ -1437,6 +1438,10 @@ static void RecordedOpponentHandleChooseMove(void)
static void RecordedOpponentHandleChooseItem(void)
{
u8 byte1 = RecordedBattle_GetBattlerAction(RECORDED_ITEM_ID, gActiveBattler);
u8 byte2 = RecordedBattle_GetBattlerAction(RECORDED_ITEM_ID, gActiveBattler);
gBattleStruct->chosenItem[gActiveBattler] = (byte1 << 8) | byte2;
BtlController_EmitOneReturnValue(BUFFER_B, gBattleStruct->chosenItem[gActiveBattler]);
RecordedOpponentBufferExecCompleted();
}

View File

@ -7,6 +7,7 @@
#include "battle_interface.h"
#include "bg.h"
#include "data.h"
#include "item_menu.h"
#include "item_use.h"
#include "link.h"
#include "main.h"
@ -1461,6 +1462,10 @@ static void RecordedPlayerHandleChooseMove(void)
static void RecordedPlayerHandleChooseItem(void)
{
u8 byte1 = RecordedBattle_GetBattlerAction(RECORDED_ITEM_ID, gActiveBattler);
u8 byte2 = RecordedBattle_GetBattlerAction(RECORDED_ITEM_ID, gActiveBattler);
gBattleStruct->chosenItem[gActiveBattler] = (byte1 << 8) | byte2;
BtlController_EmitOneReturnValue(BUFFER_B, gBattleStruct->chosenItem[gActiveBattler]);
RecordedPlayerBufferExecCompleted();
}

View File

@ -690,12 +690,17 @@ static void InitLastUsedBallAssets(void)
}
// This function is here to cover a specific case - one player's mon in a 2 vs 1 double battle. In this scenario - display singles layout.
// The same goes for a 2 vs 1 where opponent has only one pokemon.
u32 WhichBattleCoords(u32 battlerId) // 0 - singles, 1 - doubles
{
if (GetBattlerPosition(battlerId) == B_POSITION_PLAYER_LEFT
&& gPlayerPartyCount == 1
&& !(gBattleTypeFlags & BATTLE_TYPE_MULTI))
return 0;
else if (GetBattlerPosition(battlerId) == B_POSITION_OPPONENT_LEFT
&& gEnemyPartyCount == 1
&& !(gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS))
return 0;
else
return IsDoubleBattle();
}

View File

@ -594,6 +594,7 @@ static void CB2_InitBattleInternal(void)
if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS && !BATTLE_TWO_VS_ONE_OPPONENT)
CreateNPCTrainerParty(&gEnemyParty[PARTY_SIZE / 2], gTrainerBattleOpponent_B, FALSE);
SetWildMonHeldItem();
CalculateEnemyPartyCount();
}
gMain.inBattle = TRUE;
@ -3177,7 +3178,7 @@ static void BattleStartClearSetData(void)
{
gBattleStruct->usedHeldItems[i][B_SIDE_PLAYER] = 0;
gBattleStruct->usedHeldItems[i][B_SIDE_OPPONENT] = 0;
gBattleStruct->itemStolen[i].originalItem = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM);
gBattleStruct->itemLost[i].originalItem = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM);
gPartyCriticalHits[i] = 0;
gBattleStruct->allowedToChangeFormInWeather[i][B_SIDE_PLAYER] = FALSE;
gBattleStruct->allowedToChangeFormInWeather[i][B_SIDE_OPPONENT] = FALSE;
@ -3214,7 +3215,7 @@ void SwitchInClearSetData(void)
gStatuses3[gActiveBattler] &= (STATUS3_LEECHSEED_BATTLER | STATUS3_LEECHSEED | STATUS3_ALWAYS_HITS | STATUS3_PERISH_SONG | STATUS3_ROOTED
| STATUS3_GASTRO_ACID | STATUS3_EMBARGO | STATUS3_TELEKINESIS | STATUS3_MAGNET_RISE | STATUS3_HEAL_BLOCK
| STATUS3_AQUA_RING | STATUS3_POWER_TRICK);
gStatuses4[gActiveBattler] &= (STATUS4_MUD_SPORT | STATUS4_WATER_SPORT);
gStatuses4[gActiveBattler] &= (STATUS4_MUD_SPORT | STATUS4_WATER_SPORT | STATUS4_INFINITE_CONFUSION);
for (i = 0; i < gBattlersCount; i++)
{
if (GetBattlerSide(gActiveBattler) != GetBattlerSide(i)
@ -3785,7 +3786,9 @@ static void TryDoEventsBeforeFirstTurn(void)
{
for (i = 0; i < gBattlersCount; i++)
{
if (gBattleMons[i].hp == 0 || gBattleMons[i].species == SPECIES_NONE || GetMonData(GetBattlerPartyData(i), MON_DATA_IS_EGG))
struct Pokemon *party = GetBattlerParty(i);
struct Pokemon *mon = &party[gBattlerPartyIndexes[i]];
if (gBattleMons[i].hp == 0 || gBattleMons[i].species == SPECIES_NONE || GetMonData(mon, MON_DATA_IS_EGG))
gAbsentBattlerFlags |= gBitTable[i];
}
}
@ -3896,6 +3899,9 @@ static void TryDoEventsBeforeFirstTurn(void)
StopCryAndClearCrySongs();
BattleScriptExecute(BattleScript_ArenaTurnBeginning);
}
if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_BEFORE_FIRST_TURN)))
BattleScriptExecute(i == 1 ? BattleScript_TrainerASlideMsgEnd2 : BattleScript_TrainerBSlideMsgEnd2);
}
static void HandleEndTurn_ContinueBattle(void)
@ -3988,6 +3994,16 @@ void BattleTurnPassed(void)
BattleScriptExecute(BattleScript_ArenaTurnBeginning);
else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_LAST_LOW_HP)))
BattleScriptExecute(i == 1 ? BattleScript_TrainerASlideMsgEnd2 : BattleScript_TrainerBSlideMsgEnd2);
else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_LAST_HALF_HP)))
BattleScriptExecute(i == 1 ? BattleScript_TrainerASlideMsgEnd2 : BattleScript_TrainerBSlideMsgEnd2);
else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_FIRST_CRITICAL_HIT)))
BattleScriptExecute(i == 1 ? BattleScript_TrainerASlideMsgEnd2 : BattleScript_TrainerBSlideMsgEnd2);
else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_FIRST_SUPER_EFFECTIVE_HIT)))
BattleScriptExecute(i == 1 ? BattleScript_TrainerASlideMsgEnd2 : BattleScript_TrainerBSlideMsgEnd2);
else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_FIRST_STAB_MOVE)))
BattleScriptExecute(i == 1 ? BattleScript_TrainerASlideMsgEnd2 : BattleScript_TrainerBSlideMsgEnd2);
else if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_PLAYER_MON_UNAFFECTED)))
BattleScriptExecute(i == 1 ? BattleScript_TrainerASlideMsgEnd2 : BattleScript_TrainerBSlideMsgEnd2);
}
u8 IsRunningFromBattleImpossible(void)
@ -4138,6 +4154,7 @@ static void HandleTurnActionSelectionState(void)
}
else
{
gBattleStruct->itemPartyIndex[gActiveBattler] = PARTY_SIZE;
BtlController_EmitChooseAction(BUFFER_A, gChosenActionByBattler[0], gBattleResources->bufferB[0][1] | (gBattleResources->bufferB[0][2] << 8));
MarkBattlerForControllerExec(gActiveBattler);
gBattleCommunication[gActiveBattler]++;
@ -4205,10 +4222,11 @@ static void HandleTurnActionSelectionState(void)
return;
}
if ((gBattleTypeFlags & (BATTLE_TYPE_LINK
if (((gBattleTypeFlags & (BATTLE_TYPE_LINK
| BATTLE_TYPE_FRONTIER_NO_PYRAMID
| BATTLE_TYPE_EREADER_TRAINER
| BATTLE_TYPE_RECORDED_LINK))
&& !gTestRunnerEnabled)
// Or if currently held by Sky Drop
|| gStatuses3[gActiveBattler] & STATUS3_SKY_DROPPED)
{
@ -5007,7 +5025,8 @@ static void CheckMegaEvolutionBeforeTurn(void)
if (gBattleStruct->mega.toEvolve & gBitTable[gActiveBattler]
&& !(gProtectStructs[gActiveBattler].noValidMoves))
{
struct Pokemon *mon = GetBattlerPartyData(gActiveBattler);
struct Pokemon *party = GetBattlerParty(gActiveBattler);
struct Pokemon *mon = &party[gBattlerPartyIndexes[gActiveBattler]];
gBattleStruct->mega.toEvolve &= ~(gBitTable[gActiveBattler]);
gLastUsedItem = gBattleMons[gActiveBattler].item;
@ -5361,9 +5380,9 @@ static void HandleEndTurn_FinishBattle(void)
TestRunner_Battle_AfterLastTurn();
BeginFastPaletteFade(3);
FadeOutMapMusic(5);
#if B_TRAINERS_KNOCK_OFF_ITEMS == TRUE
#if B_TRAINERS_KNOCK_OFF_ITEMS == TRUE || B_RESTORE_HELD_BATTLE_ITEMS == TRUE
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
TryRestoreStolenItems();
TryRestoreHeldItems();
#endif
for (i = 0; i < PARTY_SIZE; i++)
{

View File

@ -435,11 +435,11 @@ static const u8 sText_ExclamationMark3[] = _("!");
static const u8 sText_ExclamationMark4[] = _("!");
static const u8 sText_ExclamationMark5[] = _("!");
static const u8 sText_HP[] = _("HP");
static const u8 sText_Attack[] = _("attack");
static const u8 sText_Defense[] = _("defense");
static const u8 sText_Speed[] = _("speed");
static const u8 sText_SpAttack[] = _("sp. attack");
static const u8 sText_SpDefense[] = _("sp. defense");
static const u8 sText_Attack[] = _("Attack");
static const u8 sText_Defense[] = _("Defense");
static const u8 sText_Speed[] = _("Speed");
static const u8 sText_SpAttack[] = _("Sp. Atk");
static const u8 sText_SpDefense[] = _("Sp. Def");
static const u8 sText_Accuracy[] = _("accuracy");
static const u8 sText_Evasiveness[] = _("evasiveness");
@ -465,9 +465,9 @@ const u8 *const gPokeblockWasTooXStringTable[FLAVOR_COUNT] =
[FLAVOR_SOUR] = sText_PokeblockWasTooSour
};
static const u8 sText_PlayerUsedItem[] = _("{B_PLAYER_NAME} used\n{B_LAST_ITEM}!");
static const u8 sText_PlayerUsedItem[] = _("You used\n{B_LAST_ITEM}!");
static const u8 sText_WallyUsedItem[] = _("WALLY used\n{B_LAST_ITEM}!");
static const u8 sText_Trainer1UsedItem[] = _("{B_TRAINER1_CLASS} {B_TRAINER1_NAME}\nused {B_LAST_ITEM}!");
static const u8 sText_Trainer1UsedItem[] = _("{B_ATK_TRAINER_CLASS} {B_ATK_TRAINER_NAME}\nused {B_LAST_ITEM}!");
static const u8 sText_TrainerBlockedBall[] = _("The TRAINER blocked the BALL!");
static const u8 sText_DontBeAThief[] = _("Don't be a thief!");
static const u8 sText_ItDodgedBall[] = _("It dodged the thrown BALL!\nThis POKéMON can't be caught!");
@ -555,7 +555,7 @@ static const u8 sText_VanishedInstantly[] =_("{B_ATK_NAME_WITH_PREFIX} vanished\
static const u8 sText_ProtectedTeam[] =_("{B_CURRENT_MOVE} protected\n{B_ATK_TEAM2} team!");
static const u8 sText_SharedItsGuard[] =_("{B_ATK_NAME_WITH_PREFIX} shared its\nguard with the target!");
static const u8 sText_SharedItsPower[] =_("{B_ATK_NAME_WITH_PREFIX} shared its\npower with the target!");
static const u8 sText_SwapsDefAndSpDefOfAllPkmn[] =_("It created a bizarre area in which the\nDefense and Sp.Def stats are swapped!");
static const u8 sText_SwapsDefAndSpDefOfAllPkmn[] =_("It created a bizarre area in which the\nDefense and Sp. Def stats are swapped!");
static const u8 sText_BecameNimble[] =_("{B_ATK_NAME_WITH_PREFIX} became nimble!");
static const u8 sText_HurledIntoTheAir[] =_("{B_DEF_NAME_WITH_PREFIX} was hurled\ninto the air!");
static const u8 sText_HeldItemsLoseEffects[] =_("It created a bizarre area in which\nPokémon's held items lose their effects!");
@ -783,9 +783,17 @@ static const u8 sText_ShellTrapDidntWork[] = _("{B_ATK_NAME_WITH_PREFIX}'s shell
static const u8 sText_CouldntFullyProtect[] = _("{B_DEF_NAME_WITH_PREFIX} couldn't fully protect\nitself and got hurt!");
static const u8 sText_StockpiledEffectWoreOff[] = _("{B_ATK_NAME_WITH_PREFIX}'s stockpiled\neffect wore off!");
static const u8 sText_PkmnRevivedReadyToFight[] = _("{B_BUFF1} was revived and\nis ready to fight again!");
static const u8 sText_ItemRestoredSpeciesHealth[] = _("{B_BUFF1} had its\nHP restored!");
static const u8 sText_ItemCuredSpeciesStatus[] = _("{B_BUFF1} had\nits status healed!");
static const u8 sText_ItemRestoredSpeciesPP[] = _("{B_BUFF1} had its\nPP restored!");
static const u8 sText_AtkTrappedDef[] = _("{B_ATK_NAME_WITH_PREFIX} trapped\nthe {B_DEF_NAME_WITH_PREFIX}!");
const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
{
[STRINGID_THUNDERCAGETRAPPED - BATTLESTRINGS_TABLE_START] = sText_AtkTrappedDef,
[STRINGID_ITEMRESTOREDSPECIESHEALTH - BATTLESTRINGS_TABLE_START] = sText_ItemRestoredSpeciesHealth,
[STRINGID_ITEMCUREDSPECIESSTATUS - BATTLESTRINGS_TABLE_START] = sText_ItemCuredSpeciesStatus,
[STRINGID_ITEMRESTOREDSPECIESPP - BATTLESTRINGS_TABLE_START] = sText_ItemRestoredSpeciesPP,
[STRINGID_PKMNREVIVEDREADYTOFIGHT - BATTLESTRINGS_TABLE_START] = sText_PkmnRevivedReadyToFight,
[STRINGID_STOCKPILEDEFFECTWOREOFF - BATTLESTRINGS_TABLE_START] = sText_StockpiledEffectWoreOff,
[STRINGID_COULDNTFULLYPROTECT - BATTLESTRINGS_TABLE_START] = sText_CouldntFullyProtect,
@ -1424,6 +1432,11 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
[STRINGID_PKMNSABILITYPREVENTSABILITY - BATTLESTRINGS_TABLE_START] = sText_PkmnsAbilityPreventsAbility,
};
const u16 gTrainerUsedItemStringIds[] =
{
STRINGID_PLAYERUSEDITEM, STRINGID_TRAINER1USEDITEM
};
const u16 gZEffectStringIds[] =
{
[B_MSG_Z_RESET_STATS] = STRINGID_ZMOVERESETSSTATS,
@ -1668,6 +1681,7 @@ const u16 gWrappedStringIds[NUM_TRAPPING_MOVES] =
[B_MSG_WRAPPED_MAGMA_STORM] = STRINGID_TRAPPEDBYSWIRLINGMAGMA, // MOVE_MAGMA_STORM
[B_MSG_WRAPPED_INFESTATION] = STRINGID_INFESTATION, // MOVE_INFESTATION
[B_MSG_WRAPPED_SNAP_TRAP] = STRINGID_PKMNINSNAPTRAP, // MOVE_SNAP_TRAP
[B_MSG_WRAPPED_THUNDER_CAGE]= STRINGID_THUNDERCAGETRAPPED, // MOVE_THUNDER_CAGE
};
const u16 gMistUsedStringIds[] =
@ -1820,16 +1834,6 @@ const u16 gSafariPokeblockResultStringIds[] =
[B_MSG_MON_IGNORED] = STRINGID_PKMNIGNOREDX
};
const u16 gTrainerItemCuredStatusStringIds[] =
{
[AI_HEAL_CONFUSION] = STRINGID_PKMNSITEMSNAPPEDOUT,
[AI_HEAL_PARALYSIS] = STRINGID_PKMNSITEMCUREDPARALYSIS,
[AI_HEAL_FREEZE] = STRINGID_PKMNSITEMDEFROSTEDIT,
[AI_HEAL_BURN] = STRINGID_PKMNSITEMHEALEDBURN,
[AI_HEAL_POISON] = STRINGID_PKMNSITEMCUREDPOISON,
[AI_HEAL_SLEEP] = STRINGID_PKMNSITEMWOKEIT
};
const u16 gBerryEffectStringIds[] =
{
[B_MSG_CURED_PROBLEM] = STRINGID_PKMNSITEMCUREDPROBLEM,
@ -3892,6 +3896,14 @@ struct TrainerSlide
const u8 *msgLastSwitchIn;
const u8 *msgLastLowHp;
const u8 *msgFirstDown;
const u8 *msgLastHalfHp;
const u8 *msgFirstCriticalHit;
const u8 *msgFirstSuperEffectiveHit;
const u8 *msgFirstSTABMove;
const u8 *msgPlayerMonUnaffected;
const u8 *msgMegaEvolution;
const u8 *msgZMove;
const u8 *msgBeforeFirstTurn;
};
static const struct TrainerSlide sTrainerSlides[] =
@ -3903,6 +3915,14 @@ static const struct TrainerSlide sTrainerSlides[] =
.msgLastSwitchIn = sText_AarghAlmostHadIt,
.msgLastLowHp = sText_BoxIsFull,
.msgFirstDown = sText_123Poof,
.msgLastHalfHp = sText_ShootSoClose,
.msgFirstCriticalHit = sText_CriticalHit,
.msgFirstSuperEffectiveHit = sText_SuperEffective,
.msgFirstSTABMove = sText_ABoosted,
.msgPlayerMonUnaffected = sText_ButNoEffect,
.msgMegaEvolution = sText_PowderExplodes,
.msgZMove = sText_Electromagnetism,
.msgBeforeFirstTurn = sText_GravityIntensified,
},
*/
};
@ -3923,12 +3943,35 @@ static u32 GetEnemyMonCount(u32 firstId, u32 lastId, bool32 onlyAlive)
return count;
}
static bool32 IsBattlerHpLow(u32 battler)
enum
{
if ((gBattleMons[battler].hp * 100) / gBattleMons[battler].maxHP < 25)
return TRUE;
else
return FALSE;
LESS_THAN,
EQUAL,
GREATER_THAN,
LESS_THAN_OR_EQUAL,
GREATER_THAN_OR_EQUAL,
NOT_EQUAL,
};
u32 BattlerHPPercentage(u32 battlerId, u32 operation, u32 threshold)
{
switch (operation)
{
case LESS_THAN:
return gBattleMons[battlerId].hp < (gBattleMons[battlerId].maxHP / threshold);
case EQUAL:
return gBattleMons[battlerId].hp == (gBattleMons[battlerId].maxHP / threshold);
case GREATER_THAN:
return gBattleMons[battlerId].hp > (gBattleMons[battlerId].maxHP / threshold);
case LESS_THAN_OR_EQUAL:
return gBattleMons[battlerId].hp <= (gBattleMons[battlerId].maxHP / threshold);
case GREATER_THAN_OR_EQUAL:
return gBattleMons[battlerId].hp >= (gBattleMons[battlerId].maxHP / threshold);
case NOT_EQUAL:
return gBattleMons[battlerId].hp != (gBattleMons[battlerId].maxHP / threshold);
default:
break;
}
}
u32 ShouldDoTrainerSlide(u32 battlerId, u32 which)
@ -3976,7 +4019,7 @@ u32 ShouldDoTrainerSlide(u32 battlerId, u32 which)
case TRAINER_SLIDE_LAST_LOW_HP:
if (sTrainerSlides[i].msgLastLowHp != NULL
&& GetEnemyMonCount(firstId, lastId, TRUE) == 1
&& IsBattlerHpLow(battlerId)
&& BattlerHPPercentage(battlerId, GREATER_THAN_OR_EQUAL, 4)
&& !gBattleStruct->trainerSlideLowHpMsgDone)
{
gBattleStruct->trainerSlideLowHpMsgDone = TRUE;
@ -3991,6 +4034,79 @@ u32 ShouldDoTrainerSlide(u32 battlerId, u32 which)
return retValue;
}
break;
case TRAINER_SLIDE_LAST_HALF_HP:
if (sTrainerSlides[i].msgLastHalfHp != NULL
&& GetEnemyMonCount(firstId, lastId, TRUE) == GetEnemyMonCount(firstId, lastId, FALSE) - 1
&& BattlerHPPercentage(battlerId, LESS_THAN_OR_EQUAL, 2) && BattlerHPPercentage(battlerId, GREATER_THAN, 4)
&& !gBattleStruct->trainerSlideHalfHpMsgDone)
{
gBattleStruct->trainerSlideHalfHpMsgDone = TRUE;
gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgLastHalfHp;
return TRUE;
}
break;
case TRAINER_SLIDE_FIRST_CRITICAL_HIT:
if (sTrainerSlides[i].msgFirstCriticalHit != NULL && gBattleStruct->trainerSlideFirstCriticalHitMsgState == 1)
{
gBattleStruct->trainerSlideFirstCriticalHitMsgState = 2;
gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgFirstCriticalHit;
return TRUE;
}
break;
case TRAINER_SLIDE_FIRST_SUPER_EFFECTIVE_HIT:
if (sTrainerSlides[i].msgFirstSuperEffectiveHit != NULL
&& gBattleStruct->trainerSlideFirstSuperEffectiveHitMsgState == 1
&& gBattleMons[battlerId].hp)
{
gBattleStruct->trainerSlideFirstSuperEffectiveHitMsgState = 2;
gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgFirstSuperEffectiveHit;
return TRUE;
}
break;
case TRAINER_SLIDE_FIRST_STAB_MOVE:
if (sTrainerSlides[i].msgFirstSTABMove != NULL
&& gBattleStruct->trainerSlideFirstSTABMoveMsgState == 1
&& GetEnemyMonCount(firstId, lastId, TRUE) == GetEnemyMonCount(firstId, lastId, FALSE))
{
gBattleStruct->trainerSlideFirstSTABMoveMsgState = 2;
gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgFirstSTABMove;
return TRUE;
}
break;
case TRAINER_SLIDE_PLAYER_MON_UNAFFECTED:
if (sTrainerSlides[i].msgPlayerMonUnaffected != NULL
&& gBattleStruct->trainerSlidePlayerMonUnaffectedMsgState == 1
&& GetEnemyMonCount(firstId, lastId, TRUE) == GetEnemyMonCount(firstId, lastId, FALSE))
{
gBattleStruct->trainerSlidePlayerMonUnaffectedMsgState = 2;
gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgPlayerMonUnaffected;
return TRUE;
}
break;
case TRAINER_SLIDE_MEGA_EVOLUTION:
if (sTrainerSlides[i].msgMegaEvolution != NULL && !gBattleStruct->trainerSlideMegaEvolutionMsgDone)
{
gBattleStruct->trainerSlideMegaEvolutionMsgDone = TRUE;
gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgMegaEvolution;
return TRUE;
}
break;
case TRAINER_SLIDE_Z_MOVE:
if (sTrainerSlides[i].msgZMove != NULL && !gBattleStruct->trainerSlideZMoveMsgDone)
{
gBattleStruct->trainerSlideZMoveMsgDone = TRUE;
gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgZMove;
return TRUE;
}
break;
case TRAINER_SLIDE_BEFORE_FIRST_TURN:
if (sTrainerSlides[i].msgBeforeFirstTurn != NULL && !gBattleStruct->trainerSlideBeforeFirstTurnMsgDone)
{
gBattleStruct->trainerSlideBeforeFirstTurnMsgDone = TRUE;
gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgBeforeFirstTurn;
return TRUE;
}
break;
}
break;
}

View File

@ -1299,11 +1299,18 @@ static void TryCloseBagToGiveItem(u8 taskId)
static void BagAction_UseInBattle(u8 taskId)
{
if (ItemId_GetBattleFunc(gSpecialVar_ItemId) != NULL)
{
CloseMenuActionWindow();
ItemId_GetBattleFunc(gSpecialVar_ItemId)(taskId);
}
// Safety check
u16 type = ItemId_GetType(gSpecialVar_ItemId);
if (!ItemId_GetBattleUsage(gSpecialVar_ItemId))
return;
CloseMenuActionWindow();
if (type == ITEM_USE_BAG_MENU)
ItemUseInBattle_BagMenu(taskId);
else if (type == ITEM_USE_PARTY_MENU)
ItemUseInBattle_PartyMenu(taskId);
else if (type == ITEM_USE_PARTY_MENU_MOVES)
ItemUseInBattle_PartyMenuChooseMove(taskId);
}
static void Task_BeginItemSwap(u8 taskId)

View File

@ -52,6 +52,7 @@
#include "constants/battle_string_ids.h"
#include "constants/hold_effects.h"
#include "constants/items.h"
#include "constants/item_effects.h"
#include "constants/map_types.h"
#include "constants/moves.h"
#include "constants/party_menu.h"
@ -978,6 +979,7 @@ static const u8 sForbiddenMoves[MOVES_COUNT] =
[MOVE_STRUGGLE] = 0xFF, // Neither Struggle
[MOVE_AFTER_YOU] = FORBIDDEN_METRONOME,
[MOVE_APPLE_ACID] = FORBIDDEN_METRONOME,
[MOVE_ARMOR_CANNON] = FORBIDDEN_METRONOME,
[MOVE_ARM_THRUST] = FORBIDDEN_PARENTAL_BOND,
[MOVE_ASSIST] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT,
[MOVE_ASTRAL_BARRAGE] = FORBIDDEN_METRONOME,
@ -993,6 +995,7 @@ static const u8 sForbiddenMoves[MOVES_COUNT] =
[MOVE_BESTOW] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
[MOVE_BIDE] = FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT | FORBIDDEN_PARENTAL_BOND, // Note: Bide should work with Parental Bond. This will be addressed in future.
[MOVE_BLAST_BURN] = FORBIDDEN_INSTRUCT,
[MOVE_BLAZING_TORQUE] = FORBIDDEN_MIMIC | FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT,
[MOVE_BODY_PRESS] = FORBIDDEN_METRONOME,
[MOVE_BONE_RUSH] = FORBIDDEN_PARENTAL_BOND,
[MOVE_BONEMERANG] = FORBIDDEN_PARENTAL_BOND,
@ -1004,9 +1007,14 @@ static const u8 sForbiddenMoves[MOVES_COUNT] =
[MOVE_BUZZY_BUZZ] = FORBIDDEN_METRONOME,
[MOVE_CELEBRATE] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT,
[MOVE_CHATTER] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_MIMIC | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT,
[MOVE_CHILLING_WATER] = FORBIDDEN_METRONOME,
[MOVE_CHILLY_RECEPTION] = FORBIDDEN_METRONOME,
[MOVE_CIRCLE_THROW] = FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
[MOVE_CLANGOROUS_SOUL] = FORBIDDEN_METRONOME,
[MOVE_COLLISION_COURSE] = FORBIDDEN_METRONOME,
[MOVE_COMBAT_TORQUE] = FORBIDDEN_MIMIC | FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT,
[MOVE_COMET_PUNCH] = FORBIDDEN_PARENTAL_BOND,
[MOVE_COMEUPPANCE] = FORBIDDEN_METRONOME,
[MOVE_COPYCAT] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT,
[MOVE_COUNTER] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
[MOVE_COVET] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
@ -1017,9 +1025,11 @@ static const u8 sForbiddenMoves[MOVES_COUNT] =
[MOVE_DIAMOND_STORM] = FORBIDDEN_METRONOME,
[MOVE_DIG] = FORBIDDEN_ASSIST | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT | FORBIDDEN_PARENTAL_BOND,
[MOVE_DIVE] = FORBIDDEN_ASSIST | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT | FORBIDDEN_PARENTAL_BOND,
[MOVE_DOODLE] = FORBIDDEN_METRONOME,
[MOVE_DOUBLE_IRON_BASH] = FORBIDDEN_METRONOME | FORBIDDEN_PARENTAL_BOND,
[MOVE_DOUBLE_HIT] = FORBIDDEN_PARENTAL_BOND,
[MOVE_DOUBLE_KICK] = FORBIDDEN_PARENTAL_BOND,
[MOVE_DOUBLE_SHOCK] = FORBIDDEN_METRONOME,
[MOVE_DOUBLE_SLAP] = FORBIDDEN_PARENTAL_BOND,
[MOVE_DRAGON_ASCENT] = FORBIDDEN_METRONOME,
[MOVE_DRAGON_ENERGY] = FORBIDDEN_METRONOME,
@ -1029,6 +1039,7 @@ static const u8 sForbiddenMoves[MOVES_COUNT] =
[MOVE_DUAL_CHOP] = FORBIDDEN_PARENTAL_BOND,
[MOVE_DUAL_WINGBEAT] = FORBIDDEN_PARENTAL_BOND,
[MOVE_DYNAMAX_CANNON] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT,
[MOVE_ELECTRO_DRIFT] = FORBIDDEN_METRONOME,
[MOVE_ENDEAVOR] = FORBIDDEN_PARENTAL_BOND,
[MOVE_ENDURE] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
[MOVE_ETERNABEAM] = FORBIDDEN_METRONOME | FORBIDDEN_INSTRUCT,
@ -1036,6 +1047,7 @@ static const u8 sForbiddenMoves[MOVES_COUNT] =
[MOVE_FALSE_SURRENDER] = FORBIDDEN_METRONOME,
[MOVE_FEINT] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
[MOVE_FIERY_WRATH] = FORBIDDEN_METRONOME,
[MOVE_FILLET_AWAY] = FORBIDDEN_METRONOME,
[MOVE_FINAL_GAMBIT] = FORBIDDEN_PARENTAL_BOND,
[MOVE_FISSURE] = FORBIDDEN_PARENTAL_BOND,
[MOVE_FLEUR_CANNON] = FORBIDDEN_METRONOME,
@ -1061,16 +1073,20 @@ static const u8 sForbiddenMoves[MOVES_COUNT] =
[MOVE_HORN_DRILL] = FORBIDDEN_PARENTAL_BOND,
[MOVE_HYDRO_CANNON] = FORBIDDEN_INSTRUCT,
[MOVE_HYPER_BEAM] = FORBIDDEN_INSTRUCT,
[MOVE_HYPER_DRILL] = FORBIDDEN_METRONOME,
[MOVE_HYPERSPACE_FURY] = FORBIDDEN_METRONOME,
[MOVE_HYPERSPACE_HOLE] = FORBIDDEN_METRONOME,
[MOVE_ICE_BALL] = FORBIDDEN_INSTRUCT | FORBIDDEN_PARENTAL_BOND,
[MOVE_ICE_BURN] = FORBIDDEN_METRONOME | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT | FORBIDDEN_PARENTAL_BOND,
[MOVE_ICICLE_SPEAR] = FORBIDDEN_PARENTAL_BOND,
[MOVE_INSTRUCT] = FORBIDDEN_METRONOME | FORBIDDEN_INSTRUCT,
[MOVE_JET_PUNCH] = FORBIDDEN_METRONOME,
[MOVE_JUNGLE_HEALING] = FORBIDDEN_METRONOME,
[MOVE_KINGS_SHIELD] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_INSTRUCT,
[MOVE_LIFE_DEW] = FORBIDDEN_METRONOME,
[MOVE_LIGHT_OF_RUIN] = FORBIDDEN_METRONOME,
[MOVE_MAKE_IT_RAIN] = FORBIDDEN_METRONOME,
[MOVE_MAGICAL_TORQUE] = FORBIDDEN_MIMIC | FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT,
[MOVE_MAT_BLOCK] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
[MOVE_ME_FIRST] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT,
[MOVE_METEOR_ASSAULT] = FORBIDDEN_METRONOME | FORBIDDEN_INSTRUCT,
@ -1084,32 +1100,47 @@ static const u8 sForbiddenMoves[MOVES_COUNT] =
[MOVE_MOONGEIST_BEAM] = FORBIDDEN_METRONOME,
[MOVE_NATURE_POWER] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT,
[MOVE_NATURES_MADNESS] = FORBIDDEN_METRONOME,
[MOVE_NOXIOUS_TORQUE] = FORBIDDEN_MIMIC | FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT,
[MOVE_OBSTRUCT] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_INSTRUCT,
[MOVE_ORDER_UP] = FORBIDDEN_METRONOME,
[MOVE_ORIGIN_PULSE] = FORBIDDEN_METRONOME,
[MOVE_OUTRAGE] = FORBIDDEN_INSTRUCT,
[MOVE_OVERDRIVE] = FORBIDDEN_METRONOME,
[MOVE_PHANTOM_FORCE] = FORBIDDEN_ASSIST | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT | FORBIDDEN_PARENTAL_BOND,
[MOVE_PHOTON_GEYSER] = FORBIDDEN_METRONOME,
[MOVE_PLASMA_FISTS] = FORBIDDEN_METRONOME,
[MOVE_POPULATION_BOMB] = FORBIDDEN_METRONOME,
[MOVE_POUNCE] = FORBIDDEN_METRONOME,
[MOVE_POWER_SHIFT] = FORBIDDEN_METRONOME,
[MOVE_PRECIPICE_BLADES] = FORBIDDEN_METRONOME,
[MOVE_PRISMATIC_LASER] = FORBIDDEN_INSTRUCT,
[MOVE_PROTECT] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
[MOVE_PYRO_BALL] = FORBIDDEN_METRONOME,
[MOVE_QUASH] = FORBIDDEN_METRONOME,
[MOVE_QUICK_GUARD] = FORBIDDEN_METRONOME,
[MOVE_RAGE_FIST] = FORBIDDEN_METRONOME,
[MOVE_RAGE_POWDER] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
[MOVE_RAGING_BULL] = FORBIDDEN_METRONOME,
[MOVE_RAGING_FURY] = FORBIDDEN_METRONOME,
[MOVE_RAZOR_WIND] = FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT | FORBIDDEN_PARENTAL_BOND,
[MOVE_RELIC_SONG] = FORBIDDEN_METRONOME,
[MOVE_REVIVAL_BLESSING] = FORBIDDEN_METRONOME,
[MOVE_ROAR] = FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
[MOVE_ROAR_OF_TIME] = FORBIDDEN_INSTRUCT,
[MOVE_ROCK_BLAST] = FORBIDDEN_PARENTAL_BOND,
[MOVE_ROCK_WRECKER] = FORBIDDEN_INSTRUCT,
[MOVE_ROLLOUT] = FORBIDDEN_INSTRUCT | FORBIDDEN_PARENTAL_BOND,
[MOVE_RUINATION] = FORBIDDEN_METRONOME,
[MOVE_SAPPY_SEED] = FORBIDDEN_METRONOME,
[MOVE_SALT_CURE] = FORBIDDEN_METRONOME,
[MOVE_SCALE_SHOT] = FORBIDDEN_PARENTAL_BOND,
[MOVE_SECRET_SWORD] = FORBIDDEN_METRONOME,
[MOVE_SELF_DESTRUCT] = FORBIDDEN_PARENTAL_BOND,
[MOVE_SHADOW_FORCE] = FORBIDDEN_ASSIST | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT | FORBIDDEN_PARENTAL_BOND,
[MOVE_SHED_TAIL] = FORBIDDEN_METRONOME,
[MOVE_SHEER_COLD] = FORBIDDEN_PARENTAL_BOND,
[MOVE_SHELL_TRAP] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT,
[MOVE_SILK_TRAP] = FORBIDDEN_METRONOME,
[MOVE_SIZZLY_SLIDE] = FORBIDDEN_METRONOME,
[MOVE_SKETCH] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_MIMIC | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT,
[MOVE_SKULL_BASH] = FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT | FORBIDDEN_PARENTAL_BOND,
@ -1120,10 +1151,12 @@ static const u8 sForbiddenMoves[MOVES_COUNT] =
[MOVE_SNARL] = FORBIDDEN_METRONOME,
[MOVE_SNATCH] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_INSTRUCT,
[MOVE_SNORE] = FORBIDDEN_METRONOME,
[MOVE_SNOWSCAPE] = FORBIDDEN_METRONOME,
[MOVE_SOLAR_BEAM] = FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT | FORBIDDEN_PARENTAL_BOND,
[MOVE_SOLAR_BLADE] = FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT | FORBIDDEN_PARENTAL_BOND,
[MOVE_SPARKLY_SWIRL] = FORBIDDEN_METRONOME,
[MOVE_SPECTRAL_THIEF] = FORBIDDEN_METRONOME,
[MOVE_SPICY_EXTRACT] = FORBIDDEN_METRONOME,
[MOVE_SPIKE_CANNON] = FORBIDDEN_PARENTAL_BOND,
[MOVE_SPIKY_SHIELD] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
[MOVE_SPIRIT_BREAK] = FORBIDDEN_METRONOME,
@ -1143,17 +1176,21 @@ static const u8 sForbiddenMoves[MOVES_COUNT] =
[MOVE_THRASH] = FORBIDDEN_INSTRUCT,
[MOVE_THUNDER_CAGE] = FORBIDDEN_METRONOME,
[MOVE_THUNDEROUS_KICK] = FORBIDDEN_METRONOME,
[MOVE_TIDY_UP] = FORBIDDEN_METRONOME,
[MOVE_TRAILBLAZE] = FORBIDDEN_METRONOME,
[MOVE_TRANSFORM] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_MIMIC | FORBIDDEN_INSTRUCT,
[MOVE_TRICK] = FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
[MOVE_TRIPLE_AXEL] = FORBIDDEN_PARENTAL_BOND,
[MOVE_TRIPLE_KICK] = FORBIDDEN_PARENTAL_BOND,
[MOVE_TWINEEDLE] = FORBIDDEN_PARENTAL_BOND,
[MOVE_TWIN_BEAM] = FORBIDDEN_METRONOME,
[MOVE_UPROAR] = FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT | FORBIDDEN_PARENTAL_BOND,
[MOVE_V_CREATE] = FORBIDDEN_METRONOME,
[MOVE_VEEVEE_VOLLEY] = FORBIDDEN_METRONOME,
[MOVE_WATER_SHURIKEN] = FORBIDDEN_PARENTAL_BOND,
[MOVE_WHIRLWIND] = FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT,
[MOVE_WICKED_BLOW] = FORBIDDEN_METRONOME,
[MOVE_WICKED_TORQUE] = FORBIDDEN_MIMIC | FORBIDDEN_METRONOME | FORBIDDEN_ASSIST | FORBIDDEN_COPYCAT | FORBIDDEN_SLEEP_TALK | FORBIDDEN_INSTRUCT,
[MOVE_WIDE_GUARD] = FORBIDDEN_METRONOME,
[MOVE_ZIPPY_ZAP] = FORBIDDEN_METRONOME,
};
@ -2567,6 +2604,11 @@ static void Cmd_critmessage(void)
if (gIsCriticalHit == TRUE && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT))
{
PrepareStringBattle(STRINGID_CRITICALHIT, gBattlerAttacker);
// Signal for the trainer slide-in system.
if (GetBattlerSide(gBattlerTarget) != B_SIDE_PLAYER && gBattleStruct->trainerSlideFirstCriticalHitMsgState != 2)
gBattleStruct->trainerSlideFirstCriticalHitMsgState = 1;
gBattleCommunication[MSG_DISPLAY] = 1;
}
gBattlescriptCurrInstr = cmd->nextInstr;
@ -2646,7 +2688,13 @@ static void Cmd_resultmessage(void)
{
case MOVE_RESULT_SUPER_EFFECTIVE:
if (!gMultiHitCounter) // Don't print effectiveness on each hit in a multi hit attack
{
// Signal for the trainer slide-in system.
if (GetBattlerSide(gBattlerTarget) != B_SIDE_PLAYER && gBattleStruct->trainerSlideFirstSuperEffectiveHitMsgState != 2)
gBattleStruct->trainerSlideFirstSuperEffectiveHitMsgState = 1;
stringId = STRINGID_SUPEREFFECTIVE;
}
break;
case MOVE_RESULT_NOT_VERY_EFFECTIVE:
if (!gMultiHitCounter)
@ -6437,10 +6485,7 @@ bool32 CanBattlerSwitch(u32 battlerId)
}
else if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
{
if (GetBattlerSide(battlerId) == B_SIDE_OPPONENT)
party = gEnemyParty;
else
party = gPlayerParty;
party = GetBattlerParty(battlerId);
lastMonId = 0;
if (battlerId & 2)
@ -6481,10 +6526,7 @@ bool32 CanBattlerSwitch(u32 battlerId)
}
else
{
if (GetBattlerSide(battlerId) == B_SIDE_OPPONENT)
party = gEnemyParty;
else
party = gPlayerParty;
party = GetBattlerParty(battlerId);
lastMonId = 0;
if (GetLinkTrainerFlankId(GetBattlerMultiplayerId(battlerId)) == TRUE)
@ -7638,10 +7680,7 @@ static void Cmd_drawpartystatussummary(void)
gActiveBattler = GetBattlerForBattleScript(cmd->battler);
if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER)
party = gPlayerParty;
else
party = gEnemyParty;
party = GetBattlerParty(gActiveBattler);
for (i = 0; i < PARTY_SIZE; i++)
{
@ -7861,7 +7900,7 @@ static void BestowItem(u32 battlerAtk, u32 battlerDef)
// Called by Cmd_removeitem. itemId represents the item that was removed, not being given.
static bool32 TrySymbiosis(u32 battler, u32 itemId)
{
if (!gBattleStruct->itemStolen[gBattlerPartyIndexes[battler]].stolen
if (!gBattleStruct->itemLost[gBattlerPartyIndexes[battler]].stolen
&& gBattleStruct->changedItems[battler] == ITEM_NONE
&& GetBattlerHoldEffect(battler, TRUE) != HOLD_EFFECT_EJECT_BUTTON
&& GetBattlerHoldEffect(battler, TRUE) != HOLD_EFFECT_EJECT_PACK
@ -8699,7 +8738,8 @@ static bool32 CourtChangeSwapSideStatuses(void)
static void HandleScriptMegaPrimal(u32 caseId, u32 battlerId, bool32 isMega)
{
struct Pokemon *mon = GetBattlerPartyData(battlerId);
struct Pokemon *party = GetBattlerParty(battlerId);
struct Pokemon *mon = &party[gBattlerPartyIndexes[battlerId]];
u32 position = GetBattlerPosition(battlerId);
u32 side = GET_BATTLER_SIDE(battlerId);
@ -8732,8 +8772,7 @@ static void HandleScriptMegaPrimal(u32 caseId, u32 battlerId, bool32 isMega)
static bool32 CanTeleport(u8 battlerId)
{
u8 side = GetBattlerSide(battlerId);
struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty;
struct Pokemon *party = GetBattlerParty(battlerId);
u32 species, count, i;
for (i = 0; i < PARTY_SIZE; i++)
@ -11095,15 +11134,6 @@ static void Cmd_various(void)
AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, gActiveBattler, 0, 0, 0);
return;
}
case VARIOUS_JUMP_IF_SHELL_TRAP:
{
VARIOUS_ARGS(const u8 *jumpInstr);
if (gProtectStructs[gActiveBattler].shellTrap)
gBattlescriptCurrInstr = cmd->jumpInstr;
else
gBattlescriptCurrInstr = cmd->nextInstr;
return;
}
case VARIOUS_ACTIVATE_TERRAIN_CHANGE_ABILITIES:
{
VARIOUS_ARGS();
@ -11136,6 +11166,15 @@ static void Cmd_various(void)
gBattlescriptCurrInstr = cmd->nextInstr;
return;
}
case VARIOUS_JUMP_IF_SHELL_TRAP:
{
VARIOUS_ARGS(const u8 *jumpInstr);
if (gProtectStructs[gActiveBattler].shellTrap)
gBattlescriptCurrInstr = cmd->jumpInstr;
else
gBattlescriptCurrInstr = cmd->nextInstr;
return;
}
case VARIOUS_TRY_REVIVAL_BLESSING:
{
VARIOUS_ARGS(const u8 *failInstr);
@ -11152,7 +11191,7 @@ static void Cmd_various(void)
// Battler selected! Revive and go to next instruction.
if (gSelectedMonPartyId != PARTY_SIZE)
{
struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty;
struct Pokemon *party = GetSideParty(side);
u16 hp = GetMonData(&party[gSelectedMonPartyId], MON_DATA_MAX_HP) / 2;
BtlController_EmitSetMonData(BUFFER_A, REQUEST_HP_BATTLE, gBitTable[gSelectedMonPartyId], sizeof(hp), &hp);
@ -11174,12 +11213,36 @@ static void Cmd_various(void)
// Open party menu, wait to go to next instruction.
else
{
BtlController_EmitChoosePokemon(BUFFER_A, PARTY_ACTION_CHOOSE_FAINTED_MON, PARTY_SIZE, ABILITY_NONE, gBattleStruct->battlerPartyOrders[gActiveBattler]);
{
BtlController_EmitChoosePokemon(BUFFER_A, PARTY_ACTION_CHOOSE_FAINTED_MON, PARTY_SIZE, ABILITY_NONE, gBattleStruct->battlerPartyOrders[gBattlerAttacker]);
MarkBattlerForControllerExec(gBattlerAttacker);
}
return;
}
case VARIOUS_TRY_TRAINER_SLIDE_MSG_Z_MOVE:
{
VARIOUS_ARGS();
if ((i = ShouldDoTrainerSlide(gActiveBattler, TRAINER_SLIDE_Z_MOVE)))
{
gBattleScripting.battler = gActiveBattler;
BattleScriptPush(cmd->nextInstr);
gBattlescriptCurrInstr = (i == 1 ? BattleScript_TrainerASlideMsgRet : BattleScript_TrainerBSlideMsgRet);
return;
}
break;
}
case VARIOUS_TRY_TRAINER_SLIDE_MSG_MEGA_EVOLUTION:
{
VARIOUS_ARGS();
if ((i = ShouldDoTrainerSlide(gActiveBattler, TRAINER_SLIDE_MEGA_EVOLUTION)))
{
gBattleScripting.battler = gActiveBattler;
BattleScriptPush(cmd->nextInstr);
gBattlescriptCurrInstr = (i == 1 ? BattleScript_TrainerASlideMsgRet : BattleScript_TrainerBSlideMsgRet);
return;
}
break;
}
} // End of switch (cmd->id)
gBattlescriptCurrInstr = cmd->nextInstr;
@ -12236,10 +12299,7 @@ static void Cmd_forcerandomswitch(void)
|| redCardForcedSwitch
)
{
if (GetBattlerSide(gBattlerTarget) == B_SIDE_PLAYER)
party = gPlayerParty;
else
party = gEnemyParty;
party = GetBattlerParty(gBattlerTarget);
if (BATTLE_TWO_VS_ONE_OPPONENT && GetBattlerSide(gBattlerTarget) == B_SIDE_OPPONENT)
{
@ -13438,16 +13498,11 @@ static void Cmd_healpartystatus(void)
if (gCurrentMove == MOVE_HEAL_BELL)
{
struct Pokemon *party;
struct Pokemon *party = GetBattlerParty(gBattlerAttacker);
s32 i;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_BELL;
if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER)
party = gPlayerParty;
else
party = gEnemyParty;
if (GetBattlerAbility(gBattlerAttacker) != ABILITY_SOUNDPROOF)
{
gBattleMons[gBattlerAttacker].status1 = 0;
@ -14075,12 +14130,7 @@ static void Cmd_trydobeatup(void)
gBattleStruct->beatUpSlot++;
gBattlescriptCurrInstr = cmd->nextInstr;
#else
struct Pokemon *party;
if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER)
party = gPlayerParty;
else
party = gEnemyParty;
struct Pokemon *party = GetBattlerParty(gBattlerAttacker);
if (gBattleMons[gBattlerTarget].hp == 0)
{
@ -14774,10 +14824,7 @@ static void Cmd_assistattackselect(void)
if (validMoves != NULL)
{
if (GET_BATTLER_SIDE(gBattlerAttacker) != B_SIDE_PLAYER)
party = gEnemyParty;
else
party = gPlayerParty;
party = GetBattlerParty(gBattlerAttacker);
for (monId = 0; monId < PARTY_SIZE; monId++)
{
@ -16306,7 +16353,7 @@ u8 GetFirstFaintedPartyIndex(u8 battlerId)
u32 i;
u32 start = 0;
u32 end = PARTY_SIZE;
struct Pokemon *party = (GetBattlerSide(battlerId) == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty;
struct Pokemon *party = GetBattlerParty(battlerId);
// Check whether partner is separate trainer.
if ((GetBattlerSide(battlerId) == B_SIDE_PLAYER && gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
@ -16338,3 +16385,149 @@ u8 GetFirstFaintedPartyIndex(u8 battlerId)
// Returns PARTY_SIZE if none found.
return PARTY_SIZE;
}
void BS_ItemRestoreHP(void) {
NATIVE_ARGS();
u16 healAmount;
u32 battlerId = MAX_BATTLERS_COUNT;
u32 healParam = GetItemEffect(gLastUsedItem)[6];
u32 side = GetBattlerSide(gBattlerAttacker);
struct Pokemon *party = GetSideParty(side);
u16 hp = GetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_HP);
u16 maxHP = GetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_MAX_HP);
gBattleCommunication[MULTIUSE_STATE] = 0;
// Track the number of Revives used in a battle.
if (hp == 0 && side == B_SIDE_PLAYER && gBattleResults.numRevivesUsed < 255)
gBattleResults.numRevivesUsed++;
// Check if the recipient is an active battler.
if (gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[gBattlerAttacker])
battlerId = gBattlerAttacker;
else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE
&& gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)])
battlerId = BATTLE_PARTNER(gBattlerAttacker);
// Get amount to heal.
switch (healParam)
{
case ITEM6_HEAL_HP_FULL:
healAmount = maxHP;
break;
case ITEM6_HEAL_HP_HALF:
healAmount = maxHP / 2;
break;
case ITEM6_HEAL_HP_QUARTER:
healAmount = maxHP / 4;
break;
default:
healAmount = healParam;
break;
}
if (hp + healAmount > maxHP)
healAmount = maxHP - hp;
// Heal is applied as move damage if battler is active.
if (battlerId != MAX_BATTLERS_COUNT && hp != 0)
{
gBattleMoveDamage = -healAmount;
}
else
{
hp += healAmount;
SetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_HP, &hp);
// Revived battlers on the field need to be brought back.
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && battlerId != MAX_BATTLERS_COUNT)
{
gAbsentBattlerFlags &= ~gBitTable[battlerId];
gBattleCommunication[MULTIUSE_STATE] = TRUE;
}
}
PREPARE_SPECIES_BUFFER(gBattleTextBuff1, GetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_SPECIES));
gBattlescriptCurrInstr = cmd->nextInstr;
}
void BS_ItemCureStatus(void) {
NATIVE_ARGS();
struct Pokemon *party = GetBattlerParty(gBattlerAttacker);
// Heal Status1 conditions.
HealStatusConditions(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], gBattleStruct->itemPartyIndex[gBattlerAttacker], GetItemStatus1Mask(gLastUsedItem), gBattlerAttacker);
// Heal Status2 conditions if battler is active.
if (gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[gBattlerAttacker])
{
gBattleMons[gBattlerAttacker].status2 &= ~GetItemStatus2Mask(gLastUsedItem);
}
else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE
&& gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)])
{
gBattleMons[gBattlerAttacker].status2 &= ~GetItemStatus2Mask(gLastUsedItem);
gBattlerTarget = BATTLE_PARTNER(gBattlerAttacker);
}
if (GetItemStatus1Mask(gLastUsedItem) & STATUS1_SLEEP)
gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_NIGHTMARE;
if (GetItemStatus2Mask(gLastUsedItem) & STATUS2_CONFUSION)
gStatuses4[gBattlerAttacker] &= ~STATUS4_INFINITE_CONFUSION;
PREPARE_SPECIES_BUFFER(gBattleTextBuff1, GetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_SPECIES));
gBattlescriptCurrInstr = cmd->nextInstr;
}
void BS_ItemIncreaseStat(void) {
NATIVE_ARGS();
u16 statId = GetItemEffect(gLastUsedItem)[1];
u16 stages = ItemId_GetHoldEffectParam(gLastUsedItem);
SET_STATCHANGER(statId, stages, FALSE);
gBattlescriptCurrInstr = cmd->nextInstr;
}
void BS_ItemRestorePP(void) {
NATIVE_ARGS();
const u8 *effect = GetItemEffect(gLastUsedItem);
u32 i, pp, maxPP, moveId;
u32 loopEnd = MAX_MON_MOVES;
u32 battlerId = MAX_BATTLERS_COUNT;
struct Pokemon *mon = (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER) ? &gPlayerParty[gBattleStruct->itemPartyIndex[gBattlerAttacker]] : &gEnemyParty[gBattleStruct->itemPartyIndex[gBattlerAttacker]];
// Check whether to apply to all moves.
if (effect[4] & ITEM4_HEAL_PP_ONE)
{
i = gChosenMovePos;
loopEnd = gChosenMovePos + 1;
}
// Check if the recipient is an active battler.
if (gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[gBattlerAttacker])
battlerId = gBattlerAttacker;
else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE
&& gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)])
battlerId = BATTLE_PARTNER(gBattlerAttacker);
// Heal PP!
for (i = 0; i < loopEnd; i++)
{
pp = GetMonData(mon, MON_DATA_PP1 + i, NULL);
moveId = GetMonData(mon, MON_DATA_MOVE1 + i, NULL);
maxPP = CalculatePPWithBonus(moveId, GetMonData(mon, MON_DATA_PP_BONUSES, NULL), i);
if (pp != maxPP)
{
pp += effect[6];
if (pp > maxPP)
pp = maxPP;
SetMonData(mon, MON_DATA_PP1 + i, &pp);
// Update battler PP if needed.
if (battlerId != MAX_BATTLERS_COUNT
&& gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[battlerId]
&& MOVE_IS_PERMANENT(battlerId, i))
{
gBattleMons[battlerId].pp[i] = pp;
}
}
}
PREPARE_SPECIES_BUFFER(gBattleTextBuff1, GetMonData(mon, MON_DATA_SPECIES));
gBattlescriptCurrInstr = cmd->nextInstr;
}

View File

@ -21,6 +21,7 @@
#include "sprite.h"
#include "string_util.h"
#include "task.h"
#include "test_runner.h"
#include "trig.h"
#include "window.h"
#include "battle_message.h"
@ -63,6 +64,7 @@ static void SetRandomMultiHitCounter();
static u32 GetBattlerItemHoldEffectParam(u8 battlerId, u16 item);
static u16 GetInverseTypeMultiplier(u16 multiplier);
static u16 GetSupremeOverlordModifier(u8 battlerId);
static bool8 CanBeInfinitelyConfused(u8 battlerId);
extern const u8 *const gBattleScriptsForMoveEffects[];
extern const u8 *const gBattlescriptsForRunningByItem[];
@ -224,14 +226,9 @@ static const u16 sEntrainmentTargetSimpleBeamBannedAbilities[] =
static u8 CalcBeatUpPower(void)
{
struct Pokemon *party;
u8 basePower;
u16 species;
if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER)
party = gPlayerParty;
else
party = gEnemyParty;
struct Pokemon *party = GetBattlerParty(gBattlerAttacker);
// Party slot is incremented by the battle script for Beat Up after this damage calculation
species = GetMonData(&party[gBattleStruct->beatUpSlot], MON_DATA_SPECIES);
@ -550,93 +547,13 @@ void HandleAction_Switch(void)
void HandleAction_UseItem(void)
{
gBattlerAttacker = gBattlerTarget = gBattlerByTurnOrder[gCurrentTurnActionNumber];
gActiveBattler = gBattlerAttacker = gBattlerByTurnOrder[gCurrentTurnActionNumber];
gBattle_BG0_X = 0;
gBattle_BG0_Y = 0;
ClearFuryCutterDestinyBondGrudge(gBattlerAttacker);
gLastUsedItem = gBattleResources->bufferB[gBattlerAttacker][1] | (gBattleResources->bufferB[gBattlerAttacker][2] << 8);
if (gLastUsedItem <= LAST_BALL) // is ball
{
gBattlescriptCurrInstr = BattleScript_BallThrow;
}
else if (gLastUsedItem == ITEM_POKE_DOLL || gLastUsedItem == ITEM_FLUFFY_TAIL)
{
gBattlescriptCurrInstr = gBattlescriptsForRunningByItem[0]; // BattleScript_RunByUsingItem
}
else if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER)
{
gBattlescriptCurrInstr = gBattlescriptsForUsingItem[0]; // BattleScript_PlayerUsesItem
}
else
{
gBattleScripting.battler = gBattlerAttacker;
switch (*(gBattleStruct->AI_itemType + (gBattlerAttacker >> 1)))
{
case AI_ITEM_FULL_RESTORE:
case AI_ITEM_HEAL_HP:
break;
case AI_ITEM_CURE_CONDITION:
gBattleCommunication[MULTISTRING_CHOOSER] = AI_HEAL_CONFUSION;
if (*(gBattleStruct->AI_itemFlags + gBattlerAttacker / 2) & (1 << AI_HEAL_CONFUSION))
{
if (*(gBattleStruct->AI_itemFlags + gBattlerAttacker / 2) & 0x3E)
gBattleCommunication[MULTISTRING_CHOOSER] = AI_HEAL_SLEEP;
}
else
{
// Check for other statuses, stopping at first (shouldn't be more than one)
while (!(*(gBattleStruct->AI_itemFlags + gBattlerAttacker / 2) & 1))
{
*(gBattleStruct->AI_itemFlags + gBattlerAttacker / 2) >>= 1;
gBattleCommunication[MULTISTRING_CHOOSER]++;
// MULTISTRING_CHOOSER will be either AI_HEAL_PARALYSIS, AI_HEAL_FREEZE,
// AI_HEAL_BURN, AI_HEAL_POISON, or AI_HEAL_SLEEP
}
}
break;
case AI_ITEM_X_STAT:
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STAT_ROSE_ITEM;
if (*(gBattleStruct->AI_itemFlags + (gBattlerAttacker >> 1)) & (1 << AI_DIRE_HIT))
{
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_USED_DIRE_HIT;
}
else
{
PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_ATK)
PREPARE_STRING_BUFFER(gBattleTextBuff2, CHAR_X)
while (!((*(gBattleStruct->AI_itemFlags + (gBattlerAttacker >> 1))) & 1))
{
*(gBattleStruct->AI_itemFlags + gBattlerAttacker / 2) >>= 1;
gBattleTextBuff1[2]++;
}
gBattleScripting.animArg1 = gBattleTextBuff1[2] + 14;
gBattleScripting.animArg2 = 0;
}
break;
case AI_ITEM_GUARD_SPEC:
// It seems probable that at some point there was a special message for
// an AI trainer using Guard Spec in a double battle.
// There isn't now however, and the assignment to 2 below goes out of
// bounds for gMistUsedStringIds and instead prints "{mon} is getting pumped"
// from the next table, gFocusEnergyUsedStringIds.
// In any case this isn't an issue in the retail version, as no trainers
// are ever given any Guard Spec to use.
#ifndef UBFIX
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
gBattleCommunication[MULTISTRING_CHOOSER] = 2;
else
#endif
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_MIST;
break;
}
gBattlescriptCurrInstr = gBattlescriptsForUsingItem[*(gBattleStruct->AI_itemType + gBattlerAttacker / 2)];
}
gBattlescriptCurrInstr = gBattlescriptsForUsingItem[ItemId_GetBattleUsage(gLastUsedItem) - 1];
gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT;
}
@ -914,7 +831,7 @@ void HandleAction_ActionFinished(void)
u32 i, j;
bool32 afterYouActive = gSpecialStatuses[gBattlerByTurnOrder[gCurrentTurnActionNumber + 1]].afterYou;
#endif
*(gBattleStruct->monToSwitchIntoId + gBattlerByTurnOrder[gCurrentTurnActionNumber]) = PARTY_SIZE;
*(gBattleStruct->monToSwitchIntoId + gBattlerByTurnOrder[gCurrentTurnActionNumber]) = gSelectedMonPartyId = PARTY_SIZE;
gCurrentTurnActionNumber++;
gCurrentActionFuncId = gActionsByTurnOrder[gCurrentTurnActionNumber];
SpecialStatusesClear();
@ -1610,6 +1527,12 @@ void PrepareStringBattle(u16 stringId, u8 battler)
}
#endif
// Signal for the trainer slide-in system.
if ((stringId == STRINGID_ITDOESNTAFFECT || stringId == STRINGID_PKMNWASNTAFFECTED || stringId == STRINGID_PKMNUNAFFECTED)
&& GetBattlerSide(gBattlerTarget) == B_SIDE_OPPONENT
&& gBattleStruct->trainerSlidePlayerMonUnaffectedMsgState != 2)
gBattleStruct->trainerSlidePlayerMonUnaffectedMsgState = 1;
gActiveBattler = battler;
BtlController_EmitPrintString(BUFFER_A, stringId);
MarkBattlerForControllerExec(gActiveBattler);
@ -2067,7 +1990,7 @@ u8 GetImprisonedMovesCount(u8 battlerId, u16 move)
u32 GetBattlerFriendshipScore(u8 battlerId)
{
u8 side = GetBattlerSide(battlerId);
struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty;
struct Pokemon *party = GetSideParty(side);
u16 species = GetMonData(&party[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES);
if (side != B_SIDE_PLAYER)
@ -3607,7 +3530,8 @@ u8 AtkCanceller_UnableToUseMove(void)
case CANCELLER_CONFUSED: // confusion
if (gBattleMons[gBattlerAttacker].status2 & STATUS2_CONFUSION)
{
gBattleMons[gBattlerAttacker].status2 -= STATUS2_CONFUSION_TURN(1);
if (!(gStatuses4[gBattlerAttacker] & STATUS4_INFINITE_CONFUSION))
gBattleMons[gBattlerAttacker].status2 -= STATUS2_CONFUSION_TURN(1);
if (gBattleMons[gBattlerAttacker].status2 & STATUS2_CONFUSION)
{
// confusion dmg
@ -3834,14 +3758,9 @@ u8 AtkCanceller_UnableToUseMove(void)
#if B_BEAT_UP >= GEN_5
else if (gBattleMoves[gCurrentMove].effect == EFFECT_BEAT_UP)
{
struct Pokemon* party;
struct Pokemon* party = GetBattlerParty(gBattlerAttacker);
int i;
if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER)
party = gPlayerParty;
else
party = gEnemyParty;
for (i = 0; i < PARTY_SIZE; i++)
{
if (GetMonData(&party[i], MON_DATA_HP)
@ -3938,10 +3857,7 @@ bool8 HasNoMonsToSwitch(u8 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2)
}
else if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
{
if (GetBattlerSide(battler) == B_SIDE_PLAYER)
party = gPlayerParty;
else
party = gEnemyParty;
party = GetBattlerParty(battler);
playerId = ((battler & BIT_FLANK) / 2);
for (i = playerId * MULTI_PARTY_SIZE; i < playerId * MULTI_PARTY_SIZE + MULTI_PARTY_SIZE; i++)
@ -3975,12 +3891,7 @@ bool8 HasNoMonsToSwitch(u8 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2)
else
{
flankId = GetBattlerMultiplayerId(battler);
if (GetBattlerSide(battler) == B_SIDE_PLAYER)
party = gPlayerParty;
else
party = gEnemyParty;
party = GetBattlerParty(battler);
playerId = GetLinkTrainerFlankId(flankId);
}
@ -4149,7 +4060,7 @@ static void ShouldChangeFormInWeather(u8 battler)
{
int i;
int side = GetBattlerSide(battler);
struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty;
struct Pokemon *party = GetSideParty(side);
for (i = 0; i < PARTY_SIZE; i++)
{
@ -4295,8 +4206,7 @@ bool8 ChangeTypeBasedOnTerrain(u8 battlerId)
static u16 GetSupremeOverlordModifier(u8 battlerId)
{
u32 i;
u8 side = GetBattlerSide(battlerId);
struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty;
struct Pokemon *party = GetBattlerParty(battlerId);
u16 modifier = UQ_4_12(1.0);
bool8 appliedFirstBoost = FALSE;
@ -5990,7 +5900,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
gBattlescriptCurrInstr = BattleScript_AbilityCuredStatus;
break;
case 2: // get rid of confusion
gBattleMons[battler].status2 &= ~STATUS2_CONFUSION;
RemoveConfusionStatus(battler);
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_AbilityCuredStatus;
break;
@ -6928,7 +6838,7 @@ static u8 ItemEffectMoveEnd(u32 battlerId, u16 holdEffect)
case HOLD_EFFECT_CURE_CONFUSION:
if (gBattleMons[battlerId].status2 & STATUS2_CONFUSION && !UnnerveOn(battlerId, gLastUsedItem))
{
gBattleMons[battlerId].status2 &= ~STATUS2_CONFUSION;
RemoveConfusionStatus(battlerId);
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_BerryCureConfusionRet;
effect = ITEM_EFFECT_OTHER;
@ -6969,7 +6879,7 @@ static u8 ItemEffectMoveEnd(u32 battlerId, u16 holdEffect)
StringCopy(gBattleTextBuff1, gStatusConditionString_ConfusionJpn);
gBattleMons[battlerId].status1 = 0;
gBattleMons[battlerId].status2 &= ~STATUS2_CONFUSION;
RemoveConfusionStatus(battlerId);
BattleScriptPushCursor();
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_CURED_PROBLEM;
gBattlescriptCurrInstr = BattleScript_BerryCureChosenStatusRet;
@ -7007,6 +6917,21 @@ static u8 ItemEffectMoveEnd(u32 battlerId, u16 holdEffect)
effect = ITEM_EFFECT_OTHER;
}
break;
case HOLD_EFFECT_BERSERK_GENE:
BufferStatChange(battlerId, STAT_ATK, STRINGID_STATROSE);
gEffectBattler = battlerId;
if (CanBeInfinitelyConfused(gEffectBattler))
{
gStatuses4[gEffectBattler] |= STATUS4_INFINITE_CONFUSION;
}
SET_STATCHANGER(STAT_ATK, 2, FALSE);
gBattleScripting.animArg1 = 14 + STAT_ATK;
gBattleScripting.animArg2 = 0;
BattleScriptPushCursorAndCallback(BattleScript_BerserkGeneRet);
effect = ITEM_STATS_CHANGE;
break;
}
return effect;
@ -7185,7 +7110,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn)
else
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_NORMALIZED_STATUS;
gBattleMons[battlerId].status1 = 0;
gBattleMons[battlerId].status2 &= ~STATUS2_CONFUSION;
RemoveConfusionStatus(battlerId);
BattleScriptExecute(BattleScript_BerryCureChosenStatusEnd2);
effect = ITEM_STATUS_CHANGE;
}
@ -7246,6 +7171,21 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn)
}
}
break;
case HOLD_EFFECT_BERSERK_GENE:
BufferStatChange(battlerId, STAT_ATK, STRINGID_STATROSE);
gEffectBattler = battlerId;
if (CanBeInfinitelyConfused(gEffectBattler))
{
gStatuses4[gEffectBattler] |= STATUS4_INFINITE_CONFUSION;
}
SET_STATCHANGER(STAT_ATK, 2, FALSE);
gBattleScripting.animArg1 = 14 + STAT_ATK;
gBattleScripting.animArg2 = 0;
BattleScriptPushCursorAndCallback(BattleScript_BerserkGeneRet);
effect = ITEM_STATS_CHANGE;
break;
}
if (effect != 0)
{
@ -7281,11 +7221,11 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn)
case HOLD_EFFECT_RESTORE_PP:
if (!moveTurn)
{
struct Pokemon *mon;
struct Pokemon *party = GetBattlerParty(battlerId);
struct Pokemon *mon = &party[gBattlerPartyIndexes[battlerId]];
u8 ppBonuses;
u16 move;
mon = GetBattlerPartyData(battlerId);
for (i = 0; i < MAX_MON_MOVES; i++)
{
move = GetMonData(mon, MON_DATA_MOVE1 + i);
@ -7466,7 +7406,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn)
case HOLD_EFFECT_CURE_CONFUSION:
if (gBattleMons[battlerId].status2 & STATUS2_CONFUSION && !UnnerveOn(battlerId, gLastUsedItem))
{
gBattleMons[battlerId].status2 &= ~STATUS2_CONFUSION;
RemoveConfusionStatus(battlerId);
BattleScriptExecute(BattleScript_BerryCureConfusionEnd2);
effect = ITEM_EFFECT_OTHER;
}
@ -7511,7 +7451,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn)
else
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_NORMALIZED_STATUS;
gBattleMons[battlerId].status1 = 0;
gBattleMons[battlerId].status2 &= ~STATUS2_CONFUSION;
RemoveConfusionStatus(battlerId);
BattleScriptExecute(BattleScript_BerryCureChosenStatusEnd2);
effect = ITEM_STATUS_CHANGE;
}
@ -7529,6 +7469,21 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn)
if (!moveTurn)
effect = TrySetMicleBerry(battlerId, gLastUsedItem, TRUE);
break;
case HOLD_EFFECT_BERSERK_GENE:
BufferStatChange(battlerId, STAT_ATK, STRINGID_STATROSE);
gEffectBattler = battlerId;
if (CanBeInfinitelyConfused(gEffectBattler))
{
gStatuses4[gEffectBattler] |= STATUS4_INFINITE_CONFUSION;
}
SET_STATCHANGER(STAT_ATK, 2, FALSE);
gBattleScripting.animArg1 = 14 + STAT_ATK;
gBattleScripting.animArg2 = 0;
BattleScriptPushCursorAndCallback(BattleScript_BerserkGeneRet);
effect = ITEM_STATS_CHANGE;
break;
}
if (effect != 0)
@ -8156,7 +8111,6 @@ u32 GetBattlerHoldEffect(u8 battlerId, bool32 checkNegating)
return ItemId_GetHoldEffect(gBattleMons[battlerId].item);
}
//
static u32 GetBattlerItemHoldEffectParam(u8 battlerId, u16 item)
{
if (item == ITEM_ENIGMA_BERRY_E_READER)
@ -9874,6 +9828,10 @@ static u16 CalcTypeEffectivenessMultiplierInternal(u16 move, u8 moveType, u8 bat
}
}
// Signal for the trainer slide-in system.
if (GetBattlerSide(battlerDef) != B_SIDE_PLAYER && modifier && gBattleStruct->trainerSlideFirstSTABMoveMsgState != 2)
gBattleStruct->trainerSlideFirstSTABMoveMsgState = 1;
return modifier;
}
@ -10317,10 +10275,7 @@ bool32 SetIllusionMon(struct Pokemon *mon, u32 battlerId)
if (GetMonAbility(mon) != ABILITY_ILLUSION)
return FALSE;
if (GetBattlerSide(battlerId) == B_SIDE_PLAYER)
party = gPlayerParty;
else
party = gEnemyParty;
party = GetBattlerParty(battlerId);
if (IsBattlerAlive(BATTLE_PARTNER(battlerId)))
partnerMon = &party[gBattlerPartyIndexes[BATTLE_PARTNER(battlerId)]];
@ -10445,17 +10400,6 @@ bool32 TestMoveFlags(u16 move, u32 flag)
return FALSE;
}
struct Pokemon *GetBattlerPartyData(u8 battlerId)
{
struct Pokemon *mon;
if (GetBattlerSide(battlerId) == B_SIDE_PLAYER)
mon = &gPlayerParty[gBattlerPartyIndexes[battlerId]];
else
mon = &gEnemyParty[gBattlerPartyIndexes[battlerId]];
return mon;
}
static u8 GetFlingPowerFromItemId(u16 itemId)
{
if (itemId >= ITEM_TM01 && itemId <= ITEM_HM08)
@ -10606,18 +10550,20 @@ void SortBattlersBySpeed(u8 *battlers, bool8 slowToFast)
}
}
void TryRestoreStolenItems(void)
void TryRestoreHeldItems(void)
{
u32 i;
u16 stolenItem = ITEM_NONE;
u16 lostItem = ITEM_NONE;
for (i = 0; i < PARTY_SIZE; i++)
{
if (gBattleStruct->itemStolen[i].stolen)
#if B_RESTORE_HELD_BATTLE_ITEMS == FALSE
if (gBattleStruct->itemLost[i].stolen)
#endif
{
stolenItem = gBattleStruct->itemStolen[i].originalItem;
if (stolenItem != ITEM_NONE && ItemId_GetPocket(stolenItem) != POCKET_BERRIES)
SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &stolenItem); // Restore stolen non-berry items
lostItem = gBattleStruct->itemLost[i].originalItem;
if (lostItem != ITEM_NONE && ItemId_GetPocket(lostItem) != POCKET_BERRIES)
SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &lostItem); // Restore stolen non-berry items
}
}
}
@ -10671,8 +10617,8 @@ void TrySaveExchangedItem(u8 battlerId, u16 stolenItem)
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER
&& !(gBattleTypeFlags & BATTLE_TYPE_FRONTIER)
&& GetBattlerSide(battlerId) == B_SIDE_PLAYER
&& stolenItem == gBattleStruct->itemStolen[gBattlerPartyIndexes[battlerId]].originalItem)
gBattleStruct->itemStolen[gBattlerPartyIndexes[battlerId]].stolen = TRUE;
&& stolenItem == gBattleStruct->itemLost[gBattlerPartyIndexes[battlerId]].originalItem)
gBattleStruct->itemLost[gBattlerPartyIndexes[battlerId]].stolen = TRUE;
#endif
}
@ -10915,3 +10861,21 @@ void RecalcBattlerStats(u32 battler, struct Pokemon *mon)
CopyMonLevelAndBaseStatsToBattleMon(battler, mon);
CopyMonAbilityAndTypesToBattleMon(battler, mon);
}
void RemoveConfusionStatus(u8 battlerId)
{
gBattleMons[battlerId].status2 &= ~STATUS2_CONFUSION;
gStatuses4[battlerId] &= ~STATUS4_INFINITE_CONFUSION;
}
static bool8 CanBeInfinitelyConfused(u8 battlerId)
{
if (gBattleMons[battlerId].ability == ABILITY_OWN_TEMPO
|| IsBattlerTerrainAffected(battlerId, STATUS_FIELD_MISTY_TERRAIN)
|| gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_SAFEGUARD)
{
return FALSE;
}
return TRUE;
}

View File

@ -215,11 +215,7 @@ bool32 IsViableZMove(u8 battlerId, u16 move)
if (move != MOVE_NONE && zMove != MOVE_Z_STATUS && gBattleMoves[move].type == ItemId_GetSecondaryId(item))
{
if (IS_MOVE_STATUS(move))
gBattleStruct->zmove.chosenZMove = move;
else
gBattleStruct->zmove.chosenZMove = GetTypeBasedZMove(move, battlerId);
gBattleStruct->zmove.chosenZMove = GetTypeBasedZMove(move, battlerId);
return TRUE;
}
}

View File

@ -1079,7 +1079,7 @@ const struct CompressedSpriteSheet gBattleAnimPicTable[] =
{gBattleAnimSpriteGfx_RedFist, 0x0200, ANIM_TAG_RED_FIST},
{gBattleAnimSpriteGfx_SlamHit, 0x1000, ANIM_TAG_SLAM_HIT},
{gBattleAnimSpriteGfx_Ring, 0x0180, ANIM_TAG_RING},
#if NEW_ROCKS_PARTICLE
#if B_NEW_ROCKS_PARTICLE == TRUE
{gBattleAnimSpriteGfx_NewRocks, 0x0C00, ANIM_TAG_ROCKS},
#else
{gBattleAnimSpriteGfx_Rocks, 0x0C00, ANIM_TAG_ROCKS},
@ -1529,7 +1529,7 @@ const struct CompressedSpritePalette gBattleAnimPaletteTable[] =
{gBattleAnimSpritePal_HumanoidFoot, ANIM_TAG_RED_FIST},
{gBattleAnimSpritePal_SlamHit, ANIM_TAG_SLAM_HIT},
{gBattleAnimSpritePal_Ring, ANIM_TAG_RING},
#if NEW_ROCKS_PARTICLE
#if B_NEW_ROCKS_PARTICLE == TRUE
{gBattleAnimSpritePal_NewRocks, ANIM_TAG_ROCKS},
#else
{gBattleAnimSpritePal_Rocks, ANIM_TAG_ROCKS},

View File

@ -1998,3 +1998,6 @@ const u32 gItemIconPalette_GriseousCore[] = INCBIN_U32("graphics/items/icon_pale
const u32 gItemIcon_LustrousGlobe[] = INCBIN_U32("graphics/items/icons/lustrous_globe.4bpp.lz");
const u32 gItemIconPalette_LustrousGlobe[] = INCBIN_U32("graphics/items/icon_palettes/lustrous_globe.gbapal.lz");
const u32 gItemIcon_BerserkGene[] = INCBIN_U32("graphics/items/icons/berserk_gene.4bpp.lz");
const u32 gItemIconPalette_BerserkGene[] = INCBIN_U32("graphics/items/icon_palettes/berserk_gene.gbapal.lz");

View File

@ -843,6 +843,7 @@ const u32 *const gItemIconTable[ITEMS_COUNT + 1][2] =
[ITEM_BLACK_AUGURITE] = {gItemIcon_BlackAugurite, gItemIconPalette_BlackAugurite},
[ITEM_LINKING_CORD] = {gItemIcon_LinkingCord, gItemIconPalette_LinkingCord},
[ITEM_PEAT_BLOCK] = {gItemIcon_PeatBlock, gItemIconPalette_PeatBlock},
[ITEM_BERSERK_GENE] = {gItemIcon_BerserkGene, gItemIconPalette_BerserkGene},
// Return to field arrow
[ITEMS_COUNT] = {gItemIcon_ReturnToFieldArrow, gItemIconPalette_ReturnToFieldArrow},
};

File diff suppressed because it is too large Load Diff

View File

@ -272,7 +272,7 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] =
[SPECIES_KRICKETOT] = {{EVO_LEVEL, 10, SPECIES_KRICKETUNE}},
[SPECIES_SHINX] = {{EVO_LEVEL, 15, SPECIES_LUXIO}},
[SPECIES_LUXIO] = {{EVO_LEVEL, 30, SPECIES_LUXRAY}},
[SPECIES_BUDEW] = {{EVO_FRIENDSHIP, 0, SPECIES_ROSELIA}},
[SPECIES_BUDEW] = {{EVO_FRIENDSHIP_DAY, 0, SPECIES_ROSELIA}},
[SPECIES_CRANIDOS] = {{EVO_LEVEL, 30, SPECIES_RAMPARDOS}},
[SPECIES_SHIELDON] = {{EVO_LEVEL, 30, SPECIES_BASTIODON}},
[SPECIES_BURMY] = {{EVO_LEVEL_FEMALE, 20, SPECIES_WORMADAM},

View File

@ -533,8 +533,6 @@ const u8 *const gItemEffectTable[ITEMS_COUNT] =
[ITEM_DIRE_HIT] = gItemEffect_DireHit,
[ITEM_GUARD_SPEC] = gItemEffect_GuardSpec,
//[ITEM_MAX_MUSHROOMS] = gItemEffect_MaxMushrooms, // Todo
// Evolution Items
[ITEM_FIRE_STONE] = gItemEffect_EvoItem,
[ITEM_WATER_STONE] = gItemEffect_EvoItem,

View File

@ -3907,3 +3907,8 @@ static const u8 sLustrousGlobeDesc[] = _(
"A large, glowing gem\n"
"that lets Palkia\n"
"change form.");
static const u8 sBerserkGene[] = _(
"Sharply boosts\n"
"Attack, but causes\n"
"lasting confusion.");

View File

@ -7,12 +7,15 @@
#include "malloc.h"
#include "secret_base.h"
#include "item_menu.h"
#include "party_menu.h"
#include "strings.h"
#include "load_save.h"
#include "item_use.h"
#include "battle_pyramid.h"
#include "battle_pyramid_bag.h"
#include "constants/battle.h"
#include "constants/items.h"
#include "constants/item_effects.h"
#include "constants/hold_effects.h"
static bool8 CheckPyramidBagHasItem(u16 itemId, u16 count);
@ -922,14 +925,36 @@ ItemUseFunc ItemId_GetFieldFunc(u16 itemId)
return gItems[SanitizeItemId(itemId)].fieldUseFunc;
}
// Returns an item's battle effect script ID.
u8 ItemId_GetBattleUsage(u16 itemId)
{
return gItems[SanitizeItemId(itemId)].battleUsage;
}
ItemUseFunc ItemId_GetBattleFunc(u16 itemId)
{
return gItems[SanitizeItemId(itemId)].battleUseFunc;
u16 item = SanitizeItemId(itemId);
// Handle E-Reader berries.
if (item == ITEM_ENIGMA_BERRY_E_READER)
{
switch (GetItemEffectType(gSpecialVar_ItemId))
{
case ITEM_EFFECT_X_ITEM:
return EFFECT_ITEM_INCREASE_STAT;
case ITEM_EFFECT_HEAL_HP:
return EFFECT_ITEM_RESTORE_HP;
case ITEM_EFFECT_CURE_POISON:
case ITEM_EFFECT_CURE_SLEEP:
case ITEM_EFFECT_CURE_BURN:
case ITEM_EFFECT_CURE_FREEZE:
case ITEM_EFFECT_CURE_PARALYSIS:
case ITEM_EFFECT_CURE_ALL_STATUS:
case ITEM_EFFECT_CURE_CONFUSION:
case ITEM_EFFECT_CURE_INFATUATION:
return EFFECT_ITEM_CURE_STATUS;
case ITEM_EFFECT_HEAL_PP:
return EFFECT_ITEM_RESTORE_PP;
default:
return 0;
}
}
else
return gItems[item].battleUsage;
}
u8 ItemId_GetSecondaryId(u16 itemId)
@ -941,3 +966,38 @@ u8 ItemId_GetFlingPower(u16 itemId)
{
return gItems[SanitizeItemId(itemId)].flingPower;
}
u32 GetItemStatus1Mask(u16 itemId)
{
const u8 *effect = GetItemEffect(itemId);
switch (effect[3])
{
case ITEM3_PARALYSIS:
return STATUS1_PARALYSIS;
case ITEM3_FREEZE:
return STATUS1_FREEZE;
case ITEM3_BURN:
return STATUS1_BURN;
case ITEM3_POISON:
return STATUS1_POISON | STATUS1_TOXIC_POISON;
case ITEM3_SLEEP:
return STATUS1_SLEEP;
case ITEM3_STATUS_ALL:
return STATUS1_ANY;
}
return 0;
}
u32 GetItemStatus2Mask(u16 itemId)
{
const u8 *effect = GetItemEffect(itemId);
if (effect[3] & ITEM3_STATUS_ALL)
return STATUS2_INFATUATION | STATUS2_CONFUSION;
else if (effect[0] & ITEM0_INFATUATION)
return STATUS2_INFATUATION;
else if (effect[3] & ITEM3_CONFUSION)
return STATUS2_CONFUSION;
else
return 0;
}

View File

@ -1985,11 +1985,18 @@ static void ItemMenu_Cancel(u8 taskId)
static void ItemMenu_UseInBattle(u8 taskId)
{
if (ItemId_GetBattleFunc(gSpecialVar_ItemId))
{
RemoveContextWindow();
ItemId_GetBattleFunc(gSpecialVar_ItemId)(taskId);
}
// Safety check
u16 type = ItemId_GetType(gSpecialVar_ItemId);
if (!ItemId_GetBattleUsage(gSpecialVar_ItemId))
return;
RemoveContextWindow();
if (type == ITEM_USE_BAG_MENU)
ItemUseInBattle_BagMenu(taskId);
else if (type == ITEM_USE_PARTY_MENU)
ItemUseInBattle_PartyMenu(taskId);
else if (type == ITEM_USE_PARTY_MENU_MOVES)
ItemUseInBattle_PartyMenuChooseMove(taskId);
}
void CB2_ReturnToBagMenuPocket(void)

View File

@ -75,6 +75,7 @@ static void Task_CloseCantUseKeyItemMessage(u8);
static void SetDistanceOfClosestHiddenItem(u8, s16, s16);
static void CB2_OpenPokeblockFromBag(void);
static void ItemUseOnFieldCB_Honey(u8 taskId);
static bool32 CannotUseBagBattleItem(u16 itemId);
// EWRAM variables
EWRAM_DATA static void(*sItemUseOnFieldCB)(u8 taskId) = NULL;
@ -86,9 +87,10 @@ EWRAM_DATA static void(*sItemUseOnFieldCB)(u8 taskId) = NULL;
// Never occurs in vanilla, but can occur with improperly created items
static const MainCallback sItemUseCallbacks[] =
{
[ITEM_USE_PARTY_MENU - 1] = CB2_ShowPartyMenuForItemUse,
[ITEM_USE_FIELD - 1] = CB2_ReturnToField,
[ITEM_USE_PBLOCK_CASE - 1] = NULL,
[ITEM_USE_PARTY_MENU - 1] = CB2_ShowPartyMenuForItemUse,
[ITEM_USE_FIELD - 1] = CB2_ReturnToField,
[ITEM_USE_PBLOCK_CASE - 1] = NULL,
[ITEM_USE_PARTY_MENU_MOVES - 1] = CB2_ShowPartyMenuForItemUse,
};
static const u8 sClockwiseDirections[] = {DIR_NORTH, DIR_EAST, DIR_SOUTH, DIR_WEST};
@ -1105,25 +1107,6 @@ static void Task_UseStatIncreaseItem(u8 taskId)
}
}
// e.g. X Attack, Guard Spec
void ItemUseInBattle_StatIncrease(u8 taskId)
{
u16 partyId = gBattlerPartyIndexes[gBattlerInMenuId];
if (ExecuteTableBasedItemEffect(&gPlayerParty[partyId], gSpecialVar_ItemId, partyId, 0) != FALSE)
{
if (!InBattlePyramid())
DisplayItemMessage(taskId, FONT_NORMAL, gText_WontHaveEffect, CloseItemMessage);
else
DisplayItemMessageInBattlePyramid(taskId, gText_WontHaveEffect, Task_CloseBattlePyramidBagMessage);
}
else
{
gTasks[taskId].func = Task_UseStatIncreaseItem;
gTasks[taskId].data[8] = 0;
}
}
static void ItemUseInBattle_ShowPartyMenu(u8 taskId)
{
if (!InBattlePyramid())
@ -1138,40 +1121,119 @@ static void ItemUseInBattle_ShowPartyMenu(u8 taskId)
}
}
void ItemUseInBattle_Medicine(u8 taskId)
void ItemUseInBattle_PartyMenu(u8 taskId)
{
gItemUseCB = ItemUseCB_Medicine;
gItemUseCB = ItemUseCB_BattleScript;
ItemUseInBattle_ShowPartyMenu(taskId);
}
// Unused. Sacred Ash cannot be used in battle
void ItemUseInBattle_SacredAsh(u8 taskId)
void ItemUseInBattle_PartyMenuChooseMove(u8 taskId)
{
gItemUseCB = ItemUseCB_SacredAsh;
gItemUseCB = ItemUseCB_BattleChooseMove;
ItemUseInBattle_ShowPartyMenu(taskId);
}
void ItemUseInBattle_PPRecovery(u8 taskId)
// Returns whether an item can be used in battle and sets the fail text.
static bool32 CannotUseBagBattleItem(u16 itemId)
{
gItemUseCB = ItemUseCB_PPRecovery;
ItemUseInBattle_ShowPartyMenu(taskId);
}
u8 cannotUse = FALSE;
u16 battleUsage = ItemId_GetBattleUsage(itemId);
const u8* failStr = NULL;
// Fluffy Tail / Poke Doll
void ItemUseInBattle_Escape(u8 taskId)
{
if((gBattleTypeFlags & BATTLE_TYPE_TRAINER) == FALSE)
// Embargo Check
if ((gPartyMenu.slotId == 0 && gStatuses3[B_POSITION_PLAYER_LEFT] & STATUS3_EMBARGO)
|| (gPartyMenu.slotId == 1 && gStatuses3[B_POSITION_PLAYER_RIGHT] & STATUS3_EMBARGO))
{
return TRUE;
}
// X-Items
if (battleUsage == EFFECT_ITEM_INCREASE_STAT
&& gBattleMons[gBattlerInMenuId].statStages[gItemEffectTable[itemId][1]] == MAX_STAT_STAGE)
{
cannotUse++;
}
// Dire Hit
if (battleUsage == EFFECT_ITEM_SET_FOCUS_ENERGY
&& (gBattleMons[gBattlerInMenuId].status2 & STATUS2_FOCUS_ENERGY))
{
cannotUse++;
}
// Guard Spec
if (battleUsage == EFFECT_ITEM_SET_MIST
&& gSideStatuses[GetBattlerSide(gBattlerInMenuId)] & SIDE_STATUS_MIST)
{
cannotUse++;
}
// Escape Items
if (battleUsage == EFFECT_ITEM_ESCAPE
&& gBattleTypeFlags & BATTLE_TYPE_TRAINER)
{
cannotUse++;
}
// Poke Balls
if (battleUsage == EFFECT_ITEM_THROW_BALL)
{
switch (GetBallThrowableState())
{
case BALL_THROW_UNABLE_TWO_MONS:
failStr = sText_CantThrowPokeBall_TwoMons;
cannotUse++;
break;
case BALL_THROW_UNABLE_NO_ROOM:
failStr = gText_BoxFull;
cannotUse++;
break;
#if B_SEMI_INVULNERABLE_CATCH >= GEN_4
case BALL_THROW_UNABLE_SEMI_INVULNERABLE:
failStr = sText_CantThrowPokeBall_SemiInvulnerable;
cannotUse++;
break;
#endif
case BALL_THROW_UNABLE_DISABLED_FLAG:
failStr = sText_CantThrowPokeBall_Disabled;
cannotUse++;
break;
}
}
// Max Mushrooms
if (battleUsage == EFFECT_ITEM_INCREASE_ALL_STATS)
{
u32 i;
for (i = 1; i < NUM_STATS; i++)
{
if (CompareStat(gBattlerInMenuId, i, MAX_STAT_STAGE, CMP_EQUAL))
{
cannotUse++;
break;
}
}
}
if (failStr != NULL)
StringExpandPlaceholders(gStringVar4, failStr);
else
StringExpandPlaceholders(gStringVar4, gText_WontHaveEffect);
return cannotUse;
}
void ItemUseInBattle_BagMenu(u8 taskId)
{
if (CannotUseBagBattleItem(gSpecialVar_ItemId))
{
RemoveUsedItem();
if (!InBattlePyramid())
DisplayItemMessage(taskId, FONT_NORMAL, gStringVar4, Task_FadeAndCloseBagMenu);
DisplayItemMessage(taskId, FONT_NORMAL, gStringVar4, CloseItemMessage);
else
DisplayItemMessageInBattlePyramid(taskId, gStringVar4, CloseBattlePyramidBag);
DisplayItemMessageInBattlePyramid(taskId, gStringVar4, Task_CloseBattlePyramidBagMessage);
}
else
{
DisplayDadsAdviceCannotUseItemMessage(taskId, gTasks[taskId].tUsingRegisteredKeyItem);
PlaySE(SE_SELECT);
RemoveUsedItem();
ScheduleBgCopyTilemapToVram(2);
if (!InBattlePyramid())
gTasks[taskId].func = Task_FadeAndCloseBagMenu;
else
gTasks[taskId].func = CloseBattlePyramidBag;
}
}
@ -1219,33 +1281,6 @@ void ItemUseOutOfBattle_EnigmaBerry(u8 taskId)
}
}
void ItemUseInBattle_EnigmaBerry(u8 taskId)
{
switch (GetItemEffectType(gSpecialVar_ItemId))
{
case ITEM_EFFECT_X_ITEM:
ItemUseInBattle_StatIncrease(taskId);
break;
case ITEM_EFFECT_HEAL_HP:
case ITEM_EFFECT_CURE_POISON:
case ITEM_EFFECT_CURE_SLEEP:
case ITEM_EFFECT_CURE_BURN:
case ITEM_EFFECT_CURE_FREEZE:
case ITEM_EFFECT_CURE_PARALYSIS:
case ITEM_EFFECT_CURE_ALL_STATUS:
case ITEM_EFFECT_CURE_CONFUSION:
case ITEM_EFFECT_CURE_INFATUATION:
ItemUseInBattle_Medicine(taskId);
break;
case ITEM_EFFECT_HEAL_PP:
ItemUseInBattle_PPRecovery(taskId);
break;
default:
ItemUseOutOfBattle_CannotUse(taskId);
break;
}
}
void ItemUseOutOfBattle_FormChange(u8 taskId)
{
gItemUseCB = ItemUseCB_FormChange;

View File

@ -401,6 +401,25 @@ void Overworld_ResetStateAfterDigEscRope(void)
FlagClear(FLAG_SYS_USE_FLASH);
}
#if B_RESET_FLAGS_VARS_AFTER_WHITEOUT == TRUE
void Overworld_ResetBattleFlagsAndVars(void)
{
#if VAR_TERRAIN != 0
VarSet(VAR_TERRAIN, 0);
#endif
#if B_VAR_WILD_AI_FLAGS != 0
VarSet(B_VAR_WILD_AI_FLAGS,0);
#endif
FlagClear(B_FLAG_INVERSE_BATTLE);
FlagClear(B_FLAG_FORCE_DOUBLE_WILD);
FlagClear(B_SMART_WILD_AI_FLAG);
FlagClear(B_FLAG_NO_BAG_USE);
FlagClear(B_FLAG_NO_CATCHING);
}
#endif
static void Overworld_ResetStateAfterWhiteOut(void)
{
ResetInitialPlayerAvatarState();
@ -409,8 +428,8 @@ static void Overworld_ResetStateAfterWhiteOut(void)
FlagClear(FLAG_SYS_SAFARI_MODE);
FlagClear(FLAG_SYS_USE_STRENGTH);
FlagClear(FLAG_SYS_USE_FLASH);
#if VAR_TERRAIN != 0
VarSet(VAR_TERRAIN, 0);
#if B_RESET_FLAGS_VARS_AFTER_WHITEOUT == TRUE
Overworld_ResetBattleFlagsAndVars();
#endif
// If you were defeated by Kyogre/Groudon and the step counter has
// maxed out, end the abnormal weather.

View File

@ -391,8 +391,8 @@ static void Task_DisplayHPRestoredMessage(u8);
static u16 ItemEffectToMonEv(struct Pokemon *, u8);
static void ItemEffectToStatString(u8, u8 *);
static void ReturnToUseOnWhichMon(u8);
static void SetSelectedMoveForPPItem(u8);
static void TryUsePPItem(u8);
static void SetSelectedMoveForItem(u8);
static void TryUseItemOnMove(u8);
static void Task_LearnedMove(u8);
static void Task_ReplaceMoveYesNo(u8);
static void Task_DoLearnedMoveFanfareAfterText(u8);
@ -481,6 +481,9 @@ static bool8 SetUpFieldMove_Fly(void);
static bool8 SetUpFieldMove_Waterfall(void);
static bool8 SetUpFieldMove_Dive(void);
void TryItemHoldFormChange(struct Pokemon *mon);
static void ShowMoveSelectWindow(u8 slot);
static void Task_HandleWhichMoveInput(u8 taskId);
static bool32 CannotUsePartyBattleItem(u16 itemId, struct Pokemon* mon);
// static const data
#include "data/party_menu.h"
@ -4302,12 +4305,7 @@ static void Task_SetSacredAshCB(u8 taskId)
static bool8 IsHPRecoveryItem(u16 item)
{
const u8 *effect;
if (item == ITEM_ENIGMA_BERRY_E_READER)
effect = gSaveBlock1Ptr->enigmaBerry.itemEffect;
else
effect = gItemEffectTable[item];
const u8 *effect = GetItemEffect(item);
if (effect == NULL)
return FALSE;
@ -4397,18 +4395,94 @@ static bool8 IsItemFlute(u16 item)
return FALSE;
}
static bool8 ExecuteTableBasedItemEffect_(u8 partyMonIndex, u16 item, u8 monMoveIndex)
static bool32 CannotUsePartyBattleItem(u16 itemId, struct Pokemon* mon)
{
if (gMain.inBattle)
u8 i;
u8 cannotUse = FALSE;
u16 battleUsage = ItemId_GetBattleUsage(itemId);
u16 hp = GetMonData(mon, MON_DATA_HP);
// Embargo Check
if ((gPartyMenu.slotId == 0 && gStatuses3[B_POSITION_PLAYER_LEFT] & STATUS3_EMBARGO)
|| (gPartyMenu.slotId == 1 && gStatuses3[B_POSITION_PLAYER_RIGHT] & STATUS3_EMBARGO))
{
if ((partyMonIndex == 0 && gStatuses3[B_POSITION_PLAYER_LEFT] & STATUS3_EMBARGO)
|| (partyMonIndex == 1 && gStatuses3[B_POSITION_PLAYER_RIGHT] & STATUS3_EMBARGO))
return TRUE; // cannot use on this mon
else
return ExecuteTableBasedItemEffect(&gPlayerParty[partyMonIndex], item, GetPartyIdFromBattleSlot(partyMonIndex), monMoveIndex);
return FALSE;
}
// Items that restore HP (Potions, Sitrus Berry, etc.)
if (battleUsage == EFFECT_ITEM_RESTORE_HP && (hp == 0 || hp == GetMonData(mon, MON_DATA_MAX_HP)))
{
cannotUse++;
}
// Items that cure status (Burn Heal, Awakening, etc.)
if (battleUsage == EFFECT_ITEM_CURE_STATUS
&& !((GetMonData(mon, MON_DATA_STATUS) & GetItemStatus1Mask(itemId))
|| (gPartyMenu.slotId == 0 && gBattleMons[gBattlerInMenuId].status2 & GetItemStatus2Mask(itemId))))
{
cannotUse++;
}
// Items that restore HP and cure status (Full Restore)
if (battleUsage == EFFECT_ITEM_HEAL_AND_CURE_STATUS
&& (hp == 0 || hp == GetMonData(mon, MON_DATA_MAX_HP))
&& !((GetMonData(mon, MON_DATA_STATUS) & GetItemStatus1Mask(itemId))
|| (gPartyMenu.slotId == 0 && gBattleMons[gBattlerInMenuId].status2 & GetItemStatus2Mask(itemId))))
{
cannotUse++;
}
// Items that revive a party member
if (battleUsage == EFFECT_ITEM_REVIVE && hp != 0)
{
cannotUse++;
}
// Items that restore PP (Elixir, Ether, Leppa Berry)
if (battleUsage == EFFECT_ITEM_RESTORE_PP)
{
if (GetItemEffect(itemId)[6] == ITEM4_HEAL_PP)
{
for (i = 0; i < MAX_MON_MOVES; i++)
{
if (GetMonData(mon, MON_DATA_PP1 + i) < CalculatePPWithBonus(GetMonData(mon, MON_DATA_MOVE1 + i), GetMonData(mon, MON_DATA_PP_BONUSES), i));
break;
}
if (i == MAX_MON_MOVES)
cannotUse++;
}
else if (GetMonData(mon, MON_DATA_PP1 + gPartyMenu.data1) == CalculatePPWithBonus(GetMonData(mon, MON_DATA_MOVE1 + gPartyMenu.data1), GetMonData(mon, MON_DATA_PP_BONUSES), gPartyMenu.data1))
{
cannotUse++;
}
}
return cannotUse;
}
// Battle scripts called in HandleAction_UseItem
void ItemUseCB_BattleScript(u8 taskId, TaskFunc task)
{
struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
if (CannotUsePartyBattleItem(gSpecialVar_ItemId, mon))
{
gPartyMenuUseExitCallback = FALSE;
PlaySE(SE_SELECT);
DisplayPartyMenuMessage(gText_WontHaveEffect, TRUE);
ScheduleBgCopyTilemapToVram(2);
gTasks[taskId].func = task;
}
else
return ExecuteTableBasedItemEffect(&gPlayerParty[partyMonIndex], item, partyMonIndex, monMoveIndex);
{
gBattleStruct->itemPartyIndex[gBattlerInMenuId] = GetPartyIdFromBattleSlot(gPartyMenu.slotId);
gPartyMenuUseExitCallback = TRUE;
PlaySE(SE_SELECT);
RemoveBagItem(gSpecialVar_ItemId, 1);
ScheduleBgCopyTilemapToVram(2);
gTasks[taskId].func = task;
}
}
void ItemUseCB_BattleChooseMove(u8 taskId, TaskFunc task)
{
PlaySE(SE_SELECT);
DisplayPartyMenuStdMessage(PARTY_MSG_RESTORE_WHICH_MOVE);
ShowMoveSelectWindow(gPartyMenu.slotId);
gTasks[taskId].func = Task_HandleWhichMoveInput;
}
void ItemUseCB_Medicine(u8 taskId, TaskFunc task)
@ -4431,7 +4505,7 @@ void ItemUseCB_Medicine(u8 taskId, TaskFunc task)
if (hp == GetMonData(mon, MON_DATA_MAX_HP))
canHeal = FALSE;
}
cannotUse = ExecuteTableBasedItemEffect_(gPartyMenu.slotId, item, 0);
cannotUse = ExecuteTableBasedItemEffect(mon, item, gPartyMenu.slotId, 0);
}
if (cannotUse != FALSE)
@ -4692,7 +4766,7 @@ void ItemUseCB_ReduceEV(u8 taskId, TaskFunc task)
u8 effectType = GetItemEffectType(item);
u16 friendship = GetMonData(mon, MON_DATA_FRIENDSHIP);
u16 ev = ItemEffectToMonEv(mon, effectType);
bool8 cannotUseEffect = ExecuteTableBasedItemEffect_(gPartyMenu.slotId, item, 0);
bool8 cannotUseEffect = ExecuteTableBasedItemEffect(mon, item, gPartyMenu.slotId, 0);
u16 newFriendship = GetMonData(mon, MON_DATA_FRIENDSHIP);
u16 newEv = ItemEffectToMonEv(mon, effectType);
@ -4808,25 +4882,19 @@ static void Task_HandleWhichMoveInput(u8 taskId)
else
{
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
SetSelectedMoveForPPItem(taskId);
SetSelectedMoveForItem(taskId);
}
}
}
void ItemUseCB_PPRecovery(u8 taskId, TaskFunc task)
{
const u8 *effect;
u16 item = gSpecialVar_ItemId;
if (item == ITEM_ENIGMA_BERRY_E_READER)
effect = gSaveBlock1Ptr->enigmaBerry.itemEffect;
else
effect = gItemEffectTable[item];
const u8 *effect = GetItemEffect(gSpecialVar_ItemId);
if (effect == NULL || !(effect[4] & ITEM4_HEAL_PP_ONE))
{
gPartyMenu.data1 = 0;
TryUsePPItem(taskId);
TryUseItemOnMove(taskId);
}
else
{
@ -4837,11 +4905,11 @@ void ItemUseCB_PPRecovery(u8 taskId, TaskFunc task)
}
}
static void SetSelectedMoveForPPItem(u8 taskId)
static void SetSelectedMoveForItem(u8 taskId)
{
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
gPartyMenu.data1 = Menu_GetCursorPos();
TryUsePPItem(taskId);
TryUseItemOnMove(taskId);
}
static void ReturnToUseOnWhichMon(u8 taskId)
@ -4852,34 +4920,58 @@ static void ReturnToUseOnWhichMon(u8 taskId)
DisplayPartyMenuStdMessage(PARTY_MSG_USE_ON_WHICH_MON);
}
static void TryUsePPItem(u8 taskId)
static void TryUseItemOnMove(u8 taskId)
{
u16 move = MOVE_NONE;
s16 *moveSlot = &gPartyMenu.data1;
u16 item = gSpecialVar_ItemId;
struct PartyMenu *ptr = &gPartyMenu;
struct Pokemon *mon;
if (ExecuteTableBasedItemEffect_(ptr->slotId, item, *moveSlot))
struct Pokemon *mon = &gPlayerParty[ptr->slotId];
// In battle, set appropriate variables to be used in battle script.
if (gMain.inBattle)
{
gPartyMenuUseExitCallback = FALSE;
PlaySE(SE_SELECT);
DisplayPartyMenuMessage(gText_WontHaveEffect, TRUE);
ScheduleBgCopyTilemapToVram(2);
gTasks[taskId].func = Task_ClosePartyMenuAfterText;
if (CannotUsePartyBattleItem(gSpecialVar_ItemId, mon))
{
gPartyMenuUseExitCallback = FALSE;
PlaySE(SE_SELECT);
DisplayPartyMenuMessage(gText_WontHaveEffect, TRUE);
ScheduleBgCopyTilemapToVram(2);
gTasks[taskId].func = Task_ClosePartyMenuAfterText;
}
else
{
gBattleStruct->itemPartyIndex[gBattlerInMenuId] = GetPartyIdFromBattleSlot(gPartyMenu.slotId);
gChosenMovePos = ptr->data1;
gPartyMenuUseExitCallback = TRUE;
RemoveBagItem(gSpecialVar_ItemId, 1);
ScheduleBgCopyTilemapToVram(2);
gTasks[taskId].func = Task_ClosePartyMenuAfterText;
}
}
// Outside of battle, only PP items are used on moves.
else
{
gPartyMenuUseExitCallback = TRUE;
mon = &gPlayerParty[ptr->slotId];
PlaySE(SE_USE_ITEM);
RemoveBagItem(item, 1);
move = GetMonData(mon, MON_DATA_MOVE1 + *moveSlot);
StringCopy(gStringVar1, gMoveNames[move]);
GetMedicineItemEffectMessage(item);
DisplayPartyMenuMessage(gStringVar4, TRUE);
ScheduleBgCopyTilemapToVram(2);
gTasks[taskId].func = Task_ClosePartyMenuAfterText;
u16 move = MOVE_NONE;
s16 *moveSlot = &gPartyMenu.data1;
u16 item = gSpecialVar_ItemId;
if (ExecuteTableBasedItemEffect(mon, item, ptr->slotId, *moveSlot))
{
gPartyMenuUseExitCallback = FALSE;
PlaySE(SE_SELECT);
DisplayPartyMenuMessage(gText_WontHaveEffect, TRUE);
ScheduleBgCopyTilemapToVram(2);
gTasks[taskId].func = Task_ClosePartyMenuAfterText;
}
else
{
gPartyMenuUseExitCallback = TRUE;
PlaySE(SE_USE_ITEM);
RemoveBagItem(item, 1);
move = GetMonData(mon, MON_DATA_MOVE1 + *moveSlot);
StringCopy(gStringVar1, gMoveNames[move]);
GetMedicineItemEffectMessage(item);
DisplayPartyMenuMessage(gStringVar4, TRUE);
ScheduleBgCopyTilemapToVram(2);
gTasks[taskId].func = Task_ClosePartyMenuAfterText;
}
}
}
@ -4993,7 +5085,7 @@ static void Task_LearnedMove(u8 taskId)
if (move[1] == 0)
{
AdjustFriendship(mon, FRIENDSHIP_EVENT_LEARN_TMHM);
if (item < ITEM_HM01_CUT)
if (!ItemId_GetImportance(item))
RemoveBagItem(item, 1);
}
GetMonNickname(mon, gStringVar1);
@ -5193,7 +5285,7 @@ void ItemUseCB_RareCandy(u8 taskId, TaskFunc task)
if (sInitialLevel != MAX_LEVEL)
{
BufferMonStatsToTaskData(mon, arrayPtr);
cannotUseEffect = ExecuteTableBasedItemEffect_(gPartyMenu.slotId, *itemPtr, 0);
cannotUseEffect = ExecuteTableBasedItemEffect(mon, *itemPtr, gPartyMenu.slotId, 0);
BufferMonStatsToTaskData(mon, &ptr->data[NUM_STATS]);
}
else
@ -5460,7 +5552,7 @@ static void UseSacredAsh(u8 taskId)
}
hp = GetMonData(mon, MON_DATA_HP);
if (ExecuteTableBasedItemEffect_(gPartyMenu.slotId, gSpecialVar_ItemId, 0))
if (ExecuteTableBasedItemEffect(mon, gSpecialVar_ItemId, gPartyMenu.slotId, 0))
{
gTasks[taskId].func = Task_SacredAshLoop;
return;
@ -5527,7 +5619,7 @@ void ItemUseCB_EvolutionStone(u8 taskId, TaskFunc task)
{
PlaySE(SE_SELECT);
gCB2_AfterEvolution = gPartyMenu.exitCallback;
if (ExecuteTableBasedItemEffect_(gPartyMenu.slotId, gSpecialVar_ItemId, 0))
if (ExecuteTableBasedItemEffect(&gPlayerParty[gPartyMenu.slotId], gSpecialVar_ItemId, gPartyMenu.slotId, 0))
{
gPartyMenuUseExitCallback = FALSE;
DisplayPartyMenuMessage(gText_WontHaveEffect, TRUE);
@ -5692,16 +5784,18 @@ void TryItemHoldFormChange(struct Pokemon *mon)
#undef tAnimWait
#undef tNextFunc
const u8* GetItemEffect(u16 item)
{
if (item == ITEM_ENIGMA_BERRY_E_READER)
return gSaveBlock1Ptr->enigmaBerry.itemEffect;
else
return gItemEffectTable[item];
}
u8 GetItemEffectType(u16 item)
{
const u8 *itemEffect;
u32 statusCure;
// Read the item's effect properties.
if (item == ITEM_ENIGMA_BERRY_E_READER)
itemEffect = gSaveBlock1Ptr->enigmaBerry.itemEffect;
else
itemEffect = gItemEffectTable[item];
const u8 *itemEffect = GetItemEffect(item);
if (itemEffect == NULL)
return ITEM_EFFECT_NONE;

View File

@ -1920,7 +1920,7 @@ const struct SpindaSpot gSpindaSpotGraphics[] =
#include "data/pokemon/item_effects.h"
const s8 gNatureStatTable[NUM_NATURES][NUM_NATURE_STATS] =
{ // Attack Defense Speed Sp.Atk Sp.Def
{ // Attack Defense Speed Sp.Atk Sp. Def
[NATURE_HARDY] = { 0, 0, 0, 0, 0 },
[NATURE_LONELY] = { +1, -1, 0, 0, 0 },
[NATURE_BRAVE] = { +1, 0, -1, 0, 0 },
@ -5749,55 +5749,16 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov
// Get item hold effect
heldItem = GetMonData(mon, MON_DATA_HELD_ITEM, NULL);
if (heldItem == ITEM_ENIGMA_BERRY_E_READER)
{
if (gMain.inBattle)
holdEffect = gEnigmaBerries[gBattlerInMenuId].holdEffect;
else
holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect;
}
holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect;
else
{
holdEffect = ItemId_GetHoldEffect(heldItem);
}
// Get battler id (if relevant)
gPotentialItemEffectBattler = gBattlerInMenuId;
if (gMain.inBattle)
{
gActiveBattler = gBattlerInMenuId;
i = (GetBattlerSide(gActiveBattler) != B_SIDE_PLAYER);
while (i < gBattlersCount)
{
if (gBattlerPartyIndexes[i] == partyIndex)
{
battlerId = i;
break;
}
i += 2;
}
}
else
{
gActiveBattler = 0;
battlerId = MAX_BATTLERS_COUNT;
}
// Skip using the item if it won't do anything
if (gItemEffectTable[item] == NULL && item != ITEM_ENIGMA_BERRY_E_READER)
return TRUE;
// Get item effect
if (item == ITEM_ENIGMA_BERRY_E_READER)
{
if (gMain.inBattle)
itemEffect = gEnigmaBerries[gActiveBattler].itemEffect;
else
itemEffect = gSaveBlock1Ptr->enigmaBerry.itemEffect;
}
else
{
itemEffect = gItemEffectTable[item];
}
itemEffect = GetItemEffect(item);
// Do item effect
for (i = 0; i < ITEM_EFFECT_ARG_START; i++)
@ -5806,85 +5767,13 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov
{
// Handle ITEM0 effects (infatuation, Dire Hit, X Attack). ITEM0_SACRED_ASH is handled in party_menu.c
// Now handled in item battle scripts.
case 0:
// Cure infatuation
if ((itemEffect[i] & ITEM0_INFATUATION)
&& gMain.inBattle && battlerId != MAX_BATTLERS_COUNT && (gBattleMons[battlerId].status2 & STATUS2_INFATUATION))
{
gBattleMons[battlerId].status2 &= ~STATUS2_INFATUATION;
retVal = FALSE;
}
// Dire Hit
if ((itemEffect[i] & ITEM0_DIRE_HIT)
&& !(gBattleMons[gActiveBattler].status2 & STATUS2_FOCUS_ENERGY))
{
gBattleMons[gActiveBattler].status2 |= STATUS2_FOCUS_ENERGY;
retVal = FALSE;
}
break;
// Handle ITEM1 effects (in-battle stat boosting effects)
// Now handled in item battle scripts.
case 1:
// X Attack
if ((itemEffect[i] & ITEM1_X_ATTACK)
&& gBattleMons[gActiveBattler].statStages[STAT_ATK] < MAX_STAT_STAGE)
{
gBattleMons[gActiveBattler].statStages[STAT_ATK] += X_ITEM_STAGES;
if (gBattleMons[gActiveBattler].statStages[STAT_ATK] > MAX_STAT_STAGE)
gBattleMons[gActiveBattler].statStages[STAT_ATK] = MAX_STAT_STAGE;
retVal = FALSE;
}
// X Defense
if ((itemEffect[i] & ITEM1_X_DEFENSE)
&& gBattleMons[gActiveBattler].statStages[STAT_DEF] < MAX_STAT_STAGE)
{
gBattleMons[gActiveBattler].statStages[STAT_DEF] += X_ITEM_STAGES;
if (gBattleMons[gActiveBattler].statStages[STAT_DEF] > MAX_STAT_STAGE)
gBattleMons[gActiveBattler].statStages[STAT_DEF] = MAX_STAT_STAGE;
retVal = FALSE;
}
// X Speed
if ((itemEffect[i] & ITEM1_X_SPEED)
&& gBattleMons[gActiveBattler].statStages[STAT_SPEED] < MAX_STAT_STAGE)
{
gBattleMons[gActiveBattler].statStages[STAT_SPEED] += X_ITEM_STAGES;
if (gBattleMons[gActiveBattler].statStages[STAT_SPEED] > MAX_STAT_STAGE)
gBattleMons[gActiveBattler].statStages[STAT_SPEED] = MAX_STAT_STAGE;
retVal = FALSE;
}
// X Sp Attack
if ((itemEffect[i] & ITEM1_X_SPATK)
&& gBattleMons[gActiveBattler].statStages[STAT_SPATK] < MAX_STAT_STAGE)
{
gBattleMons[gActiveBattler].statStages[STAT_SPATK] += X_ITEM_STAGES;
if (gBattleMons[gActiveBattler].statStages[STAT_SPATK] > MAX_STAT_STAGE)
gBattleMons[gActiveBattler].statStages[STAT_SPATK] = MAX_STAT_STAGE;
retVal = FALSE;
}
// X Sp Defense
if ((itemEffect[i] & ITEM1_X_SPDEF)
&& gBattleMons[gActiveBattler].statStages[STAT_SPDEF] < MAX_STAT_STAGE)
{
gBattleMons[gActiveBattler].statStages[STAT_SPDEF] += X_ITEM_STAGES;
if (gBattleMons[gActiveBattler].statStages[STAT_SPDEF] > MAX_STAT_STAGE)
gBattleMons[gActiveBattler].statStages[STAT_SPDEF] = MAX_STAT_STAGE;
retVal = FALSE;
}
// X Accuracy
if ((itemEffect[i] & ITEM1_X_ACCURACY)
&& gBattleMons[gActiveBattler].statStages[STAT_ACC] < MAX_STAT_STAGE)
{
gBattleMons[gActiveBattler].statStages[STAT_ACC] += X_ITEM_STAGES;
if (gBattleMons[gActiveBattler].statStages[STAT_ACC] > MAX_STAT_STAGE)
gBattleMons[gActiveBattler].statStages[STAT_ACC] = MAX_STAT_STAGE;
retVal = FALSE;
}
break;
// Formerly used by the item effects of the X Sp. Atk and the X Accuracy
case 2:
@ -5892,14 +5781,6 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov
// Handle ITEM3 effects (Guard Spec, Rare Candy, cure status)
case 3:
// Guard Spec
if ((itemEffect[i] & ITEM3_GUARD_SPEC)
&& gSideTimers[GetBattlerSide(gActiveBattler)].mistTimer == 0)
{
gSideTimers[GetBattlerSide(gActiveBattler)].mistTimer = 5;
retVal = FALSE;
}
// Rare Candy / EXP Candy
if ((itemEffect[i] & ITEM3_LEVEL_UP)
&& GetMonData(mon, MON_DATA_LEVEL, NULL) != MAX_LEVEL)
@ -5928,13 +5809,8 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov
}
// Cure status
if ((itemEffect[i] & ITEM3_SLEEP)
&& HealStatusConditions(mon, partyIndex, STATUS1_SLEEP, battlerId) == 0)
{
if (battlerId != MAX_BATTLERS_COUNT)
gBattleMons[battlerId].status2 &= ~STATUS2_NIGHTMARE;
if ((itemEffect[i] & ITEM3_SLEEP) && HealStatusConditions(mon, partyIndex, STATUS1_SLEEP, battlerId) == 0)
retVal = FALSE;
}
if ((itemEffect[i] & ITEM3_POISON) && HealStatusConditions(mon, partyIndex, STATUS1_PSN_ANY | STATUS1_TOXIC_COUNTER, battlerId) == 0)
retVal = FALSE;
if ((itemEffect[i] & ITEM3_BURN) && HealStatusConditions(mon, partyIndex, STATUS1_BURN, battlerId) == 0)
@ -5943,12 +5819,6 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov
retVal = FALSE;
if ((itemEffect[i] & ITEM3_PARALYSIS) && HealStatusConditions(mon, partyIndex, STATUS1_PARALYSIS, battlerId) == 0)
retVal = FALSE;
if ((itemEffect[i] & ITEM3_CONFUSION) // heal confusion
&& gMain.inBattle && battlerId != MAX_BATTLERS_COUNT && (gBattleMons[battlerId].status2 & STATUS2_CONFUSION))
{
gBattleMons[battlerId].status2 &= ~STATUS2_CONFUSION;
retVal = FALSE;
}
break;
// Handle ITEM4 effects (Change HP/Atk EVs, HP heal, PP heal, PP up, Revive, and evolution stones)
@ -5997,7 +5867,7 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov
if (itemEffect[10] & ITEM10_IS_VITAMIN)
evCap = EV_ITEM_RAISE_LIMIT;
else
evCap = 252;
evCap = MAX_PER_STAT_EVS;
if (dataSigned >= evCap)
break;
@ -6023,6 +5893,10 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov
break;
}
dataSigned += evChange;
#if I_EV_LOWERING_BERRY_JUMP == GEN_4
if (dataSigned > 100)
dataSigned = 100;
#endif
if (dataSigned < 0)
dataSigned = 0;
}
@ -6035,38 +5909,12 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov
break;
case 2: // ITEM4_HEAL_HP
// If Revive, update number of times revive has been used
if (effectFlags & (ITEM4_REVIVE >> 2))
// Check use validity.
if ((effectFlags & (ITEM4_REVIVE >> 2) && GetMonData(mon, MON_DATA_HP, NULL) != 0)
|| (!(effectFlags & (ITEM4_REVIVE >> 2)) && GetMonData(mon, MON_DATA_HP, NULL) == 0))
{
if (GetMonData(mon, MON_DATA_HP, NULL) != 0)
{
itemEffectParam++;
break;
}
if (gMain.inBattle)
{
if (battlerId != MAX_BATTLERS_COUNT)
{
gAbsentBattlerFlags &= ~gBitTable[battlerId];
CopyPlayerPartyMonToBattleData(battlerId, GetPartyIdFromBattlePartyId(gBattlerPartyIndexes[battlerId]));
if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER && gBattleResults.numRevivesUsed < 255)
gBattleResults.numRevivesUsed++;
}
else
{
gAbsentBattlerFlags &= ~gBitTable[gActiveBattler ^ 2];
if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER && gBattleResults.numRevivesUsed < 255)
gBattleResults.numRevivesUsed++;
}
}
}
else
{
if (GetMonData(mon, MON_DATA_HP, NULL) == 0)
{
itemEffectParam++;
break;
}
itemEffectParam++;
break;
}
// Get amount of HP to restore
@ -6094,35 +5942,11 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov
// Only restore HP if not at max health
if (GetMonData(mon, MON_DATA_MAX_HP, NULL) != GetMonData(mon, MON_DATA_HP, NULL))
{
if (!usedByAI)
{
// Restore HP
dataUnsigned = GetMonData(mon, MON_DATA_HP, NULL) + dataUnsigned;
if (dataUnsigned > GetMonData(mon, MON_DATA_MAX_HP, NULL))
dataUnsigned = GetMonData(mon, MON_DATA_MAX_HP, NULL);
SetMonData(mon, MON_DATA_HP, &dataUnsigned);
// Update battler (if applicable)
if (gMain.inBattle && battlerId != MAX_BATTLERS_COUNT)
{
gBattleMons[battlerId].hp = dataUnsigned;
if (!(effectFlags & (ITEM4_REVIVE >> 2)) && GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER)
{
if (gBattleResults.numHealingItemsUsed < 255)
gBattleResults.numHealingItemsUsed++;
temp2 = gActiveBattler;
gActiveBattler = battlerId;
BtlController_EmitGetMonData(BUFFER_A, REQUEST_ALL_BATTLE, 0);
MarkBattlerForControllerExec(gActiveBattler);
gActiveBattler = temp2;
}
}
}
else
{
gBattleMoveDamage = -dataUnsigned;
}
// Restore HP
dataUnsigned = GetMonData(mon, MON_DATA_HP, NULL) + dataUnsigned;
if (dataUnsigned > GetMonData(mon, MON_DATA_MAX_HP, NULL))
dataUnsigned = GetMonData(mon, MON_DATA_MAX_HP, NULL);
SetMonData(mon, MON_DATA_HP, &dataUnsigned);
retVal = FALSE;
}
effectFlags &= ~(ITEM4_REVIVE >> 2);
@ -6147,11 +5971,6 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov
dataUnsigned = CalculatePPWithBonus(moveId, GetMonData(mon, MON_DATA_PP_BONUSES, NULL), temp2);
}
SetMonData(mon, MON_DATA_PP1 + temp2, &dataUnsigned);
// Heal battler PP too (if applicable)
if (gMain.inBattle && battlerId != MAX_BATTLERS_COUNT && MOVE_IS_PERMANENT(battlerId, temp2))
gBattleMons[battlerId].pp[temp2] = dataUnsigned;
retVal = FALSE;
}
}
@ -6173,11 +5992,6 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov
dataUnsigned = CalculatePPWithBonus(moveId, GetMonData(mon, MON_DATA_PP_BONUSES, NULL), moveIndex);
}
SetMonData(mon, MON_DATA_PP1 + moveIndex, &dataUnsigned);
// Heal battler PP too (if applicable)
if (gMain.inBattle && battlerId != MAX_BATTLERS_COUNT && MOVE_IS_PERMANENT(battlerId, moveIndex))
gBattleMons[battlerId].pp[moveIndex] = dataUnsigned;
retVal = FALSE;
}
}
@ -6233,7 +6047,7 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov
if (itemEffect[10] & ITEM10_IS_VITAMIN)
evCap = EV_ITEM_RAISE_LIMIT;
else
evCap = 252;
evCap = MAX_PER_STAT_EVS;
if (dataSigned >= evCap)
break;
@ -6259,6 +6073,10 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov
break;
}
dataSigned += evChange;
#if I_BERRY_EV_JUMP == GEN_4
if (dataSigned > 100)
dataSigned = 100;
#endif
if (dataSigned < 0)
dataSigned = 0;
}
@ -6829,7 +6647,7 @@ u16 GetEvolutionTargetSpecies(struct Pokemon *mon, u8 mode, u16 evolutionItem, s
RtcCalcLocalTime();
if (gLocalTime.hours >= 0 && gLocalTime.hours < 12 && gEvolutionTable[species][i].param == evolutionItem)
targetSpecies = gEvolutionTable[species][i].targetSpecies;
break;
break;
}
}
break;

View File

@ -639,7 +639,10 @@ static void BuyMenuPrintPriceInList(u8 windowId, u32 itemId, u8 y)
5);
}
StringExpandPlaceholders(gStringVar4, gText_PokedollarVar1);
if (ItemId_GetImportance(itemId) && (CheckBagHasItem(itemId, 1) || CheckPCHasItem(itemId, 1)))
StringCopy(gStringVar4, gText_SoldOut);
else
StringExpandPlaceholders(gStringVar4, gText_PokedollarVar1);
x = GetStringRightAlignXOffset(FONT_NARROW, gStringVar4, 120);
AddTextPrinterParameterized4(windowId, FONT_NARROW, x, y, 0, 0, sShopBuyMenuTextColors[COLORID_ITEM_LIST], TEXT_SKIP_DRAW, gStringVar4);
}
@ -989,7 +992,9 @@ static void Task_BuyMenu(u8 taskId)
else
sShopData->totalCost = gDecorations[itemId].price;
if (!IsEnoughMoney(&gSaveBlock1Ptr->money, sShopData->totalCost))
if (ItemId_GetImportance(itemId) && (CheckBagHasItem(itemId, 1) || CheckPCHasItem(itemId, 1)))
BuyMenuDisplayMessage(taskId, gText_ThatItemIsSoldOut, BuyMenuReturnToItemList);
else if (!IsEnoughMoney(&gSaveBlock1Ptr->money, sShopData->totalCost))
{
BuyMenuDisplayMessage(taskId, gText_YouDontHaveMoney, BuyMenuReturnToItemList);
}
@ -998,7 +1003,15 @@ static void Task_BuyMenu(u8 taskId)
if (sMartInfo.martType == MART_TYPE_NORMAL)
{
CopyItemName(itemId, gStringVar1);
if (ItemId_GetPocket(itemId) == POCKET_TM_HM)
if (ItemId_GetImportance(itemId))
{
ConvertIntToDecimalStringN(gStringVar2, sShopData->totalCost, STR_CONV_MODE_LEFT_ALIGN, 6);
StringExpandPlaceholders(gStringVar4, gText_YouWantedVar1ThatllBeVar2);
tItemCount = 1;
sShopData->totalCost = (ItemId_GetPrice(tItemId) >> IsPokeNewsActive(POKENEWS_SLATEPORT)) * tItemCount;
BuyMenuDisplayMessage(taskId, gStringVar4, BuyMenuConfirmPurchase);
}
else if (ItemId_GetPocket(itemId) == POCKET_TM_HM)
{
StringCopy(gStringVar2, gMoveNames[ItemIdToBattleMoveId(itemId)]);
BuyMenuDisplayMessage(taskId, gText_Var1CertainlyHowMany2, Task_BuyHowManyDialogueInit);
@ -1103,8 +1116,8 @@ static void BuyMenuTryMakePurchase(u8 taskId)
{
if (AddBagItem(tItemId, tItemCount) == TRUE)
{
BuyMenuDisplayMessage(taskId, gText_HereYouGoThankYou, BuyMenuSubtractMoney);
RecordItemPurchase(taskId);
BuyMenuDisplayMessage(taskId, gText_HereYouGoThankYou, BuyMenuSubtractMoney);
}
else
{
@ -1170,6 +1183,7 @@ static void BuyMenuReturnToItemList(u8 taskId)
s16 *data = gTasks[taskId].data;
ClearDialogWindowAndFrameToTransparent(WIN_MESSAGE, FALSE);
RedrawListMenu(tListTaskId);
BuyMenuPrintCursor(tListTaskId, COLORID_ITEM_LIST);
PutWindowTilemap(WIN_ITEM_LIST);
PutWindowTilemap(WIN_ITEM_DESCRIPTION);

View File

@ -341,6 +341,8 @@ const u8 gText_Var1DisdainfullyAteVar2[] = _("{STR_VAR_1} disdainfully ate the\n
const u8 gText_ShopBuy[] = _("BUY");
const u8 gText_ShopSell[] = _("SELL");
const u8 gText_ShopQuit[] = _("QUIT");
const u8 gText_ThatItemIsSoldOut[] = _("I'm sorry, but that item is sold out.{PAUSE_UNTIL_PRESS}");
const u8 gText_SoldOut[] = _("SOLD OUT");
const u8 gText_InBagVar1[] = _("IN BAG: {STR_VAR_1}");
const u8 gText_QuitShopping[] = _("Quit shopping.");
const u8 gText_Var1CertainlyHowMany[] = _("{STR_VAR_1}? Certainly.\nHow many would you like?");

View File

@ -21,7 +21,7 @@ SINGLE_BATTLE_TEST("Contrary raises Attack when Intimidated", s16 damage)
if (ability == ABILITY_CONTRARY) {
ABILITY_POPUP(opponent, ABILITY_CONTRARY);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Spinda's attack rose!");
MESSAGE("Foe Spinda's Attack rose!");
}
HP_BAR(player, captureDamage: &results[i].damage);
}
@ -49,11 +49,11 @@ SINGLE_BATTLE_TEST("Contrary raises stats after using a move which would normall
if (ability == ABILITY_CONTRARY) {
// ABILITY_POPUP(opponent, ABILITY_CONTRARY);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Spinda's sp. attack sharply rose!");
MESSAGE("Foe Spinda's Sp. Atk sharply rose!");
}
else {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Spinda's sp. attack harshly fell!");
MESSAGE("Foe Spinda's Sp. Atk harshly fell!");
}
// MESSAGE("Foe Spinda used Overheat!");
@ -61,11 +61,11 @@ SINGLE_BATTLE_TEST("Contrary raises stats after using a move which would normall
if (ability == ABILITY_CONTRARY) {
// ABILITY_POPUP(opponent, ABILITY_CONTRARY);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Spinda's sp. attack sharply rose!");
MESSAGE("Foe Spinda's Sp. Atk sharply rose!");
}
else {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Spinda's sp. attack harshly fell!");
MESSAGE("Foe Spinda's Sp. Atk harshly fell!");
}
}
FINALLY {
@ -95,11 +95,11 @@ SINGLE_BATTLE_TEST("Contrary lowers a stat after using a move which would normal
if (ability == ABILITY_CONTRARY) {
// ABILITY_POPUP(opponent, ABILITY_CONTRARY);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Spinda's attack harshly fell!");
MESSAGE("Foe Spinda's Attack harshly fell!");
}
else {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Spinda's attack sharply rose!");
MESSAGE("Foe Spinda's Attack sharply rose!");
}
// MESSAGE("Foe Spinda used Tackle!");
@ -127,11 +127,11 @@ SINGLE_BATTLE_TEST("Contrary raises a stat after using a move which would normal
if (ability == ABILITY_CONTRARY) {
// ABILITY_POPUP(opponent, ABILITY_CONTRARY);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Spinda's attack rose!");
MESSAGE("Foe Spinda's Attack rose!");
}
else {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Spinda's attack fell!");
MESSAGE("Foe Spinda's Attack fell!");
}
MESSAGE("Foe Spinda used Tackle!");

View File

@ -7,7 +7,7 @@ ASSUMPTIONS
ASSUME(gBattleMoves[MOVE_TRI_ATTACK].split == SPLIT_SPECIAL);
}
SINGLE_BATTLE_TEST("Download raises Attack if player has lower Def than Sp.Def", s16 damage)
SINGLE_BATTLE_TEST("Download raises Attack if player has lower Def than Sp. Def", s16 damage)
{
u32 ability;
PARAMETRIZE { ability = ABILITY_TRACE; }
@ -22,7 +22,7 @@ SINGLE_BATTLE_TEST("Download raises Attack if player has lower Def than Sp.Def",
{
ABILITY_POPUP(opponent, ABILITY_DOWNLOAD);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Porygon's Download raised its attack!");
MESSAGE("Foe Porygon's Download raised its Attack!");
}
HP_BAR(player, captureDamage: &results[i].damage);
} FINALLY {
@ -30,7 +30,7 @@ SINGLE_BATTLE_TEST("Download raises Attack if player has lower Def than Sp.Def",
}
}
SINGLE_BATTLE_TEST("Download raises Sp.Attack if enemy has lower Sp.Def than Def", s16 damage)
SINGLE_BATTLE_TEST("Download raises Sp.Attack if enemy has lower Sp. Def than Def", s16 damage)
{
u32 ability;
PARAMETRIZE { ability = ABILITY_TRACE; }
@ -45,7 +45,7 @@ SINGLE_BATTLE_TEST("Download raises Sp.Attack if enemy has lower Sp.Def than Def
{
ABILITY_POPUP(player, ABILITY_DOWNLOAD);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Porygon's Download raised its sp. attack!");
MESSAGE("Porygon's Download raised its Sp. Atk!");
}
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
@ -79,10 +79,10 @@ SINGLE_BATTLE_TEST("Download doesn't activate if target hasn't been sent out yet
{
ABILITY_POPUP(player, ABILITY_DOWNLOAD);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Porygon's Download raised its attack!");
MESSAGE("Porygon's Download raised its Attack!");
ABILITY_POPUP(opponent, ABILITY_DOWNLOAD);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Porygon2's Download raised its sp. attack!");
MESSAGE("Foe Porygon2's Download raised its Sp. Atk!");
}
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player);
HP_BAR(opponent, captureDamage: &results[i].damagePhysical);

View File

@ -104,7 +104,7 @@ SINGLE_BATTLE_TEST("Intimidate and Eject Button force the opponent to Attack")
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_EJECT_BUTTON); };
OPPONENT(SPECIES_HITMONTOP) { Moves(MOVE_TACKLE); };
} WHEN {
TURN {
TURN {
MOVE(player, MOVE_QUICK_ATTACK);
MOVE(opponent, MOVE_TACKLE);
SEND_OUT(opponent, 1);

View File

@ -74,11 +74,11 @@ DOUBLE_BATTLE_TEST("Magic Bounce bounces back moves hitting both foes at two foe
MESSAGE("Abra's Leer was bounced back by Foe Espeon's Magic Bounce!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_LEER, opponentLeft);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft);
MESSAGE("Abra's defense fell!");
MESSAGE("Abra's Defense fell!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight);
MESSAGE("Kadabra's defense fell!");
MESSAGE("Kadabra's Defense fell!");
// Also check if second original target gets hit by Leer as this was once bugged
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight);
MESSAGE("Foe Wynaut's defense fell!");
MESSAGE("Foe Wynaut's Defense fell!");
}
}

View File

@ -63,6 +63,6 @@ SINGLE_BATTLE_TEST("Oblivious prevents Intimidate")
ABILITY_POPUP(opponent, ABILITY_INTIMIDATE);
ABILITY_POPUP(player, ABILITY_OBLIVIOUS);
NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); }
MESSAGE("Slowpoke's attack was not lowered!");
MESSAGE("Slowpoke's Attack was not lowered!");
}
}

View File

@ -1,7 +1,7 @@
#include "global.h"
#include "test_battle.h"
SINGLE_BATTLE_TEST("Speed Boost gradually boosts speed")
SINGLE_BATTLE_TEST("Speed Boost gradually boosts Speed")
{
GIVEN {
PLAYER(SPECIES_TORCHIC) { Ability(ABILITY_SPEED_BOOST); Speed(99); };

View File

@ -102,7 +102,7 @@ SINGLE_BATTLE_TEST("Volt Absorb prevents Cell Battery from activating")
NONE_OF {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Using Cell Battery, the attack of Jolteon rose!");
MESSAGE("Using Cell Battery, the Attack of Jolteon rose!");
}
}

View File

@ -0,0 +1,187 @@
#include "global.h"
#include "test_battle.h"
ASSUMPTIONS
{
ASSUME(gItems[ITEM_BERSERK_GENE].holdEffect == HOLD_EFFECT_BERSERK_GENE);
}
SINGLE_BATTLE_TEST("Berserk Gene sharply raises attack at the start of battle", s16 damage)
{
u16 useItem;
PARAMETRIZE { useItem = FALSE; }
PARAMETRIZE { useItem = TRUE; }
if (useItem) PASSES_RANDOMLY(66, 100, RNG_CONFUSION);
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { if (useItem) Item(ITEM_BERSERK_GENE); };
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN {
MOVE(player, MOVE_TACKLE);
}
} SCENE {
if (useItem)
{
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Using Berserk Gene, the Attack of Wobbuffet sharply rose!");
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_CONFUSION, player);
MESSAGE("Wobbuffet became confused!");
}
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(2.0), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Berserk Gene activates on switch in", s16 damage)
{
u16 useItem;
PARAMETRIZE { useItem = FALSE; }
PARAMETRIZE { useItem = TRUE; }
if (useItem) PASSES_RANDOMLY(66, 100, RNG_CONFUSION);
GIVEN {
PLAYER(SPECIES_WYNAUT);
PLAYER(SPECIES_WOBBUFFET) { if (useItem) Item(ITEM_BERSERK_GENE); };
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN {
SWITCH(player, 1);
} TURN {
MOVE(player, MOVE_TACKLE);
}
} SCENE {
if (useItem)
{
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Using Berserk Gene, the Attack of Wobbuffet sharply rose!");
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_CONFUSION, player);
MESSAGE("Wobbuffet became confused!");
}
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(2.0), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Berserk Gene does not confuse a Pokemon with Own Tempo but still raises attack sharply", s16 damage)
{
u16 useItem;
PARAMETRIZE { useItem = FALSE; }
PARAMETRIZE { useItem = TRUE; }
GIVEN {
PLAYER(SPECIES_SLOWBRO) { Ability(ABILITY_OWN_TEMPO); if (useItem) Item(ITEM_BERSERK_GENE); };
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN {
MOVE(player, MOVE_TACKLE);
}
} SCENE {
if (useItem)
{
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Using Berserk Gene, the Attack of Slowbro sharply rose!");
ABILITY_POPUP(player, ABILITY_OWN_TEMPO);
MESSAGE("Slowbro's Own Tempo prevents confusion!");
}
HP_BAR(opponent, captureDamage: &results[i].damage);
NONE_OF
{
MESSAGE("Slowbro became confused!");
}
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, Q_4_12(2.0), results[1].damage);
}
}
SINGLE_BATTLE_TEST("Berserk Gene does not confuse on Misty Terrain but still raises attack sharply")
{
GIVEN {
ASSUME(P_GEN_7_POKEMON == TRUE);
PLAYER(SPECIES_TAPU_FINI) { Ability(ABILITY_MISTY_SURGE); Item(ITEM_BERSERK_GENE); };
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN {
MOVE(player, MOVE_TACKLE);
}
} SCENE {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Using Berserk Gene, the Attack of Tapu Fini sharply rose!");
NONE_OF
{
MESSAGE("Tapu Fini became confused!");
}
}
}
SINGLE_BATTLE_TEST("Berserk Gene does not confuse when Safeguard is active")
{
GIVEN {
PLAYER(SPECIES_WYNAUT);
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_BERSERK_GENE); };
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_SAFEGUARD); }
TURN { SWITCH(player, 1); }
} SCENE {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Using Berserk Gene, the Attack of Wobbuffet sharply rose!");
MESSAGE("Wobbuffet's party is protected by SAFEGUARD!");
NONE_OF
{
MESSAGE("Wobbuffet became confused!");
}
}
}
SINGLE_BATTLE_TEST("Berserk Gene causes confusion for more than 5 turns") // how else would be check for infinite?
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_BERSERK_GENE); };
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN {}
TURN {}
TURN {}
TURN {}
TURN {}
TURN {}
} SCENE {
NONE_OF
{
MESSAGE("Wobbuffet snapped out of confusion!");
}
}
}
SINGLE_BATTLE_TEST("Berserk Gene causes infinite confusion") // check if bit is set
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_BERSERK_GENE); };
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN {}
} SCENE {
} THEN {
EXPECT(gStatuses4[GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)] & STATUS4_INFINITE_CONFUSION);
}
}
SINGLE_BATTLE_TEST("Berserk Gene causes confusion timer to not tick down", u32 status2)
{
u32 turns;
PARAMETRIZE { turns = 1; }
PARAMETRIZE { turns = 2; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_BERSERK_GENE); };
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
u32 count;
for (count = 0; count < turns; count++) {
TURN {}
}
} THEN {
results[i].status2 = player->status2;
} FINALLY {
EXPECT_EQ(results[0].status2, results[1].status2);
}
}

View File

@ -0,0 +1,25 @@
#include "global.h"
#include "test_battle.h"
SINGLE_BATTLE_TEST("X-Attack sharply raises battler's Attack stat", s16 damage)
{
u16 useItem;
PARAMETRIZE { useItem = FALSE; }
PARAMETRIZE { useItem = TRUE; }
GIVEN {
ASSUME(gItems[ITEM_X_ATTACK].battleUsage == EFFECT_ITEM_INCREASE_STAT);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
if (useItem) TURN { USE_ITEM(player, ITEM_X_ATTACK); }
TURN { MOVE(player, MOVE_TACKLE); }
} SCENE {
MESSAGE("Wobbuffet used Tackle!");
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
if (B_X_ITEMS_BUFF >= GEN_7)
EXPECT_MUL_EQ(results[0].damage, Q_4_12(2.0), results[1].damage);
else
EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage);
}
}

View File

@ -0,0 +1,37 @@
#include "global.h"
#include "test_battle.h"
SINGLE_BATTLE_TEST("Potion restores a battler's HP by 20")
{
s16 damage;
GIVEN {
ASSUME(gItems[ITEM_POTION].battleUsage == EFFECT_ITEM_RESTORE_HP);
PLAYER(SPECIES_WOBBUFFET) { HP(50); MaxHP(100); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { USE_ITEM(player, ITEM_POTION, partyIndex: 0); }
} SCENE {
HP_BAR(player, captureDamage: &damage);
} FINALLY {
EXPECT_EQ(damage, -20);
}
}
SINGLE_BATTLE_TEST("Sitrus Berry restores a battler's HP")
{
s16 damage;
GIVEN {
ASSUME(gItems[ITEM_SITRUS_BERRY].battleUsage == EFFECT_ITEM_RESTORE_HP);
PLAYER(SPECIES_WOBBUFFET) { HP(50); MaxHP(100); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { USE_ITEM(player, ITEM_SITRUS_BERRY, partyIndex: 0); }
} SCENE {
HP_BAR(player, captureDamage: &damage);
} FINALLY {
if (I_SITRUS_BERRY_HEAL >= GEN_4)
EXPECT_EQ(damage, -25);
else
EXPECT_EQ(damage, -30);
}
}

View File

@ -0,0 +1,19 @@
#include "global.h"
#include "test_battle.h"
SINGLE_BATTLE_TEST("Ether restores the PP of one of a battler's moves")
{
GIVEN {
ASSUME(gItems[ITEM_ETHER].battleUsage == EFFECT_ITEM_RESTORE_PP);
ASSUME(gItems[ITEM_ETHER].type == ITEM_USE_PARTY_MENU_MOVES);
PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_TACKLE, MOVE_CONFUSION); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_TACKLE); }
TURN { MOVE(player, MOVE_CONFUSION); }
TURN { USE_ITEM(player, ITEM_ETHER, partyIndex: 0, move: MOVE_TACKLE); }
} FINALLY {
EXPECT_EQ(player->pp[0], 35);
EXPECT_EQ(player->pp[1], 24);
}
}

View File

@ -54,7 +54,7 @@ SINGLE_BATTLE_TEST("Turn order is determined by priority")
}
}
SINGLE_BATTLE_TEST("Turn order is determined by speed if priority ties")
SINGLE_BATTLE_TEST("Turn order is determined by Speed if priority ties")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Speed(2); }
@ -67,7 +67,7 @@ SINGLE_BATTLE_TEST("Turn order is determined by speed if priority ties")
}
}
SINGLE_BATTLE_TEST("Turn order is determined randomly if priority and speed tie")
SINGLE_BATTLE_TEST("Turn order is determined randomly if priority and Speed tie")
{
KNOWN_FAILING; // The algorithm is significantly biased.
PASSES_RANDOMLY(1, 2);

View File

@ -22,7 +22,7 @@ SINGLE_BATTLE_TEST("Growl lowers Attack", s16 damage)
if (lowerAttack) {
ANIMATION(ANIM_TYPE_MOVE, MOVE_GROWL, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Wobbuffet's attack fell!");
MESSAGE("Foe Wobbuffet's Attack fell!");
}
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent);
HP_BAR(player, captureDamage: &results[i].damage);

View File

@ -22,7 +22,7 @@ SINGLE_BATTLE_TEST("Meditate raises Attack", s16 damage)
if (raiseAttack) {
ANIMATION(ANIM_TYPE_MOVE, MOVE_MEDITATE, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Wobbuffet's attack rose!");
MESSAGE("Wobbuffet's Attack rose!");
}
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player);
HP_BAR(opponent, captureDamage: &results[i].damage);

View File

@ -22,7 +22,7 @@ SINGLE_BATTLE_TEST("Howl raises user's Attack", s16 damage)
if (raiseAttack) {
ANIMATION(ANIM_TYPE_MOVE, MOVE_HOWL, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Wobbuffet's attack rose!");
MESSAGE("Wobbuffet's Attack rose!");
}
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player);
HP_BAR(opponent, captureDamage: &results[i].damage);
@ -50,9 +50,9 @@ DOUBLE_BATTLE_TEST("Howl raises user's and partner's Attack", s16 damageLeft, s1
if (raiseAttack) {
ANIMATION(ANIM_TYPE_MOVE, MOVE_HOWL, playerLeft);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft);
MESSAGE("Wobbuffet's attack rose!");
MESSAGE("Wobbuffet's Attack rose!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight);
MESSAGE("Wynaut's attack rose!");
MESSAGE("Wynaut's Attack rose!");
}
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, playerLeft);
HP_BAR(opponentLeft, captureDamage: &results[i].damageLeft);

View File

@ -22,7 +22,7 @@ SINGLE_BATTLE_TEST("Tail Whip lowers Defense", s16 damage)
if (lowerDefense) {
ANIMATION(ANIM_TYPE_MOVE, MOVE_TAIL_WHIP, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Wobbuffet's defense fell!");
MESSAGE("Foe Wobbuffet's Defense fell!");
}
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player);
HP_BAR(opponent, captureDamage: &results[i].damage);

View File

@ -22,7 +22,7 @@ SINGLE_BATTLE_TEST("Harden raises Defense", s16 damage)
if (raiseDefense) {
ANIMATION(ANIM_TYPE_MOVE, MOVE_HARDEN, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Wobbuffet's defense rose!");
MESSAGE("Wobbuffet's Defense rose!");
}
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent);
HP_BAR(player, captureDamage: &results[i].damage);

View File

@ -165,7 +165,7 @@ DOUBLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes Stealth Rock and S
MESSAGE("Pointed stones dug into Wobbuffet!");
MESSAGE("Wobbuffet was caught in a Sticky Web!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft);
MESSAGE("Wobbuffet's speed fell!");
MESSAGE("Wobbuffet's Speed fell!");
}
else {
NONE_OF {
@ -173,7 +173,7 @@ DOUBLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes Stealth Rock and S
MESSAGE("Pointed stones dug into Wobbuffet!");
MESSAGE("Wobbuffet was caught in a Sticky Web!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft);
MESSAGE("Wobbuffet's speed fell!");
MESSAGE("Wobbuffet's Speed fell!");
}
}
}

View File

@ -22,7 +22,7 @@ SINGLE_BATTLE_TEST("Confide lowers Special Attack", s16 damage)
if (lowerSpecialAttack) {
ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFIDE, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Wobbuffet's sp. attack fell!");
MESSAGE("Foe Wobbuffet's Sp. Atk fell!");
}
ANIMATION(ANIM_TYPE_MOVE, MOVE_GUST, opponent);
HP_BAR(player, captureDamage: &results[i].damage);

View File

@ -22,7 +22,7 @@ SINGLE_BATTLE_TEST("Tail Glow drastically raises Special Attack", s16 damage)
if (raiseSpecialAttack) {
ANIMATION(ANIM_TYPE_MOVE, MOVE_TAIL_GLOW, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Wobbuffet's sp. attack drastically rose!");
MESSAGE("Wobbuffet's Sp. Atk drastically rose!");
}
ANIMATION(ANIM_TYPE_MOVE, MOVE_GUST, player);
HP_BAR(opponent, captureDamage: &results[i].damage);

View File

@ -142,7 +142,7 @@ SINGLE_BATTLE_TEST("Swallow heals HP depending on Stockpile's count", s16 hpHeal
}
}
SINGLE_BATTLE_TEST("Stockpile temporarily raises Def and Sp.Def", s16 dmgPyhsical, s16 dmgSpecial)
SINGLE_BATTLE_TEST("Stockpile temporarily raises Def and Sp. Def", s16 dmgPyhsical, s16 dmgSpecial)
{
u16 move;
PARAMETRIZE {move = MOVE_STOCKPILE;}
@ -161,8 +161,8 @@ SINGLE_BATTLE_TEST("Stockpile temporarily raises Def and Sp.Def", s16 dmgPyhsica
if (move == MOVE_STOCKPILE) {
MESSAGE("Wobbuffet stockpiled 1!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Wobbuffet's defense rose!");
MESSAGE("Wobbuffet's sp. defense rose!");
MESSAGE("Wobbuffet's Defense rose!");
MESSAGE("Wobbuffet's Sp. Def rose!");
}
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent);
@ -176,7 +176,7 @@ SINGLE_BATTLE_TEST("Stockpile temporarily raises Def and Sp.Def", s16 dmgPyhsica
}
}
DOUBLE_BATTLE_TEST("Stockpile's Def and Sp.Def boost is lost after using Spit Up or Swallow", s16 dmgPyhsicalBefore, s16 dmgPhysicalAfter, s16 dmgSpecialBefore, s16 dmgSpecialAfter)
DOUBLE_BATTLE_TEST("Stockpile's Def and Sp. Def boost is lost after using Spit Up or Swallow", s16 dmgPyhsicalBefore, s16 dmgPhysicalAfter, s16 dmgSpecialBefore, s16 dmgSpecialAfter)
{
u8 count;
u16 move;
@ -217,24 +217,24 @@ DOUBLE_BATTLE_TEST("Stockpile's Def and Sp.Def boost is lost after using Spit Up
ANIMATION(ANIM_TYPE_MOVE, move, playerLeft);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft);
if (count == 1) {
MESSAGE("Wobbuffet's defense fell!");
MESSAGE("Wobbuffet's Defense fell!");
}
else if (count == 2) {
MESSAGE("Wobbuffet's defense harshly fell!");
MESSAGE("Wobbuffet's Defense harshly fell!");
}
else {
MESSAGE("Wobbuffet's defense severely fell!");
MESSAGE("Wobbuffet's Defense severely fell!");
}
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft);
if (count == 1) {
MESSAGE("Wobbuffet's sp. defense fell!");
MESSAGE("Wobbuffet's Sp. Def fell!");
}
else if (count == 2) {
MESSAGE("Wobbuffet's sp. defense harshly fell!");
MESSAGE("Wobbuffet's Sp. Def harshly fell!");
}
else {
MESSAGE("Wobbuffet's sp. defense severely fell!");
MESSAGE("Wobbuffet's Sp. Def severely fell!");
}
MESSAGE("Wobbuffet's stockpiled effect wore off!");

View File

@ -53,7 +53,7 @@ SINGLE_BATTLE_TEST("Burn deals 1/16th damage per turn")
}
}
SINGLE_BATTLE_TEST("Burn reduces attack by 50%", s16 damage)
SINGLE_BATTLE_TEST("Burn reduces Attack by 50%", s16 damage)
{
bool32 burned;
PARAMETRIZE { burned = FALSE; }
@ -113,7 +113,7 @@ SINGLE_BATTLE_TEST("Freeze is thawed by user's Flame Wheel")
}
}
SINGLE_BATTLE_TEST("Paralysis reduces speed by 50%")
SINGLE_BATTLE_TEST("Paralysis reduces Speed by 50%")
{
u16 playerSpeed;
bool32 playerFirst;

View File

@ -31,7 +31,7 @@ SINGLE_BATTLE_TEST("Electric Terrain activates Electric Seed and Mimicry")
TURN { MOVE(player, MOVE_ELECTRIC_TERRAIN); }
} SCENE {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Using Electric Seed, the defense of Wobbuffet rose!");
MESSAGE("Using Electric Seed, the Defense of Wobbuffet rose!");
ABILITY_POPUP(opponent);
MESSAGE("Foe Stunfisk's type changed to Electr!");
} FINALLY {

View File

@ -27,7 +27,7 @@ SINGLE_BATTLE_TEST("Grassy Terrain activates Grassy Seed and Mimicry")
TURN { MOVE(player, MOVE_GRASSY_TERRAIN); }
} SCENE {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Using Grassy Seed, the defense of Wobbuffet rose!");
MESSAGE("Using Grassy Seed, the Defense of Wobbuffet rose!");
ABILITY_POPUP(opponent);
MESSAGE("Foe Stunfisk's type changed to Grass!");
} FINALLY {

View File

@ -31,7 +31,7 @@ SINGLE_BATTLE_TEST("Misty Terrain activates Misty Seed and Mimicry")
TURN { MOVE(player, MOVE_MISTY_TERRAIN); }
} SCENE {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Using Misty Seed, the sp. defense of Wobbuffet rose!");
MESSAGE("Using Misty Seed, the Sp. Def of Wobbuffet rose!");
ABILITY_POPUP(opponent);
MESSAGE("Foe Stunfisk's type changed to Fairy!");
} FINALLY {

Some files were not shown because too many files have changed in this diff Show More