Merge branch '_RHH/master' into _RHH/upcoming
# Conflicts: # asm/macros/battle_script.inc # include/constants/battle_string_ids.h # src/battle_ai_switch_items.c # src/battle_main.c # src/battle_script_commands.c # src/battle_util.c # src/frontier_util.c # test/battle/ai/ai.c
This commit is contained in:
commit
98eb4e5027
2
Makefile
2
Makefile
@ -484,7 +484,7 @@ $(DATA_SRC_SUBDIR)/pokemon/teachable_learnsets.h: $(DATA_ASM_BUILDDIR)/event_scr
|
||||
define TEST_DEP
|
||||
$1: $2 $$(shell $(SCANINC) -I include -I tools/agbcc/include -I gflib $2)
|
||||
@echo "$$(CC1) <flags> -o $$@ $$<"
|
||||
@$$(CPP) $$(CPPFLAGS) $$< | $$(PREPROC) $$< charmap.txt -i | $$(CC1) $$(CFLAGS) -o - - | cat - <(echo -e ".text\n\t.align\t2, 0") | $$(AS) $$(ASFLAGS) -o $$@ -
|
||||
@$$(CPP) $$(CPPFLAGS) $$< | $$(PREPROC) -i $$< charmap.txt | $$(CC1) $$(CFLAGS) -o - - | cat - <(echo -e ".text\n\t.align\t2, 0") | $$(AS) $$(ASFLAGS) -o $$@ -
|
||||
endef
|
||||
$(foreach src, $(TEST_SRCS), $(eval $(call TEST_DEP,$(patsubst $(TEST_SUBDIR)/%.c,$(TEST_BUILDDIR)/%.o,$(src)),$(src),$(patsubst $(TEST_SUBDIR)/%.c,%,$(src)))))
|
||||
|
||||
|
||||
@ -1652,6 +1652,12 @@
|
||||
.4byte \failInstr
|
||||
.endm
|
||||
|
||||
.macro copyfoesstatincrease battler:req, failInstr:req
|
||||
callnative BS_CopyFoesStatIncrease
|
||||
.byte \battler
|
||||
.4byte \failInstr
|
||||
.endm
|
||||
|
||||
.macro removeweather
|
||||
callnative BS_RemoveWeather
|
||||
.endm
|
||||
|
||||
@ -853,13 +853,11 @@ BattleScript_OctolockEndTurn::
|
||||
playstatchangeanimation BS_ATTACKER, BIT_DEF | BIT_SPDEF, STAT_CHANGE_NEGATIVE
|
||||
setstatchanger STAT_DEF, 1, TRUE
|
||||
statbuffchange STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_NOT_PROTECT_AFFECTED, BattleScript_OctolockTryLowerSpDef
|
||||
BattleScript_OctolockTryLowerDef:
|
||||
printfromtable gStatDownStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
BattleScript_OctolockTryLowerSpDef:
|
||||
setstatchanger STAT_SPDEF, 1, TRUE
|
||||
statbuffchange STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_NOT_PROTECT_AFFECTED, BattleScript_OctlockTurnDmgEnd
|
||||
BattleScript_OctolockTurnDmgPrintMsg:
|
||||
printfromtable gStatDownStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
BattleScript_OctlockTurnDmgEnd:
|
||||
@ -999,7 +997,6 @@ BattleScript_EffectStuffCheeks::
|
||||
jumpifnotberry BS_ATTACKER, BattleScript_ButItFailed
|
||||
attackanimation
|
||||
waitanimation
|
||||
BattleScript_StuffCheeksEatBerry:
|
||||
setbyte sBERRY_OVERRIDE, 1
|
||||
orword gHitMarker, HITMARKER_DISABLE_ANIMATION
|
||||
consumeberry BS_ATTACKER, TRUE
|
||||
@ -1211,10 +1208,6 @@ BattleScript_StrengthSapLower:
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
goto BattleScript_StrengthSapHp
|
||||
@ Drain HP without lowering a stat
|
||||
BattleScript_StrengthSapTryHp:
|
||||
jumpiffullhp BS_ATTACKER, BattleScript_ButItFailed
|
||||
attackanimation
|
||||
waitanimation
|
||||
BattleScript_StrengthSapHp:
|
||||
jumpifability BS_TARGET, ABILITY_LIQUID_OOZE, BattleScript_StrengthSapManipulateDmg
|
||||
jumpifstatus3 BS_ATTACKER, STATUS3_HEAL_BLOCK, BattleScript_MoveEnd
|
||||
@ -1345,8 +1338,6 @@ BattleScript_EffectPartingShotTrySpAtk:
|
||||
BattleScript_EffectPartingShotSwitch:
|
||||
moveendall
|
||||
goto BattleScript_MoveSwitch
|
||||
BattleScript_PartingShotEnd:
|
||||
end
|
||||
|
||||
BattleScript_EffectPowder::
|
||||
attackcanceler
|
||||
@ -1549,7 +1540,6 @@ BattleScript_RototillerLoop:
|
||||
jumpifstat BS_TARGET, CMP_EQUAL, STAT_SPATK, MAX_STAT_STAGE, BattleScript_RototillerCantRaiseMultipleStats
|
||||
BattleScript_RototillerCheckAffected:
|
||||
jumpifnotrototilleraffected BS_TARGET, BattleScript_RototillerNoEffect
|
||||
BattleScript_RototillerAffected:
|
||||
setbyte sSTAT_ANIM_PLAYED, FALSE
|
||||
playstatchangeanimation BS_TARGET, BIT_ATK | BIT_SPATK, 0
|
||||
setstatchanger STAT_ATK, 1, FALSE
|
||||
@ -1780,7 +1770,6 @@ BattleScript_EffectAutotomize::
|
||||
BattleScript_AutotomizeAttackAnim::
|
||||
attackanimation
|
||||
waitanimation
|
||||
BattleScript_AutotomizeDoAnim::
|
||||
setgraphicalstatchangevalues
|
||||
playanimation BS_ATTACKER, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1
|
||||
BattleScript_AutotomizePrintString::
|
||||
@ -2691,7 +2680,6 @@ BattleScript_TryTailwindAbilitiesLoop_Iter:
|
||||
BattleScript_TryTailwindAbilitiesLoop_Increment:
|
||||
addbyte gBattlerTarget, 0x1
|
||||
jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_TryTailwindAbilitiesLoop_Iter
|
||||
BattleScript_TryTailwindAbilitiesLoop_Ret:
|
||||
restoretarget
|
||||
return
|
||||
|
||||
@ -2792,7 +2780,6 @@ BattleScript_EffectPlaceholder::
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_EffectHit::
|
||||
BattleScript_HitFromAtkCanceler::
|
||||
attackcanceler
|
||||
BattleScript_HitFromAccCheck::
|
||||
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
|
||||
@ -3285,14 +3272,6 @@ BattleScript_RoarBlockedByDynamax:
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_EffectMultiHit::
|
||||
attackcanceler
|
||||
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
|
||||
attackstring
|
||||
ppreduce
|
||||
setmultihitcounter 0
|
||||
initmultihitstring
|
||||
sethword sMULTIHIT_EFFECT, 0
|
||||
BattleScript_MultiHitLoop::
|
||||
jumpifhasnohp BS_ATTACKER, BattleScript_MultiHitEnd
|
||||
jumpifhasnohp BS_TARGET, BattleScript_MultiHitPrintStrings
|
||||
@ -3705,7 +3684,6 @@ BattleScript_EffectParalyze::
|
||||
jumpifshieldsdown BS_TARGET, BattleScript_AbilityProtectsDoesntAffect
|
||||
jumpifsubstituteblocks BattleScript_ButItFailed
|
||||
typecalc
|
||||
BattleScript_BattleScript_EffectParalyzeNoTypeCalc:
|
||||
jumpifmovehadnoeffect BattleScript_ButItFailed
|
||||
jumpifstatus BS_TARGET, STATUS1_PARALYSIS, BattleScript_AlreadyParalyzed
|
||||
jumpifelectricabilityaffected BS_TARGET, ABILITY_VOLT_ABSORB, BattleScript_VoltAbsorbHeal
|
||||
@ -4632,7 +4610,6 @@ BattleScript_EffectTeleport::
|
||||
.else
|
||||
jumpifbattletype BATTLE_TYPE_TRAINER, BattleScript_FailedFromAtkCanceler
|
||||
.endif
|
||||
BattleScript_EffectTeleportTryToRunAway:
|
||||
attackcanceler
|
||||
attackstring
|
||||
ppreduce
|
||||
@ -6501,7 +6478,6 @@ BattleScript_WindPowerActivates::
|
||||
setcharge BS_TARGET
|
||||
printstring STRINGID_BEINGHITCHARGEDPKMNWITHPOWER
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
BattleScript_WindPowerActivates_Ret:
|
||||
return
|
||||
|
||||
BattleScript_ToxicDebrisActivates::
|
||||
@ -7203,7 +7179,6 @@ BattleScript_CottonDownTargetSpeedCantGoLower:
|
||||
BattleScript_CottonDownLoopIncrement:
|
||||
addbyte gBattlerTarget, 1
|
||||
jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_CottonDownLoop
|
||||
BattleScript_CottonDownReturn:
|
||||
swapattackerwithtarget
|
||||
copybyte gBattlerAttacker, sSAVED_BATTLER
|
||||
return
|
||||
@ -7822,7 +7797,6 @@ BattleScript_ActivateWeatherAbilities:
|
||||
BattleScript_ActivateWeatherAbilities_Loop:
|
||||
copybyte sBATTLER, gBattlerTarget
|
||||
activateweatherchangeabilities BS_TARGET
|
||||
BattleScript_ActivateWeatherAbilities_Increment:
|
||||
addbyte gBattlerTarget, 1
|
||||
jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_ActivateWeatherAbilities_Loop
|
||||
restoretarget
|
||||
@ -7881,7 +7855,6 @@ BattleScript_IntimidateEffect_WaitString:
|
||||
BattleScript_IntimidateLoopIncrement:
|
||||
addbyte gBattlerTarget, 1
|
||||
jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_IntimidateLoop
|
||||
BattleScript_IntimidateEnd:
|
||||
copybyte sBATTLER, gBattlerAttacker
|
||||
destroyabilitypopup
|
||||
restoretarget
|
||||
@ -7947,7 +7920,6 @@ BattleScript_SupersweetSyrupEffect_WaitString:
|
||||
BattleScript_SupersweetSyrupLoopIncrement:
|
||||
addbyte gBattlerTarget, 1
|
||||
jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_SupersweetSyrupLoop
|
||||
BattleScript_SupersweetSyrupEnd:
|
||||
copybyte sBATTLER, gBattlerAttacker
|
||||
destroyabilitypopup
|
||||
restoretarget
|
||||
@ -8106,7 +8078,6 @@ BattleScript_ActivateTerrainSeed:
|
||||
removeitem BS_TARGET
|
||||
BattleScript_ActivateTerrainAbility:
|
||||
activateterrainchangeabilities BS_TARGET
|
||||
BattleScript_ActivateTerrainEffects_Increment:
|
||||
addbyte gBattlerTarget, 0x1
|
||||
jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_ActivateTerrainSeed
|
||||
restoretarget
|
||||
@ -8362,14 +8333,12 @@ BattleScript_GrassyTerrainLoop:
|
||||
checkgrassyterrainheal BS_ATTACKER, BattleScript_GrassyTerrainLoopIncrement
|
||||
printstring STRINGID_GRASSYTERRAINHEALS
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
BattleScript_GrassyTerrainHpChange:
|
||||
orword gHitMarker, HITMARKER_IGNORE_BIDE | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE
|
||||
healthbarupdate BS_ATTACKER
|
||||
datahpupdate BS_ATTACKER
|
||||
BattleScript_GrassyTerrainLoopIncrement::
|
||||
addbyte gBattleCommunication, 1
|
||||
jumpifbytenotequal gBattleCommunication, gBattlersCount, BattleScript_GrassyTerrainLoop
|
||||
BattleScript_GrassyTerrainLoopEnd::
|
||||
bicword gHitMarker, HITMARKER_IGNORE_BIDE | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE
|
||||
jumpifword CMP_COMMON_BITS, gFieldStatuses, STATUS_FIELD_TERRAIN_PERMANENT, BattleScript_GrassyTerrainHealEnd
|
||||
BattleScript_GrassyTerrainHealEnd:
|
||||
@ -8378,7 +8347,6 @@ BattleScript_GrassyTerrainHealEnd:
|
||||
BattleScript_AbilityNoSpecificStatLoss::
|
||||
pause B_WAIT_TIME_SHORT
|
||||
call BattleScript_AbilityPopUp
|
||||
BattleScript_AbilityNoSpecificStatLossPrint:
|
||||
printstring STRINGID_PKMNSXPREVENTSYLOSS
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
setbyte cMULTISTRING_CHOOSER, B_MSG_STAT_FELL_EMPTY
|
||||
@ -9165,16 +9133,6 @@ BattleScript_ArenaTurnBeginning::
|
||||
volumeup
|
||||
end2
|
||||
|
||||
@ Unused
|
||||
BattleScript_ArenaNothingDecided::
|
||||
playse SE_DING_DONG
|
||||
arenadrawreftextbox
|
||||
arenajudgmentstring B_MSG_REF_NOTHING_IS_DECIDED
|
||||
arenawaitmessage B_MSG_REF_NOTHING_IS_DECIDED
|
||||
pause B_WAIT_TIME_LONG
|
||||
arenaerasereftextbox
|
||||
end2
|
||||
|
||||
BattleScript_ArenaDoJudgment::
|
||||
makevisible BS_PLAYER1
|
||||
waitstate
|
||||
@ -9274,7 +9232,6 @@ BattleScript_TotemFlaredToLife::
|
||||
call BattleScript_ApplyTotemVarBoost
|
||||
end2
|
||||
|
||||
@ remove the mirror herb, do totem loop
|
||||
BattleScript_MirrorHerbCopyStatChangeEnd2::
|
||||
call BattleScript_MirrorHerbCopyStatChange
|
||||
end2
|
||||
@ -9284,16 +9241,24 @@ BattleScript_MirrorHerbCopyStatChange::
|
||||
printstring STRINGID_MIRRORHERBCOPIED
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
removeitem BS_SCRIPTING
|
||||
call BattleScript_TotemVar_Ret
|
||||
copybyte gBattlerAttacker, sSAVED_BATTLER @ restore the original attacker just to be safe
|
||||
playanimation BS_SCRIPTING, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1
|
||||
BattleScript_MirrorHerbStartCopyStats:
|
||||
copyfoesstatincrease BS_SCRIPTING, BattleScript_MirrorHerbStartReturn
|
||||
statbuffchange STAT_CHANGE_ALLOW_PTR, BattleScript_MirrorHerbStartReturn
|
||||
goto BattleScript_MirrorHerbStartCopyStats
|
||||
BattleScript_MirrorHerbStartReturn:
|
||||
return
|
||||
|
||||
BattleScript_OpportunistCopyStatChange::
|
||||
call BattleScript_AbilityPopUp
|
||||
printstring STRINGID_OPPORTUNISTCOPIED
|
||||
call BattleScript_AbilityPopUpScripting
|
||||
playanimation BS_SCRIPTING, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1
|
||||
BattleScript_OpportunistStartCopyStats:
|
||||
copyfoesstatincrease BS_SCRIPTING, BattleScript_OpportunistCopyStatChangeEnd
|
||||
statbuffchange STAT_CHANGE_ALLOW_PTR, BattleScript_OpportunistCopyStatChangeEnd
|
||||
printfromtable gStatUpStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
call BattleScript_TotemVar_Ret
|
||||
copybyte gBattlerAttacker, sSAVED_BATTLER @ restore the original attacker just to be safe
|
||||
goto BattleScript_OpportunistStartCopyStats
|
||||
BattleScript_OpportunistCopyStatChangeEnd:
|
||||
end3
|
||||
|
||||
BattleScript_TotemVar::
|
||||
@ -9467,7 +9432,6 @@ BattleScript_EffectExtremeEvoboost::
|
||||
BattleScript_ExtremeEvoboostAnim:
|
||||
attackanimation
|
||||
waitanimation
|
||||
BattleScript_ExtremeEvoboostAtk::
|
||||
setbyte sSTAT_ANIM_PLAYED, FALSE
|
||||
playstatchangeanimation BS_ATTACKER, BIT_ATK | BIT_DEF | BIT_SPEED | BIT_SPATK | BIT_SPDEF, 0x0
|
||||
setstatchanger STAT_ATK, 2, FALSE
|
||||
@ -10025,7 +9989,6 @@ BattleScript_CouldntFullyProtect::
|
||||
return
|
||||
|
||||
BattleScript_BerserkGeneRet::
|
||||
BattleScript_BerserkGeneRet_Anim:
|
||||
savetarget
|
||||
copybyte gBattlerTarget, sBATTLER
|
||||
statbuffchange STAT_CHANGE_ALLOW_PTR, BattleScript_BerserkGeneRet_TryConfuse
|
||||
|
||||
@ -159,7 +159,6 @@ BattleScript_SafariBallThrow::
|
||||
BattleScript_SuccessBallThrow::
|
||||
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
|
||||
|
||||
@ -632,7 +632,7 @@ struct BattleStruct
|
||||
u8 moneyMultiplierItem:1;
|
||||
u8 moneyMultiplierMove:1;
|
||||
u8 savedTurnActionNumber;
|
||||
u8 switchInAbilitiesCounter;
|
||||
u8 eventsBeforeFirstTurnState;
|
||||
u8 faintedActionsState;
|
||||
u8 faintedActionsBattlerId;
|
||||
u8 scriptPartyIdx; // for printing the nickname
|
||||
@ -676,7 +676,7 @@ struct BattleStruct
|
||||
u16 chosenItem[MAX_BATTLERS_COUNT];
|
||||
u16 choicedMove[MAX_BATTLERS_COUNT];
|
||||
u16 changedItems[MAX_BATTLERS_COUNT];
|
||||
u8 switchInItemsCounter;
|
||||
u8 switchInBattlerCounter;
|
||||
u8 arenaTurnCounter;
|
||||
u8 turnSideTracker;
|
||||
u16 lastTakenMoveFrom[MAX_BATTLERS_COUNT][MAX_BATTLERS_COUNT]; // a 2-D array [target][attacker]
|
||||
|
||||
@ -23,6 +23,20 @@ struct MultiPartnerMenuPokemon
|
||||
#define BOUNCE_MON 0x0
|
||||
#define BOUNCE_HEALTHBOX 0x1
|
||||
|
||||
enum {
|
||||
FIRST_TURN_EVENTS_START,
|
||||
FIRST_TURN_EVENTS_OVERWORLD_WEATHER,
|
||||
FIRST_TURN_EVENTS_TERRAIN,
|
||||
FIRST_TURN_EVENTS_STARTING_STATUS,
|
||||
FIRST_TURN_EVENTS_TOTEM_BOOST,
|
||||
FIRST_TURN_EVENTS_NEUTRALIZING_GAS,
|
||||
FIRST_TURN_EVENTS_SWITCH_IN_ABILITIES,
|
||||
FIRST_TURN_EVENTS_OPPORTUNIST_1,
|
||||
FIRST_TURN_EVENTS_ITEM_EFFECTS,
|
||||
FIRST_TURN_EVENTS_OPPORTUNIST_2,
|
||||
FIRST_TURN_EVENTS_END,
|
||||
};
|
||||
|
||||
void CB2_InitBattle(void);
|
||||
void BattleMainCB2(void);
|
||||
void CB2_QuitRecordedBattle(void);
|
||||
|
||||
@ -670,51 +670,50 @@
|
||||
#define STRINGID_CURRENTMOVECANTSELECT 668
|
||||
#define STRINGID_TARGETISBEINGSALTCURED 669
|
||||
#define STRINGID_TARGETISHURTBYSALTCURE 670
|
||||
#define STRINGID_OPPORTUNISTCOPIED 671
|
||||
#define STRINGID_TARGETCOVEREDINSTICKYCANDYSYRUP 672
|
||||
#define STRINGID_SHARPSTEELFLOATS 673
|
||||
#define STRINGID_SHARPSTEELDMG 674
|
||||
#define STRINGID_PKMNBLEWAWAYSHARPSTEEL 675
|
||||
#define STRINGID_SHARPSTEELDISAPPEAREDFROMTEAM 676
|
||||
#define STRINGID_TEAMTRAPPEDWITHVINES 677
|
||||
#define STRINGID_PKMNHURTBYVINES 678
|
||||
#define STRINGID_TEAMCAUGHTINVORTEX 679
|
||||
#define STRINGID_PKMNHURTBYVORTEX 680
|
||||
#define STRINGID_TEAMSURROUNDEDBYFIRE 681
|
||||
#define STRINGID_PKMNBURNINGUP 682
|
||||
#define STRINGID_TEAMSURROUNDEDBYROCKS 683
|
||||
#define STRINGID_PKMNHURTBYROCKSTHROWN 684
|
||||
#define STRINGID_MOVEBLOCKEDBYDYNAMAX 685
|
||||
#define STRINGID_ZEROTOHEROTRANSFORMATION 686
|
||||
#define STRINGID_THETWOMOVESBECOMEONE 687
|
||||
#define STRINGID_ARAINBOWAPPEAREDONSIDE 688
|
||||
#define STRINGID_THERAINBOWDISAPPEARED 689
|
||||
#define STRINGID_WAITINGFORPARTNERSMOVE 690
|
||||
#define STRINGID_SEAOFFIREENVELOPEDSIDE 691
|
||||
#define STRINGID_HURTBYTHESEAOFFIRE 692
|
||||
#define STRINGID_THESEAOFFIREDISAPPEARED 693
|
||||
#define STRINGID_SWAMPENVELOPEDSIDE 694
|
||||
#define STRINGID_THESWAMPDISAPPEARED 695
|
||||
#define STRINGID_PKMNTELLCHILLINGRECEPTIONJOKE 696
|
||||
#define STRINGID_HOSPITALITYRESTORATION 697
|
||||
#define STRINGID_ELECTROSHOTCHARGING 698
|
||||
#define STRINGID_ITEMWASUSEDUP 699
|
||||
#define STRINGID_ATTACKERLOSTITSTYPE 700
|
||||
#define STRINGID_SHEDITSTAIL 701
|
||||
#define STRINGID_CLOAKEDINAHARSHLIGHT 702
|
||||
#define STRINGID_SUPERSWEETAROMAWAFTS 703
|
||||
#define STRINGID_DIMENSIONSWERETWISTED 704
|
||||
#define STRINGID_BIZARREARENACREATED 705
|
||||
#define STRINGID_BIZARREAREACREATED 706
|
||||
#define STRINGID_TIDYINGUPCOMPLETE 707
|
||||
#define STRINGID_PKMNTERASTALLIZEDINTO 708
|
||||
#define STRINGID_BOOSTERENERGYACTIVATES 709
|
||||
#define STRINGID_FOGCREPTUP 710
|
||||
#define STRINGID_FOGISDEEP 711
|
||||
#define STRINGID_FOGLIFTED 712
|
||||
#define STRINGID_PKMNMADESHELLGLEAM 713
|
||||
#define STRINGID_TARGETCOVEREDINSTICKYCANDYSYRUP 671
|
||||
#define STRINGID_SHARPSTEELFLOATS 672
|
||||
#define STRINGID_SHARPSTEELDMG 673
|
||||
#define STRINGID_PKMNBLEWAWAYSHARPSTEEL 674
|
||||
#define STRINGID_SHARPSTEELDISAPPEAREDFROMTEAM 675
|
||||
#define STRINGID_TEAMTRAPPEDWITHVINES 676
|
||||
#define STRINGID_PKMNHURTBYVINES 677
|
||||
#define STRINGID_TEAMCAUGHTINVORTEX 678
|
||||
#define STRINGID_PKMNHURTBYVORTEX 679
|
||||
#define STRINGID_TEAMSURROUNDEDBYFIRE 680
|
||||
#define STRINGID_PKMNBURNINGUP 681
|
||||
#define STRINGID_TEAMSURROUNDEDBYROCKS 682
|
||||
#define STRINGID_PKMNHURTBYROCKSTHROWN 683
|
||||
#define STRINGID_MOVEBLOCKEDBYDYNAMAX 684
|
||||
#define STRINGID_ZEROTOHEROTRANSFORMATION 685
|
||||
#define STRINGID_THETWOMOVESBECOMEONE 686
|
||||
#define STRINGID_ARAINBOWAPPEAREDONSIDE 687
|
||||
#define STRINGID_THERAINBOWDISAPPEARED 688
|
||||
#define STRINGID_WAITINGFORPARTNERSMOVE 689
|
||||
#define STRINGID_SEAOFFIREENVELOPEDSIDE 690
|
||||
#define STRINGID_HURTBYTHESEAOFFIRE 691
|
||||
#define STRINGID_THESEAOFFIREDISAPPEARED 692
|
||||
#define STRINGID_SWAMPENVELOPEDSIDE 693
|
||||
#define STRINGID_THESWAMPDISAPPEARED 694
|
||||
#define STRINGID_PKMNTELLCHILLINGRECEPTIONJOKE 695
|
||||
#define STRINGID_HOSPITALITYRESTORATION 696
|
||||
#define STRINGID_ELECTROSHOTCHARGING 697
|
||||
#define STRINGID_ITEMWASUSEDUP 698
|
||||
#define STRINGID_ATTACKERLOSTITSTYPE 699
|
||||
#define STRINGID_SHEDITSTAIL 700
|
||||
#define STRINGID_CLOAKEDINAHARSHLIGHT 701
|
||||
#define STRINGID_SUPERSWEETAROMAWAFTS 702
|
||||
#define STRINGID_DIMENSIONSWERETWISTED 703
|
||||
#define STRINGID_BIZARREARENACREATED 704
|
||||
#define STRINGID_BIZARREAREACREATED 705
|
||||
#define STRINGID_TIDYINGUPCOMPLETE 706
|
||||
#define STRINGID_PKMNTERASTALLIZEDINTO 707
|
||||
#define STRINGID_BOOSTERENERGYACTIVATES 708
|
||||
#define STRINGID_FOGCREPTUP 709
|
||||
#define STRINGID_FOGISDEEP 710
|
||||
#define STRINGID_FOGLIFTED 711
|
||||
#define STRINGID_PKMNMADESHELLGLEAM 712
|
||||
|
||||
#define BATTLESTRINGS_COUNT 714
|
||||
#define BATTLESTRINGS_COUNT 713
|
||||
|
||||
// This is the string id that gBattleStringsTable starts with.
|
||||
// String ids before this (e.g. STRINGID_INTROMSG) are not in the table,
|
||||
|
||||
@ -995,6 +995,8 @@ void SendOut(u32 sourceLine, struct BattlePokemon *, u32 partyIndex);
|
||||
// Static const is needed to make the modern compiler put the pattern variable in the .rodata section, instead of putting it on stack(which can break the game).
|
||||
#define MESSAGE(pattern) do {static const u8 msg[] = _(pattern); QueueMessage(__LINE__, msg);} while (0)
|
||||
#define STATUS_ICON(battler, status) QueueStatus(__LINE__, battler, (struct StatusEventContext) { status })
|
||||
#define FREEZE_OR_FROSTBURN_STATUS(battler, isFrostbite) \
|
||||
(B_USE_FROSTBITE ? STATUS_ICON(battler, frostbite: isFrostbite) : STATUS_ICON(battler, freeze: isFrostbite))
|
||||
|
||||
#define SWITCH_OUT_MESSAGE(name) ONE_OF { \
|
||||
MESSAGE(name ", that's enough! Come back!"); \
|
||||
|
||||
@ -1997,12 +1997,12 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId,
|
||||
else if (typeMatchupId != PARTY_SIZE) return typeMatchupId;
|
||||
else if (defensiveMonId != PARTY_SIZE) return defensiveMonId;
|
||||
else if (batonPassId != PARTY_SIZE) return batonPassId;
|
||||
|
||||
// If ace mon is the last available Pokemon and U-Turn/Volt Switch was used - switch to the mon.
|
||||
else if (aceMonId != PARTY_SIZE
|
||||
&& (gMovesInfo[gLastUsedMove].effect == EFFECT_HIT_ESCAPE || gMovesInfo[gLastUsedMove].effect == EFFECT_PARTING_SHOT || gMovesInfo[gLastUsedMove].effect == EFFECT_BATON_PASS))
|
||||
return aceMonId;
|
||||
}
|
||||
// If ace mon is the last available Pokemon and U-Turn/Volt Switch was used - switch to the mon.
|
||||
if (aceMonId != PARTY_SIZE
|
||||
&& (gMovesInfo[gLastUsedMove].effect == EFFECT_HIT_ESCAPE || gMovesInfo[gLastUsedMove].effect == EFFECT_PARTING_SHOT || gMovesInfo[gLastUsedMove].effect == EFFECT_BATON_PASS))
|
||||
return aceMonId;
|
||||
|
||||
return PARTY_SIZE;
|
||||
}
|
||||
|
||||
|
||||
@ -3733,8 +3733,8 @@ static void DoBattleIntro(void)
|
||||
}
|
||||
}
|
||||
|
||||
gBattleStruct->switchInAbilitiesCounter = 0;
|
||||
gBattleStruct->switchInItemsCounter = 0;
|
||||
gBattleStruct->eventsBeforeFirstTurnState = 0;
|
||||
gBattleStruct->switchInBattlerCounter = 0;
|
||||
gBattleStruct->overworldWeatherDone = FALSE;
|
||||
SetAiLogicDataForTurn(AI_DATA); // get assumed abilities, hold effects, etc of all battlers
|
||||
Ai_InitPartyStruct(); // Save mons party counts, and first 2/4 mons on the battlefield.
|
||||
@ -3769,34 +3769,35 @@ static void TryDoEventsBeforeFirstTurn(void)
|
||||
if (gBattleControllerExecFlags)
|
||||
return;
|
||||
|
||||
// Set invalid mons as absent(for example when starting a double battle with only one pokemon).
|
||||
if (!(gBattleTypeFlags & BATTLE_TYPE_SAFARI))
|
||||
switch (gBattleStruct->eventsBeforeFirstTurnState)
|
||||
{
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
case FIRST_TURN_EVENTS_START:
|
||||
// Set invalid mons as absent(for example when starting a double battle with only one pokemon).
|
||||
if (!(gBattleTypeFlags & BATTLE_TYPE_SAFARI))
|
||||
{
|
||||
struct Pokemon *party = GetBattlerParty(i);
|
||||
struct Pokemon *mon = &party[gBattlerPartyIndexes[i]];
|
||||
if (!IsBattlerAlive(i) || gBattleMons[i].species == SPECIES_NONE || GetMonData(mon, MON_DATA_IS_EGG))
|
||||
gAbsentBattlerFlags |= gBitTable[i];
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
struct Pokemon *party = GetBattlerParty(i);
|
||||
struct Pokemon *mon = &party[gBattlerPartyIndexes[i]];
|
||||
if (!IsBattlerAlive(i) || gBattleMons[i].species == SPECIES_NONE || GetMonData(mon, MON_DATA_IS_EGG))
|
||||
gAbsentBattlerFlags |= gBitTable[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Allow for illegal abilities within tests.
|
||||
#if TESTING
|
||||
if (gTestRunnerEnabled && gBattleStruct->switchInAbilitiesCounter == 0)
|
||||
{
|
||||
for (i = 0; i < gBattlersCount; ++i)
|
||||
// Allow for illegal abilities within tests.
|
||||
#if TESTING
|
||||
if (gTestRunnerEnabled)
|
||||
{
|
||||
u32 side = GetBattlerSide(i);
|
||||
u32 partyIndex = gBattlerPartyIndexes[i];
|
||||
if (TestRunner_Battle_GetForcedAbility(side, partyIndex))
|
||||
gBattleMons[i].ability = gBattleStruct->overwrittenAbilities[i] = TestRunner_Battle_GetForcedAbility(side, partyIndex);
|
||||
for (i = 0; i < gBattlersCount; ++i)
|
||||
{
|
||||
u32 side = GetBattlerSide(i);
|
||||
u32 partyIndex = gBattlerPartyIndexes[i];
|
||||
if (TestRunner_Battle_GetForcedAbility(side, partyIndex))
|
||||
gBattleMons[i].ability = gBattleStruct->overwrittenAbilities[i] = TestRunner_Battle_GetForcedAbility(side, partyIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // TESTING
|
||||
#endif // TESTING
|
||||
|
||||
if (gBattleStruct->switchInAbilitiesCounter == 0)
|
||||
{
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
gBattlerByTurnOrder[i] = i;
|
||||
for (i = 0; i < gBattlersCount - 1; i++)
|
||||
@ -3807,110 +3808,136 @@ static void TryDoEventsBeforeFirstTurn(void)
|
||||
SwapTurnOrder(i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!gBattleStruct->overworldWeatherDone
|
||||
&& AbilityBattleEffects(ABILITYEFFECT_SWITCH_IN_WEATHER, 0, 0, ABILITYEFFECT_SWITCH_IN_WEATHER, 0) != 0)
|
||||
{
|
||||
gBattleStruct->overworldWeatherDone = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gBattleStruct->terrainDone && AbilityBattleEffects(ABILITYEFFECT_SWITCH_IN_TERRAIN, 0, 0, ABILITYEFFECT_SWITCH_IN_TERRAIN, 0) != 0)
|
||||
{
|
||||
gBattleStruct->terrainDone = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gBattleStruct->startingStatusDone
|
||||
&& gBattleStruct->startingStatus
|
||||
&& AbilityBattleEffects(ABILITYEFFECT_SWITCH_IN_STATUSES, 0, 0, ABILITYEFFECT_SWITCH_IN_STATUSES, 0) != 0)
|
||||
{
|
||||
gBattleStruct->startingStatusDone = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
// Totem boosts
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
if (gQueuedStatBoosts[i].stats != 0 && !gProtectStructs[i].eatMirrorHerb && gProtectStructs[i].activateOpportunist == 0)
|
||||
gBattleStruct->eventsBeforeFirstTurnState++;
|
||||
break;
|
||||
case FIRST_TURN_EVENTS_OVERWORLD_WEATHER:
|
||||
if (!gBattleStruct->overworldWeatherDone
|
||||
&& AbilityBattleEffects(ABILITYEFFECT_SWITCH_IN_WEATHER, 0, 0, ABILITYEFFECT_SWITCH_IN_WEATHER, 0) != 0)
|
||||
{
|
||||
gBattlerAttacker = i;
|
||||
BattleScriptExecute(BattleScript_TotemVar);
|
||||
gBattleStruct->overworldWeatherDone = TRUE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check neutralizing gas
|
||||
if (AbilityBattleEffects(ABILITYEFFECT_NEUTRALIZINGGAS, 0, 0, 0, 0) != 0)
|
||||
return;
|
||||
|
||||
// Check all switch in abilities happening from the fastest mon to slowest.
|
||||
while (gBattleStruct->switchInAbilitiesCounter < gBattlersCount)
|
||||
{
|
||||
gBattlerAttacker = gBattlerByTurnOrder[gBattleStruct->switchInAbilitiesCounter++];
|
||||
|
||||
if (TryPrimalReversion(gBattlerAttacker))
|
||||
gBattleStruct->eventsBeforeFirstTurnState++;
|
||||
break;
|
||||
case FIRST_TURN_EVENTS_TERRAIN:
|
||||
if (!gBattleStruct->terrainDone
|
||||
&& AbilityBattleEffects(ABILITYEFFECT_SWITCH_IN_TERRAIN, 0, 0, ABILITYEFFECT_SWITCH_IN_TERRAIN, 0) != 0)
|
||||
{
|
||||
gBattleStruct->terrainDone = TRUE;
|
||||
return;
|
||||
if (AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, gBattlerAttacker, 0, 0, 0) != 0)
|
||||
}
|
||||
gBattleStruct->eventsBeforeFirstTurnState++;
|
||||
break;
|
||||
case FIRST_TURN_EVENTS_STARTING_STATUS:
|
||||
if (!gBattleStruct->startingStatusDone
|
||||
&& gBattleStruct->startingStatus
|
||||
&& AbilityBattleEffects(ABILITYEFFECT_SWITCH_IN_STATUSES, 0, 0, ABILITYEFFECT_SWITCH_IN_STATUSES, 0) != 0)
|
||||
{
|
||||
gBattleStruct->startingStatusDone = TRUE;
|
||||
return;
|
||||
}
|
||||
// Check all switch in items having effect from the fastest mon to slowest.
|
||||
while (gBattleStruct->switchInItemsCounter < gBattlersCount)
|
||||
{
|
||||
if (ItemBattleEffects(ITEMEFFECT_ON_SWITCH_IN, gBattlerByTurnOrder[gBattleStruct->switchInItemsCounter++], FALSE))
|
||||
}
|
||||
gBattleStruct->eventsBeforeFirstTurnState++;
|
||||
break;
|
||||
case FIRST_TURN_EVENTS_TOTEM_BOOST:
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
if (gQueuedStatBoosts[i].stats != 0 && !gProtectStructs[i].eatMirrorHerb && gProtectStructs[i].activateOpportunist == 0)
|
||||
{
|
||||
gBattlerAttacker = i;
|
||||
BattleScriptExecute(BattleScript_TotemVar);
|
||||
return;
|
||||
}
|
||||
}
|
||||
memset(gQueuedStatBoosts, 0, sizeof(gQueuedStatBoosts)); // erase all totem boosts for Mirror Herb and Opportunist
|
||||
gBattleStruct->eventsBeforeFirstTurnState++;
|
||||
break;
|
||||
case FIRST_TURN_EVENTS_NEUTRALIZING_GAS:
|
||||
if (AbilityBattleEffects(ABILITYEFFECT_NEUTRALIZINGGAS, 0, 0, 0, 0) != 0)
|
||||
return;
|
||||
gBattleStruct->eventsBeforeFirstTurnState++;
|
||||
break;
|
||||
case FIRST_TURN_EVENTS_SWITCH_IN_ABILITIES:
|
||||
while (gBattleStruct->switchInBattlerCounter < gBattlersCount) // From fastest to slowest
|
||||
{
|
||||
gBattlerAttacker = gBattlerByTurnOrder[gBattleStruct->switchInBattlerCounter++];
|
||||
|
||||
if (TryPrimalReversion(gBattlerAttacker))
|
||||
return;
|
||||
if (AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, gBattlerAttacker, 0, 0, 0) != 0)
|
||||
return;
|
||||
}
|
||||
gBattleStruct->switchInBattlerCounter = 0;
|
||||
gBattleStruct->eventsBeforeFirstTurnState++;
|
||||
break;
|
||||
case FIRST_TURN_EVENTS_OPPORTUNIST_1:
|
||||
if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, 0, 0, 0, 0))
|
||||
return;
|
||||
gBattleStruct->eventsBeforeFirstTurnState++;
|
||||
break;
|
||||
case FIRST_TURN_EVENTS_ITEM_EFFECTS:
|
||||
while (gBattleStruct->switchInBattlerCounter < gBattlersCount) // From fastest to slowest
|
||||
{
|
||||
if (ItemBattleEffects(ITEMEFFECT_ON_SWITCH_IN, gBattlerByTurnOrder[gBattleStruct->switchInBattlerCounter++], FALSE))
|
||||
return;
|
||||
}
|
||||
gBattleStruct->switchInBattlerCounter = 0;
|
||||
gBattleStruct->eventsBeforeFirstTurnState++;
|
||||
break;
|
||||
case FIRST_TURN_EVENTS_OPPORTUNIST_2:
|
||||
if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, 0, 0, 0, 0))
|
||||
return;
|
||||
gBattleStruct->eventsBeforeFirstTurnState++;
|
||||
break;
|
||||
case FIRST_TURN_EVENTS_END:
|
||||
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
|
||||
{
|
||||
*(gBattleStruct->monToSwitchIntoId + i) = PARTY_SIZE;
|
||||
gChosenActionByBattler[i] = B_ACTION_NONE;
|
||||
gChosenMoveByBattler[i] = MOVE_NONE;
|
||||
}
|
||||
TurnValuesCleanUp(FALSE);
|
||||
SpecialStatusesClear();
|
||||
*(&gBattleStruct->absentBattlerFlags) = gAbsentBattlerFlags;
|
||||
BattlePutTextOnWindow(gText_EmptyString3, B_WIN_MSG);
|
||||
AssignUsableGimmicks();
|
||||
gBattleMainFunc = HandleTurnActionSelectionState;
|
||||
ResetSentPokesToOpponentValue();
|
||||
|
||||
for (i = 0; i < BATTLE_COMMUNICATION_ENTRIES_COUNT; i++)
|
||||
gBattleCommunication[i] = 0;
|
||||
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
gBattleMons[i].status2 &= ~STATUS2_FLINCHED;
|
||||
// Record party slots of player's mons that appeared in battle
|
||||
if (!BattlerHasAi(i))
|
||||
gBattleStruct->appearedInBattle |= gBitTable[gBattlerPartyIndexes[i]];
|
||||
}
|
||||
|
||||
*(&gBattleStruct->turnEffectsTracker) = 0;
|
||||
*(&gBattleStruct->turnEffectsBattlerId) = 0;
|
||||
*(&gBattleStruct->wishPerishSongState) = 0;
|
||||
*(&gBattleStruct->wishPerishSongBattlerId) = 0;
|
||||
gBattleScripting.moveendState = 0;
|
||||
gBattleStruct->faintedActionsState = 0;
|
||||
gBattleStruct->turnCountersTracker = 0;
|
||||
gMoveResultFlags = 0;
|
||||
|
||||
memset(gQueuedStatBoosts, 0, sizeof(gQueuedStatBoosts));
|
||||
SetShellSideArmCategory();
|
||||
SetAiLogicDataForTurn(AI_DATA); // get assumed abilities, hold effects, etc of all battlers
|
||||
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_ARENA)
|
||||
{
|
||||
StopCryAndClearCrySongs();
|
||||
BattleScriptExecute(BattleScript_ArenaTurnBeginning);
|
||||
}
|
||||
|
||||
if ((i = ShouldDoTrainerSlide(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), TRAINER_SLIDE_BEFORE_FIRST_TURN)))
|
||||
BattleScriptExecute(i == 1 ? BattleScript_TrainerASlideMsgEnd2 : BattleScript_TrainerBSlideMsgEnd2);
|
||||
gBattleStruct->eventsBeforeFirstTurnState = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, 0, 0, 0, 0))
|
||||
return;
|
||||
|
||||
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
|
||||
{
|
||||
*(gBattleStruct->monToSwitchIntoId + i) = PARTY_SIZE;
|
||||
gChosenActionByBattler[i] = B_ACTION_NONE;
|
||||
gChosenMoveByBattler[i] = MOVE_NONE;
|
||||
}
|
||||
TurnValuesCleanUp(FALSE);
|
||||
SpecialStatusesClear();
|
||||
*(&gBattleStruct->absentBattlerFlags) = gAbsentBattlerFlags;
|
||||
BattlePutTextOnWindow(gText_EmptyString3, B_WIN_MSG);
|
||||
AssignUsableGimmicks();
|
||||
gBattleMainFunc = HandleTurnActionSelectionState;
|
||||
ResetSentPokesToOpponentValue();
|
||||
|
||||
for (i = 0; i < BATTLE_COMMUNICATION_ENTRIES_COUNT; i++)
|
||||
gBattleCommunication[i] = 0;
|
||||
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
gBattleMons[i].status2 &= ~STATUS2_FLINCHED;
|
||||
// Record party slots of player's mons that appeared in battle
|
||||
if (!BattlerHasAi(i))
|
||||
gBattleStruct->appearedInBattle |= gBitTable[gBattlerPartyIndexes[i]];
|
||||
}
|
||||
|
||||
*(&gBattleStruct->turnEffectsTracker) = 0;
|
||||
*(&gBattleStruct->turnEffectsBattlerId) = 0;
|
||||
*(&gBattleStruct->wishPerishSongState) = 0;
|
||||
*(&gBattleStruct->wishPerishSongBattlerId) = 0;
|
||||
gBattleScripting.moveendState = 0;
|
||||
gBattleStruct->faintedActionsState = 0;
|
||||
gBattleStruct->turnCountersTracker = 0;
|
||||
gMoveResultFlags = 0;
|
||||
|
||||
memset(gQueuedStatBoosts, 0, sizeof(gQueuedStatBoosts)); // erase all totem boosts just to be safe
|
||||
|
||||
SetShellSideArmCategory();
|
||||
SetAiLogicDataForTurn(AI_DATA); // get assumed abilities, hold effects, etc of all battlers
|
||||
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_ARENA)
|
||||
{
|
||||
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)
|
||||
|
||||
@ -829,7 +829,6 @@ static const u8 sText_TeamGainedEXP[] = _("The rest of your team gained EXP.\nPo
|
||||
static const u8 sText_CurrentMoveCantSelect[] = _("{B_BUFF1} cannot be used!\p");
|
||||
static const u8 sText_TargetIsBeingSaltCured[] = _("{B_DEF_NAME_WITH_PREFIX} is being salt cured!");
|
||||
static const u8 sText_TargetIsHurtBySaltCure[] = _("{B_DEF_NAME_WITH_PREFIX} is hurt by {B_BUFF1}!");
|
||||
static const u8 sText_OpportunistCopied[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} copied its\nopponent's stat changes!");
|
||||
static const u8 sText_TargetCoveredInStickyCandySyrup[] = _("{B_DEF_NAME_WITH_PREFIX} got covered\nin sticky syrup!");
|
||||
static const u8 sText_PkmnTellChillingReceptionJoke[] = _("{B_ATK_NAME_WITH_PREFIX} is preparing to tell a\nchillingly bad joke!");
|
||||
static const u8 sText_ZeroToHeroTransformation[] = _("{B_ATK_NAME_WITH_PREFIX} underwent a heroic\ntransformation!");
|
||||
@ -871,7 +870,6 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
|
||||
[STRINGID_ZEROTOHEROTRANSFORMATION - BATTLESTRINGS_TABLE_START] = sText_ZeroToHeroTransformation,
|
||||
[STRINGID_PKMNTELLCHILLINGRECEPTIONJOKE - BATTLESTRINGS_TABLE_START] = sText_PkmnTellChillingReceptionJoke,
|
||||
[STRINGID_MOVEBLOCKEDBYDYNAMAX - BATTLESTRINGS_TABLE_START] = sText_MoveBlockedByDynamax,
|
||||
[STRINGID_OPPORTUNISTCOPIED - BATTLESTRINGS_TABLE_START] = sText_OpportunistCopied,
|
||||
[STRINGID_TARGETISHURTBYSALTCURE - BATTLESTRINGS_TABLE_START] = sText_TargetIsHurtBySaltCure,
|
||||
[STRINGID_TARGETISBEINGSALTCURED - BATTLESTRINGS_TABLE_START] = sText_TargetIsBeingSaltCured,
|
||||
[STRINGID_CURRENTMOVECANTSELECT - BATTLESTRINGS_TABLE_START] = sText_CurrentMoveCantSelect,
|
||||
|
||||
@ -6405,6 +6405,7 @@ static void Cmd_moveend(void)
|
||||
if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE)
|
||||
SetActiveGimmick(gBattlerAttacker, GIMMICK_NONE);
|
||||
gBattleStruct->distortedTypeMatchups = 0;
|
||||
memset(gQueuedStatBoosts, 0, sizeof(gQueuedStatBoosts));
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
case MOVEEND_COUNT:
|
||||
@ -9981,7 +9982,7 @@ static void Cmd_various(void)
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = 3;
|
||||
else if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP) && CanBeSlept(gBattlerTarget, targetAbility))
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = 4;
|
||||
else if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_FROSTBITE) && CanBeFrozen(gBattlerTarget))
|
||||
else if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_FROSTBITE) && CanGetFrostbite(gBattlerTarget))
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = 5;
|
||||
else
|
||||
{
|
||||
@ -11829,27 +11830,35 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 statIncrease;
|
||||
if ((statValue + gBattleMons[battler].statStages[statId]) > MAX_STAT_STAGE)
|
||||
statIncrease = MAX_STAT_STAGE - gBattleMons[battler].statStages[statId];
|
||||
else
|
||||
statIncrease = statValue;
|
||||
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = (gBattlerTarget == battler);
|
||||
gProtectStructs[battler].statRaised = TRUE;
|
||||
|
||||
// check mirror herb
|
||||
// Check Mirror Herb / Opportunist
|
||||
for (index = 0; index < gBattlersCount; index++)
|
||||
{
|
||||
if (GetBattlerSide(index) == GetBattlerSide(battler))
|
||||
continue; // Only triggers on opposing side
|
||||
|
||||
if (GetBattlerAbility(index) == ABILITY_OPPORTUNIST
|
||||
&& gProtectStructs[battler].activateOpportunist == 0) // don't activate opportunist on other mon's opportunist raises
|
||||
&& gProtectStructs[battler].activateOpportunist == 0) // don't activate opportunist on other mon's opportunist raises
|
||||
{
|
||||
gProtectStructs[index].activateOpportunist = 2; // set stats to copy
|
||||
gQueuedStatBoosts[index].stats |= (1 << (statId - 1)); // -1 to start at atk
|
||||
gQueuedStatBoosts[index].statChanges[statId - 1] += statValue; // cumulative in case of multiple opponent boosts
|
||||
}
|
||||
else if (GetBattlerHoldEffect(index, TRUE) == HOLD_EFFECT_MIRROR_HERB
|
||||
&& gBattleMons[index].statStages[statId] < MAX_STAT_STAGE)
|
||||
if (GetBattlerHoldEffect(index, TRUE) == HOLD_EFFECT_MIRROR_HERB)
|
||||
{
|
||||
gProtectStructs[index].eatMirrorHerb = 1;
|
||||
}
|
||||
|
||||
if (gProtectStructs[index].activateOpportunist == 2 || gProtectStructs[index].eatMirrorHerb == 1)
|
||||
{
|
||||
gQueuedStatBoosts[index].stats |= (1 << (statId - 1)); // -1 to start at atk
|
||||
gQueuedStatBoosts[index].statChanges[statId - 1] = statValue;
|
||||
gQueuedStatBoosts[index].statChanges[statId - 1] += statIncrease;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -17056,6 +17065,41 @@ void BS_TryQuash(void)
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
void BS_CopyFoesStatIncrease(void)
|
||||
{
|
||||
NATIVE_ARGS(u8 battler, const u8 *jumpInstr);
|
||||
u32 stat = 0;
|
||||
u32 battler = GetBattlerForBattleScript(cmd->battler);
|
||||
|
||||
if (gQueuedStatBoosts[battler].stats == 0)
|
||||
{
|
||||
for (stat = 0; stat < (NUM_BATTLE_STATS - 1); stat++)
|
||||
{
|
||||
if (gQueuedStatBoosts[battler].statChanges[stat] != 0)
|
||||
gQueuedStatBoosts[battler].stats |= (1 << stat);
|
||||
}
|
||||
gBattlescriptCurrInstr = cmd->jumpInstr;
|
||||
return;
|
||||
}
|
||||
|
||||
for (stat = 0; stat < (NUM_BATTLE_STATS - 1); stat++)
|
||||
{
|
||||
if (gQueuedStatBoosts[battler].stats & (1 << stat))
|
||||
{
|
||||
if (gQueuedStatBoosts[battler].statChanges[stat] <= -1)
|
||||
SET_STATCHANGER(stat + 1, abs(gQueuedStatBoosts[battler].statChanges[stat]), TRUE);
|
||||
else
|
||||
SET_STATCHANGER(stat + 1, gQueuedStatBoosts[battler].statChanges[stat], FALSE);
|
||||
|
||||
gQueuedStatBoosts[battler].stats &= ~(1 << stat);
|
||||
gBattlerTarget = battler;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
return;
|
||||
}
|
||||
}
|
||||
gBattlescriptCurrInstr = cmd->jumpInstr;
|
||||
}
|
||||
|
||||
void BS_RemoveWeather(void)
|
||||
{
|
||||
NATIVE_ARGS();
|
||||
|
||||
@ -6025,9 +6025,40 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
case ABILITY_OPPORTUNIST:
|
||||
if (gProtectStructs[battler].activateOpportunist == 2)
|
||||
{
|
||||
gBattleScripting.savedBattler = gBattlerAttacker;
|
||||
gBattleScripting.battler = gBattlerAttacker = gBattlerAbility = battler;
|
||||
bool32 statBuffMoreThan1 = FALSE;
|
||||
bool32 handleSpeedAnimLater = FALSE;
|
||||
gBattleScripting.animArg1 = 0;
|
||||
gBattleScripting.battler = battler;
|
||||
gProtectStructs[battler].activateOpportunist--;
|
||||
|
||||
for (i = 0; i < (NUM_BATTLE_STATS - 1); i++)
|
||||
{
|
||||
if ((gQueuedStatBoosts[battler].stats & (1 << i)) == 0)
|
||||
continue;
|
||||
|
||||
if (i == STAT_SPEED)
|
||||
{
|
||||
handleSpeedAnimLater = TRUE;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!statBuffMoreThan1)
|
||||
statBuffMoreThan1 = ((gQueuedStatBoosts[battler].stats & (1 << i)) > 1);
|
||||
|
||||
if (gBattleScripting.animArg1 != 0) //Already set in a different stat so now boosting multiple stats
|
||||
gBattleScripting.animArg1 = (!statBuffMoreThan1 ? STAT_ANIM_MULTIPLE_PLUS1 : STAT_ANIM_MULTIPLE_PLUS2);
|
||||
else
|
||||
gBattleScripting.animArg1 = GET_STAT_BUFF_ID((i + 1)) + (!statBuffMoreThan1 ? STAT_ANIM_PLUS1 : STAT_ANIM_PLUS2);
|
||||
|
||||
}
|
||||
if (handleSpeedAnimLater)
|
||||
{
|
||||
if (gBattleScripting.animArg1 != 0) //Already set in a different stat so now boosting multiple stats
|
||||
gBattleScripting.animArg1 = (!statBuffMoreThan1 ? STAT_ANIM_MULTIPLE_PLUS1 : STAT_ANIM_MULTIPLE_PLUS2);
|
||||
else
|
||||
gBattleScripting.animArg1 = GET_STAT_BUFF_ID((STAT_SPEED + 1)) + (!statBuffMoreThan1 ? STAT_ANIM_PLUS1 : STAT_ANIM_PLUS2);
|
||||
}
|
||||
|
||||
BattleScriptPushCursorAndCallback(BattleScript_OpportunistCopyStatChange);
|
||||
effect = 1;
|
||||
}
|
||||
@ -6966,10 +6997,43 @@ static u8 TryConsumeMirrorHerb(u32 battler, bool32 execute)
|
||||
|
||||
if (gProtectStructs[battler].eatMirrorHerb)
|
||||
{
|
||||
u32 i;
|
||||
bool32 statBuffMoreThan1 = FALSE;
|
||||
bool32 handleSpeedAnimLater = FALSE;
|
||||
gBattleScripting.animArg1 = 0;
|
||||
|
||||
gLastUsedItem = gBattleMons[battler].item;
|
||||
gBattleScripting.savedBattler = gBattlerAttacker;
|
||||
gBattleScripting.battler = gBattlerAttacker = battler;
|
||||
gBattleScripting.battler = battler;
|
||||
gProtectStructs[battler].eatMirrorHerb = 0;
|
||||
|
||||
for (i = 0; i < (NUM_BATTLE_STATS - 1); i++)
|
||||
{
|
||||
if ((gQueuedStatBoosts[battler].stats & (1 << i)) == 0)
|
||||
continue;
|
||||
|
||||
if (i == STAT_SPEED)
|
||||
{
|
||||
handleSpeedAnimLater = TRUE;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!statBuffMoreThan1)
|
||||
statBuffMoreThan1 = ((gQueuedStatBoosts[battler].stats & (1 << i)) > 1);
|
||||
|
||||
if (gBattleScripting.animArg1 != 0) //Already set in a different stat so now boosting multiple stats
|
||||
gBattleScripting.animArg1 = (!statBuffMoreThan1 ? STAT_ANIM_MULTIPLE_PLUS1 : STAT_ANIM_MULTIPLE_PLUS2);
|
||||
else
|
||||
gBattleScripting.animArg1 = GET_STAT_BUFF_ID((i + 1)) + (!statBuffMoreThan1 ? STAT_ANIM_PLUS1 : STAT_ANIM_PLUS2);
|
||||
|
||||
}
|
||||
if (handleSpeedAnimLater)
|
||||
{
|
||||
if (gBattleScripting.animArg1 != 0) //Already set in a different stat so now boosting multiple stats
|
||||
gBattleScripting.animArg1 = (!statBuffMoreThan1 ? STAT_ANIM_MULTIPLE_PLUS1 : STAT_ANIM_MULTIPLE_PLUS2);
|
||||
else
|
||||
gBattleScripting.animArg1 = GET_STAT_BUFF_ID((STAT_SPEED + 1)) + (!statBuffMoreThan1 ? STAT_ANIM_PLUS1 : STAT_ANIM_PLUS2);
|
||||
}
|
||||
|
||||
if (execute)
|
||||
{
|
||||
BattleScriptExecute(BattleScript_MirrorHerbCopyStatChangeEnd2);
|
||||
@ -7496,6 +7560,9 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn)
|
||||
BattleScriptPushCursorAndCallback(BattleScript_BerserkGeneRet);
|
||||
effect = ITEM_STATS_CHANGE;
|
||||
break;
|
||||
case HOLD_EFFECT_MIRROR_HERB:
|
||||
effect = TryConsumeMirrorHerb(battler, TRUE);
|
||||
break;
|
||||
case HOLD_EFFECT_BOOSTER_ENERGY:
|
||||
if (!(gBattleStruct->boosterEnergyActivates & gBitTable[battler])
|
||||
&& (((GetBattlerAbility(battler) == ABILITY_PROTOSYNTHESIS) && !(gBattleWeather & B_WEATHER_SUN))
|
||||
|
||||
@ -16,16 +16,16 @@ SINGLE_BATTLE_TEST("Opportunist only copies foe's positive stat changes in a tur
|
||||
OPPONENT(SPECIES_ESPATHRA) { Speed(5); Ability(ability); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SHELL_SMASH); }
|
||||
TURN { MOVE(player, MOVE_TACKLE); MOVE(opponent, MOVE_TACKLE); }
|
||||
TURN { MOVE(opponent, MOVE_TACKLE); }
|
||||
} SCENE {
|
||||
if (ability == ABILITY_FRISK) {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SHELL_SMASH, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent);
|
||||
HP_BAR(player, captureDamage: &results[i].damage);
|
||||
} else {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SHELL_SMASH, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent);
|
||||
HP_BAR(player, captureDamage: &results[i].damage);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player);
|
||||
}
|
||||
} FINALLY {
|
||||
EXPECT_MUL_EQ(results[0].damage, Q_4_12(2.0), results[1].damage);
|
||||
@ -78,12 +78,10 @@ DOUBLE_BATTLE_TEST("Opportunist raises Attack only once when partner has Intimid
|
||||
if ((abilityLeft == ABILITY_CONTRARY && abilityRight != ABILITY_CONTRARY)
|
||||
|| (abilityLeft != ABILITY_CONTRARY && abilityRight == ABILITY_CONTRARY)) {
|
||||
ABILITY_POPUP(playerRight, ABILITY_OPPORTUNIST);
|
||||
MESSAGE("Espathra copied its opponent's stat changes!");
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight);
|
||||
MESSAGE("Espathra's Attack rose!");
|
||||
} else if (abilityLeft == ABILITY_CONTRARY && abilityRight == ABILITY_CONTRARY) {
|
||||
ABILITY_POPUP(playerRight, ABILITY_OPPORTUNIST);
|
||||
MESSAGE("Espathra copied its opponent's stat changes!");
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight);
|
||||
MESSAGE("Espathra's Attack sharply rose!");
|
||||
}
|
||||
@ -124,6 +122,177 @@ SINGLE_BATTLE_TEST("Opportunist does not accumulate opposing mon's stat changes"
|
||||
}
|
||||
}
|
||||
|
||||
TO_DO_BATTLE_TEST("Opportunist doesn't copy ally stat increases");
|
||||
TO_DO_BATTLE_TEST("Opportunist doesn't copy foe stat increases gained via Opportunist");
|
||||
TO_DO_BATTLE_TEST("Opportunist copies foe stat increased gained via Swagger and Flatter");
|
||||
SINGLE_BATTLE_TEST("Opportunist copies each stat increase individually from ability and move")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_ZACIAN) { Ability(ABILITY_INTREPID_SWORD); }
|
||||
OPPONENT(SPECIES_ESPATHRA) { Ability(ABILITY_OPPORTUNIST); }
|
||||
} WHEN {
|
||||
TURN { SWITCH(player, 1); }
|
||||
TURN { MOVE(player, MOVE_SWORDS_DANCE); }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(player, ABILITY_INTREPID_SWORD);
|
||||
ABILITY_POPUP(opponent, ABILITY_OPPORTUNIST);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, player);
|
||||
ABILITY_POPUP(opponent, ABILITY_OPPORTUNIST);
|
||||
} THEN {
|
||||
EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 3);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Opportunist doesn't copy foe stat increases gained via Opportunist")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_ESPATHRA) { Ability(ABILITY_OPPORTUNIST); }
|
||||
OPPONENT(SPECIES_ESPATHRA) { Ability(ABILITY_OPPORTUNIST); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SWORDS_DANCE); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, player);
|
||||
ABILITY_POPUP(opponent, ABILITY_OPPORTUNIST);
|
||||
NOT ABILITY_POPUP(player, ABILITY_OPPORTUNIST);
|
||||
} THEN {
|
||||
EXPECT_EQ(opponent->statStages[STAT_ATK], player->statStages[STAT_ATK]);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Opportunist copies foe stat increase gained via Swagger and Flatter")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_ESPATHRA) { Ability(ABILITY_OPPORTUNIST); }
|
||||
OPPONENT(SPECIES_ESPATHRA) { Ability(ABILITY_OPPORTUNIST); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_FLATTER); }
|
||||
TURN { MOVE(opponent, MOVE_SWAGGER); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_FLATTER, opponent);
|
||||
ABILITY_POPUP(opponent, ABILITY_OPPORTUNIST);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SWAGGER, opponent);
|
||||
ABILITY_POPUP(opponent, ABILITY_OPPORTUNIST);
|
||||
} THEN {
|
||||
EXPECT_EQ(opponent->statStages[STAT_SPATK], DEFAULT_STAT_STAGE + 1);
|
||||
EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 2);
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Opportunist doesn't copy ally stat increases")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_ESPATHRA) { Ability(ABILITY_OPPORTUNIST); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(playerLeft, MOVE_SWORDS_DANCE); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, playerLeft);
|
||||
NOT ABILITY_POPUP(playerRight, ABILITY_OPPORTUNIST);
|
||||
} THEN {
|
||||
EXPECT_EQ(playerRight->statStages[STAT_SPATK], DEFAULT_STAT_STAGE );
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Opportunist copies the stat increase of each opposing mon")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_ESPATHRA) { Ability(ABILITY_OPPORTUNIST); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponentRight, MOVE_SWORDS_DANCE); MOVE(opponentLeft, MOVE_SWORDS_DANCE); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, opponentRight);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, opponentLeft);
|
||||
ABILITY_POPUP(playerRight, ABILITY_OPPORTUNIST);
|
||||
} THEN {
|
||||
EXPECT_EQ(playerRight->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 4);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DOUBLE_BATTLE_TEST("Opportunist copies the stat of each pokemon that were raised at the same time")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_ESPATHRA) { Ability(ABILITY_OPPORTUNIST); }
|
||||
OPPONENT(SPECIES_ZACIAN) { Ability(ABILITY_INTREPID_SWORD); }
|
||||
OPPONENT(SPECIES_ZACIAN) { Ability(ABILITY_INTREPID_SWORD); }
|
||||
} WHEN {
|
||||
TURN { }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(opponentLeft, ABILITY_INTREPID_SWORD);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft);
|
||||
ABILITY_POPUP(opponentRight, ABILITY_INTREPID_SWORD);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight);
|
||||
ABILITY_POPUP(playerRight, ABILITY_OPPORTUNIST);
|
||||
MESSAGE("Espathra's Attack sharply rose!");
|
||||
} THEN {
|
||||
EXPECT_EQ(playerRight->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 2);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Opportunist copies the increase not the stages")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_ESPATHRA) { Ability(ABILITY_OPPORTUNIST); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_CHARM); MOVE(opponent, MOVE_CHARM); }
|
||||
TURN { MOVE(player, MOVE_CHARM); MOVE(opponent, MOVE_CHARM); }
|
||||
TURN { MOVE(player, MOVE_CHARM); MOVE(opponent, MOVE_GROWL); }
|
||||
TURN { MOVE(player, MOVE_BELLY_DRUM); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CHARM, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CHARM, opponent);
|
||||
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CHARM, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CHARM, opponent);
|
||||
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CHARM, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_GROWL, opponent);
|
||||
|
||||
ABILITY_POPUP(opponent, ABILITY_OPPORTUNIST);
|
||||
} THEN {
|
||||
EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 5); // + 11
|
||||
EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 6); // + 11
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Opportunist copies the stat increase from the incoming mon")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_ESPATHRA) { Ability(ABILITY_OPPORTUNIST); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { HP(1); }
|
||||
OPPONENT(SPECIES_ZACIAN) { Ability(ABILITY_INTREPID_SWORD); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_TACKLE); SEND_OUT(opponent, 1); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player);
|
||||
ABILITY_POPUP(opponent, ABILITY_INTREPID_SWORD);
|
||||
ABILITY_POPUP(player, ABILITY_OPPORTUNIST);
|
||||
} THEN {
|
||||
EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 1);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Opportunist and Mirror Herb stack stat increases")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_ZACIAN) { Ability(ABILITY_INTREPID_SWORD); }
|
||||
OPPONENT(SPECIES_ESPATHRA) { Ability(ABILITY_OPPORTUNIST); Item(ITEM_MIRROR_HERB); }
|
||||
} WHEN {
|
||||
TURN { }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(player, ABILITY_INTREPID_SWORD);
|
||||
ABILITY_POPUP(opponent, ABILITY_OPPORTUNIST);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent);
|
||||
} THEN {
|
||||
EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 2);
|
||||
EXPECT_EQ(opponent->statStages[STAT_DEF], DEFAULT_STAT_STAGE);
|
||||
EXPECT_EQ(opponent->statStages[STAT_SPEED], DEFAULT_STAT_STAGE);
|
||||
EXPECT_EQ(opponent->statStages[STAT_SPATK], DEFAULT_STAT_STAGE);
|
||||
EXPECT_EQ(opponent->statStages[STAT_SPDEF], DEFAULT_STAT_STAGE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,6 +67,19 @@ AI_DOUBLE_BATTLE_TEST("AI will not try to switch for the same pokemon for 2 spot
|
||||
}
|
||||
}
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: U-Turn will send out Ace Mon if it's the only one remaining")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gMovesInfo[MOVE_U_TURN].effect == EFFECT_HIT_ESCAPE);
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_ACE_POKEMON);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_U_TURN); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { EXPECT_MOVE(opponent, MOVE_U_TURN); EXPECT_SEND_OUT(opponent, 1); }
|
||||
}
|
||||
}
|
||||
|
||||
// General AI_FLAG_SMART_MON_CHOICES behaviour
|
||||
AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: Number of hits to KO calculation checks whether incoming damage is less than recurring healing to avoid an infinite loop")
|
||||
{
|
||||
|
||||
@ -24,7 +24,7 @@ SINGLE_BATTLE_TEST("Shaymin-Sky reverts to Shaymin-Land when frozen or frostbitt
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, move, opponent);
|
||||
if (move == MOVE_POWDER_SNOW) {
|
||||
STATUS_ICON(player, freeze: TRUE);
|
||||
FREEZE_OR_FROSTBURN_STATUS(player, TRUE);
|
||||
NOT HP_BAR(player); // Regression caused by Mimikyu form change
|
||||
MESSAGE("Shaymin transformed!");
|
||||
} else {
|
||||
|
||||
@ -72,7 +72,7 @@ SINGLE_BATTLE_TEST("Rawst and Lum Berries cure burn")
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Aspear and Lum Berries cure freeze")
|
||||
SINGLE_BATTLE_TEST("Aspear and Lum Berries cure freeze or frostbite")
|
||||
{
|
||||
u16 item;
|
||||
|
||||
@ -88,9 +88,9 @@ SINGLE_BATTLE_TEST("Aspear and Lum Berries cure freeze")
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ICE_PUNCH, player);
|
||||
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_FRZ, opponent);
|
||||
STATUS_ICON(opponent, freeze: TRUE);
|
||||
FREEZE_OR_FROSTBURN_STATUS(opponent, TRUE);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent);
|
||||
STATUS_ICON(opponent, freeze: FALSE);
|
||||
FREEZE_OR_FROSTBURN_STATUS(opponent, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -73,3 +73,18 @@ DOUBLE_BATTLE_TEST("Mirror Herb does not trigger for Ally's Soul Heart's stat ra
|
||||
EXPECT_EQ(playerLeft->statStages[STAT_SPATK], DEFAULT_STAT_STAGE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Mirror Herb copies the boost gained by an ability")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_ZACIAN) { Ability(ABILITY_INTREPID_SWORD); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_MIRROR_HERB); }
|
||||
} WHEN {
|
||||
TURN { }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(player, ABILITY_INTREPID_SWORD);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent);
|
||||
} THEN {
|
||||
EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,7 +7,11 @@ ASSUMPTIONS
|
||||
ASSUME(gMovesInfo[MOVE_BLIZZARD].accuracy == 70);
|
||||
}
|
||||
|
||||
#if B_USE_FROSTBITE == TRUE
|
||||
SINGLE_BATTLE_TEST("Powder Snow inflicts frostbite")
|
||||
#else
|
||||
SINGLE_BATTLE_TEST("Powder Snow inflicts freeze")
|
||||
#endif
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
@ -18,11 +22,15 @@ SINGLE_BATTLE_TEST("Powder Snow inflicts freeze")
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_POWDER_SNOW, player);
|
||||
HP_BAR(opponent);
|
||||
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_FRZ, opponent);
|
||||
STATUS_ICON(opponent, freeze: TRUE);
|
||||
FREEZE_OR_FROSTBURN_STATUS(opponent, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
#if B_USE_FROSTBITE == TRUE
|
||||
SINGLE_BATTLE_TEST("Powder Snow cannot frostbite an Ice-type Pokémon")
|
||||
#else
|
||||
SINGLE_BATTLE_TEST("Powder Snow cannot freeze an Ice-type Pokémon")
|
||||
#endif
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gSpeciesInfo[SPECIES_SNORUNT].types[0] == TYPE_ICE);
|
||||
@ -35,7 +43,7 @@ SINGLE_BATTLE_TEST("Powder Snow cannot freeze an Ice-type Pokémon")
|
||||
HP_BAR(opponent);
|
||||
NONE_OF {
|
||||
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_FRZ, opponent);
|
||||
STATUS_ICON(opponent, freeze: TRUE);
|
||||
FREEZE_OR_FROSTBURN_STATUS(opponent, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -68,10 +76,18 @@ SINGLE_BATTLE_TEST("Blizzard bypasses accuracy checks in Hail and Snow")
|
||||
}
|
||||
|
||||
#if B_STATUS_TYPE_IMMUNITY > GEN_1
|
||||
#if B_USE_FROSTBITE == TRUE
|
||||
SINGLE_BATTLE_TEST("Freezing Glare should frostbite Psychic-types")
|
||||
#else
|
||||
SINGLE_BATTLE_TEST("Freezing Glare should freeze Psychic-types")
|
||||
#endif
|
||||
#else
|
||||
#if B_USE_FROSTBITE == TRUE
|
||||
SINGLE_BATTLE_TEST("Freezing Glare shouldn't freeze Psychic-types")
|
||||
#else
|
||||
SINGLE_BATTLE_TEST("Freezing Glare shouldn't freeze Psychic-types")
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gSpeciesInfo[SPECIES_ARTICUNO_GALARIAN].types[0] == TYPE_PSYCHIC);
|
||||
@ -86,11 +102,11 @@ SINGLE_BATTLE_TEST("Freezing Glare shouldn't freeze Psychic-types")
|
||||
HP_BAR(opponent);
|
||||
#if B_STATUS_TYPE_IMMUNITY > GEN_1
|
||||
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_FRZ, opponent);
|
||||
STATUS_ICON(opponent, freeze: TRUE);
|
||||
FREEZE_OR_FROSTBURN_STATUS(opponent, TRUE);
|
||||
#else
|
||||
NONE_OF {
|
||||
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_FRZ, opponent);
|
||||
STATUS_ICON(opponent, freeze: TRUE);
|
||||
FREEZE_OR_FROSTBURN_STATUS(opponent, TRUE);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -6,7 +6,11 @@ ASSUMPTIONS
|
||||
ASSUME(MoveHasAdditionalEffect(MOVE_TRI_ATTACK, MOVE_EFFECT_TRI_ATTACK) == TRUE);
|
||||
}
|
||||
|
||||
#if B_USE_FROSTBITE == TRUE
|
||||
SINGLE_BATTLE_TEST("Tri Attack can inflict paralysis, burn or frostbite")
|
||||
#else
|
||||
SINGLE_BATTLE_TEST("Tri Attack can inflict paralysis, burn or freeze")
|
||||
#endif
|
||||
{
|
||||
u8 statusAnim;
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; }
|
||||
@ -26,14 +30,18 @@ SINGLE_BATTLE_TEST("Tri Attack can inflict paralysis, burn or freeze")
|
||||
if (statusAnim == B_ANIM_STATUS_BRN) {
|
||||
STATUS_ICON(opponent, burn: TRUE);
|
||||
} else if (statusAnim == B_ANIM_STATUS_FRZ) {
|
||||
STATUS_ICON(opponent, freeze: TRUE);
|
||||
FREEZE_OR_FROSTBURN_STATUS(opponent, TRUE);
|
||||
} else if (statusAnim == B_ANIM_STATUS_PRZ) {
|
||||
STATUS_ICON(opponent, paralysis: TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if B_USE_FROSTBITE == TRUE
|
||||
SINGLE_BATTLE_TEST("Tri Attack cannot paralyze/burn/frostbite electric/fire/ice types respectively")
|
||||
#else
|
||||
SINGLE_BATTLE_TEST("Tri Attack cannot paralyze/burn/freeze electric/fire/ice types respectively")
|
||||
#endif
|
||||
{
|
||||
u8 statusAnim;
|
||||
u16 species;
|
||||
@ -42,7 +50,7 @@ SINGLE_BATTLE_TEST("Tri Attack cannot paralyze/burn/freeze electric/fire/ice typ
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = MOVE_EFFECT_PARALYSIS; species = SPECIES_RAICHU; }
|
||||
#endif // B_PARALYZE_ELECTRIC
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_BRN; rng = MOVE_EFFECT_BURN; species = SPECIES_ARCANINE; }
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_FRZ; rng = MOVE_EFFECT_FREEZE; species = SPECIES_GLALIE; }
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_FRZ; rng = MOVE_EFFECT_FREEZE_OR_FROSTBITE; species = SPECIES_GLALIE; }
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(species);
|
||||
@ -57,7 +65,7 @@ SINGLE_BATTLE_TEST("Tri Attack cannot paralyze/burn/freeze electric/fire/ice typ
|
||||
if (statusAnim == B_ANIM_STATUS_BRN) {
|
||||
STATUS_ICON(opponent, burn: TRUE);
|
||||
} else if (statusAnim == B_ANIM_STATUS_FRZ) {
|
||||
STATUS_ICON(opponent, freeze: TRUE);
|
||||
FREEZE_OR_FROSTBURN_STATUS(opponent, TRUE);
|
||||
} else if (statusAnim == B_ANIM_STATUS_PRZ) {
|
||||
STATUS_ICON(opponent, paralysis: TRUE);
|
||||
}
|
||||
@ -65,7 +73,11 @@ SINGLE_BATTLE_TEST("Tri Attack cannot paralyze/burn/freeze electric/fire/ice typ
|
||||
}
|
||||
}
|
||||
|
||||
#if B_USE_FROSTBITE == TRUE
|
||||
SINGLE_BATTLE_TEST("Tri Attack cannot paralyze/burn/frostbite pokemon with abilities preventing respective statuses")
|
||||
#else
|
||||
SINGLE_BATTLE_TEST("Tri Attack cannot paralyze/burn/freeze pokemon with abilities preventing respective statuses")
|
||||
#endif
|
||||
{
|
||||
u8 statusAnim;
|
||||
u16 species, ability;
|
||||
@ -75,8 +87,8 @@ SINGLE_BATTLE_TEST("Tri Attack cannot paralyze/burn/freeze pokemon with abilitie
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_BRN; rng = MOVE_EFFECT_BURN; species = SPECIES_DEWPIDER; ability = ABILITY_WATER_BUBBLE; }
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_BRN; rng = MOVE_EFFECT_BURN; species = SPECIES_SEAKING; ability = ABILITY_WATER_VEIL; }
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_BRN; rng = MOVE_EFFECT_BURN; species = SPECIES_KOMALA; ability = ABILITY_COMATOSE; }
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_FRZ; rng = MOVE_EFFECT_FREEZE; species = SPECIES_CAMERUPT; ability = ABILITY_MAGMA_ARMOR; }
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_FRZ; rng = MOVE_EFFECT_FREEZE; species = SPECIES_KOMALA; ability = ABILITY_COMATOSE; }
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_FRZ; rng = MOVE_EFFECT_FREEZE_OR_FROSTBITE; species = SPECIES_CAMERUPT; ability = ABILITY_MAGMA_ARMOR; }
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_FRZ; rng = MOVE_EFFECT_FREEZE_OR_FROSTBITE; species = SPECIES_KOMALA; ability = ABILITY_COMATOSE; }
|
||||
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
@ -92,7 +104,7 @@ SINGLE_BATTLE_TEST("Tri Attack cannot paralyze/burn/freeze pokemon with abilitie
|
||||
if (statusAnim == B_ANIM_STATUS_BRN) {
|
||||
STATUS_ICON(opponent, burn: TRUE);
|
||||
} else if (statusAnim == B_ANIM_STATUS_FRZ) {
|
||||
STATUS_ICON(opponent, freeze: TRUE);
|
||||
FREEZE_OR_FROSTBURN_STATUS(opponent, TRUE);
|
||||
} else if (statusAnim == B_ANIM_STATUS_PRZ) {
|
||||
STATUS_ICON(opponent, paralysis: TRUE);
|
||||
}
|
||||
@ -100,13 +112,17 @@ SINGLE_BATTLE_TEST("Tri Attack cannot paralyze/burn/freeze pokemon with abilitie
|
||||
}
|
||||
}
|
||||
|
||||
#if B_USE_FROSTBITE == TRUE
|
||||
SINGLE_BATTLE_TEST("Tri Attack cannot paralyze/burn/frostbite a mon which is already statused")
|
||||
#else
|
||||
SINGLE_BATTLE_TEST("Tri Attack cannot paralyze/burn/freeze a mon which is already statused")
|
||||
#endif
|
||||
{
|
||||
u8 statusAnim;
|
||||
u32 rng;
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = MOVE_EFFECT_PARALYSIS; }
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_BRN; rng = MOVE_EFFECT_BURN; }
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_FRZ; rng = MOVE_EFFECT_FREEZE; }
|
||||
PARAMETRIZE { statusAnim = B_ANIM_STATUS_FRZ; rng = MOVE_EFFECT_FREEZE_OR_FROSTBITE; }
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Status1(STATUS1_SLEEP); }
|
||||
@ -121,7 +137,7 @@ SINGLE_BATTLE_TEST("Tri Attack cannot paralyze/burn/freeze a mon which is alread
|
||||
if (statusAnim == B_ANIM_STATUS_BRN) {
|
||||
STATUS_ICON(opponent, burn: TRUE);
|
||||
} else if (statusAnim == B_ANIM_STATUS_FRZ) {
|
||||
STATUS_ICON(opponent, freeze: TRUE);
|
||||
FREEZE_OR_FROSTBURN_STATUS(opponent, TRUE);
|
||||
} else if (statusAnim == B_ANIM_STATUS_PRZ) {
|
||||
STATUS_ICON(opponent, paralysis: TRUE);
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ ASSUMPTIONS
|
||||
{
|
||||
ASSUME(MoveHasAdditionalEffect(MOVE_THUNDER_FANG, MOVE_EFFECT_PARALYSIS) == TRUE);
|
||||
ASSUME(MoveHasAdditionalEffect(MOVE_THUNDER_FANG, MOVE_EFFECT_FLINCH) == TRUE);
|
||||
ASSUME(MoveHasAdditionalEffect(MOVE_ICE_FANG, MOVE_EFFECT_FREEZE) == TRUE);
|
||||
ASSUME(MoveHasAdditionalEffect(MOVE_ICE_FANG, MOVE_EFFECT_FREEZE_OR_FROSTBITE) == TRUE);
|
||||
ASSUME(MoveHasAdditionalEffect(MOVE_ICE_FANG, MOVE_EFFECT_FLINCH) == TRUE);
|
||||
ASSUME(MoveHasAdditionalEffect(MOVE_FIRE_FANG, MOVE_EFFECT_BURN) == TRUE);
|
||||
ASSUME(MoveHasAdditionalEffect(MOVE_FIRE_FANG, MOVE_EFFECT_FLINCH) == TRUE);
|
||||
@ -33,7 +33,7 @@ SINGLE_BATTLE_TEST("Thunder, Ice and Fire Fang inflict status 10% of the time")
|
||||
STATUS_ICON(opponent, paralysis: TRUE);
|
||||
} if (move == MOVE_ICE_FANG) {
|
||||
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_FRZ, opponent);
|
||||
STATUS_ICON(opponent, freeze: TRUE);
|
||||
FREEZE_OR_FROSTBURN_STATUS(opponent, TRUE);
|
||||
} if (move == MOVE_FIRE_FANG) {
|
||||
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_BRN, opponent);
|
||||
STATUS_ICON(opponent, burn: TRUE);
|
||||
|
||||
@ -113,3 +113,50 @@ TEST("ModifyPersonalityForNature can set any nature")
|
||||
ModifyPersonalityForNature(&personality, nature);
|
||||
EXPECT_EQ(GetNatureFromPersonality(personality), nature);
|
||||
}
|
||||
|
||||
static const struct TrainerMon sTestParty2[] =
|
||||
{
|
||||
{
|
||||
.species = SPECIES_WYNAUT,
|
||||
.lvl = 5,
|
||||
},
|
||||
{
|
||||
.species = SPECIES_WYNAUT,
|
||||
.lvl = 5,
|
||||
},
|
||||
{
|
||||
.species = SPECIES_WYNAUT,
|
||||
.lvl = 5,
|
||||
},
|
||||
{
|
||||
.species = SPECIES_WYNAUT,
|
||||
.lvl = 5,
|
||||
},
|
||||
{
|
||||
.species = SPECIES_WYNAUT,
|
||||
.lvl = 5,
|
||||
},
|
||||
{
|
||||
.species = SPECIES_WYNAUT,
|
||||
.lvl = 5,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct Trainer sTestTrainer2 =
|
||||
{
|
||||
.trainerName = _("Test2"),
|
||||
.trainerClass = TRAINER_CLASS_BLACK_BELT,
|
||||
.party = TRAINER_PARTY(sTestParty2),
|
||||
};
|
||||
|
||||
TEST("Trainer Class Balls apply to the entire party")
|
||||
{
|
||||
u32 j;
|
||||
struct Pokemon *testParty = Alloc(6 * sizeof(struct Pokemon));
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, &sTestTrainer2, TRUE, BATTLE_TYPE_TRAINER);
|
||||
for(j = 0; j < 6; j++)
|
||||
{
|
||||
EXPECT(GetMonData(&testParty[j], MON_DATA_POKEBALL, 0) == gTrainerClasses[sTestTrainer2.trainerClass].ball);
|
||||
}
|
||||
Free(testParty);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user