diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index c381b50f1..930d20a01 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -3,6 +3,14 @@ ## Description +## Images + + + +## Issue(s) that this PR fixes + + + ## **Discord contact info** - - \ No newline at end of file + + \ No newline at end of file diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 3419e2e56..78fb91406 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -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 @@ -2263,3 +2287,8 @@ .macro hitswitchtargetfailed various 0, VARIOUS_HIT_SWITCH_TARGET_FAILED .endm + + .macro tryrevivalblessing, jumpInstr:req + various 0, VARIOUS_TRY_REVIVAL_BLESSING + .4byte \jumpInstr + .endm diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index cca8706cb..dcfdac88e 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -22317,7 +22317,7 @@ Move_TRANSFORM: monbg ANIM_ATTACKER playsewithpan SE_M_TELEPORT, SOUND_PAN_ATTACKER waitplaysewithpan SE_M_MINIMIZE, SOUND_PAN_ATTACKER, 48 - createvisualtask AnimTask_TransformMon, 2, 0, 0 + createvisualtask AnimTask_TransformMon, 2, 0, 0, 1 waitforvisualfinish clearmonbg ANIM_ATTACKER end @@ -24406,7 +24406,7 @@ WeatherFormChangeContinue: monbg ANIM_ATTACKER playsewithpan SE_M_TELEPORT, SOUND_PAN_ATTACKER waitplaysewithpan SE_M_MINIMIZE, SOUND_PAN_ATTACKER, 48 - createvisualtask AnimTask_TransformMon, 2, 1, 0 + createvisualtask AnimTask_TransformMon, 2, 1, 0, 0 waitforvisualfinish clearmonbg ANIM_ATTACKER end @@ -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 @@ -24824,14 +24829,14 @@ General_WishHeal: General_IllusionOff: monbg ANIM_TARGET - createvisualtask AnimTask_TransformMon, 2, 0, 1 + createvisualtask AnimTask_TransformMon, 2, 0, 1, 0 waitforvisualfinish clearmonbg ANIM_TARGET end General_FormChange: monbg ANIM_ATTACKER - createvisualtask AnimTask_TransformMon, 2, 0, 1 + createvisualtask AnimTask_TransformMon, 2, 0, 1, 0 waitforvisualfinish clearmonbg ANIM_ATTACKER end @@ -24860,7 +24865,7 @@ General_MegaEvolution: delay 20 createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 0, 16, RGB_WHITEALPHA waitforvisualfinish - createvisualtask AnimTask_TransformMon, 2, 0, 1 + createvisualtask AnimTask_TransformMon, 2, 0, 1, 0 createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 16, 0, RGB_WHITEALPHA createvisualtask AnimTask_HorizontalShake, 5, 1, 5, 14 waitforvisualfinish @@ -25006,7 +25011,7 @@ General_PrimalReversion_Alpha: delay 20 createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 0, 16, RGB_WHITEALPHA waitforvisualfinish - createvisualtask AnimTask_TransformMon, 2, 0, 1 + createvisualtask AnimTask_TransformMon, 2, 0, 1, 0 createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 16, 0, RGB_WHITEALPHA createvisualtask AnimTask_HorizontalShake, 5, 1, 5, 14 waitforvisualfinish @@ -25033,7 +25038,7 @@ General_PrimalReversion_Omega: delay 20 createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 0, 16, RGB_WHITEALPHA waitforvisualfinish - createvisualtask AnimTask_TransformMon, 2, 0, 1 + createvisualtask AnimTask_TransformMon, 2, 0, 1, 0 createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 16, 0, RGB_WHITEALPHA createvisualtask AnimTask_HorizontalShake, 5, 1, 5, 14 waitforvisualfinish diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index c8bd53735..bebdac8f7 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -286,7 +286,11 @@ gBattleScriptsForMoveEffects:: .4byte BattleScript_EffectHealPulse @ EFFECT_HEAL_PULSE .4byte BattleScript_EffectQuash @ EFFECT_QUASH .4byte BattleScript_EffectIonDeluge @ EFFECT_ION_DELUGE +#if B_USE_FROSTBITE == TRUE + .4byte BattleScript_EffectFrostbiteHit @ EFFECT_FREEZE_DRY +#else .4byte BattleScript_EffectFreezeHit @ EFFECT_FREEZE_DRY +#endif .4byte BattleScript_EffectTopsyTurvy @ EFFECT_TOPSY_TURVY .4byte BattleScript_EffectMistyTerrain @ EFFECT_MISTY_TERRAIN .4byte BattleScript_EffectGrassyTerrain @ EFFECT_GRASSY_TERRAIN @@ -423,6 +427,26 @@ gBattleScriptsForMoveEffects:: .4byte BattleScript_EffectHitSetEntryHazard @ EFFECT_HIT_SET_ENTRY_HAZARD .4byte BattleScript_EffectDireClaw @ EFFECT_DIRE_CLAW .4byte BattleScript_EffectBarbBarrage @ EFFECT_BARB_BARRAGE + .4byte BattleScript_EffectRevivalBlessing @ EFFECT_REVIVAL_BLESSING + .4byte BattleScript_EffectFrostbiteHit @ EFFECT_FROSTBITE_HIT + +BattleScript_EffectRevivalBlessing:: + attackcanceler + attackstring + ppreduce + attackanimation + waitanimation + tryrevivalblessing BattleScript_ButItFailed + printstring STRINGID_PKMNREVIVEDREADYTOFIGHT + waitmessage B_WAIT_TIME_LONG + jumpifbyte CMP_EQUAL, gBattleCommunication, TRUE, BattleScript_EffectRevivalBlessingSendOut + goto BattleScript_MoveEnd + +BattleScript_EffectRevivalBlessingSendOut: + switchinanim BS_SCRIPTING, FALSE + waitstate + switchineffects BS_SCRIPTING + goto BattleScript_MoveEnd BattleScript_StealthRockActivates:: setstealthrock BattleScript_MoveEnd @@ -557,6 +581,7 @@ BattleScript_AffectionBasedStatusHeal:: jumpifstatus BS_ATTACKER, STATUS1_PARALYSIS, BattleScript_AffectionBasedStatus_HealParalysisString jumpifstatus BS_ATTACKER, STATUS1_BURN, BattleScript_AffectionBasedStatus_HealBurnString jumpifstatus BS_ATTACKER, STATUS1_FREEZE, BattleScript_AffectionBasedStatus_HealFreezeString + jumpifstatus BS_ATTACKER, STATUS1_FROSTBITE, BattleScript_AffectionBasedStatus_HealFrostbiteString end2 BattleScript_AffectionBasedStatus_HealPoisonString: printstring STRINGID_ATTACKEREXPELLEDTHEPOISON @@ -572,6 +597,9 @@ BattleScript_AffectionBasedStatus_HealBurnString: goto BattleScript_AffectionBasedStatusHeal_Continue BattleScript_AffectionBasedStatus_HealFreezeString: printstring STRINGID_ATTACKERMELTEDTHEICE + goto BattleScript_AffectionBasedStatusHeal_Continue +BattleScript_AffectionBasedStatus_HealFrostbiteString: + printstring STRINGID_ATTACKERHEALEDITSFROSTBITE BattleScript_AffectionBasedStatusHeal_Continue: waitmessage B_WAIT_TIME_LONG clearstatus BS_ATTACKER @@ -1425,8 +1453,9 @@ BattleScript_EffectBurnUp: goto BattleScript_ButItFailed BattleScript_BurnUpWorks: - setmoveeffect MOVE_EFFECT_BURN_UP | MOVE_EFFECT_CERTAIN - goto BattleScript_EffectHit + setmoveeffect MOVE_EFFECT_BURN_UP | MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN + accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE + goto BattleScript_HitFromCritCalc BattleScript_BurnUpRemoveType:: losetype BS_ATTACKER, TYPE_FIRE @@ -1442,8 +1471,9 @@ BattleScript_EffectDoubleShock: goto BattleScript_ButItFailed BattleScript_DoubleShockWorks: - setmoveeffect MOVE_EFFECT_DOUBLE_SHOCK | MOVE_EFFECT_CERTAIN - goto BattleScript_EffectHit + setmoveeffect MOVE_EFFECT_DOUBLE_SHOCK | MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN + accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE + goto BattleScript_HitFromCritCalc BattleScript_DoubleShockRemoveType:: losetype BS_ATTACKER, TYPE_ELECTRIC @@ -2610,8 +2640,7 @@ BattleScript_EffectPsychicTerrain: printfromtable gTerrainStringIds waitmessage B_WAIT_TIME_LONG playanimation BS_ATTACKER, B_ANIM_RESTORE_BG - call BattleScript_ActivateTerrainAbilities - call BattleScript_TerrainSeedLoop + call BattleScript_ActivateTerrainEffects goto BattleScript_MoveEnd BattleScript_EffectTopsyTurvy: @@ -3446,6 +3475,10 @@ BattleScript_EffectBurnHit:: setmoveeffect MOVE_EFFECT_BURN goto BattleScript_EffectHit +BattleScript_EffectFrostbiteHit:: + setmoveeffect MOVE_EFFECT_FROSTBITE + goto BattleScript_EffectHit + BattleScript_EffectSleepHit:: setmoveeffect MOVE_EFFECT_SLEEP goto BattleScript_EffectHit @@ -5156,7 +5189,7 @@ BattleScript_MoveWeatherChange:: waitanimation printfromtable gMoveWeatherChangeStringIds waitmessage B_WAIT_TIME_LONG - call BattleScript_WeatherFormChanges + call BattleScript_ActivateWeatherAbilities goto BattleScript_MoveEnd BattleScript_EffectSunnyDay:: @@ -5594,7 +5627,7 @@ BattleScript_EffectStockpileSpDef:: BattleScript_EffectStockpileEnd: stockpile 1 goto BattleScript_MoveEnd - + BattleScript_MoveEffectStockpileWoreOff:: .if B_STOCKPILE_RAISES_DEFS >= GEN_4 dostockpilestatchangeswearoff BS_ATTACKER, BattleScript_StockpileStatChangeDown @@ -5602,7 +5635,7 @@ BattleScript_MoveEffectStockpileWoreOff:: waitmessage B_WAIT_TIME_SHORT .endif return - + BattleScript_StockpileStatChangeDown: statbuffchange MOVE_EFFECT_AFFECTS_USER, BattleScript_StockpileStatChangeDown_Ret setgraphicalstatchangevalues @@ -6860,14 +6893,14 @@ BattleScript_OverworldWeatherStarts:: printfromtable gWeatherStartsStringIds waitmessage B_WAIT_TIME_LONG playanimation_var BS_ATTACKER, sB_ANIM_ARG1 - call BattleScript_WeatherFormChanges + call BattleScript_ActivateWeatherAbilities end3 BattleScript_OverworldTerrain:: printfromtable gTerrainStringIds waitmessage B_WAIT_TIME_LONG playanimation BS_SCRIPTING, B_ANIM_RESTORE_BG - call BattleScript_TerrainSeedLoop + call BattleScript_ActivateTerrainEffects end3 BattleScript_SideStatusWoreOff:: @@ -6925,15 +6958,15 @@ BattleScript_MagicRoomEnds:: printstring STRINGID_MAGICROOMENDS waitmessage B_WAIT_TIME_LONG end2 - -BattleScript_GrassyTerrainEnds: - setbyte cMULTISTRING_CHOOSER, B_MSG_TERRAINENDS_GRASS + BattleScript_TerrainEnds_Ret:: printfromtable gTerrainEndingStringIds waitmessage B_WAIT_TIME_LONG playanimation BS_ATTACKER, B_ANIM_RESTORE_BG return - + +BattleScript_GrassyTerrainEnds: + setbyte cMULTISTRING_CHOOSER, B_MSG_TERRAINENDS_GRASS BattleScript_TerrainEnds:: call BattleScript_TerrainEnds_Ret end2 @@ -7346,8 +7379,7 @@ BattleScript_SeedSowerActivates:: printstring STRINGID_TERRAINBECOMESGRASSY waitmessage B_WAIT_TIME_LONG playanimation BS_SCRIPTING, B_ANIM_RESTORE_BG - call BattleScript_ActivateTerrainAbilities - call BattleScript_TerrainSeedLoop + call BattleScript_ActivateTerrainEffects return BattleScript_AngerShellActivates:: @@ -7479,7 +7511,7 @@ BattleScript_StealthRockFree:: printstring STRINGID_PKMNBLEWAWAYSTEALTHROCK waitmessage B_WAIT_TIME_LONG return - + BattleScript_SpikesDefog:: printstring STRINGID_SPIKESDISAPPEAREDFROMTEAM waitmessage B_WAIT_TIME_LONG @@ -7854,23 +7886,26 @@ BattleScript_FocusPunchSetUp:: end2 BattleScript_MegaEvolution:: + printstring STRINGID_EMPTYSTRING3 + trytrainerslidemegaevolutionmsg BS_ATTACKER printstring STRINGID_MEGAEVOREACTING -BattleScript_MegaEvolutionAfeterString: +BattleScript_MegaEvolutionAfterString: waitmessage B_WAIT_TIME_LONG setbyte gIsCriticalHit, 0 handlemegaevo BS_ATTACKER, 0 - handlemegaevo BS_ATTACKER, 1 playanimation BS_ATTACKER, B_ANIM_MEGA_EVOLUTION waitanimation - handlemegaevo BS_ATTACKER, 2 + handlemegaevo BS_ATTACKER, 1 printstring STRINGID_MEGAEVOEVOLVED waitmessage B_WAIT_TIME_LONG switchinabilities BS_ATTACKER end2 BattleScript_WishMegaEvolution:: + printstring STRINGID_EMPTYSTRING3 + trytrainerslidemegaevolutionmsg BS_ATTACKER printstring STRINGID_FERVENTWISHREACHED - goto BattleScript_MegaEvolutionAfeterString + goto BattleScript_MegaEvolutionAfterString BattleScript_PrimalReversion:: printstring STRINGID_EMPTYSTRING3 @@ -7919,6 +7954,7 @@ BattleScript_AttackerFormChangeEnd3:: BattleScript_AttackerFormChangeEnd3NoPopup:: call BattleScript_AttackerFormChangeNoPopup + end3 BattleScript_AttackerFormChangeMoveEffect:: waitmessage 1 @@ -8104,6 +8140,11 @@ BattleScript_BurnTurnDmg:: waitmessage B_WAIT_TIME_LONG goto BattleScript_DoStatusTurnDmg +BattleScript_FrostbiteTurnDmg:: + printstring STRINGID_PKMNHURTBYFROSTBITE + waitmessage B_WAIT_TIME_LONG + goto BattleScript_DoStatusTurnDmg + BattleScript_MoveUsedIsFrozen:: printstring STRINGID_PKMNISFROZEN waitmessage B_WAIT_TIME_LONG @@ -8116,12 +8157,24 @@ BattleScript_MoveUsedUnfroze:: updatestatusicon BS_ATTACKER return +BattleScript_MoveUsedUnfrostbite:: + printfromtable gFrostbiteHealedStringIds + waitmessage B_WAIT_TIME_LONG + updatestatusicon BS_ATTACKER + return + BattleScript_DefrostedViaFireMove:: printstring STRINGID_PKMNWASDEFROSTED waitmessage B_WAIT_TIME_LONG updatestatusicon BS_TARGET return +BattleScript_FrostbiteHealedViaFireMove:: + printstring STRINGID_PKMNFROSTBITEHEALED + waitmessage B_WAIT_TIME_LONG + updatestatusicon BS_TARGET + return + BattleScript_MoveUsedIsParalyzed:: printstring STRINGID_PKMNISPARALYZED waitmessage B_WAIT_TIME_LONG @@ -8343,6 +8396,12 @@ BattleScript_MoveEffectBurn:: waitmessage B_WAIT_TIME_LONG goto BattleScript_UpdateEffectStatusIconRet +BattleScript_MoveEffectFrostbite:: + statusanimation BS_EFFECT_BATTLER + printfromtable gGotFrostbiteStringIds + waitmessage B_WAIT_TIME_LONG + goto BattleScript_UpdateEffectStatusIconRet + BattleScript_MoveEffectFreeze:: statusanimation BS_EFFECT_BATTLER printfromtable gGotFrozenStringIds @@ -8413,7 +8472,7 @@ BattleScript_DrizzleActivates:: printstring STRINGID_PKMNMADEITRAIN waitstate playanimation BS_BATTLER_0, B_ANIM_RAIN_CONTINUES - call BattleScript_WeatherFormChanges + call BattleScript_ActivateWeatherAbilities end3 BattleScript_AbilityRaisesDefenderStat:: @@ -8575,7 +8634,7 @@ BattleScript_SandstreamActivates:: printstring STRINGID_PKMNSXWHIPPEDUPSANDSTORM waitstate playanimation BS_BATTLER_0, B_ANIM_SANDSTORM_CONTINUES - call BattleScript_WeatherFormChanges + call BattleScript_ActivateWeatherAbilities end3 BattleScript_SandSpitActivates:: @@ -8584,7 +8643,7 @@ BattleScript_SandSpitActivates:: printstring STRINGID_ASANDSTORMKICKEDUP waitstate playanimation BS_BATTLER_0, B_ANIM_SANDSTORM_CONTINUES - call BattleScript_WeatherFormChanges + call BattleScript_ActivateWeatherAbilities return BattleScript_ShedSkinActivates:: @@ -8594,37 +8653,15 @@ BattleScript_ShedSkinActivates:: updatestatusicon BS_ATTACKER end3 -BattleScript_WeatherFormChanges:: - setbyte sBATTLER, 0 -BattleScript_WeatherFormChangesLoop:: - tryweatherformdatachange - activateweatherchangeabilities BS_SCRIPTING - addbyte sBATTLER, 1 - jumpifbytenotequal sBATTLER, gBattlersCount, BattleScript_WeatherFormChangesLoop - return - -BattleScript_WeatherFormChange:: - call BattleScript_DoWeatherFormChange - end3 - -BattleScript_DoWeatherFormChange:: - copybyte gBattlerAbility, sBATTLER -.if B_WEATHER_FORMS >= GEN_5 - jumpifspecies BS_SCRIPTING, SPECIES_CASTFORM, BattleScript_DoWeatherFormChange_ForecastCheck -BattleScript_DoWeatherFormChange_FlowerGiftCheck: - jumpifability BS_SCRIPTING, ABILITY_FLOWER_GIFT, BattleScript_DoWeatherFormChange_PopUp - goto BattleScript_DoWeatherFormChange_AfterPopUp -.endif -BattleScript_DoWeatherFormChange_ForecastCheck: - jumpifability BS_SCRIPTING, ABILITY_FORECAST, BattleScript_DoWeatherFormChange_PopUp - goto BattleScript_DoWeatherFormChange_AfterPopUp -BattleScript_DoWeatherFormChange_PopUp: - call BattleScript_AbilityPopUp -BattleScript_DoWeatherFormChange_AfterPopUp: - doweatherformchangeanimation - waitstate - printstring STRINGID_PKMNTRANSFORMED - waitmessage B_WAIT_TIME_LONG +BattleScript_ActivateWeatherAbilities: + copybyte sBATTLER, gBattlerAttacker + setbyte gBattlerAttacker, 0 +BattleScript_ActivateWeatherAbilities_Loop: + activateweatherchangeabilities BS_ATTACKER +BattleScript_ActivateWeatherAbilities_Increment: + addbyte gBattlerAttacker, 1 + jumpifbytenotequal gBattlerAttacker, gBattlersCount, BattleScript_ActivateWeatherAbilities_Loop + copybyte gBattlerAttacker, sBATTLER return BattleScript_TryAdrenalineOrb: @@ -8719,7 +8756,7 @@ BattleScript_DroughtActivates:: printstring STRINGID_PKMNSXINTENSIFIEDSUN waitstate playanimation BS_BATTLER_0, B_ANIM_SUN_CONTINUES - call BattleScript_WeatherFormChanges + call BattleScript_ActivateWeatherAbilities end3 BattleScript_DesolateLandActivates:: @@ -8728,7 +8765,7 @@ BattleScript_DesolateLandActivates:: printstring STRINGID_EXTREMELYHARSHSUNLIGHT waitstate playanimation BS_BATTLER_0, B_ANIM_SUN_CONTINUES - call BattleScript_WeatherFormChanges + call BattleScript_ActivateWeatherAbilities end3 BattleScript_DesolateLandEvaporatesWaterTypeMoves:: @@ -8748,7 +8785,7 @@ BattleScript_PrimordialSeaActivates:: printstring STRINGID_HEAVYRAIN waitstate playanimation BS_BATTLER_0, B_ANIM_RAIN_CONTINUES - call BattleScript_WeatherFormChanges + call BattleScript_ActivateWeatherAbilities end3 BattleScript_PrimordialSeaFizzlesOutFireTypeMoves:: @@ -8825,21 +8862,22 @@ BattleScript_SnowWarningActivates:: printstring STRINGID_SNOWWARNINGHAIL waitstate playanimation BS_BATTLER_0, B_ANIM_HAIL_CONTINUES - call BattleScript_WeatherFormChanges + call BattleScript_ActivateWeatherAbilities end3 -BattleScript_TerrainSeedLoop: +BattleScript_ActivateTerrainEffects: savetarget setbyte gBattlerTarget, 0 -BattleScript_TerrainSeedLoopIter: +BattleScript_ActivateTerrainSeed: copybyte sBATTLER, gBattlerTarget - doterrainseed BS_TARGET, BattleScript_TerrainSeedLoop_NextBattler + doterrainseed BS_TARGET, BattleScript_ActivateTerrainAbility removeitem BS_TARGET -BattleScript_TerrainSeedLoop_NextBattler: +BattleScript_ActivateTerrainAbility: + activateterrainchangeabilities BS_TARGET +BattleScript_ActivateTerrainEffects_Increment: addbyte gBattlerTarget, 0x1 - jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_TerrainSeedLoopIter + jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_ActivateTerrainSeed restoretarget - call BattleScript_ActivateSwitchInAbilities return BattleScript_ActivateSwitchInAbilities: @@ -8853,25 +8891,13 @@ BattleScript_ActivateSwitchInAbilities_Increment: copybyte gBattlerAttacker, sBATTLER return -BattleScript_ActivateTerrainAbilities: - copybyte sBATTLER, gBattlerAttacker - setbyte gBattlerAttacker, 0 -BattleScript_ActivateTerrainAbilities_Loop: - activateterrainchangeabilities BS_ATTACKER -BattleScript_ActivateTerrainAbilities_Increment: - addbyte gBattlerAttacker, 1 - jumpifbytenotequal gBattlerAttacker, gBattlersCount, BattleScript_ActivateTerrainAbilities_Loop - copybyte gBattlerAttacker, sBATTLER - return - BattleScript_ElectricSurgeActivates:: pause B_WAIT_TIME_SHORT call BattleScript_AbilityPopUp printstring STRINGID_TERRAINBECOMESELECTRIC waitmessage B_WAIT_TIME_LONG playanimation BS_SCRIPTING, B_ANIM_RESTORE_BG - call BattleScript_ActivateTerrainAbilities - call BattleScript_TerrainSeedLoop + call BattleScript_ActivateTerrainEffects end3 BattleScript_MistySurgeActivates:: @@ -8880,8 +8906,7 @@ BattleScript_MistySurgeActivates:: printstring STRINGID_TERRAINBECOMESMISTY waitmessage B_WAIT_TIME_LONG playanimation BS_SCRIPTING, B_ANIM_RESTORE_BG - call BattleScript_ActivateTerrainAbilities - call BattleScript_TerrainSeedLoop + call BattleScript_ActivateTerrainEffects end3 BattleScript_GrassySurgeActivates:: @@ -8890,8 +8915,7 @@ BattleScript_GrassySurgeActivates:: printstring STRINGID_TERRAINBECOMESGRASSY waitmessage B_WAIT_TIME_LONG playanimation BS_SCRIPTING, B_ANIM_RESTORE_BG - call BattleScript_ActivateTerrainAbilities - call BattleScript_TerrainSeedLoop + call BattleScript_ActivateTerrainEffects end3 BattleScript_PsychicSurgeActivates:: @@ -8900,8 +8924,7 @@ BattleScript_PsychicSurgeActivates:: printstring STRINGID_TERRAINBECOMESPSYCHIC waitmessage B_WAIT_TIME_LONG playanimation BS_SCRIPTING, B_ANIM_RESTORE_BG - call BattleScript_ActivateTerrainAbilities - call BattleScript_TerrainSeedLoop + call BattleScript_ActivateTerrainEffects end3 BattleScript_HurtTarget_NoString: @@ -9177,7 +9200,7 @@ BattleScript_WanderingSpiritActivates:: pause 20 destroyabilitypopup pause 40 - + copybyte gBattlerAbility, gBattlerAttacker setbyte sFIXED_ABILITY_POPUP, TRUE copyhword sABILITY_OVERWRITE, gLastUsedAbility showabilitypopup BS_ATTACKER @@ -9557,6 +9580,18 @@ BattleScript_BerryCureFrzRet:: removeitem BS_SCRIPTING return +BattleScript_BerryCureFsbEnd2:: + call BattleScript_BerryCureFrzRet + end2 + +BattleScript_BerryCureFsbRet:: + playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT + printstring STRINGID_PKMNSITEMHEALEDFROSTBITE + waitmessage B_WAIT_TIME_LONG + updatestatusicon BS_SCRIPTING + removeitem BS_SCRIPTING + return + BattleScript_BerryCureSlpEnd2:: call BattleScript_BerryCureSlpRet end2 @@ -10021,7 +10056,7 @@ BattleScript_AnnounceAirLockCloudNine:: call BattleScript_AbilityPopUp printstring STRINGID_AIRLOCKACTIVATES waitmessage B_WAIT_TIME_LONG - call BattleScript_WeatherFormChanges + call BattleScript_ActivateWeatherAbilities end3 BattleScript_QuickClawActivation:: @@ -10091,6 +10126,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 @@ -10098,6 +10135,8 @@ BattleScript_ZMoveActivateDamaging:: return BattleScript_ZMoveActivateStatus:: + printstring STRINGID_EMPTYSTRING3 + trytrainerslidezmovemsg BS_ATTACKER savetarget printstring STRINGID_ZPOWERSURROUNDS playanimation BS_ATTACKER, B_ANIM_ZMOVE_ACTIVATE, NULL @@ -10203,7 +10242,6 @@ BattleScript_EffectHitSetRemoveTerrain: setterrain BattleScript_TryFaint playanimation BS_ATTACKER, B_ANIM_RESTORE_BG printfromtable gTerrainStringIds - call BattleScript_ActivateTerrainAbilities BattleScript_TryFaint: tryfaintmon BS_TARGET goto BattleScript_MoveEnd @@ -10404,3 +10442,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 diff --git a/data/battle_scripts_2.s b/data/battle_scripts_2.s index f4c8bd5a7..9ffad7d84 100644 --- a/data/battle_scripts_2.s +++ b/data/battle_scripts_2.s @@ -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 diff --git a/data/maps/AbandonedShip_CaptainsOffice/scripts.inc b/data/maps/AbandonedShip_CaptainsOffice/scripts.inc index 7c59fec96..78fdc6434 100644 --- a/data/maps/AbandonedShip_CaptainsOffice/scripts.inc +++ b/data/maps/AbandonedShip_CaptainsOffice/scripts.inc @@ -7,7 +7,7 @@ AbandonedShip_CaptainsOffice_EventScript_CaptSternAide:: goto_if_set FLAG_EXCHANGED_SCANNER, AbandonedShip_CaptainsOffice_EventScript_ThisIsSSCactus checkitem ITEM_SCANNER goto_if_eq VAR_RESULT, TRUE, AbandonedShip_CaptainsOffice_EventScript_CanYouDeliverScanner - goto_if_set FLAG_ITEM_ABANDONED_SHIP_HIDDEN_FLOOR_ROOM_4_SCANNER, AbandonedShip_CaptainsOffice_EventScript_ThisIsSSCactus + goto_if_set FLAG_ITEM_ABANDONED_SHIP_HIDDEN_FLOOR_ROOM_2_SCANNER, AbandonedShip_CaptainsOffice_EventScript_ThisIsSSCactus msgbox AbandonedShip_CaptainsOffice_Text_NoSuccessFindingScanner, MSGBOX_DEFAULT release end diff --git a/data/maps/AbandonedShip_HiddenFloorRooms/map.json b/data/maps/AbandonedShip_HiddenFloorRooms/map.json index dce9111eb..905c85335 100644 --- a/data/maps/AbandonedShip_HiddenFloorRooms/map.json +++ b/data/maps/AbandonedShip_HiddenFloorRooms/map.json @@ -38,7 +38,7 @@ "trainer_type": "TRAINER_TYPE_NONE", "trainer_sight_or_berry_tree_id": "0", "script": "AbandonedShip_HiddenFloorRooms_EventScript_ItemScanner", - "flag": "FLAG_ITEM_ABANDONED_SHIP_HIDDEN_FLOOR_ROOM_4_SCANNER" + "flag": "FLAG_ITEM_ABANDONED_SHIP_HIDDEN_FLOOR_ROOM_2_SCANNER" }, { "graphics_id": "OBJ_EVENT_GFX_ITEM_BALL", diff --git a/data/scripts/mauville_man.inc b/data/scripts/mauville_man.inc index eda3505bf..a33636043 100644 --- a/data/scripts/mauville_man.inc +++ b/data/scripts/mauville_man.inc @@ -64,9 +64,9 @@ MauvilleCity_PokemonCenter_1F_EventScript_DeclineWritingLyrics:: MauvilleCity_PokemonCenter_1F_EventScript_Hipster:: lock faceplayer - setflag FLAG_SYS_HIPSTER_MEET + setflag FLAG_UNLOCKED_TRENDY_SAYINGS msgbox MauvilleCity_PokemonCenter_1F_Text_TeachWhatsHipAndHappening, MSGBOX_DEFAULT - special GetHipsterSpokenFlag + special HasHipsterTaughtWord goto_if_eq VAR_RESULT, FALSE, MauvilleCity_PokemonCenter_1F_EventScript_TryTeachWord msgbox MauvilleCity_PokemonCenter_1F_Text_IAlreadyTaughtYou, MSGBOX_DEFAULT release @@ -80,8 +80,8 @@ MauvilleCity_PokemonCenter_1F_EventScript_TryTeachWord:: end MauvilleCity_PokemonCenter_1F_EventScript_TeachWord:: - msgbox MauvilleCity_PokemonCenter_1F_Text_HaveYouHeardOfPhrase, MSGBOX_DEFAULT - special SetHipsterSpokenFlag + msgbox MauvilleCity_PokemonCenter_1F_Text_HaveYouHeardOfWord, MSGBOX_DEFAULT + special SetHipsterTaughtWord release end @@ -969,7 +969,7 @@ MauvilleCity_PokemonCenter_1F_Text_IveGotNothingNewToTeach: .string "what's hip and happening.\p" .string "I've got nothing new to teach you!$" -MauvilleCity_PokemonCenter_1F_Text_HaveYouHeardOfPhrase: +MauvilleCity_PokemonCenter_1F_Text_HaveYouHeardOfWord: .string "Hey, have you heard about\n" .string "“{STR_VAR_1}”?\p" .string "What's it mean? Well…\n" diff --git a/data/specials.inc b/data/specials.inc index 3d08eef4c..ded2e3f4f 100644 --- a/data/specials.inc +++ b/data/specials.inc @@ -111,8 +111,8 @@ gSpecials:: def_special Script_GetCurrentMauvilleMan def_special HasBardSongBeenChanged def_special SaveBardSongLyrics - def_special GetHipsterSpokenFlag - def_special SetHipsterSpokenFlag + def_special HasHipsterTaughtWord + def_special SetHipsterTaughtWord def_special HipsterTryTeachWord def_special PlayBardSong def_special SetMauvilleOldManObjEventGfx diff --git a/gflib/text.c b/gflib/text.c index 86dca3829..1bded26b5 100644 --- a/gflib/text.c +++ b/gflib/text.c @@ -36,7 +36,7 @@ static u32 GetGlyphWidth_Narrow(u16, bool32); static u32 GetGlyphWidth_SmallNarrow(u16, bool32); static EWRAM_DATA struct TextPrinter sTempTextPrinter = {0}; -static EWRAM_DATA struct TextPrinter sTextPrinters[NUM_TEXT_PRINTERS] = {0}; +static EWRAM_DATA struct TextPrinter sTextPrinters[WINDOWS_MAX] = {0}; static u16 sFontHalfRowLookupTable[0x51]; static u16 sLastTextBgColor; @@ -244,7 +244,7 @@ static void SetFontsPointer(const struct FontInfo *fonts) void DeactivateAllTextPrinters(void) { int printer; - for (printer = 0; printer < NUM_TEXT_PRINTERS; ++printer) + for (printer = 0; printer < WINDOWS_MAX; ++printer) sTextPrinters[printer].active = FALSE; } @@ -322,7 +322,7 @@ void RunTextPrinters(void) if (!gDisableTextPrinters) { - for (i = 0; i < NUM_TEXT_PRINTERS; ++i) + for (i = 0; i < WINDOWS_MAX; ++i) { if (sTextPrinters[i].active) { diff --git a/gflib/text.h b/gflib/text.h index a88cb990e..ff13efa9a 100644 --- a/gflib/text.h +++ b/gflib/text.h @@ -3,8 +3,6 @@ #include "characters.h" -#define NUM_TEXT_PRINTERS 32 - // Given as a text speed when all the text should be // loaded at once but not copied to vram yet. #define TEXT_SKIP_DRAW 0xFF diff --git a/gflib/window.c b/gflib/window.c index 1621a0884..76e863f10 100644 --- a/gflib/window.c +++ b/gflib/window.c @@ -9,8 +9,6 @@ u8 gTransparentTileNumber; void *gWindowBgTilemapBuffers[NUM_BACKGROUNDS]; extern u32 gWindowTileAutoAllocEnabled; -#define WINDOWS_MAX 32 - EWRAM_DATA struct Window gWindows[WINDOWS_MAX] = {0}; EWRAM_DATA static struct Window* sWindowPtr = NULL; EWRAM_DATA static u16 sWindowSize = 0; diff --git a/gflib/window.h b/gflib/window.h index 0000dd864..0f2dff2a8 100644 --- a/gflib/window.h +++ b/gflib/window.h @@ -1,6 +1,8 @@ #ifndef GUARD_WINDOW_H #define GUARD_WINDOW_H +#define WINDOWS_MAX 32 + #define PIXEL_FILL(num) ((num) | ((num) << 4)) enum { diff --git a/graphics/battle_interface/status.png b/graphics/battle_interface/status.png index 9fae45b71..0b212907e 100644 Binary files a/graphics/battle_interface/status.png and b/graphics/battle_interface/status.png differ diff --git a/graphics/battle_interface/status2.png b/graphics/battle_interface/status2.png index af7ce05d3..5d7f6459b 100644 Binary files a/graphics/battle_interface/status2.png and b/graphics/battle_interface/status2.png differ diff --git a/graphics/battle_interface/status3.png b/graphics/battle_interface/status3.png index d0febfb17..7cc8cd56d 100644 Binary files a/graphics/battle_interface/status3.png and b/graphics/battle_interface/status3.png differ diff --git a/graphics/battle_interface/status4.png b/graphics/battle_interface/status4.png index 9704a3611..c5ab2c5e1 100644 Binary files a/graphics/battle_interface/status4.png and b/graphics/battle_interface/status4.png differ diff --git a/graphics/cable_car/pylons.bin b/graphics/cable_car/pylon_pole.bin similarity index 100% rename from graphics/cable_car/pylons.bin rename to graphics/cable_car/pylon_pole.bin diff --git a/graphics/cable_car/pylon_top.bin b/graphics/cable_car/pylon_top.bin new file mode 100755 index 000000000..44b20744d Binary files /dev/null and b/graphics/cable_car/pylon_top.bin differ diff --git a/graphics/interface/status_icons.png b/graphics/interface/status_icons.png index fe802d7f6..f93406cfd 100644 Binary files a/graphics/interface/status_icons.png and b/graphics/interface/status_icons.png differ diff --git a/graphics/items/icon_palettes/berserk_gene.pal b/graphics/items/icon_palettes/berserk_gene.pal new file mode 100644 index 000000000..3ac8981aa --- /dev/null +++ b/graphics/items/icon_palettes/berserk_gene.pal @@ -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 diff --git a/graphics/items/icon_palettes/black_augurite.pal b/graphics/items/icon_palettes/black_augurite.pal new file mode 100644 index 000000000..0d67abee3 --- /dev/null +++ b/graphics/items/icon_palettes/black_augurite.pal @@ -0,0 +1,19 @@ +JASC-PAL +0100 +16 +120 192 168 +0 0 0 +111 108 124 +58 48 49 +206 206 214 +151 149 160 +142 93 117 +89 62 76 +255 255 255 +111 109 124 +194 192 202 +88 62 76 +80 74 88 +0 0 0 +0 0 0 +0 0 0 diff --git a/graphics/items/icon_palettes/linking_cord.pal b/graphics/items/icon_palettes/linking_cord.pal new file mode 100644 index 000000000..8be2b522f --- /dev/null +++ b/graphics/items/icon_palettes/linking_cord.pal @@ -0,0 +1,19 @@ +JASC-PAL +0100 +16 +128 192 168 +87 87 88 +155 158 156 +117 114 116 +0 0 0 +36 37 42 +62 66 68 +56 57 61 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 diff --git a/graphics/items/icon_palettes/peat_block.pal b/graphics/items/icon_palettes/peat_block.pal new file mode 100644 index 000000000..8d4b5e3b6 --- /dev/null +++ b/graphics/items/icon_palettes/peat_block.pal @@ -0,0 +1,19 @@ +JASC-PAL +0100 +16 +128 198 168 +32 32 32 +230 217 213 +199 189 184 +156 135 143 +102 83 83 +143 118 130 +65 56 56 +179 162 151 +117 100 100 +210 183 192 +180 158 167 +0 0 0 +0 0 0 +0 0 0 +0 0 0 diff --git a/graphics/items/icons/berserk_gene.png b/graphics/items/icons/berserk_gene.png new file mode 100644 index 000000000..faac0f676 Binary files /dev/null and b/graphics/items/icons/berserk_gene.png differ diff --git a/graphics/items/icons/black_augurite.png b/graphics/items/icons/black_augurite.png new file mode 100644 index 000000000..8be2bc188 Binary files /dev/null and b/graphics/items/icons/black_augurite.png differ diff --git a/graphics/items/icons/linking_cord.png b/graphics/items/icons/linking_cord.png new file mode 100644 index 000000000..a3f92da04 Binary files /dev/null and b/graphics/items/icons/linking_cord.png differ diff --git a/graphics/items/icons/peat_block.png b/graphics/items/icons/peat_block.png new file mode 100644 index 000000000..9c1065987 Binary files /dev/null and b/graphics/items/icons/peat_block.png differ diff --git a/graphics/pokemon/absol/icon.png b/graphics/pokemon/absol/icon.png index 681d98d1d..d58d208a7 100644 Binary files a/graphics/pokemon/absol/icon.png and b/graphics/pokemon/absol/icon.png differ diff --git a/graphics/pokemon/accelgor/icon.png b/graphics/pokemon/accelgor/icon.png index d8538bec1..5d971a97b 100644 Binary files a/graphics/pokemon/accelgor/icon.png and b/graphics/pokemon/accelgor/icon.png differ diff --git a/graphics/pokemon/aerodactyl/icon.png b/graphics/pokemon/aerodactyl/icon.png index e354dbb0d..58c96d57c 100644 Binary files a/graphics/pokemon/aerodactyl/icon.png and b/graphics/pokemon/aerodactyl/icon.png differ diff --git a/graphics/pokemon/aggron/icon.png b/graphics/pokemon/aggron/icon.png index 5410a384f..3eaa06054 100644 Binary files a/graphics/pokemon/aggron/icon.png and b/graphics/pokemon/aggron/icon.png differ diff --git a/graphics/pokemon/aipom/icon.png b/graphics/pokemon/aipom/icon.png index 43822f098..294ab74eb 100644 Binary files a/graphics/pokemon/aipom/icon.png and b/graphics/pokemon/aipom/icon.png differ diff --git a/graphics/pokemon/alakazam/icon.png b/graphics/pokemon/alakazam/icon.png index 6d136899d..e823e94cd 100644 Binary files a/graphics/pokemon/alakazam/icon.png and b/graphics/pokemon/alakazam/icon.png differ diff --git a/graphics/pokemon/altaria/icon.png b/graphics/pokemon/altaria/icon.png index f1d2698a2..8c9bf8198 100644 Binary files a/graphics/pokemon/altaria/icon.png and b/graphics/pokemon/altaria/icon.png differ diff --git a/graphics/pokemon/amoonguss/icon.png b/graphics/pokemon/amoonguss/icon.png index a0762f49c..baf242207 100644 Binary files a/graphics/pokemon/amoonguss/icon.png and b/graphics/pokemon/amoonguss/icon.png differ diff --git a/graphics/pokemon/arceus/icon.png b/graphics/pokemon/arceus/icon.png index 155bfc35b..6141c35e8 100644 Binary files a/graphics/pokemon/arceus/icon.png and b/graphics/pokemon/arceus/icon.png differ diff --git a/graphics/pokemon/ariados/icon.png b/graphics/pokemon/ariados/icon.png index c6ff8c5f8..e6206a3cb 100644 Binary files a/graphics/pokemon/ariados/icon.png and b/graphics/pokemon/ariados/icon.png differ diff --git a/graphics/pokemon/armaldo/icon.png b/graphics/pokemon/armaldo/icon.png index 5dba6557d..1277dbbbe 100644 Binary files a/graphics/pokemon/armaldo/icon.png and b/graphics/pokemon/armaldo/icon.png differ diff --git a/graphics/pokemon/articuno/icon.png b/graphics/pokemon/articuno/icon.png index 79685a2d1..c50044963 100644 Binary files a/graphics/pokemon/articuno/icon.png and b/graphics/pokemon/articuno/icon.png differ diff --git a/graphics/pokemon/azelf/icon.png b/graphics/pokemon/azelf/icon.png index c8d0af3d9..816b6f5cc 100644 Binary files a/graphics/pokemon/azelf/icon.png and b/graphics/pokemon/azelf/icon.png differ diff --git a/graphics/pokemon/azumarill/icon.png b/graphics/pokemon/azumarill/icon.png index cc79407be..8d1a62676 100644 Binary files a/graphics/pokemon/azumarill/icon.png and b/graphics/pokemon/azumarill/icon.png differ diff --git a/graphics/pokemon/beartic/icon.png b/graphics/pokemon/beartic/icon.png index c4ed605a0..991f9f265 100644 Binary files a/graphics/pokemon/beartic/icon.png and b/graphics/pokemon/beartic/icon.png differ diff --git a/graphics/pokemon/beldum/icon.png b/graphics/pokemon/beldum/icon.png index 8cac3cf71..af2260545 100644 Binary files a/graphics/pokemon/beldum/icon.png and b/graphics/pokemon/beldum/icon.png differ diff --git a/graphics/pokemon/bellsprout/icon.png b/graphics/pokemon/bellsprout/icon.png index 59ae8d037..ff6ca2c33 100644 Binary files a/graphics/pokemon/bellsprout/icon.png and b/graphics/pokemon/bellsprout/icon.png differ diff --git a/graphics/pokemon/butterfree/icon.png b/graphics/pokemon/butterfree/icon.png index 2ea823cf4..827ceee0d 100644 Binary files a/graphics/pokemon/butterfree/icon.png and b/graphics/pokemon/butterfree/icon.png differ diff --git a/graphics/pokemon/cacturne/icon.png b/graphics/pokemon/cacturne/icon.png index fd1bb1d5f..8dd74b291 100644 Binary files a/graphics/pokemon/cacturne/icon.png and b/graphics/pokemon/cacturne/icon.png differ diff --git a/graphics/pokemon/castform/icon.png b/graphics/pokemon/castform/icon.png index 6f4a5a18a..5e3c09291 100644 Binary files a/graphics/pokemon/castform/icon.png and b/graphics/pokemon/castform/icon.png differ diff --git a/graphics/pokemon/chatot/icon.png b/graphics/pokemon/chatot/icon.png index ee4eab2a1..9a8777c7a 100644 Binary files a/graphics/pokemon/chatot/icon.png and b/graphics/pokemon/chatot/icon.png differ diff --git a/graphics/pokemon/cherrim/icon.png b/graphics/pokemon/cherrim/icon.png index 145074d7a..6915d775b 100644 Binary files a/graphics/pokemon/cherrim/icon.png and b/graphics/pokemon/cherrim/icon.png differ diff --git a/graphics/pokemon/chikorita/icon.png b/graphics/pokemon/chikorita/icon.png index ef2975dc4..ed1eac67f 100644 Binary files a/graphics/pokemon/chikorita/icon.png and b/graphics/pokemon/chikorita/icon.png differ diff --git a/graphics/pokemon/chimecho/icon.png b/graphics/pokemon/chimecho/icon.png index f5480bc35..d4d6b6448 100644 Binary files a/graphics/pokemon/chimecho/icon.png and b/graphics/pokemon/chimecho/icon.png differ diff --git a/graphics/pokemon/cloyster/icon.png b/graphics/pokemon/cloyster/icon.png index a60befbbf..9f50ad4dd 100644 Binary files a/graphics/pokemon/cloyster/icon.png and b/graphics/pokemon/cloyster/icon.png differ diff --git a/graphics/pokemon/cobalion/icon.png b/graphics/pokemon/cobalion/icon.png index 376226b24..5dcdd6cb0 100644 Binary files a/graphics/pokemon/cobalion/icon.png and b/graphics/pokemon/cobalion/icon.png differ diff --git a/graphics/pokemon/cofagrigus/icon.png b/graphics/pokemon/cofagrigus/icon.png index 19476138c..1ae2b6609 100644 Binary files a/graphics/pokemon/cofagrigus/icon.png and b/graphics/pokemon/cofagrigus/icon.png differ diff --git a/graphics/pokemon/combusken/icon.png b/graphics/pokemon/combusken/icon.png index d7b1f8412..231252ccb 100644 Binary files a/graphics/pokemon/combusken/icon.png and b/graphics/pokemon/combusken/icon.png differ diff --git a/graphics/pokemon/corsola/icon.png b/graphics/pokemon/corsola/icon.png index 9fb51a0b1..e5ebe6c08 100644 Binary files a/graphics/pokemon/corsola/icon.png and b/graphics/pokemon/corsola/icon.png differ diff --git a/graphics/pokemon/cresselia/icon.png b/graphics/pokemon/cresselia/icon.png index 76b9b3639..8189ad7d1 100644 Binary files a/graphics/pokemon/cresselia/icon.png and b/graphics/pokemon/cresselia/icon.png differ diff --git a/graphics/pokemon/crobat/icon.png b/graphics/pokemon/crobat/icon.png index 5a3257411..2d42fa21b 100644 Binary files a/graphics/pokemon/crobat/icon.png and b/graphics/pokemon/crobat/icon.png differ diff --git a/graphics/pokemon/crustle/icon.png b/graphics/pokemon/crustle/icon.png index e6a99fe63..5b7014779 100644 Binary files a/graphics/pokemon/crustle/icon.png and b/graphics/pokemon/crustle/icon.png differ diff --git a/graphics/pokemon/darkrai/icon.png b/graphics/pokemon/darkrai/icon.png index 71d92afdc..c31c365bd 100644 Binary files a/graphics/pokemon/darkrai/icon.png and b/graphics/pokemon/darkrai/icon.png differ diff --git a/graphics/pokemon/deino/icon.png b/graphics/pokemon/deino/icon.png index 60822658b..0b5ec01ce 100644 Binary files a/graphics/pokemon/deino/icon.png and b/graphics/pokemon/deino/icon.png differ diff --git a/graphics/pokemon/dialga/icon.png b/graphics/pokemon/dialga/icon.png index 83db2e521..232b9bf94 100644 Binary files a/graphics/pokemon/dialga/icon.png and b/graphics/pokemon/dialga/icon.png differ diff --git a/graphics/pokemon/dodrio/icon.png b/graphics/pokemon/dodrio/icon.png index bd1692b13..19d1644a3 100644 Binary files a/graphics/pokemon/dodrio/icon.png and b/graphics/pokemon/dodrio/icon.png differ diff --git a/graphics/pokemon/donphan/icon.png b/graphics/pokemon/donphan/icon.png index ce6783910..32368b808 100644 Binary files a/graphics/pokemon/donphan/icon.png and b/graphics/pokemon/donphan/icon.png differ diff --git a/graphics/pokemon/dragonite/icon.png b/graphics/pokemon/dragonite/icon.png index 11fb866c3..12c2c141d 100644 Binary files a/graphics/pokemon/dragonite/icon.png and b/graphics/pokemon/dragonite/icon.png differ diff --git a/graphics/pokemon/drifblim/icon.png b/graphics/pokemon/drifblim/icon.png index bfa106e87..df7c888d5 100644 Binary files a/graphics/pokemon/drifblim/icon.png and b/graphics/pokemon/drifblim/icon.png differ diff --git a/graphics/pokemon/duosion/anim_front.png b/graphics/pokemon/duosion/anim_front.png index e8c48d6c0..c265b4252 100644 Binary files a/graphics/pokemon/duosion/anim_front.png and b/graphics/pokemon/duosion/anim_front.png differ diff --git a/graphics/pokemon/duosion/icon.png b/graphics/pokemon/duosion/icon.png index 90064f3be..9385bf614 100644 Binary files a/graphics/pokemon/duosion/icon.png and b/graphics/pokemon/duosion/icon.png differ diff --git a/graphics/pokemon/duosion/normal.pal b/graphics/pokemon/duosion/normal.pal index 9af82073e..1316dc666 100644 --- a/graphics/pokemon/duosion/normal.pal +++ b/graphics/pokemon/duosion/normal.pal @@ -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 diff --git a/graphics/pokemon/duskull/anim_front.png b/graphics/pokemon/duskull/anim_front.png index ede00efff..b873ffbb7 100644 Binary files a/graphics/pokemon/duskull/anim_front.png and b/graphics/pokemon/duskull/anim_front.png differ diff --git a/graphics/pokemon/duskull/back.png b/graphics/pokemon/duskull/back.png index e3817e24e..82b1266c5 100644 Binary files a/graphics/pokemon/duskull/back.png and b/graphics/pokemon/duskull/back.png differ diff --git a/graphics/pokemon/duskull/shiny.pal b/graphics/pokemon/duskull/shiny.pal index 2c59d3ae1..16dc97f5a 100644 --- a/graphics/pokemon/duskull/shiny.pal +++ b/graphics/pokemon/duskull/shiny.pal @@ -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 diff --git a/graphics/pokemon/dwebble/icon.png b/graphics/pokemon/dwebble/icon.png index 32a23fd05..4b356d5aa 100644 Binary files a/graphics/pokemon/dwebble/icon.png and b/graphics/pokemon/dwebble/icon.png differ diff --git a/graphics/pokemon/electivire/anim_front.png b/graphics/pokemon/electivire/anim_front.png index a5f05a7e8..9aae7e5b5 100644 Binary files a/graphics/pokemon/electivire/anim_front.png and b/graphics/pokemon/electivire/anim_front.png differ diff --git a/graphics/pokemon/electivire/normal.pal b/graphics/pokemon/electivire/normal.pal index e751bd37e..890828f27 100644 --- a/graphics/pokemon/electivire/normal.pal +++ b/graphics/pokemon/electivire/normal.pal @@ -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 diff --git a/graphics/pokemon/emboar/icon.png b/graphics/pokemon/emboar/icon.png index 8d6f99628..d79f6f004 100644 Binary files a/graphics/pokemon/emboar/icon.png and b/graphics/pokemon/emboar/icon.png differ diff --git a/graphics/pokemon/empoleon/icon.png b/graphics/pokemon/empoleon/icon.png index f4bbc4fd4..1e6e30582 100644 Binary files a/graphics/pokemon/empoleon/icon.png and b/graphics/pokemon/empoleon/icon.png differ diff --git a/graphics/pokemon/entei/icon.png b/graphics/pokemon/entei/icon.png index b7707797f..eeb80f460 100644 Binary files a/graphics/pokemon/entei/icon.png and b/graphics/pokemon/entei/icon.png differ diff --git a/graphics/pokemon/escavalier/icon.png b/graphics/pokemon/escavalier/icon.png index 32c398834..94f646ecf 100644 Binary files a/graphics/pokemon/escavalier/icon.png and b/graphics/pokemon/escavalier/icon.png differ diff --git a/graphics/pokemon/espeon/icon.png b/graphics/pokemon/espeon/icon.png index 86a4606c9..ebb9fd328 100644 Binary files a/graphics/pokemon/espeon/icon.png and b/graphics/pokemon/espeon/icon.png differ diff --git a/graphics/pokemon/exeggutor/icon.png b/graphics/pokemon/exeggutor/icon.png index 181225841..007641b09 100644 Binary files a/graphics/pokemon/exeggutor/icon.png and b/graphics/pokemon/exeggutor/icon.png differ diff --git a/graphics/pokemon/exploud/icon.png b/graphics/pokemon/exploud/icon.png index f803aecab..3cb142dde 100644 Binary files a/graphics/pokemon/exploud/icon.png and b/graphics/pokemon/exploud/icon.png differ diff --git a/graphics/pokemon/feraligatr/icon.png b/graphics/pokemon/feraligatr/icon.png index 2fe3556a8..74aca6aea 100644 Binary files a/graphics/pokemon/feraligatr/icon.png and b/graphics/pokemon/feraligatr/icon.png differ diff --git a/graphics/pokemon/flygon/icon.png b/graphics/pokemon/flygon/icon.png index 10788b225..f0c4e165a 100644 Binary files a/graphics/pokemon/flygon/icon.png and b/graphics/pokemon/flygon/icon.png differ diff --git a/graphics/pokemon/foongus/icon.png b/graphics/pokemon/foongus/icon.png index f6e6171a4..c6e4ab426 100644 Binary files a/graphics/pokemon/foongus/icon.png and b/graphics/pokemon/foongus/icon.png differ diff --git a/graphics/pokemon/froslass/icon.png b/graphics/pokemon/froslass/icon.png index dfaec88ce..2869fb8de 100644 Binary files a/graphics/pokemon/froslass/icon.png and b/graphics/pokemon/froslass/icon.png differ diff --git a/graphics/pokemon/gallade/icon.png b/graphics/pokemon/gallade/icon.png index a31e02fbb..fce5123d9 100644 Binary files a/graphics/pokemon/gallade/icon.png and b/graphics/pokemon/gallade/icon.png differ diff --git a/graphics/pokemon/gastly/icon.png b/graphics/pokemon/gastly/icon.png index 7a28a0575..a5dc4527d 100644 Binary files a/graphics/pokemon/gastly/icon.png and b/graphics/pokemon/gastly/icon.png differ diff --git a/graphics/pokemon/genesect/icon.png b/graphics/pokemon/genesect/icon.png index 6ab5e6f03..a448db603 100644 Binary files a/graphics/pokemon/genesect/icon.png and b/graphics/pokemon/genesect/icon.png differ diff --git a/graphics/pokemon/giratina/icon.png b/graphics/pokemon/giratina/icon.png index 7a6ba19e9..235ea4721 100644 Binary files a/graphics/pokemon/giratina/icon.png and b/graphics/pokemon/giratina/icon.png differ diff --git a/graphics/pokemon/gliscor/icon.png b/graphics/pokemon/gliscor/icon.png index deddd792d..74f4126d9 100644 Binary files a/graphics/pokemon/gliscor/icon.png and b/graphics/pokemon/gliscor/icon.png differ diff --git a/graphics/pokemon/golett/icon.png b/graphics/pokemon/golett/icon.png index 20dd1f45a..a35131748 100644 Binary files a/graphics/pokemon/golett/icon.png and b/graphics/pokemon/golett/icon.png differ diff --git a/graphics/pokemon/gothita/icon.png b/graphics/pokemon/gothita/icon.png index 19da4895b..8d280f517 100644 Binary files a/graphics/pokemon/gothita/icon.png and b/graphics/pokemon/gothita/icon.png differ diff --git a/graphics/pokemon/gothorita/icon.png b/graphics/pokemon/gothorita/icon.png index d48dfbc96..9036dc6fc 100644 Binary files a/graphics/pokemon/gothorita/icon.png and b/graphics/pokemon/gothorita/icon.png differ diff --git a/graphics/pokemon/groudon/icon.png b/graphics/pokemon/groudon/icon.png index 1c237537b..69326145c 100644 Binary files a/graphics/pokemon/groudon/icon.png and b/graphics/pokemon/groudon/icon.png differ diff --git a/graphics/pokemon/gurdurr/icon.png b/graphics/pokemon/gurdurr/icon.png index 5808e6c6a..b445d735c 100644 Binary files a/graphics/pokemon/gurdurr/icon.png and b/graphics/pokemon/gurdurr/icon.png differ diff --git a/graphics/pokemon/gyarados/icon.png b/graphics/pokemon/gyarados/icon.png index 889943b04..41ccb5aee 100644 Binary files a/graphics/pokemon/gyarados/icon.png and b/graphics/pokemon/gyarados/icon.png differ diff --git a/graphics/pokemon/hariyama/anim_front.png b/graphics/pokemon/hariyama/anim_front.png index 7b55b728e..751b2cac4 100644 Binary files a/graphics/pokemon/hariyama/anim_front.png and b/graphics/pokemon/hariyama/anim_front.png differ diff --git a/graphics/pokemon/hariyama/normal.pal b/graphics/pokemon/hariyama/normal.pal index 6ed665912..c6cfb9da7 100644 --- a/graphics/pokemon/hariyama/normal.pal +++ b/graphics/pokemon/hariyama/normal.pal @@ -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 diff --git a/graphics/pokemon/haunter/icon.png b/graphics/pokemon/haunter/icon.png index 6de894850..ea52910dd 100644 Binary files a/graphics/pokemon/haunter/icon.png and b/graphics/pokemon/haunter/icon.png differ diff --git a/graphics/pokemon/hitmontop/icon.png b/graphics/pokemon/hitmontop/icon.png index a2af3bd24..7f8d63f91 100644 Binary files a/graphics/pokemon/hitmontop/icon.png and b/graphics/pokemon/hitmontop/icon.png differ diff --git a/graphics/pokemon/ho_oh/icon.png b/graphics/pokemon/ho_oh/icon.png index 7a7ce8af6..315683cc5 100644 Binary files a/graphics/pokemon/ho_oh/icon.png and b/graphics/pokemon/ho_oh/icon.png differ diff --git a/graphics/pokemon/hoppip/icon.png b/graphics/pokemon/hoppip/icon.png index 8a9b70834..ba010a365 100644 Binary files a/graphics/pokemon/hoppip/icon.png and b/graphics/pokemon/hoppip/icon.png differ diff --git a/graphics/pokemon/huntail/icon.png b/graphics/pokemon/huntail/icon.png index 0aa9a4055..42a800657 100644 Binary files a/graphics/pokemon/huntail/icon.png and b/graphics/pokemon/huntail/icon.png differ diff --git a/graphics/pokemon/hydreigon/icon.png b/graphics/pokemon/hydreigon/icon.png index 50e9b60a9..540b13637 100644 Binary files a/graphics/pokemon/hydreigon/icon.png and b/graphics/pokemon/hydreigon/icon.png differ diff --git a/graphics/pokemon/hypno/icon.png b/graphics/pokemon/hypno/icon.png index d9e0d8334..647e829d3 100644 Binary files a/graphics/pokemon/hypno/icon.png and b/graphics/pokemon/hypno/icon.png differ diff --git a/graphics/pokemon/infernape/icon.png b/graphics/pokemon/infernape/icon.png index 6c1669864..8eb9e955c 100644 Binary files a/graphics/pokemon/infernape/icon.png and b/graphics/pokemon/infernape/icon.png differ diff --git a/graphics/pokemon/karrablast/icon.png b/graphics/pokemon/karrablast/icon.png index f155236f2..9db6f2f4d 100644 Binary files a/graphics/pokemon/karrablast/icon.png and b/graphics/pokemon/karrablast/icon.png differ diff --git a/graphics/pokemon/keldeo/icon.png b/graphics/pokemon/keldeo/icon.png index 4d8c580f2..a7b3f96ab 100644 Binary files a/graphics/pokemon/keldeo/icon.png and b/graphics/pokemon/keldeo/icon.png differ diff --git a/graphics/pokemon/kingdra/icon.png b/graphics/pokemon/kingdra/icon.png index 02fdc7125..0873dedb4 100644 Binary files a/graphics/pokemon/kingdra/icon.png and b/graphics/pokemon/kingdra/icon.png differ diff --git a/graphics/pokemon/kingler/icon.png b/graphics/pokemon/kingler/icon.png index 34a729906..3f9d0b8b7 100644 Binary files a/graphics/pokemon/kingler/icon.png and b/graphics/pokemon/kingler/icon.png differ diff --git a/graphics/pokemon/koffing/icon.png b/graphics/pokemon/koffing/icon.png index dbd1d77c8..0c5b36150 100644 Binary files a/graphics/pokemon/koffing/icon.png and b/graphics/pokemon/koffing/icon.png differ diff --git a/graphics/pokemon/krabby/icon.png b/graphics/pokemon/krabby/icon.png index 46eff557d..8cedc348d 100644 Binary files a/graphics/pokemon/krabby/icon.png and b/graphics/pokemon/krabby/icon.png differ diff --git a/graphics/pokemon/kyurem/icon.png b/graphics/pokemon/kyurem/icon.png index 6e7f6c784..9883000b0 100644 Binary files a/graphics/pokemon/kyurem/icon.png and b/graphics/pokemon/kyurem/icon.png differ diff --git a/graphics/pokemon/lairon/icon.png b/graphics/pokemon/lairon/icon.png index 24bea9dfd..27cb6edaa 100644 Binary files a/graphics/pokemon/lairon/icon.png and b/graphics/pokemon/lairon/icon.png differ diff --git a/graphics/pokemon/landorus/icon.png b/graphics/pokemon/landorus/icon.png index b86a7cf7a..4b2ec8d4f 100644 Binary files a/graphics/pokemon/landorus/icon.png and b/graphics/pokemon/landorus/icon.png differ diff --git a/graphics/pokemon/larvesta/icon.png b/graphics/pokemon/larvesta/icon.png index 1a710b252..8050f8bfd 100644 Binary files a/graphics/pokemon/larvesta/icon.png and b/graphics/pokemon/larvesta/icon.png differ diff --git a/graphics/pokemon/latias/icon.png b/graphics/pokemon/latias/icon.png index d67b91b85..9c79f1e18 100644 Binary files a/graphics/pokemon/latias/icon.png and b/graphics/pokemon/latias/icon.png differ diff --git a/graphics/pokemon/latios/icon.png b/graphics/pokemon/latios/icon.png index 95590eb52..d63fb4710 100644 Binary files a/graphics/pokemon/latios/icon.png and b/graphics/pokemon/latios/icon.png differ diff --git a/graphics/pokemon/leafeon/icon.png b/graphics/pokemon/leafeon/icon.png index dd446932b..2aabf8025 100644 Binary files a/graphics/pokemon/leafeon/icon.png and b/graphics/pokemon/leafeon/icon.png differ diff --git a/graphics/pokemon/lileep/icon.png b/graphics/pokemon/lileep/icon.png index 0f3132ed4..034453bf9 100644 Binary files a/graphics/pokemon/lileep/icon.png and b/graphics/pokemon/lileep/icon.png differ diff --git a/graphics/pokemon/lugia/icon.png b/graphics/pokemon/lugia/icon.png index 17a3aaf74..fda93844e 100644 Binary files a/graphics/pokemon/lugia/icon.png and b/graphics/pokemon/lugia/icon.png differ diff --git a/graphics/pokemon/luxray/icon.png b/graphics/pokemon/luxray/icon.png index 20d02d897..9514dbc9b 100644 Binary files a/graphics/pokemon/luxray/icon.png and b/graphics/pokemon/luxray/icon.png differ diff --git a/graphics/pokemon/magnemite/icon.png b/graphics/pokemon/magnemite/icon.png index ffefd1a45..95b81cae0 100644 Binary files a/graphics/pokemon/magnemite/icon.png and b/graphics/pokemon/magnemite/icon.png differ diff --git a/graphics/pokemon/magneton/icon.png b/graphics/pokemon/magneton/icon.png index 733049b1d..bde234ea1 100644 Binary files a/graphics/pokemon/magneton/icon.png and b/graphics/pokemon/magneton/icon.png differ diff --git a/graphics/pokemon/manaphy/icon.png b/graphics/pokemon/manaphy/icon.png index 4c491d486..97dbb79c0 100644 Binary files a/graphics/pokemon/manaphy/icon.png and b/graphics/pokemon/manaphy/icon.png differ diff --git a/graphics/pokemon/manectric/icon.png b/graphics/pokemon/manectric/icon.png index 5379bbafa..5d7f3e950 100644 Binary files a/graphics/pokemon/manectric/icon.png and b/graphics/pokemon/manectric/icon.png differ diff --git a/graphics/pokemon/marowak/icon.png b/graphics/pokemon/marowak/icon.png index a97389705..af56d377c 100644 Binary files a/graphics/pokemon/marowak/icon.png and b/graphics/pokemon/marowak/icon.png differ diff --git a/graphics/pokemon/masquerain/anim_front.png b/graphics/pokemon/masquerain/anim_front.png index 7508ae76d..190c8d079 100644 Binary files a/graphics/pokemon/masquerain/anim_front.png and b/graphics/pokemon/masquerain/anim_front.png differ diff --git a/graphics/pokemon/masquerain/normal.pal b/graphics/pokemon/masquerain/normal.pal index bd8d9c4c7..3d0291bad 100644 --- a/graphics/pokemon/masquerain/normal.pal +++ b/graphics/pokemon/masquerain/normal.pal @@ -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 diff --git a/graphics/pokemon/mawile/icon.png b/graphics/pokemon/mawile/icon.png index ea60047c8..f6605a647 100644 Binary files a/graphics/pokemon/mawile/icon.png and b/graphics/pokemon/mawile/icon.png differ diff --git a/graphics/pokemon/medicham/icon.png b/graphics/pokemon/medicham/icon.png index 9e4bbc27c..798839283 100644 Binary files a/graphics/pokemon/medicham/icon.png and b/graphics/pokemon/medicham/icon.png differ diff --git a/graphics/pokemon/meganium/icon.png b/graphics/pokemon/meganium/icon.png index e05a33daf..d7d390fe9 100644 Binary files a/graphics/pokemon/meganium/icon.png and b/graphics/pokemon/meganium/icon.png differ diff --git a/graphics/pokemon/meloetta/icon.png b/graphics/pokemon/meloetta/icon.png index 376f3953a..f640f8099 100644 Binary files a/graphics/pokemon/meloetta/icon.png and b/graphics/pokemon/meloetta/icon.png differ diff --git a/graphics/pokemon/meowth/icon.png b/graphics/pokemon/meowth/icon.png index b0a11aadd..b721e3440 100644 Binary files a/graphics/pokemon/meowth/icon.png and b/graphics/pokemon/meowth/icon.png differ diff --git a/graphics/pokemon/mesprit/icon.png b/graphics/pokemon/mesprit/icon.png index 86368bae2..2e5343d28 100644 Binary files a/graphics/pokemon/mesprit/icon.png and b/graphics/pokemon/mesprit/icon.png differ diff --git a/graphics/pokemon/metagross/mega/back.png b/graphics/pokemon/metagross/mega/back.png index 00bfdd181..86c2b6e14 100644 Binary files a/graphics/pokemon/metagross/mega/back.png and b/graphics/pokemon/metagross/mega/back.png differ diff --git a/graphics/pokemon/metagross/mega/front.png b/graphics/pokemon/metagross/mega/front.png index 6ed2cfbeb..1ebb0470a 100644 Binary files a/graphics/pokemon/metagross/mega/front.png and b/graphics/pokemon/metagross/mega/front.png differ diff --git a/graphics/pokemon/metang/icon.png b/graphics/pokemon/metang/icon.png index 3916b6531..8d27afff4 100644 Binary files a/graphics/pokemon/metang/icon.png and b/graphics/pokemon/metang/icon.png differ diff --git a/graphics/pokemon/mew/icon.png b/graphics/pokemon/mew/icon.png index 6e7175f43..d4b6ec9a7 100644 Binary files a/graphics/pokemon/mew/icon.png and b/graphics/pokemon/mew/icon.png differ diff --git a/graphics/pokemon/mewtwo/icon.png b/graphics/pokemon/mewtwo/icon.png index 8463a04dd..b0dc90165 100644 Binary files a/graphics/pokemon/mewtwo/icon.png and b/graphics/pokemon/mewtwo/icon.png differ diff --git a/graphics/pokemon/mienfoo/icon.png b/graphics/pokemon/mienfoo/icon.png index b0a6ecf41..e5c5367ee 100644 Binary files a/graphics/pokemon/mienfoo/icon.png and b/graphics/pokemon/mienfoo/icon.png differ diff --git a/graphics/pokemon/mienshao/icon.png b/graphics/pokemon/mienshao/icon.png index d73849304..ff001b212 100644 Binary files a/graphics/pokemon/mienshao/icon.png and b/graphics/pokemon/mienshao/icon.png differ diff --git a/graphics/pokemon/milotic/icon.png b/graphics/pokemon/milotic/icon.png index 5caf28bad..f67de2931 100644 Binary files a/graphics/pokemon/milotic/icon.png and b/graphics/pokemon/milotic/icon.png differ diff --git a/graphics/pokemon/minccino/icon.png b/graphics/pokemon/minccino/icon.png index 27dd5405d..fbddf0e08 100644 Binary files a/graphics/pokemon/minccino/icon.png and b/graphics/pokemon/minccino/icon.png differ diff --git a/graphics/pokemon/mismagius/icon.png b/graphics/pokemon/mismagius/icon.png index ad707f8cd..07e075c1e 100644 Binary files a/graphics/pokemon/mismagius/icon.png and b/graphics/pokemon/mismagius/icon.png differ diff --git a/graphics/pokemon/moltres/icon.png b/graphics/pokemon/moltres/icon.png index 99affaa0b..70de85450 100644 Binary files a/graphics/pokemon/moltres/icon.png and b/graphics/pokemon/moltres/icon.png differ diff --git a/graphics/pokemon/monferno/icon.png b/graphics/pokemon/monferno/icon.png index 8a01ec515..9fbfd1255 100644 Binary files a/graphics/pokemon/monferno/icon.png and b/graphics/pokemon/monferno/icon.png differ diff --git a/graphics/pokemon/mothim/icon.png b/graphics/pokemon/mothim/icon.png index ce6f8f0f6..331245868 100644 Binary files a/graphics/pokemon/mothim/icon.png and b/graphics/pokemon/mothim/icon.png differ diff --git a/graphics/pokemon/muk/icon.png b/graphics/pokemon/muk/icon.png index f56a9b367..3168d1be4 100644 Binary files a/graphics/pokemon/muk/icon.png and b/graphics/pokemon/muk/icon.png differ diff --git a/graphics/pokemon/munna/icon.png b/graphics/pokemon/munna/icon.png index c7b2a7b04..c97d44e6d 100644 Binary files a/graphics/pokemon/munna/icon.png and b/graphics/pokemon/munna/icon.png differ diff --git a/graphics/pokemon/musharna/icon.png b/graphics/pokemon/musharna/icon.png index 4dfba9d12..c51d8ade6 100644 Binary files a/graphics/pokemon/musharna/icon.png and b/graphics/pokemon/musharna/icon.png differ diff --git a/graphics/pokemon/nidoking/icon.png b/graphics/pokemon/nidoking/icon.png index 377cb6672..93d0b5f80 100644 Binary files a/graphics/pokemon/nidoking/icon.png and b/graphics/pokemon/nidoking/icon.png differ diff --git a/graphics/pokemon/oddish/icon.png b/graphics/pokemon/oddish/icon.png index 32515b89f..bef94316f 100644 Binary files a/graphics/pokemon/oddish/icon.png and b/graphics/pokemon/oddish/icon.png differ diff --git a/graphics/pokemon/onix/icon.png b/graphics/pokemon/onix/icon.png index 947ead4ee..b4de2a1cd 100644 Binary files a/graphics/pokemon/onix/icon.png and b/graphics/pokemon/onix/icon.png differ diff --git a/graphics/pokemon/palkia/icon.png b/graphics/pokemon/palkia/icon.png index d84e9b8c3..1476f20af 100644 Binary files a/graphics/pokemon/palkia/icon.png and b/graphics/pokemon/palkia/icon.png differ diff --git a/graphics/pokemon/paras/icon.png b/graphics/pokemon/paras/icon.png index 26d937231..6bc817d0b 100644 Binary files a/graphics/pokemon/paras/icon.png and b/graphics/pokemon/paras/icon.png differ diff --git a/graphics/pokemon/parasect/icon.png b/graphics/pokemon/parasect/icon.png index c6aaff12d..27b8e0989 100644 Binary files a/graphics/pokemon/parasect/icon.png and b/graphics/pokemon/parasect/icon.png differ diff --git a/graphics/pokemon/pelipper/icon.png b/graphics/pokemon/pelipper/icon.png index 43ae7c276..49debae71 100644 Binary files a/graphics/pokemon/pelipper/icon.png and b/graphics/pokemon/pelipper/icon.png differ diff --git a/graphics/pokemon/phione/icon.png b/graphics/pokemon/phione/icon.png index 1bfec4bbd..c24a936ff 100644 Binary files a/graphics/pokemon/phione/icon.png and b/graphics/pokemon/phione/icon.png differ diff --git a/graphics/pokemon/pichu/icon.png b/graphics/pokemon/pichu/icon.png index 5e3de4b99..d29fa7fb4 100644 Binary files a/graphics/pokemon/pichu/icon.png and b/graphics/pokemon/pichu/icon.png differ diff --git a/graphics/pokemon/pignite/icon.png b/graphics/pokemon/pignite/icon.png index 78b1a8d72..1190d639a 100644 Binary files a/graphics/pokemon/pignite/icon.png and b/graphics/pokemon/pignite/icon.png differ diff --git a/graphics/pokemon/politoed/icon.png b/graphics/pokemon/politoed/icon.png index 8ea308aa3..ffc6a38a4 100644 Binary files a/graphics/pokemon/politoed/icon.png and b/graphics/pokemon/politoed/icon.png differ diff --git a/graphics/pokemon/probopass/icon.png b/graphics/pokemon/probopass/icon.png index fe2df5f2e..dbbe9c16a 100644 Binary files a/graphics/pokemon/probopass/icon.png and b/graphics/pokemon/probopass/icon.png differ diff --git a/graphics/pokemon/raikou/icon.png b/graphics/pokemon/raikou/icon.png index fb0d48a5f..77cc29d7e 100644 Binary files a/graphics/pokemon/raikou/icon.png and b/graphics/pokemon/raikou/icon.png differ diff --git a/graphics/pokemon/rapidash/icon.png b/graphics/pokemon/rapidash/icon.png index 92dae70a6..a15a0a18a 100644 Binary files a/graphics/pokemon/rapidash/icon.png and b/graphics/pokemon/rapidash/icon.png differ diff --git a/graphics/pokemon/reshiram/icon.png b/graphics/pokemon/reshiram/icon.png index 721b3a70f..9bd6457f3 100644 Binary files a/graphics/pokemon/reshiram/icon.png and b/graphics/pokemon/reshiram/icon.png differ diff --git a/graphics/pokemon/reuniclus/anim_front.png b/graphics/pokemon/reuniclus/anim_front.png index 9f9f38975..c635f0bef 100644 Binary files a/graphics/pokemon/reuniclus/anim_front.png and b/graphics/pokemon/reuniclus/anim_front.png differ diff --git a/graphics/pokemon/rotom/icon.png b/graphics/pokemon/rotom/icon.png index 354b6fd3d..e2ecc8b80 100644 Binary files a/graphics/pokemon/rotom/icon.png and b/graphics/pokemon/rotom/icon.png differ diff --git a/graphics/pokemon/rufflet/icon.png b/graphics/pokemon/rufflet/icon.png index 331e60465..f9129355a 100644 Binary files a/graphics/pokemon/rufflet/icon.png and b/graphics/pokemon/rufflet/icon.png differ diff --git a/graphics/pokemon/salamence/icon.png b/graphics/pokemon/salamence/icon.png index 16cdf981f..74b4ae776 100644 Binary files a/graphics/pokemon/salamence/icon.png and b/graphics/pokemon/salamence/icon.png differ diff --git a/graphics/pokemon/sandslash/icon.png b/graphics/pokemon/sandslash/icon.png index a1d72a1ba..18970df15 100644 Binary files a/graphics/pokemon/sandslash/icon.png and b/graphics/pokemon/sandslash/icon.png differ diff --git a/graphics/pokemon/scraggy/icon.png b/graphics/pokemon/scraggy/icon.png index e63301f36..f1baf8d07 100644 Binary files a/graphics/pokemon/scraggy/icon.png and b/graphics/pokemon/scraggy/icon.png differ diff --git a/graphics/pokemon/sentret/icon.png b/graphics/pokemon/sentret/icon.png index 9a8040833..e95d75ccd 100644 Binary files a/graphics/pokemon/sentret/icon.png and b/graphics/pokemon/sentret/icon.png differ diff --git a/graphics/pokemon/seviper/icon.png b/graphics/pokemon/seviper/icon.png index 192e40a16..f6beb9f85 100644 Binary files a/graphics/pokemon/seviper/icon.png and b/graphics/pokemon/seviper/icon.png differ diff --git a/graphics/pokemon/sewaddle/icon.png b/graphics/pokemon/sewaddle/icon.png index 755c745d7..ae517307b 100644 Binary files a/graphics/pokemon/sewaddle/icon.png and b/graphics/pokemon/sewaddle/icon.png differ diff --git a/graphics/pokemon/sharpedo/icon.png b/graphics/pokemon/sharpedo/icon.png index 2782511a3..87a1c7e40 100644 Binary files a/graphics/pokemon/sharpedo/icon.png and b/graphics/pokemon/sharpedo/icon.png differ diff --git a/graphics/pokemon/shellder/icon.png b/graphics/pokemon/shellder/icon.png index 8d74f8262..8ffeb3edf 100644 Binary files a/graphics/pokemon/shellder/icon.png and b/graphics/pokemon/shellder/icon.png differ diff --git a/graphics/pokemon/shiftry/icon.png b/graphics/pokemon/shiftry/icon.png index 14b4bdab6..3d2be13a6 100644 Binary files a/graphics/pokemon/shiftry/icon.png and b/graphics/pokemon/shiftry/icon.png differ diff --git a/graphics/pokemon/sigilyph/icon.png b/graphics/pokemon/sigilyph/icon.png index c599ce22a..afaf880d5 100644 Binary files a/graphics/pokemon/sigilyph/icon.png and b/graphics/pokemon/sigilyph/icon.png differ diff --git a/graphics/pokemon/slakoth/icon.png b/graphics/pokemon/slakoth/icon.png index 3b408571f..e11811efe 100644 Binary files a/graphics/pokemon/slakoth/icon.png and b/graphics/pokemon/slakoth/icon.png differ diff --git a/graphics/pokemon/slowking/icon.png b/graphics/pokemon/slowking/icon.png index c4d5bdbe7..8527e8982 100644 Binary files a/graphics/pokemon/slowking/icon.png and b/graphics/pokemon/slowking/icon.png differ diff --git a/graphics/pokemon/snorlax/icon.png b/graphics/pokemon/snorlax/icon.png index efb140e86..36aeeabee 100644 Binary files a/graphics/pokemon/snorlax/icon.png and b/graphics/pokemon/snorlax/icon.png differ diff --git a/graphics/pokemon/solrock/icon.png b/graphics/pokemon/solrock/icon.png index 4a0410cb5..07a416c28 100644 Binary files a/graphics/pokemon/solrock/icon.png and b/graphics/pokemon/solrock/icon.png differ diff --git a/graphics/pokemon/staraptor/icon.png b/graphics/pokemon/staraptor/icon.png index 1116f07df..ecad4e21b 100644 Binary files a/graphics/pokemon/staraptor/icon.png and b/graphics/pokemon/staraptor/icon.png differ diff --git a/graphics/pokemon/staravia/icon.png b/graphics/pokemon/staravia/icon.png index 468f38dd2..8fcb75d87 100644 Binary files a/graphics/pokemon/staravia/icon.png and b/graphics/pokemon/staravia/icon.png differ diff --git a/graphics/pokemon/steelix/icon.png b/graphics/pokemon/steelix/icon.png index 2cceec69a..defe78d7d 100644 Binary files a/graphics/pokemon/steelix/icon.png and b/graphics/pokemon/steelix/icon.png differ diff --git a/graphics/pokemon/suicune/icon.png b/graphics/pokemon/suicune/icon.png index 48a3d97fb..fbaff5a8c 100644 Binary files a/graphics/pokemon/suicune/icon.png and b/graphics/pokemon/suicune/icon.png differ diff --git a/graphics/pokemon/swablu/icon.png b/graphics/pokemon/swablu/icon.png index c1aa25e99..46be1f403 100644 Binary files a/graphics/pokemon/swablu/icon.png and b/graphics/pokemon/swablu/icon.png differ diff --git a/graphics/pokemon/swalot/icon.png b/graphics/pokemon/swalot/icon.png index 3611b27fe..09f7162d2 100644 Binary files a/graphics/pokemon/swalot/icon.png and b/graphics/pokemon/swalot/icon.png differ diff --git a/graphics/pokemon/tauros/icon.png b/graphics/pokemon/tauros/icon.png index 08975b0bc..de4bdd330 100644 Binary files a/graphics/pokemon/tauros/icon.png and b/graphics/pokemon/tauros/icon.png differ diff --git a/graphics/pokemon/tentacool/icon.png b/graphics/pokemon/tentacool/icon.png index 5870f50b8..64a9ef364 100644 Binary files a/graphics/pokemon/tentacool/icon.png and b/graphics/pokemon/tentacool/icon.png differ diff --git a/graphics/pokemon/tentacruel/icon.png b/graphics/pokemon/tentacruel/icon.png index 60bfe216d..e6a797e52 100644 Binary files a/graphics/pokemon/tentacruel/icon.png and b/graphics/pokemon/tentacruel/icon.png differ diff --git a/graphics/pokemon/thundurus/icon.png b/graphics/pokemon/thundurus/icon.png index 9295bb752..9b1166511 100644 Binary files a/graphics/pokemon/thundurus/icon.png and b/graphics/pokemon/thundurus/icon.png differ diff --git a/graphics/pokemon/tirtouga/icon.png b/graphics/pokemon/tirtouga/icon.png index feb79c7d2..dfb298376 100644 Binary files a/graphics/pokemon/tirtouga/icon.png and b/graphics/pokemon/tirtouga/icon.png differ diff --git a/graphics/pokemon/tornadus/icon.png b/graphics/pokemon/tornadus/icon.png index a95eccdb3..271e4c6b6 100644 Binary files a/graphics/pokemon/tornadus/icon.png and b/graphics/pokemon/tornadus/icon.png differ diff --git a/graphics/pokemon/tropius/icon.png b/graphics/pokemon/tropius/icon.png index 647767ca3..9e7b61b53 100644 Binary files a/graphics/pokemon/tropius/icon.png and b/graphics/pokemon/tropius/icon.png differ diff --git a/graphics/pokemon/trubbish/icon.png b/graphics/pokemon/trubbish/icon.png index cbf0483f6..b7fa282cd 100644 Binary files a/graphics/pokemon/trubbish/icon.png and b/graphics/pokemon/trubbish/icon.png differ diff --git a/graphics/pokemon/typhlosion/hisuian/normal.pal b/graphics/pokemon/typhlosion/hisuian/normal.pal index 0dfea70f6..8a9fe94af 100755 --- a/graphics/pokemon/typhlosion/hisuian/normal.pal +++ b/graphics/pokemon/typhlosion/hisuian/normal.pal @@ -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 diff --git a/graphics/pokemon/typhlosion/hisuian/pal.pal b/graphics/pokemon/typhlosion/hisuian/pal.pal deleted file mode 100755 index 8a9fe94af..000000000 --- a/graphics/pokemon/typhlosion/hisuian/pal.pal +++ /dev/null @@ -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 diff --git a/graphics/pokemon/typhlosion/icon.png b/graphics/pokemon/typhlosion/icon.png index b69680648..e5e5ea51c 100644 Binary files a/graphics/pokemon/typhlosion/icon.png and b/graphics/pokemon/typhlosion/icon.png differ diff --git a/graphics/pokemon/tyranitar/icon.png b/graphics/pokemon/tyranitar/icon.png index 3ab06613c..b692b9976 100644 Binary files a/graphics/pokemon/tyranitar/icon.png and b/graphics/pokemon/tyranitar/icon.png differ diff --git a/graphics/pokemon/vanilluxe/icon.png b/graphics/pokemon/vanilluxe/icon.png index a7814563b..c2f85c1e3 100644 Binary files a/graphics/pokemon/vanilluxe/icon.png and b/graphics/pokemon/vanilluxe/icon.png differ diff --git a/graphics/pokemon/venusaur/icon.png b/graphics/pokemon/venusaur/icon.png index c841ddde4..ce3b2290a 100644 Binary files a/graphics/pokemon/venusaur/icon.png and b/graphics/pokemon/venusaur/icon.png differ diff --git a/graphics/pokemon/victini/icon.png b/graphics/pokemon/victini/icon.png index dfbab1baa..686f4a499 100644 Binary files a/graphics/pokemon/victini/icon.png and b/graphics/pokemon/victini/icon.png differ diff --git a/graphics/pokemon/vileplume/icon.png b/graphics/pokemon/vileplume/icon.png index a3cb2b0b5..3dcf11ce3 100644 Binary files a/graphics/pokemon/vileplume/icon.png and b/graphics/pokemon/vileplume/icon.png differ diff --git a/graphics/pokemon/virizion/icon.png b/graphics/pokemon/virizion/icon.png index 4f7390e1f..68c0abd73 100644 Binary files a/graphics/pokemon/virizion/icon.png and b/graphics/pokemon/virizion/icon.png differ diff --git a/graphics/pokemon/volcarona/icon.png b/graphics/pokemon/volcarona/icon.png index c518ab0b4..a37d965d9 100644 Binary files a/graphics/pokemon/volcarona/icon.png and b/graphics/pokemon/volcarona/icon.png differ diff --git a/graphics/pokemon/voltorb/icon.png b/graphics/pokemon/voltorb/icon.png index 551dbf281..f0113355b 100644 Binary files a/graphics/pokemon/voltorb/icon.png and b/graphics/pokemon/voltorb/icon.png differ diff --git a/graphics/pokemon/wailord/icon.png b/graphics/pokemon/wailord/icon.png index a6a6ff135..de5a2c707 100644 Binary files a/graphics/pokemon/wailord/icon.png and b/graphics/pokemon/wailord/icon.png differ diff --git a/graphics/pokemon/watchog/icon.png b/graphics/pokemon/watchog/icon.png index 9ea2f1330..4051ebde8 100644 Binary files a/graphics/pokemon/watchog/icon.png and b/graphics/pokemon/watchog/icon.png differ diff --git a/graphics/pokemon/weezing/icon.png b/graphics/pokemon/weezing/icon.png index c39338498..5c2421a2a 100644 Binary files a/graphics/pokemon/weezing/icon.png and b/graphics/pokemon/weezing/icon.png differ diff --git a/graphics/pokemon/woobat/icon.png b/graphics/pokemon/woobat/icon.png index 354353e88..c3640d5ad 100644 Binary files a/graphics/pokemon/woobat/icon.png and b/graphics/pokemon/woobat/icon.png differ diff --git a/graphics/pokemon/wormadam/icon.png b/graphics/pokemon/wormadam/icon.png index eb622fca2..866acd17b 100644 Binary files a/graphics/pokemon/wormadam/icon.png and b/graphics/pokemon/wormadam/icon.png differ diff --git a/graphics/pokemon/wormadam/sandy_cloak/icon.png b/graphics/pokemon/wormadam/sandy_cloak/icon.png index 2c165141b..a45417a61 100644 Binary files a/graphics/pokemon/wormadam/sandy_cloak/icon.png and b/graphics/pokemon/wormadam/sandy_cloak/icon.png differ diff --git a/graphics/pokemon/wormadam/trash_cloak/icon.png b/graphics/pokemon/wormadam/trash_cloak/icon.png index f971e3fb5..6834629e9 100644 Binary files a/graphics/pokemon/wormadam/trash_cloak/icon.png and b/graphics/pokemon/wormadam/trash_cloak/icon.png differ diff --git a/graphics/pokemon/wynaut/icon.png b/graphics/pokemon/wynaut/icon.png index 042c18235..c3f81995e 100644 Binary files a/graphics/pokemon/wynaut/icon.png and b/graphics/pokemon/wynaut/icon.png differ diff --git a/graphics/pokemon/yanmega/anim_front.png b/graphics/pokemon/yanmega/anim_front.png index d50d34b73..f5b4db9af 100644 Binary files a/graphics/pokemon/yanmega/anim_front.png and b/graphics/pokemon/yanmega/anim_front.png differ diff --git a/graphics/pokemon/zangoose/icon.png b/graphics/pokemon/zangoose/icon.png index 83a9ce97f..80f3b7c45 100644 Binary files a/graphics/pokemon/zangoose/icon.png and b/graphics/pokemon/zangoose/icon.png differ diff --git a/graphics/pokemon/zekrom/icon.png b/graphics/pokemon/zekrom/icon.png index 33115bae9..c4380ec69 100644 Binary files a/graphics/pokemon/zekrom/icon.png and b/graphics/pokemon/zekrom/icon.png differ diff --git a/graphics/pokemon/zoroark/icon.png b/graphics/pokemon/zoroark/icon.png index 08d5206f3..338a576a4 100644 Binary files a/graphics/pokemon/zoroark/icon.png and b/graphics/pokemon/zoroark/icon.png differ diff --git a/graphics/pokemon/zweilous/icon.png b/graphics/pokemon/zweilous/icon.png index 7baef54fb..1c0a166af 100644 Binary files a/graphics/pokemon/zweilous/icon.png and b/graphics/pokemon/zweilous/icon.png differ diff --git a/include/battle.h b/include/battle.h index f1818d583..466a9138d 100644 --- a/include/battle.h +++ b/include/battle.h @@ -3,6 +3,7 @@ // should they be included here or included individually by every file? #include "constants/battle.h" +#include "constants/form_change_types.h" #include "battle_main.h" #include "battle_message.h" #include "battle_util.h" @@ -61,6 +62,7 @@ struct ResourceFlags struct DisableStruct { u32 transformedMonPersonality; + u32 transformedMonOtId; u16 disabledMove; u16 encoredMove; u8 protectUses; @@ -273,8 +275,8 @@ struct AiPartyMon struct AIPartyData // Opposing battlers - party mons. { - struct AiPartyMon mons[2][PARTY_SIZE]; // 2 parties(player, opponent). Used to save information on opposing party. - u8 count[2]; + struct AiPartyMon mons[NUM_BATTLE_SIDES][PARTY_SIZE]; // 2 parties(player, opponent). Used to save information on opposing party. + u8 count[NUM_BATTLE_SIDES]; }; struct AiLogicData @@ -478,13 +480,7 @@ struct LinkBattlerHeader struct MegaEvolutionData { u8 toEvolve; // As flags using gBitTable. - u8 evolvedPartyIds[2]; // As flags using gBitTable; bool8 alreadyEvolved[4]; // Array id is used for mon position. - u16 evolvedSpecies[MAX_BATTLERS_COUNT]; - u16 playerEvolvedSpecies; - u8 primalRevertedPartyIds[2]; // As flags using gBitTable; - u16 primalRevertedSpecies[MAX_BATTLERS_COUNT]; - u16 playerPrimalRevertedSpecies; u8 battlerId; bool8 playerSelect; u8 triggerSpriteId; @@ -518,7 +514,7 @@ struct ZMoveData u8 splits[MAX_BATTLERS_COUNT]; }; -struct StolenItem +struct LostItem { u16 originalItem:15; u16 stolen:1; @@ -582,8 +578,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; @@ -643,7 +637,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 @@ -663,6 +657,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) @@ -721,6 +724,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 @@ -964,6 +978,7 @@ extern u8 gBattlerStatusSummaryTaskId[MAX_BATTLERS_COUNT]; extern u8 gBattlerInMenuId; extern bool8 gDoingBattleAnim; extern u32 gTransformedPersonalities[MAX_BATTLERS_COUNT]; +extern u32 gTransformedOtIds[MAX_BATTLERS_COUNT]; extern u8 gPlayerDpadHoldFrames; extern struct BattleSpriteData *gBattleSpritesDataPtr; extern struct MonSpritesGfx *gMonSpritesGfxPtr; diff --git a/include/battle_ai_switch_items.h b/include/battle_ai_switch_items.h index 70dc41b34..622593b6d 100644 --- a/include/battle_ai_switch_items.h +++ b/include/battle_ai_switch_items.h @@ -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); diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index 11eba7b66..1a0fbc264 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -9,7 +9,8 @@ bool32 AI_RandLessThan(u8 val); void RecordLastUsedMoveByTarget(void); -bool32 IsBattlerAIControlled(u32 battlerId); +bool32 BattlerHasAi(u32 battlerId); +bool32 IsAiBattlerAware(u32 battlerId); void ClearBattlerMoveHistory(u8 battlerId); void RecordLastUsedMoveBy(u32 battlerId, u32 move); void RecordKnownMove(u8 battlerId, u32 move); @@ -129,6 +130,7 @@ bool32 IsSemiInvulnerable(u8 battlerDef, u16 move); // status checks bool32 AI_CanBeBurned(u8 battler, u16 ability); +bool32 AI_CanGetFrostbite(u8 battler, u16 ability); bool32 AI_CanBeConfused(u8 battler, u16 ability); bool32 AI_CanSleep(u8 battler, u16 ability); bool32 IsBattlerIncapacitated(u8 battler, u16 ability); @@ -139,11 +141,13 @@ bool32 AI_CanParalyze(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u1 bool32 AI_CanConfuse(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 battlerAtkPartner, u16 move, u16 partnerMove); bool32 ShouldBurnSelf(u8 battler, u16 ability); bool32 AI_CanBurn(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 battlerAtkPartner, u16 move, u16 partnerMove); +bool32 AI_CanGiveFrostbite(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 battlerAtkPartner, u16 move, u16 partnerMove); bool32 AI_CanBeInfatuated(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 atkGender, u8 defGender); bool32 AnyPartyMemberStatused(u8 battlerId, bool32 checkSoundproof); u32 ShouldTryToFlinch(u8 battlerAtk, u8 battlerDef, u16 atkAbility, u16 defAbility, u16 move); bool32 ShouldTrap(u8 battlerAtk, u8 battlerDef, u16 move); bool32 IsWakeupTurn(u8 battler); +bool32 AI_IsBattlerAsleepOrComatose(u8 battlerId); // partner logic u16 GetAllyChosenMove(u8 battlerId); @@ -168,10 +172,11 @@ bool32 SideHasMoveSplit(u8 battlerId, u8 split); // score increases void IncreaseStatUpScore(u8 battlerAtk, u8 battlerDef, u8 statId, s16 *score); -void IncreasePoisonScore(u8 battlerAtk, u8 battlerdef, u16 move, s16 *score); -void IncreaseBurnScore(u8 battlerAtk, u8 battlerdef, u16 move, s16 *score); +void IncreasePoisonScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score); +void IncreaseBurnScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score); void IncreaseParalyzeScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score); void IncreaseSleepScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score); void IncreaseConfusionScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score); +void IncreaseFrostbiteScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score); -#endif //GUARD_BATTLE_AI_UTIL_H \ No newline at end of file +#endif //GUARD_BATTLE_AI_UTIL_H diff --git a/include/battle_gfx_sfx_util.h b/include/battle_gfx_sfx_util.h index 491d5fefd..9a0b79c31 100644 --- a/include/battle_gfx_sfx_util.h +++ b/include/battle_gfx_sfx_util.h @@ -23,7 +23,7 @@ bool8 BattleInitAllSprites(u8 *state1, u8 *battlerId); void ClearSpritesHealthboxAnimData(void); void CopyAllBattleSpritesInvisibilities(void); void CopyBattleSpriteInvisibility(u8 battlerId); -void HandleSpeciesGfxDataChange(u8 attacker, u8 target, bool8 notTransform, bool32 megaEvo, bool8 trackEnemyPersonality); +void HandleSpeciesGfxDataChange(u8 attacker, u8 target, bool8 castform, bool32 megaEvo, bool8 trackEnemyPersonality); void BattleLoadSubstituteOrMonSpriteGfx(u8 battlerId, bool8 loadMonSprite); void LoadBattleMonGfxAndAnimate(u8 battlerId, bool8 loadMonSprite, u8 spriteId); void TrySetBehindSubstituteSpriteBit(u8 battlerId, u16 move); diff --git a/include/battle_interface.h b/include/battle_interface.h index e0f30b309..e2937748a 100644 --- a/include/battle_interface.h +++ b/include/battle_interface.h @@ -81,7 +81,6 @@ u8 CreateSafariPlayerHealthboxSprites(void); void SetBattleBarStruct(u8 battler, u8 healthboxSpriteId, s32 maxVal, s32 currVal, s32 receivedValue); void SetHealthboxSpriteInvisible(u8 healthboxSpriteId); void SetHealthboxSpriteVisible(u8 healthboxSpriteId); -void DestoryHealthboxSprite(u8 healthboxSpriteId); void DummyBattleInterfaceFunc(u8 healthboxSpriteId, bool8 isDoubleBattleBankOnly); void UpdateOamPriorityInAllHealthboxes(u8 priority, bool32 hideHpBoxes); void InitBattlerHealthboxCoords(u8 battler); diff --git a/include/battle_main.h b/include/battle_main.h index 8d1aad454..4f20e4c17 100644 --- a/include/battle_main.h +++ b/include/battle_main.h @@ -70,6 +70,8 @@ void SpecialStatusesClear(void); void SetTypeBeforeUsingMove(u16 move, u8 battlerAtk); bool32 IsWildMonSmart(void); u8 CreateNPCTrainerPartyFromTrainer(struct Pokemon *party, const struct Trainer *trainer, bool32 firstTrainer, u32 battleTypeFlags); +void ModifyPersonalityForNature(u32 *personality, u32 newNature); +u32 GeneratePersonalityForGender(u32 gender, u32 species); extern struct MultiPartnerMenuPokemon gMultiPartnerParty[MULTI_PARTY_SIZE]; diff --git a/include/battle_message.h b/include/battle_message.h index 19f8bc4ca..93bb63022 100644 --- a/include/battle_message.h +++ b/include/battle_message.h @@ -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); diff --git a/include/battle_script_commands.h b/include/battle_script_commands.h index d65728628..dcf601e80 100644 --- a/include/battle_script_commands.h +++ b/include/battle_script_commands.h @@ -46,6 +46,7 @@ u8 GetCatchingBattler(void); u32 GetHighestStatId(u32 battlerId); bool32 ProteanTryChangeType(u32 battler, u32 ability, u32 move, u32 moveType); bool32 DoSwitchInAbilitiesItems(u32 battlerId); +u8 GetFirstFaintedPartyIndex(u8 battlerId); extern void (* const gBattleScriptingCommandsTable[])(void); extern const u8 gBattlePalaceNatureToMoveGroupLikelihood[NUM_NATURES][4]; diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 248f28119..d387fd155 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -110,9 +110,12 @@ extern const u8 BattleScript_MoveUsedWokeUp[]; extern const u8 BattleScript_MonWokeUpInUproar[]; extern const u8 BattleScript_PoisonTurnDmg[]; extern const u8 BattleScript_BurnTurnDmg[]; +extern const u8 BattleScript_FrostbiteTurnDmg[]; extern const u8 BattleScript_MoveUsedIsFrozen[]; extern const u8 BattleScript_MoveUsedUnfroze[]; +extern const u8 BattleScript_MoveUsedUnfrostbite[]; extern const u8 BattleScript_DefrostedViaFireMove[]; +extern const u8 BattleScript_FrostbiteHealedViaFireMove[]; extern const u8 BattleScript_MoveUsedIsParalyzed[]; extern const u8 BattleScript_MoveUsedFlinched[]; extern const u8 BattleScript_PrintUproarOverTurns[]; @@ -133,6 +136,7 @@ extern const u8 BattleScript_MoveEffectSleep[]; extern const u8 BattleScript_YawnMakesAsleep[]; extern const u8 BattleScript_MoveEffectPoison[]; extern const u8 BattleScript_MoveEffectBurn[]; +extern const u8 BattleScript_MoveEffectFrostbite[]; extern const u8 BattleScript_MoveEffectFreeze[]; extern const u8 BattleScript_MoveEffectParalysis[]; extern const u8 BattleScript_MoveEffectUproar[]; @@ -151,9 +155,6 @@ extern const u8 BattleScript_TraceActivatesEnd3[]; extern const u8 BattleScript_RainDishActivates[]; extern const u8 BattleScript_SandstreamActivates[]; extern const u8 BattleScript_ShedSkinActivates[]; -extern const u8 BattleScript_WeatherFormChanges[]; -extern const u8 BattleScript_WeatherFormChangesLoop[]; -extern const u8 BattleScript_WeatherFormChange[]; extern const u8 BattleScript_IntimidateActivates[]; extern const u8 BattleScript_DroughtActivates[]; extern const u8 BattleScript_TookAttack[]; @@ -197,6 +198,8 @@ extern const u8 BattleScript_BerryCureBrnEnd2[]; extern const u8 BattleScript_BerryCureBrnRet[]; extern const u8 BattleScript_BerryCureFrzEnd2[]; extern const u8 BattleScript_BerryCureFrzRet[]; +extern const u8 BattleScript_BerryCureFsbEnd2[]; +extern const u8 BattleScript_BerryCureFsbRet[]; extern const u8 BattleScript_BerryCureSlpEnd2[]; extern const u8 BattleScript_BerryCureSlpRet[]; extern const u8 BattleScript_BerryCureConfusionEnd2[]; @@ -463,6 +466,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[]; diff --git a/include/battle_util.h b/include/battle_util.h index 0661081e4..e28e41aad 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -173,12 +173,11 @@ u16 CalcPartyMonTypeEffectivenessMultiplier(u16 move, u16 speciesDef, u16 abilit u16 GetTypeModifier(u8 atkType, u8 defType); s32 GetStealthHazardDamage(u8 hazardType, u8 battlerId); s32 GetStealthHazardDamageByTypesAndHP(u8 hazardType, u8 type1, u8 type2, u32 maxHp); -u16 GetMegaEvolutionSpecies(u16 preEvoSpecies, u16 heldItemId); -u16 GetPrimalReversionSpecies(u16 preEvoSpecies, u16 heldItemId); -u16 GetWishMegaEvolutionSpecies(u16 preEvoSpecies, u16 moveId1, u16 moveId2, u16 moveId3, u16 moveId4); bool32 CanMegaEvolve(u8 battlerId); -void UndoMegaEvolution(u32 monId); -void UndoFormChange(u32 monId, u32 side, bool32 isSwitchingOut); +bool32 IsBattlerMegaEvolved(u8 battlerId); +bool32 IsBattlerPrimalReverted(u8 battlerId); +u16 GetBattleFormChangeTargetSpecies(u8 battlerId, u16 method); +bool32 TryBattleFormChange(u8 battlerId, u16 method); bool32 DoBattlersShareType(u32 battler1, u32 battler2); bool32 CanBattlerGetOrLoseItem(u8 battlerId, u16 itemId); u32 GetIllusionMonSpecies(u32 battlerId); @@ -188,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); @@ -197,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); @@ -207,13 +205,15 @@ void SortBattlersBySpeed(u8 *battlers, bool8 slowToFast); bool32 CompareStat(u8 battlerId, u8 statId, u8 cmpTo, u8 cmpKind); bool32 TryRoomService(u8 battlerId); void BufferStatChange(u8 battlerId, u8 statId, u8 stringId); -void DoBurmyFormChange(u32 monId); bool32 BlocksPrankster(u16 move, u8 battlerPrankster, u8 battlerDef, bool32 checkTarget); u16 GetUsedHeldItem(u8 battler); bool32 IsBattlerWeatherAffected(u8 battlerId, u32 weatherFlags); u32 GetBattlerMoveTargetType(u8 battlerId, u16 move); bool32 CanTargetBattler(u8 battlerAtk, u8 battlerDef, u16 move); bool8 IsMoveAffectedByParentalBond(u16 move, u8 battlerId); +void CopyMonLevelAndBaseStatsToBattleMon(u32 battler, struct Pokemon *mon); +void CopyMonAbilityAndTypesToBattleMon(u32 battler, struct Pokemon *mon); +void RecalcBattlerStats(u32 battler, struct Pokemon *mon); // Ability checks bool32 IsRolePlayBannedAbilityAtk(u16 ability); bool32 IsRolePlayBannedAbility(u16 ability); @@ -228,11 +228,13 @@ bool32 CanBePoisoned(u8 battlerAttacker, u8 battlerTarget); bool32 CanBeBurned(u8 battlerId); bool32 CanBeParalyzed(u8 battlerId); bool32 CanBeFrozen(u8 battlerId); +bool32 CanGetFrostbite(u8 battlerId); bool32 CanBeConfused(u8 battlerId); bool32 IsBattlerTerrainAffected(u8 battlerId, u32 terrainFlag); 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 diff --git a/include/config/battle.h b/include/config/battle.h index 4a3d6382f..da58c8bbf 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -98,7 +98,9 @@ #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_SHINY GEN_LATEST // In Gen4+, Transform will copy the shiny state of the opponent instead of maintaining its own shiny state. +#define B_TRANSFORM_FORM_CHANGES GEN_LATEST // In Gen5+, Transformed Pokemon cannot change forms. // Ability settings #define B_EXPANDED_ABILITY_NAMES TRUE // If TRUE, ability names are increased from 12 characters to 16 characters. @@ -126,6 +128,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. @@ -155,6 +158,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. @@ -182,29 +188,32 @@ #define B_LAST_USED_BALL_BUTTON R_BUTTON // If last used ball is implemented, this button (or button combo) will trigger throwing the last used ball. // Other settings -#define B_DOUBLE_WILD_CHANCE 0 // % chance of encountering two Pokémon in a Wild Encounter. -#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) -#define B_AFFECTION_MECHANICS FALSE // In Gen6+, there's a stat called affection that can trigger different effects in battle. From LGPE onwards, those effects use friendship instead. -#define B_TRAINER_CLASS_POKE_BALLS GEN_LATEST // In Gen7+, trainers will use certain types of Poké Balls depending on their trainer class. -#define B_OBEDIENCE_MECHANICS GEN_LATEST // In PLA+ (here Gen8+), obedience restrictions also apply to non-outsider Pokémon, albeit based on their level met rather than actual level +#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_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) +#define B_AFFECTION_MECHANICS FALSE // In Gen6+, there's a stat called affection that can trigger different effects in battle. From LGPE onwards, those effects use friendship instead. +#define B_TRAINER_CLASS_POKE_BALLS GEN_LATEST // In Gen7+, trainers will use certain types of Poké Balls depending on their trainer class. +#define B_OBEDIENCE_MECHANICS GEN_LATEST // In PLA+ (here Gen8+), obedience restrictions also apply to non-outsider Pokémon, albeit based on their level met rather than actual level +#define B_USE_FROSTBITE FALSE // In PLA, Frostbite replaces Freeze. Enabling this flag does the same here. Moves can still be cherry-picked to either Freeze or Frostbite. Freeze-Dry, Secret Power & Tri Attack depend on this config. // Animation Settings -#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_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. -#define B_NEW_TEETH_PARTICLE FALSE // If set to TRUE, it updates Bite/Crunch teeth particle. -#define B_NEW_HANDS_FEET_PARTICLE FALSE // If set to TRUE, it updates chop/kick/punch particles. -#define B_NEW_SPIKES_PARTICLE FALSE // If set to TRUE, it updates Spikes particle. -#define B_NEW_FLY_BUBBLE_PARTICLE FALSE // If set to TRUE, it updates Fly's 'bubble' particle. -#define B_NEW_CURSE_NAIL_PARTICLE FALSE // If set to TRUE, it updates Curse's nail. -#define B_NEW_BATON_PASS_BALL_PARTICLE FALSE // If set to TRUE, it updates Baton Pass' Poké Ball sprite. -#define B_NEW_MORNING_SUN_STAR_PARTICLE FALSE // If set to TRUE, it updates Morning Sun's star particles. -#define B_NEW_IMPACT_PALETTE FALSE // If set to TRUE, it updates the basic 'hit' palette. -#define B_NEW_SURF_PARTICLE_PALETTE FALSE // If set to TRUE, it updates Surf's wave palette. +#define B_NEW_SWORD_PARTICLE TRUE // If set to TRUE, it updates Swords Dance's particle. +#define B_NEW_LEECH_SEED_PARTICLE TRUE // If set to TRUE, it updates Leech Seed's animation particle. +#define B_NEW_HORN_ATTACK_PARTICLE TRUE // 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 TRUE // If set to TRUE, it updates leaf particle. +#define B_NEW_EMBER_PARTICLES TRUE // If set to TRUE, it updates Ember's fire particle. +#define B_NEW_MEAN_LOOK_PARTICLE TRUE // If set to TRUE, it updates Mean Look's eye particle. +#define B_NEW_TEETH_PARTICLE TRUE // If set to TRUE, it updates Bite/Crunch teeth particle. +#define B_NEW_HANDS_FEET_PARTICLE TRUE // If set to TRUE, it updates chop/kick/punch particles. +#define B_NEW_SPIKES_PARTICLE TRUE // If set to TRUE, it updates Spikes particle. +#define B_NEW_FLY_BUBBLE_PARTICLE TRUE // If set to TRUE, it updates Fly's 'bubble' particle. +#define B_NEW_CURSE_NAIL_PARTICLE TRUE // If set to TRUE, it updates Curse's nail. +#define B_NEW_BATON_PASS_BALL_PARTICLE TRUE // If set to TRUE, it updates Baton Pass' Poké Ball sprite. +#define B_NEW_MORNING_SUN_STAR_PARTICLE TRUE // If set to TRUE, it updates Morning Sun's star particles. +#define B_NEW_IMPACT_PALETTE TRUE // If set to TRUE, it updates the basic 'hit' palette. +#define B_NEW_SURF_PARTICLE_PALETTE TRUE // If set to TRUE, it updates Surf's wave palette. #endif // GUARD_CONFIG_BATTLE_H diff --git a/include/config/item.h b/include/config/item.h index 031af3724..88cfeeb7c 100644 --- a/include/config/item.h +++ b/include/config/item.h @@ -2,12 +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_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. diff --git a/include/config/overworld.h b/include/config/overworld.h index 7831858d2..f62588b5f 100644 --- a/include/config/overworld.h +++ b/include/config/overworld.h @@ -4,6 +4,9 @@ // Movement config #define OW_RUNNING_INDOORS GEN_LATEST // In Gen4+, players are allowed to run indoors. +// Other settings +#define OW_POISON_DAMAGE GEN_LATEST // In Gen4, Pokémon no longer faint from Poison in the overworld. In Gen5+, they no longer take damage at all. + // Overworld flags // To use the following features in scripting, replace the 0s with the flag ID you're assigning it to. // Eg: Replace with FLAG_UNUSED_0x264 so you can use that flag to toggle the feature. diff --git a/include/config/pokemon.h b/include/config/pokemon.h index ce5faf2a6..1cde573c9 100644 --- a/include/config/pokemon.h +++ b/include/config/pokemon.h @@ -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. diff --git a/include/constants/battle.h b/include/constants/battle.h index 61c3776c6..950d98484 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -115,8 +115,9 @@ #define STATUS1_TOXIC_POISON (1 << 7) #define STATUS1_TOXIC_COUNTER (1 << 8 | 1 << 9 | 1 << 10 | 1 << 11) #define STATUS1_TOXIC_TURN(num) ((num) << 8) +#define STATUS1_FROSTBITE (1 << 12) #define STATUS1_PSN_ANY (STATUS1_POISON | STATUS1_TOXIC_POISON) -#define STATUS1_ANY (STATUS1_SLEEP | STATUS1_POISON | STATUS1_BURN | STATUS1_FREEZE | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON) +#define STATUS1_ANY (STATUS1_SLEEP | STATUS1_POISON | STATUS1_BURN | STATUS1_FREEZE | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON | STATUS1_FROSTBITE) // Volatile status ailments // These are removed after exiting the battle or switching out @@ -185,6 +186,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) @@ -269,6 +271,7 @@ #define MOVE_RESULT_NO_EFFECT (MOVE_RESULT_MISSED | MOVE_RESULT_DOESNT_AFFECT_FOE | MOVE_RESULT_FAILED) // Battle Weather flags +#define B_WEATHER_NONE 0 #define B_WEATHER_RAIN_TEMPORARY (1 << 0) #define B_WEATHER_RAIN_DOWNPOUR (1 << 1) // unused #define B_WEATHER_RAIN_PERMANENT (1 << 2) @@ -305,79 +308,80 @@ #define MOVE_EFFECT_FREEZE 4 #define MOVE_EFFECT_PARALYSIS 5 #define MOVE_EFFECT_TOXIC 6 -#define PRIMARY_STATUS_MOVE_EFFECT MOVE_EFFECT_TOXIC // All above move effects apply primary status -#define MOVE_EFFECT_CONFUSION 7 -#define MOVE_EFFECT_FLINCH 8 -#define MOVE_EFFECT_TRI_ATTACK 9 -#define MOVE_EFFECT_UPROAR 10 -#define MOVE_EFFECT_PAYDAY 11 -#define MOVE_EFFECT_CHARGING 12 -#define MOVE_EFFECT_WRAP 13 -#define MOVE_EFFECT_BURN_UP 14 // MOVE_EFFECT_BURN_UP replaces unused MOVE_EFFECT_RECOIL_25 so that stat change animations don't break -#define MOVE_EFFECT_ATK_PLUS_1 15 -#define MOVE_EFFECT_DEF_PLUS_1 16 -#define MOVE_EFFECT_SPD_PLUS_1 17 -#define MOVE_EFFECT_SP_ATK_PLUS_1 18 -#define MOVE_EFFECT_SP_DEF_PLUS_1 19 -#define MOVE_EFFECT_ACC_PLUS_1 20 -#define MOVE_EFFECT_EVS_PLUS_1 21 -#define MOVE_EFFECT_ATK_MINUS_1 22 -#define MOVE_EFFECT_DEF_MINUS_1 23 -#define MOVE_EFFECT_SPD_MINUS_1 24 -#define MOVE_EFFECT_SP_ATK_MINUS_1 25 -#define MOVE_EFFECT_SP_DEF_MINUS_1 26 -#define MOVE_EFFECT_ACC_MINUS_1 27 -#define MOVE_EFFECT_EVS_MINUS_1 28 -#define MOVE_EFFECT_RECHARGE 29 -#define MOVE_EFFECT_RAGE 30 -#define MOVE_EFFECT_STEAL_ITEM 31 -#define MOVE_EFFECT_PREVENT_ESCAPE 32 -#define MOVE_EFFECT_NIGHTMARE 33 -#define MOVE_EFFECT_ALL_STATS_UP 34 -#define MOVE_EFFECT_RAPIDSPIN 35 -#define MOVE_EFFECT_REMOVE_STATUS 36 -#define MOVE_EFFECT_ATK_DEF_DOWN 37 -#define MOVE_EFFECT_SCALE_SHOT 38 // MOVE_EFFECT_SCALE_SHOT replaces unused MOVE_EFFECT_RECOIL_33 so that stat change animations don't break -#define MOVE_EFFECT_ATK_PLUS_2 39 -#define MOVE_EFFECT_DEF_PLUS_2 40 -#define MOVE_EFFECT_SPD_PLUS_2 41 -#define MOVE_EFFECT_SP_ATK_PLUS_2 42 -#define MOVE_EFFECT_SP_DEF_PLUS_2 43 -#define MOVE_EFFECT_ACC_PLUS_2 44 -#define MOVE_EFFECT_EVS_PLUS_2 45 -#define MOVE_EFFECT_ATK_MINUS_2 46 -#define MOVE_EFFECT_DEF_MINUS_2 47 -#define MOVE_EFFECT_SPD_MINUS_2 48 -#define MOVE_EFFECT_SP_ATK_MINUS_2 49 -#define MOVE_EFFECT_SP_DEF_MINUS_2 50 -#define MOVE_EFFECT_ACC_MINUS_2 51 -#define MOVE_EFFECT_EVS_MINUS_2 52 -#define MOVE_EFFECT_THRASH 53 -#define MOVE_EFFECT_KNOCK_OFF 54 -#define MOVE_EFFECT_DEF_SPDEF_DOWN 55 -#define MOVE_EFFECT_CLEAR_SMOG 56 -#define MOVE_EFFECT_SP_ATK_TWO_DOWN 57 -#define MOVE_EFFECT_SMACK_DOWN 58 -#define MOVE_EFFECT_FLAME_BURST 59 -#define MOVE_EFFECT_FEINT 60 -#define MOVE_EFFECT_SPECTRAL_THIEF 61 -#define MOVE_EFFECT_V_CREATE 62 -#define MOVE_EFFECT_HAPPY_HOUR 63 -#define MOVE_EFFECT_CORE_ENFORCER 64 -#define MOVE_EFFECT_THROAT_CHOP 65 -#define MOVE_EFFECT_INCINERATE 66 -#define MOVE_EFFECT_BUG_BITE 67 -#define MOVE_EFFECT_RECOIL_HP_25 68 -#define MOVE_EFFECT_RELIC_SONG 69 -#define MOVE_EFFECT_TRAP_BOTH 70 -#define MOVE_EFFECT_DOUBLE_SHOCK 71 -#define MOVE_EFFECT_ROUND 72 -#define MOVE_EFFECT_STOCKPILE_WORE_OFF 73 -#define MOVE_EFFECT_DIRE_CLAW 74 -#define MOVE_EFFECT_STEALTH_ROCK 75 -#define MOVE_EFFECT_SPIKES 76 +#define MOVE_EFFECT_FROSTBITE 7 +#define PRIMARY_STATUS_MOVE_EFFECT MOVE_EFFECT_FROSTBITE // All above move effects apply primary status +#define MOVE_EFFECT_CONFUSION 8 +#define MOVE_EFFECT_FLINCH 9 +#define MOVE_EFFECT_TRI_ATTACK 10 +#define MOVE_EFFECT_UPROAR 11 +#define MOVE_EFFECT_PAYDAY 12 +#define MOVE_EFFECT_CHARGING 13 +#define MOVE_EFFECT_WRAP 14 +#define MOVE_EFFECT_BURN_UP 15 // MOVE_EFFECT_BURN_UP replaces unused MOVE_EFFECT_RECOIL_25 so that stat change animations don't break +#define MOVE_EFFECT_ATK_PLUS_1 16 +#define MOVE_EFFECT_DEF_PLUS_1 17 +#define MOVE_EFFECT_SPD_PLUS_1 18 +#define MOVE_EFFECT_SP_ATK_PLUS_1 19 +#define MOVE_EFFECT_SP_DEF_PLUS_1 20 +#define MOVE_EFFECT_ACC_PLUS_1 21 +#define MOVE_EFFECT_EVS_PLUS_1 22 +#define MOVE_EFFECT_ATK_MINUS_1 23 +#define MOVE_EFFECT_DEF_MINUS_1 24 +#define MOVE_EFFECT_SPD_MINUS_1 25 +#define MOVE_EFFECT_SP_ATK_MINUS_1 26 +#define MOVE_EFFECT_SP_DEF_MINUS_1 27 +#define MOVE_EFFECT_ACC_MINUS_1 28 +#define MOVE_EFFECT_EVS_MINUS_1 29 +#define MOVE_EFFECT_RECHARGE 30 +#define MOVE_EFFECT_RAGE 31 +#define MOVE_EFFECT_STEAL_ITEM 32 +#define MOVE_EFFECT_PREVENT_ESCAPE 33 +#define MOVE_EFFECT_NIGHTMARE 34 +#define MOVE_EFFECT_ALL_STATS_UP 35 +#define MOVE_EFFECT_RAPIDSPIN 36 +#define MOVE_EFFECT_REMOVE_STATUS 37 +#define MOVE_EFFECT_ATK_DEF_DOWN 38 +#define MOVE_EFFECT_SCALE_SHOT 39 // MOVE_EFFECT_SCALE_SHOT replaces unused MOVE_EFFECT_RECOIL_33 so that stat change animations don't break +#define MOVE_EFFECT_ATK_PLUS_2 40 +#define MOVE_EFFECT_DEF_PLUS_2 41 +#define MOVE_EFFECT_SPD_PLUS_2 42 +#define MOVE_EFFECT_SP_ATK_PLUS_2 43 +#define MOVE_EFFECT_SP_DEF_PLUS_2 44 +#define MOVE_EFFECT_ACC_PLUS_2 45 +#define MOVE_EFFECT_EVS_PLUS_2 46 +#define MOVE_EFFECT_ATK_MINUS_2 47 +#define MOVE_EFFECT_DEF_MINUS_2 48 +#define MOVE_EFFECT_SPD_MINUS_2 49 +#define MOVE_EFFECT_SP_ATK_MINUS_2 50 +#define MOVE_EFFECT_SP_DEF_MINUS_2 51 +#define MOVE_EFFECT_ACC_MINUS_2 52 +#define MOVE_EFFECT_EVS_MINUS_2 53 +#define MOVE_EFFECT_THRASH 54 +#define MOVE_EFFECT_KNOCK_OFF 55 +#define MOVE_EFFECT_DEF_SPDEF_DOWN 56 +#define MOVE_EFFECT_CLEAR_SMOG 57 +#define MOVE_EFFECT_SP_ATK_TWO_DOWN 58 +#define MOVE_EFFECT_SMACK_DOWN 59 +#define MOVE_EFFECT_FLAME_BURST 60 +#define MOVE_EFFECT_FEINT 61 +#define MOVE_EFFECT_SPECTRAL_THIEF 62 +#define MOVE_EFFECT_V_CREATE 63 +#define MOVE_EFFECT_HAPPY_HOUR 64 +#define MOVE_EFFECT_CORE_ENFORCER 65 +#define MOVE_EFFECT_THROAT_CHOP 66 +#define MOVE_EFFECT_INCINERATE 67 +#define MOVE_EFFECT_BUG_BITE 68 +#define MOVE_EFFECT_RECOIL_HP_25 69 +#define MOVE_EFFECT_RELIC_SONG 70 +#define MOVE_EFFECT_TRAP_BOTH 71 +#define MOVE_EFFECT_DOUBLE_SHOCK 72 +#define MOVE_EFFECT_ROUND 73 +#define MOVE_EFFECT_STOCKPILE_WORE_OFF 74 +#define MOVE_EFFECT_DIRE_CLAW 75 +#define MOVE_EFFECT_STEALTH_ROCK 76 +#define MOVE_EFFECT_SPIKES 77 -#define NUM_MOVE_EFFECTS 77 +#define NUM_MOVE_EFFECTS 78 #define MOVE_EFFECT_AFFECTS_USER 0x4000 #define MOVE_EFFECT_CERTAIN 0x8000 diff --git a/include/constants/battle_ai.h b/include/constants/battle_ai.h index 1cfb9cd4d..1316054cd 100644 --- a/include/constants/battle_ai.h +++ b/include/constants/battle_ai.h @@ -57,6 +57,7 @@ #define AI_FLAG_SCREENER (1 << 14) // AI prefers screening effects like reflect, mist, etc. TODO unfinished #define AI_FLAG_SMART_SWITCHING (1 << 15) // AI includes a lot more switching checks #define AI_FLAG_ACE_POKEMON (1 << 16) // AI has an Ace Pokemon. The last Pokemon in the party will not be used until it's the last one remaining. +#define AI_FLAG_OMNISCIENT (1 << 17) // AI has full knowledge of player moves, abilities, hold items // 'other' ai logic flags #define AI_FLAG_ROAMING (1 << 29) diff --git a/include/constants/battle_anim.h b/include/constants/battle_anim.h index 4316191a2..46e229a31 100644 --- a/include/constants/battle_anim.h +++ b/include/constants/battle_anim.h @@ -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 diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index 27ad6601f..5df12b449 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -404,7 +404,9 @@ #define EFFECT_HIT_SET_ENTRY_HAZARD 398 #define EFFECT_DIRE_CLAW 399 #define EFFECT_BARB_BARRAGE 400 +#define EFFECT_REVIVAL_BLESSING 401 +#define EFFECT_FROSTBITE_HIT 402 -#define NUM_BATTLE_MOVE_EFFECTS 401 +#define NUM_BATTLE_MOVE_EFFECTS 403 #endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 26064bcfb..2be15be58 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -89,176 +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_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 @@ -332,10 +335,9 @@ #define MOVEEND_PICKPOCKET 30 #define MOVEEND_DANCER 31 #define MOVEEND_EMERGENCY_EXIT 32 -#define MOVEEND_WEATHER_FORM 33 -#define MOVEEND_SYMBIOSIS 34 -#define MOVEEND_CLEAR_BITS 35 -#define MOVEEND_COUNT 36 +#define MOVEEND_SYMBIOSIS 33 +#define MOVEEND_CLEAR_BITS 34 +#define MOVEEND_COUNT 35 // switch cases #define B_SWITCH_NORMAL 0 diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index 4051a3a6d..9ce49894e 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -647,9 +647,21 @@ #define STRINGID_STEALTHROCKDISAPPEAREDFROMTEAM 645 #define STRINGID_COULDNTFULLYPROTECT 646 #define STRINGID_STOCKPILEDEFFECTWOREOFF 647 -#define STRINGID_MIRRORHERBCOPIED 648 +#define STRINGID_PKMNREVIVEDREADYTOFIGHT 648 +#define STRINGID_ITEMRESTOREDSPECIESHEALTH 649 +#define STRINGID_ITEMCUREDSPECIESSTATUS 650 +#define STRINGID_ITEMRESTOREDSPECIESPP 651 +#define STRINGID_THUNDERCAGETRAPPED 652 +#define STRINGID_PKMNHURTBYFROSTBITE 653 +#define STRINGID_PKMNGOTFROSTBITE 654 +#define STRINGID_PKMNSITEMHEALEDFROSTBITE 655 +#define STRINGID_ATTACKERHEALEDITSFROSTBITE 656 +#define STRINGID_PKMNFROSTBITEHEALED 657 +#define STRINGID_PKMNFROSTBITEHEALED2 658 +#define STRINGID_PKMNFROSTBITEHEALEDBY 659 +#define STRINGID_MIRRORHERBCOPIED 660 -#define BATTLESTRINGS_COUNT 649 +#define BATTLESTRINGS_COUNT 661 // This is the string id that gBattleStringsTable starts with. // String ids before this (e.g. STRINGID_INTROMSG) are not in the table, @@ -857,6 +869,10 @@ #define B_MSG_DEFROSTED 0 #define B_MSG_DEFROSTED_BY_MOVE 1 +// gFrostbiteHealedStringIds +#define B_MSG_FROSTBITE_HEALED 0 +#define B_MSG_FROSTBITE_HEALED_BY_MOVE 1 + // gBattlePalaceFlavorTextTable #define B_MSG_GLINT_IN_EYE 0 #define B_MSG_GETTING_IN_POS 1 @@ -914,16 +930,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 diff --git a/include/constants/easy_chat.h b/include/constants/easy_chat.h index b5875b881..b1f38941f 100644 --- a/include/constants/easy_chat.h +++ b/include/constants/easy_chat.h @@ -1095,7 +1095,7 @@ #define EC_WORD_OLD ((EC_GROUP_TRENDY_SAYING << EC_MASK_BITS) | 30) #define EC_WORD_YOUNG ((EC_GROUP_TRENDY_SAYING << EC_MASK_BITS) | 31) #define EC_WORD_UGLY ((EC_GROUP_TRENDY_SAYING << EC_MASK_BITS) | 32) -#define NUM_ADDITIONAL_PHRASES 33 +#define NUM_TRENDY_SAYINGS 33 // Special Berry Masters Wife phrases #define NOT_SPECIAL_PHRASE 0 diff --git a/include/constants/flags.h b/include/constants/flags.h index 99a8377a7..59bde846c 100644 --- a/include/constants/flags.h +++ b/include/constants/flags.h @@ -1123,7 +1123,7 @@ #define FLAG_ITEM_NEW_MAUVILLE_ULTRA_BALL 0x433 #define FLAG_ITEM_NEW_MAUVILLE_ESCAPE_ROPE 0x434 #define FLAG_ITEM_ABANDONED_SHIP_HIDDEN_FLOOR_ROOM_6_LUXURY_BALL 0x435 -#define FLAG_ITEM_ABANDONED_SHIP_HIDDEN_FLOOR_ROOM_4_SCANNER 0x436 +#define FLAG_ITEM_ABANDONED_SHIP_HIDDEN_FLOOR_ROOM_2_SCANNER 0x436 #define FLAG_ITEM_SCORCHED_SLAB_TM11 0x437 #define FLAG_ITEM_METEOR_FALLS_B1F_2R_TM02 0x438 #define FLAG_ITEM_SHOAL_CAVE_ENTRANCE_BIG_PEARL 0x439 @@ -1348,7 +1348,7 @@ #define FLAG_UNUSED_0x863 (SYSTEM_FLAGS + 0x3) // Unused Flag #define FLAG_SYS_GAME_CLEAR (SYSTEM_FLAGS + 0x4) #define FLAG_SYS_CHAT_USED (SYSTEM_FLAGS + 0x5) -#define FLAG_SYS_HIPSTER_MEET (SYSTEM_FLAGS + 0x6) +#define FLAG_UNLOCKED_TRENDY_SAYINGS (SYSTEM_FLAGS + 0x6) // Badges #define FLAG_BADGE01_GET (SYSTEM_FLAGS + 0x7) diff --git a/include/constants/form_change_types.h b/include/constants/form_change_types.h new file mode 100644 index 000000000..651bcf788 --- /dev/null +++ b/include/constants/form_change_types.h @@ -0,0 +1,98 @@ +#ifndef GUARD_CONSTANTS_FORM_CHANGE_TYPES_H +#define GUARD_CONSTANTS_FORM_CHANGE_TYPES_H + +// FORM_CHANGE_BATTLE_HP_PERCENT param2 arguments +#define HP_HIGHER_THAN 1 +#define HP_LOWER_EQ_THAN 2 +// FORM_CHANGE_MOVE param2 Arguments +#define WHEN_LEARNED 0 +#define WHEN_FORGOTTEN 1 +// FORM_CHANGE_ITEM_USE param2 Arguments +#define DAY 1 +#define NIGHT 2 + +#define FORM_CHANGE_TERMINATOR 0 + +// Form change that activates when the specified item is given to or taken from the selected Pokémon. +// param1: item to hold. +// param2: ability to check for, optional. +#define FORM_CHANGE_ITEM_HOLD 1 + +// Form change that activates when the item is used on the selected Pokémon. +// param1: item to use +// param2: time of day to check, optional. +// - DAY if Form change that activates in the daytime. +// - NIGHT if Form change that activates at nighttime. +#define FORM_CHANGE_ITEM_USE 2 + +// TODO: Form change that activates when the Pokémon learns or forgets the move. +// param1: move to check for +// param2: +// - WHEN_LEARNED if Form change that activates when move is forgotten +// - WHEN_FORGOTTEN if Form change that activates when move is learned +#define FORM_CHANGE_MOVE 3 + +// Form change that activates when the Pokémon is withdrawn from the PC or Daycare. +// Daycare withdraw done, PC withdraw TODO. +// - No parameters. +#define FORM_CHANGE_WITHDRAW 4 + +// Form change that activates when the Pokémon faints, either in battle or in the overworld by poison. +// If species is not specified and it's on the player's side, it will try to use the value +// saved in gBattleStruct->changedSpecies from a previous form change. +// - No parameters. +#define FORM_CHANGE_FAINT 5 + +// Form change that activates when the Pokémon is sent out at the beginning of a battle +// param1: item to hold, optional +// param2: a move that will be replaced, optional +// param3: a new move to replace it with, optional +#define FORM_CHANGE_BEGIN_BATTLE 6 + +// Form change that activates at the end of a battle. If species is not specified and it's on the player's side, it will try to use the value saved in gBattleStruct->changedSpecies from a previous form change. +// param1: item to hold, optional +// param2: a move that will be replaced, optional +// param3: a new move to replace it with, optional +#define FORM_CHANGE_END_BATTLE 7 + +// Form change that activates at the end of a battle based on the terrain if it participated in the battle and hasn't fainted. Takes priority over FORM_CHANGE_END_BATTLE. +// param1: battle terrain to check. +#define FORM_CHANGE_END_BATTLE_TERRAIN 8 + +// Form change that activates when the Pokémon is switched out in battle. +// - No parameters. +#define FORM_CHANGE_BATTLE_SWITCH 9 + +// Form change that activates when the Pokémon's HP % passes a certain threshold. +// param1: Ability to check. +// param2: HP comparer +// - HP_HIGHER_THAN if the form triggers when the current HP is higher than the specified threshold. +// - HP_LOWER_EQ_THAN if the form triggers when the current HP is lower or equal than the specified threshold. +// param3: HP percentage threshold. +#define FORM_CHANGE_BATTLE_HP_PERCENT 10 + +// Form change that activates when the mon has the defined item. +// If it's on the player's side, it also requires ITEM_MEGA_RING in the user's bag and for the player to trigger it by pressing START before selecting a move. +// param1: item to hold. +#define FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM 11 + +// Form change that activates when the mon has the defined move. +// If it's on the player's side, it also requires ITEM_MEGA_RING in the user's bag and for the player to trigger it by pressing START before selecting a move. +// param1: move to have. +#define FORM_CHANGE_BATTLE_MEGA_EVOLUTION_MOVE 12 + +// Form change that activates automatically when entering battle with the specified item. +// If the item is a Red Orb, it uses the Omega Symbol for the animation and icon. Otherwise, it defaults to the Alpha symbol. +// The battle indicator icon is based on the species, with Primal Groudon's as Omega and otherwise being Alpha. +// param1: item to hold. +#define FORM_CHANGE_BATTLE_PRIMAL_REVERSION 13 + +// Form change that activates when a specific weather is set during battle. +// param1: weather to check +#define FORM_CHANGE_BATTLE_WEATHER 14 + +// Form change that activates automatically when the turn ends. +// param1: ability to check. +#define FORM_CHANGE_BATTLE_TURN_END 15 + +#endif // GUARD_CONSTANTS_FORM_CHANGE_TYPES_H diff --git a/include/constants/hold_effects.h b/include/constants/hold_effects.h index 5fc268cb0..9f877cffa 100644 --- a/include/constants/hold_effects.h +++ b/include/constants/hold_effects.h @@ -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 diff --git a/include/constants/item_effects.h b/include/constants/item_effects.h index c3970b9c1..fca792451 100644 --- a/include/constants/item_effects.h +++ b/include/constants/item_effects.h @@ -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 @@ -74,7 +74,7 @@ #define ITEM_EFFECT_CURE_POISON 3 #define ITEM_EFFECT_CURE_SLEEP 4 #define ITEM_EFFECT_CURE_BURN 5 -#define ITEM_EFFECT_CURE_FREEZE 6 +#define ITEM_EFFECT_CURE_FREEZE_FROSTBITE 6 #define ITEM_EFFECT_CURE_PARALYSIS 7 #define ITEM_EFFECT_CURE_CONFUSION 8 #define ITEM_EFFECT_CURE_INFATUATION 9 diff --git a/include/constants/items.h b/include/constants/items.h index 2d186601b..57ed63feb 100644 --- a/include/constants/items.h +++ b/include/constants/items.h @@ -969,7 +969,12 @@ #define ITEM_GRISEOUS_CORE 793 #define ITEM_LUSTROUS_GLOBE 794 -#define ITEMS_COUNT 795 +#define ITEM_BLACK_AUGURITE 795 +#define ITEM_LINKING_CORD 796 +#define ITEM_PEAT_BLOCK 797 +#define ITEM_BERSERK_GENE 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 @@ -1026,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 diff --git a/include/constants/party_menu.h b/include/constants/party_menu.h index 2c632d30c..fd94afe54 100644 --- a/include/constants/party_menu.h +++ b/include/constants/party_menu.h @@ -11,6 +11,7 @@ #define AILMENT_BRN 5 #define AILMENT_PKRS 6 #define AILMENT_FNT 7 +#define AILMENT_FSB 8 #define PARTY_LAYOUT_SINGLE 0 #define PARTY_LAYOUT_DOUBLE 1 @@ -48,6 +49,7 @@ #define PARTY_ACTION_MOVE_TUTOR 12 #define PARTY_ACTION_MINIGAME 13 #define PARTY_ACTION_REUSABLE_ITEM 14 // Unused. The only reusable items are handled separately +#define PARTY_ACTION_CHOOSE_FAINTED_MON 15 // IDs for DisplayPartyMenuStdMessage, to display the message at the bottom of the party menu #define PARTY_MSG_CHOOSE_MON 0 diff --git a/include/constants/pokemon.h b/include/constants/pokemon.h index 0a9b6d153..ff2a44dc9 100644 --- a/include/constants/pokemon.h +++ b/include/constants/pokemon.h @@ -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 @@ -269,9 +273,6 @@ #define F_SUMMARY_SCREEN_FLIP_SPRITE 0x80 // Evolution types -#define EVO_MEGA_EVOLUTION 0xffff // Not an actual evolution, used to temporarily mega evolve in battle. -#define EVO_MOVE_MEGA_EVOLUTION 0xfffe // Mega Evolution that checks for a move instead of held item. -#define EVO_PRIMAL_REVERSION 0xfffd // Not an actual evolution, used to undergo primal reversion in battle. #define EVO_FRIENDSHIP 1 // Pokémon levels up with friendship ≥ 220 #define EVO_FRIENDSHIP_DAY 2 // Pokémon levels up during the day with friendship ≥ 220 #define EVO_FRIENDSHIP_NIGHT 3 // Pokémon levels up at night with friendship ≥ 220 @@ -310,6 +311,7 @@ #define EVO_SCRIPT_TRIGGER_DMG 36 // Pokémon has specified HP below max, then player interacts trigger #define EVO_DARK_SCROLL 37 // interacts with Scroll of Darkness #define EVO_WATER_SCROLL 38 // interacts with Scroll of Waters +#define EVO_ITEM_NIGHT 39 // specified item is used on Pokémon at night #define EVOS_PER_MON 10 @@ -321,15 +323,6 @@ #define EVO_MODE_BATTLE_SPECIAL 4 #define EVO_MODE_OVERWORLD_SPECIAL 5 -// Form change types -#define FORM_CHANGE_END 0 -#define FORM_ITEM_HOLD 1 -#define FORM_ITEM_USE 2 -#define FORM_MOVE 3 -#define FORM_WITHDRAW 4 -#define FORM_BATTLE_BEGIN 5 -#define FORM_BATTLE_END 6 - #define MON_PIC_WIDTH 64 #define MON_PIC_HEIGHT 64 #define MON_PIC_SIZE (MON_PIC_WIDTH * MON_PIC_HEIGHT / 2) @@ -357,13 +350,14 @@ #define SPECIES_FLAG_LEGENDARY (1 << 0) #define SPECIES_FLAG_MYTHICAL (1 << 1) #define SPECIES_FLAG_MEGA_EVOLUTION (1 << 2) -#define SPECIES_FLAG_ULTRA_BEAST (1 << 3) -#define SPECIES_FLAG_ALOLAN_FORM (1 << 4) -#define SPECIES_FLAG_GALARIAN_FORM (1 << 5) -#define SPECIES_FLAG_HISUIAN_FORM (1 << 6) -#define SPECIES_FLAG_GENDER_DIFFERENCE (1 << 7) -#define SPECIES_FLAG_ALL_PERFECT_IVS (1 << 8) -#define SPECIES_FLAG_CANNOT_BE_TRADED (1 << 9) +#define SPECIES_FLAG_PRIMAL_REVERSION (1 << 3) +#define SPECIES_FLAG_ULTRA_BEAST (1 << 4) +#define SPECIES_FLAG_ALOLAN_FORM (1 << 5) +#define SPECIES_FLAG_GALARIAN_FORM (1 << 6) +#define SPECIES_FLAG_HISUIAN_FORM (1 << 7) +#define SPECIES_FLAG_GENDER_DIFFERENCE (1 << 8) +#define SPECIES_FLAG_ALL_PERFECT_IVS (1 << 9) +#define SPECIES_FLAG_CANNOT_BE_TRADED (1 << 10) #define LEGENDARY_PERFECT_IV_COUNT 3 diff --git a/include/easy_chat.h b/include/easy_chat.h index d84af93fc..2cec441d5 100644 --- a/include/easy_chat.h +++ b/include/easy_chat.h @@ -128,11 +128,11 @@ void InitializeEasyChatWordArray(u16 *words, u16 length); u8 *ConvertEasyChatWordsToString(u8 *dest, const u16 *src, u16 columns, u16 rows); bool8 IsBardWordInvalid(u16 word); u16 GetRandomEasyChatWordFromGroup(u16 group); -u16 GetNewHipsterPhraseToTeach(void); +u16 UnlockRandomTrendySaying(void); u16 EasyChat_GetNumWordsInGroup(u8); u16 GetRandomEasyChatWordFromUnlockedGroup(u16); void DoEasyChatScreen(u8 type, u16 *words, MainCallback callback, u8 displayedPersonType); void InitQuestionnaireWords(void); -void UnlockAdditionalPhrase(u8 additionalPhraseId); +void UnlockTrendySaying(u8 wordIndex); #endif // GUARD_EASYCHAT_H diff --git a/include/field_control_avatar.h b/include/field_control_avatar.h index e02fcd5af..b259eb53c 100644 --- a/include/field_control_avatar.h +++ b/include/field_control_avatar.h @@ -32,7 +32,7 @@ bool8 TryDoDiveWarp(struct MapPosition *position, u16 b); int SetCableClubWarp(void); u8 TrySetDiveWarp(void); const u8 *GetInteractedLinkPlayerScript(struct MapPosition *position, u8 metatileBehavior, u8 direction); -u8 *GetCoordEventScriptAtMapPosition(struct MapPosition *position); +const u8 *GetCoordEventScriptAtMapPosition(struct MapPosition *position); void ClearPoisonStepCounter(void); #endif // GUARD_FIELDCONTROLAVATAR_H diff --git a/include/fieldmap.h b/include/fieldmap.h index f2dbefae8..47072bd1b 100644 --- a/include/fieldmap.h +++ b/include/fieldmap.h @@ -48,8 +48,8 @@ void LoadSecondaryTilesetPalette(struct MapLayout const *mapLayout); void CopySecondaryTilesetToVramUsingHeap(struct MapLayout const *mapLayout); void CopyPrimaryTilesetToVram(const struct MapLayout *); void CopySecondaryTilesetToVram(const struct MapLayout *); -struct MapHeader const *const GetMapHeaderFromConnection(struct MapConnection *connection); -struct MapConnection *GetMapConnectionAtPos(s16 x, s16 y); +const struct MapHeader *const GetMapHeaderFromConnection(const struct MapConnection *connection); +const struct MapConnection *GetMapConnectionAtPos(s16 x, s16 y); void MapGridSetMetatileImpassabilityAt(int x, int y, bool32 impassable); // field_region_map.c diff --git a/include/global.fieldmap.h b/include/global.fieldmap.h index d8fea5b23..7461929c3 100644 --- a/include/global.fieldmap.h +++ b/include/global.fieldmap.h @@ -50,10 +50,10 @@ struct MapLayout { /*0x00*/ s32 width; /*0x04*/ s32 height; - /*0x08*/ u16 *border; - /*0x0C*/ u16 *map; - /*0x10*/ struct Tileset *primaryTileset; - /*0x14*/ struct Tileset *secondaryTileset; + /*0x08*/ const u16 *border; + /*0x0C*/ const u16 *map; + /*0x10*/ const struct Tileset *primaryTileset; + /*0x14*/ const struct Tileset *secondaryTileset; }; struct BackupMapLayout @@ -98,7 +98,7 @@ struct CoordEvent u8 elevation; u16 trigger; u16 index; - u8 *script; + const u8 *script; }; struct BgEvent @@ -107,7 +107,7 @@ struct BgEvent u8 elevation; u8 kind; // The "kind" field determines how to access bgUnion union below. union { - u8 *script; + const u8 *script; struct { u16 item; u16 hiddenItemId; @@ -122,10 +122,10 @@ struct MapEvents u8 warpCount; u8 coordEventCount; u8 bgEventCount; - struct ObjectEventTemplate *objectEvents; - struct WarpEvent *warps; - struct CoordEvent *coordEvents; - struct BgEvent *bgEvents; + const struct ObjectEventTemplate *objectEvents; + const struct WarpEvent *warps; + const struct CoordEvent *coordEvents; + const struct BgEvent *bgEvents; }; struct MapConnection @@ -139,7 +139,7 @@ struct MapConnection struct MapConnections { s32 count; - struct MapConnection *connections; + const struct MapConnection *connections; }; struct MapHeader diff --git a/include/global.h b/include/global.h index f7d166bb5..c20f2ed42 100644 --- a/include/global.h +++ b/include/global.h @@ -137,7 +137,7 @@ #define NUM_DEX_FLAG_BYTES ROUND_BITS_TO_BYTES(POKEMON_SLOTS_NUMBER) #define NUM_FLAG_BYTES ROUND_BITS_TO_BYTES(FLAGS_COUNT) -#define NUM_ADDITIONAL_PHRASE_BYTES ROUND_BITS_TO_BYTES(NUM_ADDITIONAL_PHRASES) +#define NUM_TRENDY_SAYING_BYTES ROUND_BITS_TO_BYTES(NUM_TRENDY_SAYINGS) // Calls m0/m1/.../m8 depending on how many arguments are passed. #define VARARG_8(m, ...) CAT(m, NARG_8(__VA_ARGS__))(__VA_ARGS__) @@ -687,7 +687,7 @@ struct MauvilleManGiddy struct MauvilleManHipster { u8 id; - bool8 alreadySpoken; + bool8 taughtWord; u8 language; }; @@ -1045,7 +1045,7 @@ struct SaveBlock1 /*0x2BC8*/ u16 easyChatBattleWon[EASY_CHAT_BATTLE_WORDS_COUNT]; /*0x2BD4*/ u16 easyChatBattleLost[EASY_CHAT_BATTLE_WORDS_COUNT]; /*0x2BE0*/ struct Mail mail[MAIL_COUNT]; - /*0x2E20*/ u8 additionalPhrases[NUM_ADDITIONAL_PHRASE_BYTES]; // bitfield for 33 additional phrases in easy chat system + /*0x2E20*/ u8 unlockedTrendySayings[NUM_TRENDY_SAYING_BYTES]; // Bitfield for unlockable Easy Chat words in EC_GROUP_TRENDY_SAYING /*0x2E25*/ //u8 padding5[3]; /*0x2E28*/ OldMan oldMan; /*0x2e64*/ struct DewfordTrend dewfordTrends[SAVED_TRENDS_COUNT]; diff --git a/include/graphics.h b/include/graphics.h index 7cf903034..ad23dc67c 100644 --- a/include/graphics.h +++ b/include/graphics.h @@ -7997,6 +7997,12 @@ extern const u32 gItemIcon_RibbonSweet[]; extern const u32 gItemIconPalette_RibbonSweet[]; extern const u32 gItemIcon_Everstone[]; extern const u32 gItemIconPalette_Everstone[]; +extern const u32 gItemIcon_BlackAugurite[]; +extern const u32 gItemIconPalette_BlackAugurite[]; +extern const u32 gItemIcon_LinkingCord[]; +extern const u32 gItemIconPalette_LinkingCord[]; +extern const u32 gItemIcon_PeatBlock[]; +extern const u32 gItemIconPalette_PeatBlock[]; // Nectars extern const u32 gItemIcon_RedNectar[]; extern const u32 gItemIconPalette_RedNectar[]; @@ -8872,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[]; diff --git a/include/item.h b/include/item.h index cf2209e0e..a99782f80 100644 --- a/include/item.h +++ b/include/item.h @@ -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 diff --git a/include/item_use.h b/include/item_use.h index 812e984ec..afa87c697 100644 --- a/include/item_use.h +++ b/include/item_use.h @@ -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); diff --git a/include/party_menu.h b/include/party_menu.h index afb320e18..31e591074 100644 --- a/include/party_menu.h +++ b/include/party_menu.h @@ -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); diff --git a/include/pokemon.h b/include/pokemon.h index 581677cae..6b476c5fc 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -346,7 +346,7 @@ struct BattleMove s8 priority; u32 flags; u8 split; - u8 argument; + u16 argument; u8 zMoveEffect; }; @@ -414,6 +414,7 @@ extern const u16 gUnionRoomFacilityClasses[]; extern const struct SpriteTemplate gBattlerSpriteTemplates[]; extern const s8 gNatureStatTable[][5]; extern const u16 *const gFormSpeciesIdTables[NUM_SPECIES]; +extern const struct FormChange *const gFormChangeTablePointers[NUM_SPECIES]; extern const u32 sExpCandyExperienceTable[]; void ZeroBoxMonData(struct BoxPokemon *boxMon); @@ -565,10 +566,12 @@ u8 *MonSpritesGfxManager_GetSpritePtr(u8 managerId, u8 spriteNum); u16 GetFormSpeciesId(u16 speciesId, u8 formId); u8 GetFormIdFromFormSpeciesId(u16 formSpeciesId); u16 GetFormChangeTargetSpecies(struct Pokemon *mon, u16 method, u32 arg); -u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *mon, u16 method, u32 arg); +u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *boxMon, u16 method, u32 arg); +bool32 DoesSpeciesHaveFormChangeMethod(u16 species, u16 method); u16 MonTryLearningNewMoveEvolution(struct Pokemon *mon, bool8 firstMove); bool32 ShouldShowFemaleDifferences(u16 species, u32 personality); -void TryToSetBattleFormChangeMoves(struct Pokemon *mon); +bool32 TryFormChange(u32 monId, u32 side, u16 method); +void TryToSetBattleFormChangeMoves(struct Pokemon *mon, u16 method); u32 GetMonFriendshipScore(struct Pokemon *pokemon); void UpdateMonPersonality(struct BoxPokemon *boxMon, u32 personality); diff --git a/include/random.h b/include/random.h index 60c718348..e7c2a3e28 100644 --- a/include/random.h +++ b/include/random.h @@ -29,7 +29,12 @@ void SeedRng2(u16 seed); * * RandomTag identifies the purpose of the value. * - * RandomUniform(tag, lo, hi) returns a number from lo to hi inclusive. + * RandomUniform(tag, lo, hi) returns a number from lo to hi inclusive + * with uniform probability. + * + * RandomElement(tag, array) returns an element in array with uniform + * probability. The array must be known at compile-time (e.g. a global + * const array). * * RandomPercentage(tag, t) returns FALSE with probability (1-t)/100, * and TRUE with probability t/100. @@ -47,6 +52,7 @@ enum RandomTag RNG_CRITICAL_HIT, RNG_CUTE_CHARM, RNG_DAMAGE_MODIFIER, + RNG_DIRE_CLAW, RNG_FLAME_BODY, RNG_FORCE_RANDOM_SWITCH, RNG_FROZEN, @@ -60,6 +66,7 @@ enum RandomTag RNG_SPEED_TIE, RNG_STATIC, RNG_STENCH, + RNG_TRI_ATTACK, }; #define RandomWeighted(tag, ...) \ @@ -73,14 +80,34 @@ enum RandomTag #define RandomPercentage(tag, t) \ ({ \ - const u8 weights[] = { 100 - t, t }; \ - RandomWeightedArray(tag, 100, ARRAY_COUNT(weights), weights); \ + u32 r; \ + if (t <= 0) \ + { \ + r = FALSE; \ + } \ + else if (t >= 100) \ + { \ + r = TRUE; \ + } \ + else \ + { \ + const u8 weights[] = { 100 - t, t }; \ + r = RandomWeightedArray(tag, 100, ARRAY_COUNT(weights), weights); \ + } \ + r; \ + }) + +#define RandomElement(tag, array) \ + ({ \ + *(typeof((array)[0]) *)RandomElementArray(tag, array, sizeof((array)[0]), ARRAY_COUNT(array)); \ }) u32 RandomUniform(enum RandomTag, u32 lo, u32 hi); u32 RandomWeightedArray(enum RandomTag, u32 sum, u32 n, const u8 *weights); +const void *RandomElementArray(enum RandomTag, const void *array, size_t size, size_t count); u32 RandomUniformDefault(enum RandomTag, u32 lo, u32 hi); u32 RandomWeightedArrayDefault(enum RandomTag, u32 sum, u32 n, const u8 *weights); +const void *RandomElementArrayDefault(enum RandomTag, const void *array, size_t size, size_t count); #endif // GUARD_RANDOM_H diff --git a/include/recorded_battle.h b/include/recorded_battle.h index fbe14a656..d04e89c36 100644 --- a/include/recorded_battle.h +++ b/include/recorded_battle.h @@ -44,6 +44,7 @@ enum RECORDED_MOVE_TARGET, RECORDED_PARTY_INDEX, RECORDED_BATTLE_PALACE_ACTION, + RECORDED_ITEM_ID, }; extern u32 gRecordedBattleRngSeed; diff --git a/include/strings.h b/include/strings.h index 959bb8c22..4019dee0b 100644 --- a/include/strings.h +++ b/include/strings.h @@ -475,6 +475,7 @@ extern const u8 gText_EscapeFromHere[]; extern const u8 gText_PkmnCuredOfPoison[]; extern const u8 gText_PkmnWokeUp2[]; extern const u8 gText_PkmnBurnHealed[]; +extern const u8 gText_PkmnFrostbiteHealed[]; extern const u8 gText_PkmnThawedOut[]; extern const u8 gText_PkmnCuredOfParalysis[]; extern const u8 gText_PkmnGotOverInfatuation[]; @@ -1025,6 +1026,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[]; diff --git a/sound/direct_sound_data.inc b/sound/direct_sound_data.inc index 05a1b7145..3020a8f1a 100644 --- a/sound/direct_sound_data.inc +++ b/sound/direct_sound_data.inc @@ -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 diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 19eedb41c..7dc33dd3b 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -257,6 +257,8 @@ static void CopyBattlerDataToAIParty(u32 bPosition, u32 side) void Ai_InitPartyStruct(void) { u32 i; + bool32 isOmniscient = (AI_THINKING_STRUCT->aiFlags & AI_FLAG_OMNISCIENT); + struct Pokemon *mon; AI_PARTY->count[B_SIDE_PLAYER] = gPlayerPartyCount; AI_PARTY->count[B_SIDE_OPPONENT] = gEnemyPartyCount; @@ -278,6 +280,17 @@ void Ai_InitPartyStruct(void) { if (GetMonData(&gPlayerParty[i], MON_DATA_HP) == 0) AI_PARTY->mons[B_SIDE_PLAYER][i].isFainted = TRUE; + + if (isOmniscient) + { + u32 j; + mon = &gPlayerParty[i]; + AI_PARTY->mons[B_SIDE_PLAYER][i].item = GetMonData(mon, MON_DATA_HELD_ITEM); + AI_PARTY->mons[B_SIDE_PLAYER][i].heldEffect = ItemId_GetHoldEffect(AI_PARTY->mons[B_SIDE_PLAYER][i].item); + AI_PARTY->mons[B_SIDE_PLAYER][i].ability = GetMonAbility(mon); + for (j = 0; j < MAX_MON_MOVES; j++) + AI_PARTY->mons[B_SIDE_PLAYER][i].moves[j] = GetMonData(mon, MON_DATA_MOVE1 + j); + } } } @@ -354,7 +367,7 @@ void GetAiLogicData(void) for (battlerAtk = 0; battlerAtk < gBattlersCount; battlerAtk++) { if (!IsBattlerAlive(battlerAtk) - || !IsBattlerAIControlled(battlerAtk)) { + || !IsAiBattlerAware(battlerAtk)) { continue; } @@ -974,7 +987,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) } break; case EFFECT_DREAM_EATER: - if (!(gBattleMons[battlerDef].status1 & STATUS1_SLEEP) || AI_DATA->abilities[battlerDef] == ABILITY_COMATOSE) + if (!AI_IsBattlerAsleepOrComatose(battlerDef)) score -= 8; else if (effectiveness == AI_EFFECTIVENESS_x0) score -= 10; @@ -1453,7 +1466,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) break; case EFFECT_SNORE: case EFFECT_SLEEP_TALK: - if (IsWakeupTurn(battlerAtk) || (!(gBattleMons[battlerAtk].status1 & STATUS1_SLEEP) || AI_DATA->abilities[battlerAtk] != ABILITY_COMATOSE)) + if (IsWakeupTurn(battlerAtk) || !AI_IsBattlerAsleepOrComatose(battlerAtk)) score -= 10; // if mon will wake up, is not asleep, or is not comatose break; case EFFECT_MEAN_LOOK: @@ -1463,7 +1476,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) case EFFECT_NIGHTMARE: if (gBattleMons[battlerDef].status2 & STATUS2_NIGHTMARE) score -= 10; - else if (!(gBattleMons[battlerDef].status1 & STATUS1_SLEEP) || AI_DATA->abilities[battlerDef] == ABILITY_COMATOSE) + else if (!AI_IsBattlerAsleepOrComatose(battlerDef)) score -= 8; else if (DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, AI_DATA->partnerMove)) score -= 10; @@ -1712,7 +1725,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) score -= 10; break; case EFFECT_REFRESH: - if (!(gBattleMons[battlerDef].status1 & (STATUS1_PSN_ANY | STATUS1_BURN | STATUS1_PARALYSIS))) + if (!(gBattleMons[battlerDef].status1 & (STATUS1_PSN_ANY | STATUS1_BURN | STATUS1_PARALYSIS | STATUS1_FROSTBITE))) score -= 10; break; case EFFECT_PSYCHO_SHIFT: @@ -1721,6 +1734,9 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) else if (gBattleMons[battlerAtk].status1 & STATUS1_BURN && !AI_CanBurn(battlerAtk, battlerDef, AI_DATA->abilities[battlerDef], BATTLE_PARTNER(battlerAtk), move, AI_DATA->partnerMove)) score -= 10; + else if (gBattleMons[battlerAtk].status1 & STATUS1_FROSTBITE && !AI_CanGiveFrostbite(battlerAtk, battlerDef, + AI_DATA->abilities[battlerDef], BATTLE_PARTNER(battlerAtk), move, AI_DATA->partnerMove)) + score -= 10; else if (gBattleMons[battlerAtk].status1 & STATUS1_PARALYSIS && !AI_CanParalyze(battlerAtk, battlerDef, AI_DATA->abilities[battlerDef], move, AI_DATA->partnerMove)) score -= 10; else if (gBattleMons[battlerAtk].status1 & STATUS1_SLEEP && !AI_CanPutToSleep(battlerAtk, battlerDef, AI_DATA->abilities[battlerDef], move, AI_DATA->partnerMove)) @@ -2610,6 +2626,15 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) if (gBattleMons[battlerAtk].hp <= gBattleMons[battlerAtk].maxHP / 3) score -= 10; break;*/ + case EFFECT_REVIVAL_BLESSING: + if (GetFirstFaintedPartyIndex(battlerAtk) == PARTY_SIZE) + score -= 10; + else if (CanAIFaintTarget(battlerAtk, battlerDef, 0)) + score -= 10; + else if (CanTargetFaintAi(battlerDef, battlerAtk) + && AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_SLOWER) + score -= 10; + break; case EFFECT_PLACEHOLDER: return 0; // cannot even select } // move effect checks @@ -3059,12 +3084,8 @@ static bool32 IsPinchBerryItemEffect(u16 holdEffect) case HOLD_EFFECT_SP_DEFENSE_UP: case HOLD_EFFECT_CRITICAL_UP: case HOLD_EFFECT_RANDOM_STAT_UP: - #ifdef HOLD_EFFECT_CUSTAP_BERRY case HOLD_EFFECT_CUSTAP_BERRY: - #endif - #ifdef HOLD_EFFECT_MICLE_BERRY case HOLD_EFFECT_MICLE_BERRY: - #endif return TRUE; } @@ -3121,7 +3142,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) score++; // check thawing moves - if ((gBattleMons[battlerAtk].status1 & STATUS1_FREEZE) && TestMoveFlags(move, FLAG_THAW_USER)) + if ((gBattleMons[battlerAtk].status1 & (STATUS1_FREEZE | STATUS1_FROSTBITE)) && TestMoveFlags(move, FLAG_THAW_USER)) score += (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) ? 20 : 10; // check burn @@ -3143,6 +3164,25 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) } } + // check frostbite + if (gBattleMons[battlerAtk].status1 & STATUS1_FROSTBITE) + { + switch (AI_DATA->abilities[battlerAtk]) + { + case ABILITY_GUTS: + break; + case ABILITY_NATURAL_CURE: + if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_SMART_SWITCHING + && HasOnlyMovesWithSplit(battlerAtk, SPLIT_SPECIAL, TRUE)) + score = 90; // Force switch if all your attacking moves are special and you have Natural Cure. + break; + default: + if (IS_MOVE_SPECIAL(move) && gBattleMoves[move].effect != EFFECT_FACADE) + score -= 2; + break; + } + } + // attacker ability checks switch (AI_DATA->abilities[battlerAtk]) { @@ -3580,7 +3620,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) case EFFECT_SUBSTITUTE: if (gStatuses3[battlerDef] & STATUS3_PERISH_SONG) score += 3; - if (gBattleMons[battlerDef].status1 & (STATUS1_BURN | STATUS1_PSN_ANY)) + if (gBattleMons[battlerDef].status1 & (STATUS1_BURN | STATUS1_PSN_ANY | STATUS1_FROSTBITE)) score++; if (HasMoveEffect(battlerDef, EFFECT_SLEEP) || HasMoveEffect(battlerDef, EFFECT_TOXIC) @@ -3780,7 +3820,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) case EFFECT_NIGHTMARE: if (AI_DATA->abilities[battlerDef] != ABILITY_MAGIC_GUARD && !(gBattleMons[battlerDef].status2 & STATUS2_NIGHTMARE) - && (AI_DATA->abilities[battlerDef] == ABILITY_COMATOSE || gBattleMons[battlerDef].status1 & STATUS1_SLEEP)) + && AI_IsBattlerAsleepOrComatose(battlerDef)) { score += 5; if (IsBattlerTrapped(battlerDef, TRUE)) @@ -3839,7 +3879,6 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score); break; case MOVE_KINGS_SHIELD: - #if (defined SPECIES_AEGISLASH && defined SPECIES_AEGISLASH_BLADE) if (AI_DATA->abilities[battlerAtk] == ABILITY_STANCE_CHANGE //Special logic for Aegislash && gBattleMons[battlerAtk].species == SPECIES_AEGISLASH_BLADE && !IsBattlerIncapacitated(battlerDef, AI_DATA->abilities[battlerDef])) @@ -3847,7 +3886,6 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) score += 3; break; } - #endif //fallthrough default: // protect ProtectChecks(battlerAtk, battlerDef, move, predictedMove, &score); @@ -4369,6 +4407,8 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) IncreaseParalyzeScore(battlerAtk, battlerDef, move, &score); else if (gBattleMons[battlerAtk].status1 & STATUS1_SLEEP) IncreaseSleepScore(battlerAtk, battlerDef, move, &score); + else if (gBattleMons[battlerAtk].status1 & STATUS1_FROSTBITE) + IncreaseFrostbiteScore(battlerAtk, battlerDef, move, &score); break; case EFFECT_GRUDGE: break; @@ -4516,7 +4556,6 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) score += 3; break; case EFFECT_RELIC_SONG: - #if (defined SPECIES_MELOETTA && defined SPECIES_MELOETTA_PIROUETTE) if (!(gBattleMons[battlerAtk].status2 & STATUS2_TRANSFORMED)) // Don't try to change form if it's transformed. { if (gBattleMons[battlerAtk].species == SPECIES_MELOETTA && gBattleMons[battlerDef].defense < gBattleMons[battlerDef].spDefense) @@ -4524,7 +4563,6 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) else if (gBattleMons[battlerAtk].species == SPECIES_MELOETTA_PIROUETTE && gBattleMons[battlerDef].spDefense < gBattleMons[battlerDef].defense) score += 3; // Change to Aria if can do more damage } - #endif break; case EFFECT_ELECTRIC_TERRAIN: case EFFECT_MISTY_TERRAIN: @@ -4759,7 +4797,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) score += 2; break; case EFFECT_FACADE: - if (gBattleMons[battlerAtk].status1 & (STATUS1_POISON | STATUS1_BURN | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON)) + if (gBattleMons[battlerAtk].status1 & (STATUS1_POISON | STATUS1_BURN | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON | STATUS1_FROSTBITE)) score++; break; case EFFECT_FOCUS_PUNCH: @@ -4795,6 +4833,10 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) score++; } break; + case EFFECT_REVIVAL_BLESSING: + if (GetFirstFaintedPartyIndex(battlerAtk) != PARTY_SIZE) + score += 2; + break; //case EFFECT_EXTREME_EVOBOOST: // TODO //break; //case EFFECT_CLANGOROUS_SOUL: // TODO diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index d1272d67d..d7fd062ba 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -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" @@ -198,9 +200,8 @@ static bool8 FindMonThatAbsorbsOpponentsMove(void) if (GetMonData(&party[i], MON_DATA_HP) == 0) continue; - if (GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) == SPECIES_NONE) - continue; - if (GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) == SPECIES_EGG) + species = GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG); + if (species == SPECIES_NONE || species == SPECIES_EGG) continue; if (i == gBattlerPartyIndexes[battlerIn1]) continue; @@ -213,12 +214,7 @@ static bool8 FindMonThatAbsorbsOpponentsMove(void) if (IsAceMon(gActiveBattler, i)) continue; - - species = GetMonData(&party[i], MON_DATA_SPECIES); - if (GetMonData(&party[i], MON_DATA_ABILITY_NUM) != 0) - monAbility = gSpeciesInfo[species].abilities[1]; - else - monAbility = gSpeciesInfo[species].abilities[0]; + monAbility = GetMonAbility(&party[i]); if (absorbingTypeAbility == monAbility && Random() & 1) { @@ -570,9 +566,8 @@ static bool8 FindMonWithFlagsAndSuperEffective(u16 flags, u8 moduloPercent) if (GetMonData(&party[i], MON_DATA_HP) == 0) continue; - if (GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) == SPECIES_NONE) - continue; - if (GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) == SPECIES_EGG) + species = GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG); + if (species == SPECIES_NONE || species == SPECIES_EGG) continue; if (i == gBattlerPartyIndexes[battlerIn1]) continue; @@ -585,12 +580,7 @@ static bool8 FindMonWithFlagsAndSuperEffective(u16 flags, u8 moduloPercent) if (IsAceMon(gActiveBattler, i)) continue; - - species = GetMonData(&party[i], MON_DATA_SPECIES); - if (GetMonData(&party[i], MON_DATA_ABILITY_NUM) != 0) - monAbility = gSpeciesInfo[species].abilities[1]; - else - monAbility = gSpeciesInfo[species].abilities[0]; + monAbility = GetMonAbility(&party[i]); CalcPartyMonTypeEffectivenessMultiplier(gLastLandedMoves[gActiveBattler], species, monAbility); if (gMoveResultFlags & flags) @@ -964,7 +954,9 @@ u8 GetMostSuitableMonToSwitchInto(void) // Get invalid slots ids. for (i = firstId; i < lastId; i++) { - if (GetMonData(&party[i], MON_DATA_SPECIES) == SPECIES_NONE + u16 species = GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG); + if (species == SPECIES_NONE + || species == SPECIES_EGG || GetMonData(&party[i], MON_DATA_HP) == 0 || gBattlerPartyIndexes[battlerIn1] == i || gBattlerPartyIndexes[battlerIn2] == i @@ -1005,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; @@ -1080,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); + if (itemEffects[3] & ITEM3_FREEZE && (gBattleMons[gActiveBattler].status1 & STATUS1_FREEZE || gBattleMons[gActiveBattler].status1 & STATUS1_FROSTBITE)) 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; } diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index a9e3ed3e0..3adbd77ae 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -457,7 +457,7 @@ void RecordLastUsedMoveByTarget(void) RecordKnownMove(gBattlerTarget, gLastMoves[gBattlerTarget]); } -bool32 IsBattlerAIControlled(u32 battlerId) +bool32 BattlerHasAi(u32 battlerId) { switch (GetBattlerPosition(battlerId)) { @@ -473,6 +473,14 @@ bool32 IsBattlerAIControlled(u32 battlerId) } } +bool32 IsAiBattlerAware(u32 battlerId) +{ + if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_OMNISCIENT) + return TRUE; + + return BattlerHasAi(battlerId); +} + void ClearBattlerMoveHistory(u8 battlerId) { memset(BATTLE_HISTORY->usedMoves[battlerId], 0, sizeof(BATTLE_HISTORY->usedMoves[battlerId])); @@ -529,7 +537,7 @@ void ClearBattlerItemEffectHistory(u8 battlerId) void SaveBattlerData(u8 battlerId) { - if (!IsBattlerAIControlled(battlerId)) + if (!BattlerHasAi(battlerId)) { u32 i; @@ -580,7 +588,7 @@ static bool32 ShouldFailForIllusion(u16 illusionSpecies, u32 battlerId) void SetBattlerData(u8 battlerId) { - if (!IsBattlerAIControlled(battlerId)) + if (!BattlerHasAi(battlerId)) { u32 i, species, illusionSpecies; @@ -623,7 +631,7 @@ void SetBattlerData(u8 battlerId) void RestoreBattlerData(u8 battlerId) { - if (!IsBattlerAIControlled(battlerId)) + if (!BattlerHasAi(battlerId)) { u32 i; @@ -1121,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++) { @@ -1223,15 +1231,15 @@ s32 AI_GetAbility(u32 battlerId) return gBattleStruct->overwrittenAbilities[battlerId]; // The AI knows its own ability. - if (IsBattlerAIControlled(battlerId)) + if (IsAiBattlerAware(battlerId)) return knownAbility; // Check neutralizing gas, gastro acid if (knownAbility == ABILITY_NONE) return knownAbility; - if (BATTLE_HISTORY->abilities[battlerId] != ABILITY_NONE) - return BATTLE_HISTORY->abilities[battlerId]; + if (AI_PARTY->mons[GetBattlerSide(battlerId)][gBattlerPartyIndexes[battlerId]].ability != ABILITY_NONE) + return AI_PARTY->mons[GetBattlerSide(battlerId)][gBattlerPartyIndexes[battlerId]].ability; // Abilities that prevent fleeing - treat as always known if (knownAbility == ABILITY_SHADOW_TAG || knownAbility == ABILITY_MAGNET_PULL || knownAbility == ABILITY_ARENA_TRAP) @@ -1256,8 +1264,8 @@ u16 AI_GetHoldEffect(u32 battlerId) { u32 holdEffect; - if (!IsBattlerAIControlled(battlerId)) - holdEffect = BATTLE_HISTORY->itemEffects[battlerId]; + if (!IsAiBattlerAware(battlerId)) + holdEffect = AI_PARTY->mons[GetBattlerSide(battlerId)][gBattlerPartyIndexes[battlerId]].heldEffect; else holdEffect = GetBattlerHoldEffect(battlerId, FALSE); @@ -1670,7 +1678,7 @@ void ProtectChecks(u8 battlerAtk, u8 battlerDef, u16 move, u16 predictedMove, s1 (*score) -= min(uses, 3); } - if (gBattleMons[battlerAtk].status1 & (STATUS1_PSN_ANY | STATUS1_BURN) + if (gBattleMons[battlerAtk].status1 & (STATUS1_PSN_ANY | STATUS1_BURN | STATUS1_FROSTBITE) || gBattleMons[battlerAtk].status2 & (STATUS2_CURSED | STATUS2_INFATUATION) || gStatuses3[battlerAtk] & (STATUS3_PERISH_SONG | STATUS3_LEECHSEED | STATUS3_YAWN)) { @@ -1881,7 +1889,7 @@ bool32 CanIndexMoveFaintTarget(u8 battlerAtk, u8 battlerDef, u8 index, u8 numHit u16 *GetMovesArray(u32 battler) { - if (IsBattlerAIControlled(battler) || IsBattlerAIControlled(BATTLE_PARTNER(battler))) + if (IsAiBattlerAware(battler) || IsAiBattlerAware(BATTLE_PARTNER(battler))) return gBattleMons[battler].moves; else return gBattleResources->battleHistory->usedMoves[battler]; @@ -2758,6 +2766,7 @@ bool32 AI_CanSleep(u8 battler, u16 ability) { if (ability == ABILITY_INSOMNIA || ability == ABILITY_VITAL_SPIRIT + || ability == ABILITY_COMATOSE || gBattleMons[battler].status1 & STATUS1_ANY || gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SAFEGUARD || (gFieldStatuses & (STATUS_FIELD_MISTY_TERRAIN | STATUS_FIELD_ELECTRIC_TERRAIN)) @@ -2831,6 +2840,7 @@ bool32 AI_CanPoison(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16 static bool32 AI_CanBeParalyzed(u8 battler, u16 ability) { if (ability == ABILITY_LIMBER + || ability == ABILITY_COMATOSE || IS_BATTLER_OF_TYPE(battler, TYPE_ELECTRIC) || gBattleMons[battler].status1 & STATUS1_ANY || IsAbilityStatusProtected(battler)) @@ -2876,6 +2886,7 @@ bool32 AI_CanBeBurned(u8 battler, u16 ability) { if (ability == ABILITY_WATER_VEIL || ability == ABILITY_WATER_BUBBLE + || ability == ABILITY_COMATOSE || IS_BATTLER_OF_TYPE(battler, TYPE_FIRE) || gBattleMons[battler].status1 & STATUS1_ANY || IsAbilityStatusProtected(battler) @@ -2884,6 +2895,18 @@ bool32 AI_CanBeBurned(u8 battler, u16 ability) return TRUE; } +bool32 AI_CanGetFrostbite(u8 battler, u16 ability) +{ + if (ability == ABILITY_MAGMA_ARMOR + || ability == ABILITY_COMATOSE + || IS_BATTLER_OF_TYPE(battler, TYPE_ICE) + || gBattleMons[battler].status1 & STATUS1_ANY + || IsAbilityStatusProtected(battler) + || gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SAFEGUARD) + return FALSE; + return TRUE; +} + bool32 ShouldBurnSelf(u8 battler, u16 ability) { if (AI_CanBeBurned(battler, ability) && ( @@ -2910,6 +2933,18 @@ bool32 AI_CanBurn(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 battlerAtkPar return TRUE; } +bool32 AI_CanGiveFrostbite(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 battlerAtkPartner, u16 move, u16 partnerMove) +{ + if (!AI_CanGetFrostbite(battlerDef, defAbility) + || AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0 + || DoesSubstituteBlockMove(battlerAtk, battlerDef, move) + || PartnerMoveEffectIsStatusSameTarget(battlerAtkPartner, battlerDef, partnerMove)) + { + return FALSE; + } + return TRUE; +} + bool32 AI_CanBeInfatuated(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 atkGender, u8 defGender) { if ((gBattleMons[battlerDef].status2 & STATUS2_INFATUATION) @@ -3136,7 +3171,7 @@ u16 GetAllyChosenMove(u8 battlerId) { u8 partnerBattler = BATTLE_PARTNER(battlerId); - if (!IsBattlerAlive(partnerBattler) || !IsBattlerAIControlled(partnerBattler)) + if (!IsBattlerAlive(partnerBattler) || !IsAiBattlerAware(partnerBattler)) return MOVE_NONE; else if (partnerBattler > battlerId) // Battler with the lower id chooses the move first. return gLastMoves[partnerBattler]; @@ -3412,7 +3447,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++) @@ -3709,6 +3744,25 @@ void IncreaseConfusionScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score) } } +void IncreaseFrostbiteScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score) +{ + if ((AI_THINKING_STRUCT->aiFlags & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0)) + return; + + if (AI_CanGiveFrostbite(battlerAtk, battlerDef, AI_DATA->abilities[battlerDef], BATTLE_PARTNER(battlerAtk), move, AI_DATA->partnerMove)) + { + (*score)++; // frostbite is good + if (HasMoveWithSplit(battlerDef, SPLIT_SPECIAL)) + { + if (CanTargetFaintAi(battlerDef, battlerAtk)) + *score += 2; // frostbiting the target to stay alive is cool + } + + if (HasMoveEffect(battlerAtk, EFFECT_HEX) || HasMoveEffect(BATTLE_PARTNER(battlerAtk), EFFECT_HEX)) + (*score)++; + } +} + bool32 AI_MoveMakesContact(u32 ability, u32 holdEffect, u16 move) { if (TestMoveFlags(move, FLAG_MAKES_CONTACT) @@ -3749,3 +3803,8 @@ bool32 ShouldUseZMove(u8 battlerAtk, u8 battlerDef, u16 chosenMove) return FALSE; } + +bool32 AI_IsBattlerAsleepOrComatose(u8 battlerId) +{ + return (gBattleMons[battlerId].status1 & STATUS1_SLEEP) || AI_DATA->abilities[battlerId] == ABILITY_COMATOSE; +} diff --git a/src/battle_anim_effects_3.c b/src/battle_anim_effects_3.c index ff5f04446..7d449c767 100755 --- a/src/battle_anim_effects_3.c +++ b/src/battle_anim_effects_3.c @@ -2350,6 +2350,8 @@ void AnimTask_TransformMon(u8 taskId) SetAnimBgAttribute(2, BG_ANIM_MOSAIC, 1); gTasks[taskId].data[10] = gBattleAnimArgs[0]; + gTasks[taskId].data[11] = gBattleAnimArgs[1]; + gTasks[taskId].data[12] = gBattleAnimArgs[2]; gTasks[taskId].data[0]++; break; case 1: @@ -2364,7 +2366,7 @@ void AnimTask_TransformMon(u8 taskId) } break; case 2: - HandleSpeciesGfxDataChange(gBattleAnimAttacker, gBattleAnimTarget, gTasks[taskId].data[10], gBattleAnimArgs[1], TRUE); + HandleSpeciesGfxDataChange(gBattleAnimAttacker, gBattleAnimTarget, gTasks[taskId].data[10], gTasks[taskId].data[11], gTasks[taskId].data[12]); GetBgDataForTransform(&animBg, gBattleAnimAttacker); if (IsContest()) diff --git a/src/battle_anim_new.c b/src/battle_anim_new.c index b3502fcb9..715e5b3e2 100644 --- a/src/battle_anim_new.c +++ b/src/battle_anim_new.c @@ -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); } diff --git a/src/battle_anim_throw.c b/src/battle_anim_throw.c index a3197d447..3fc2000e4 100755 --- a/src/battle_anim_throw.c +++ b/src/battle_anim_throw.c @@ -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); } diff --git a/src/battle_controller_link_opponent.c b/src/battle_controller_link_opponent.c index 908363907..b4936da5c 100644 --- a/src/battle_controller_link_opponent.c +++ b/src/battle_controller_link_opponent.c @@ -1395,6 +1395,7 @@ static void LinkOpponentHandleMoveAnimation(void) gWeatherMoveAnim = gBattleResources->bufferA[gActiveBattler][12] | (gBattleResources->bufferA[gActiveBattler][13] << 8); gAnimDisableStructPtr = (struct DisableStruct *)&gBattleResources->bufferA[gActiveBattler][16]; gTransformedPersonalities[gActiveBattler] = gAnimDisableStructPtr->transformedMonPersonality; + gTransformedOtIds[gActiveBattler] = gAnimDisableStructPtr->transformedMonOtId; gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 0; gBattlerControllerFuncs[gActiveBattler] = LinkOpponentDoMoveAnimation; BattleTv_SetDataBasedOnMove(move, gWeatherMoveAnim, gAnimDisableStructPtr); diff --git a/src/battle_controller_link_partner.c b/src/battle_controller_link_partner.c index 1ef5d6355..d07a92e93 100644 --- a/src/battle_controller_link_partner.c +++ b/src/battle_controller_link_partner.c @@ -1232,6 +1232,7 @@ static void LinkPartnerHandleMoveAnimation(void) gWeatherMoveAnim = gBattleResources->bufferA[gActiveBattler][12] | (gBattleResources->bufferA[gActiveBattler][13] << 8); gAnimDisableStructPtr = (struct DisableStruct *)&gBattleResources->bufferA[gActiveBattler][16]; gTransformedPersonalities[gActiveBattler] = gAnimDisableStructPtr->transformedMonPersonality; + gTransformedOtIds[gActiveBattler] = gAnimDisableStructPtr->transformedMonOtId; gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 0; gBattlerControllerFuncs[gActiveBattler] = LinkPartnerDoMoveAnimation; BattleTv_SetDataBasedOnMove(move, gWeatherMoveAnim, gAnimDisableStructPtr); diff --git a/src/battle_controller_opponent.c b/src/battle_controller_opponent.c index 79283b067..c3e4a9037 100644 --- a/src/battle_controller_opponent.c +++ b/src/battle_controller_opponent.c @@ -20,6 +20,7 @@ #include "main.h" #include "m4a.h" #include "palette.h" +#include "party_menu.h" #include "pokeball.h" #include "pokemon.h" #include "random.h" @@ -33,6 +34,7 @@ #include "constants/battle_anim.h" #include "constants/items.h" #include "constants/moves.h" +#include "constants/party_menu.h" #include "constants/songs.h" #include "constants/trainers.h" #include "trainer_hill.h" @@ -226,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) @@ -1466,6 +1470,7 @@ static void OpponentHandleMoveAnimation(void) gWeatherMoveAnim = gBattleResources->bufferA[gActiveBattler][12] | (gBattleResources->bufferA[gActiveBattler][13] << 8); gAnimDisableStructPtr = (struct DisableStruct *)&gBattleResources->bufferA[gActiveBattler][16]; gTransformedPersonalities[gActiveBattler] = gAnimDisableStructPtr->transformedMonPersonality; + gTransformedOtIds[gActiveBattler] = gAnimDisableStructPtr->transformedMonOtId; gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 0; gBattlerControllerFuncs[gActiveBattler] = OpponentDoMoveAnimation; } @@ -1665,7 +1670,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(); } @@ -1674,7 +1679,13 @@ static void OpponentHandleChoosePokemon(void) s32 chosenMonId; s32 pokemonInBattle = 1; - if (*(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler) == PARTY_SIZE) + // Choosing Revival Blessing target + if ((gBattleResources->bufferA[gActiveBattler][1] & 0xF) == PARTY_ACTION_CHOOSE_FAINTED_MON) + { + chosenMonId = gSelectedMonPartyId = GetFirstFaintedPartyIndex(gActiveBattler); + } + // Switching out + else if (*(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler) == PARTY_SIZE) { chosenMonId = GetMostSuitableMonToSwitchInto(); @@ -1709,17 +1720,17 @@ static void OpponentHandleChoosePokemon(void) } } } + *(gBattleStruct->monToSwitchIntoId + gActiveBattler) = chosenMonId; } else { chosenMonId = *(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler); *(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler) = PARTY_SIZE; + *(gBattleStruct->monToSwitchIntoId + gActiveBattler) = chosenMonId; } - - - *(gBattleStruct->monToSwitchIntoId + gActiveBattler) = chosenMonId; BtlController_EmitChosenMonReturnValue(BUFFER_B, chosenMonId, NULL); OpponentBufferExecCompleted(); + } static u8 CountAIAliveNonEggMonsExcept(u8 slotToIgnore) @@ -1961,7 +1972,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) @@ -1969,7 +1980,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); @@ -1984,7 +1995,7 @@ static void Task_StartSendOutAnim(u8 taskId) gActiveBattler ^= BIT_FLANK; } gBattlerControllerFuncs[gActiveBattler] = Intro_TryShinyAnimShowHealthbox; - gActiveBattler = savedActiveBank; + gActiveBattler = savedActiveBattler; DestroyTask(taskId); } diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index 82a9d7b7a..b9eb566c0 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -2709,6 +2709,7 @@ static void PlayerHandleMoveAnimation(void) gWeatherMoveAnim = gBattleResources->bufferA[gActiveBattler][12] | (gBattleResources->bufferA[gActiveBattler][13] << 8); gAnimDisableStructPtr = (struct DisableStruct *)&gBattleResources->bufferA[gActiveBattler][16]; gTransformedPersonalities[gActiveBattler] = gAnimDisableStructPtr->transformedMonPersonality; + gTransformedOtIds[gActiveBattler] = gAnimDisableStructPtr->transformedMonOtId; gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 0; gBattlerControllerFuncs[gActiveBattler] = PlayerDoMoveAnimation; BattleTv_SetDataBasedOnMove(move, gWeatherMoveAnim, gAnimDisableStructPtr); @@ -2907,7 +2908,8 @@ static void PlayerHandleChoosePokemon(void) for (i = 0; i < ARRAY_COUNT(gBattlePartyCurrentOrder); i++) gBattlePartyCurrentOrder[i] = gBattleResources->bufferA[gActiveBattler][4 + i]; - if (gBattleTypeFlags & BATTLE_TYPE_ARENA && (gBattleResources->bufferA[gActiveBattler][1] & 0xF) != PARTY_ACTION_CANT_SWITCH) + if (gBattleTypeFlags & BATTLE_TYPE_ARENA && (gBattleResources->bufferA[gActiveBattler][1] & 0xF) != PARTY_ACTION_CANT_SWITCH + && (gBattleResources->bufferA[gActiveBattler][1] & 0xF) != PARTY_ACTION_CHOOSE_FAINTED_MON) { BtlController_EmitChosenMonReturnValue(BUFFER_B, gBattlerPartyIndexes[gActiveBattler] + 1, gBattlePartyCurrentOrder); PlayerBufferExecCompleted(); diff --git a/src/battle_controller_player_partner.c b/src/battle_controller_player_partner.c index 88bc4f974..b94d5347a 100644 --- a/src/battle_controller_player_partner.c +++ b/src/battle_controller_player_partner.c @@ -16,6 +16,7 @@ #include "main.h" #include "m4a.h" #include "palette.h" +#include "party_menu.h" #include "pokeball.h" #include "pokemon.h" #include "reshow_battle_screen.h" @@ -27,6 +28,7 @@ #include "window.h" #include "constants/battle_anim.h" #include "constants/songs.h" +#include "constants/party_menu.h" #include "constants/trainers.h" static void PlayerPartnerHandleGetMonData(void); @@ -1431,6 +1433,7 @@ static void PlayerPartnerHandleMoveAnimation(void) gWeatherMoveAnim = gBattleResources->bufferA[gActiveBattler][12] | (gBattleResources->bufferA[gActiveBattler][13] << 8); gAnimDisableStructPtr = (struct DisableStruct *)&gBattleResources->bufferA[gActiveBattler][16]; gTransformedPersonalities[gActiveBattler] = gAnimDisableStructPtr->transformedMonPersonality; + gTransformedOtIds[gActiveBattler] = gAnimDisableStructPtr->transformedMonOtId; gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 0; gBattlerControllerFuncs[gActiveBattler] = PlayerPartnerDoMoveAnimation; } @@ -1549,25 +1552,33 @@ static void PlayerPartnerHandleChooseItem(void) static void PlayerPartnerHandleChoosePokemon(void) { - s32 chosenMonId = GetMostSuitableMonToSwitchInto(); - - if (chosenMonId == PARTY_SIZE) // just switch to the next mon + s32 chosenMonId; + // Choosing Revival Blessing target + if ((gBattleResources->bufferA[gActiveBattler][1] & 0xF) == PARTY_ACTION_CHOOSE_FAINTED_MON) { - u8 playerMonIdentity = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT); - u8 selfIdentity = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT); - - for (chosenMonId = PARTY_SIZE / 2; chosenMonId < PARTY_SIZE; chosenMonId++) + chosenMonId = gSelectedMonPartyId = GetFirstFaintedPartyIndex(gActiveBattler); + } + // Switching out + else + { + chosenMonId = GetMostSuitableMonToSwitchInto(); + if (chosenMonId == PARTY_SIZE) // just switch to the next mon { - if (GetMonData(&gPlayerParty[chosenMonId], MON_DATA_HP) != 0 - && chosenMonId != gBattlerPartyIndexes[playerMonIdentity] - && chosenMonId != gBattlerPartyIndexes[selfIdentity]) + u8 playerMonIdentity = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT); + u8 selfIdentity = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT); + + for (chosenMonId = PARTY_SIZE / 2; chosenMonId < PARTY_SIZE; chosenMonId++) { - break; + if (GetMonData(&gPlayerParty[chosenMonId], MON_DATA_HP) != 0 + && chosenMonId != gBattlerPartyIndexes[playerMonIdentity] + && chosenMonId != gBattlerPartyIndexes[selfIdentity]) + { + break; + } } } + *(gBattleStruct->monToSwitchIntoId + gActiveBattler) = chosenMonId; } - - *(gBattleStruct->monToSwitchIntoId + gActiveBattler) = chosenMonId; BtlController_EmitChosenMonReturnValue(BUFFER_B, chosenMonId, NULL); PlayerPartnerBufferExecCompleted(); } diff --git a/src/battle_controller_recorded_opponent.c b/src/battle_controller_recorded_opponent.c index 2e93d625d..ea9882054 100644 --- a/src/battle_controller_recorded_opponent.c +++ b/src/battle_controller_recorded_opponent.c @@ -10,11 +10,13 @@ #include "battle_tv.h" #include "bg.h" #include "data.h" +#include "item_menu.h" #include "item_use.h" #include "link.h" #include "main.h" #include "m4a.h" #include "palette.h" +#include "party_menu.h" #include "pokeball.h" #include "pokemon.h" #include "recorded_battle.h" @@ -1325,6 +1327,7 @@ static void RecordedOpponentHandleMoveAnimation(void) gWeatherMoveAnim = gBattleResources->bufferA[gActiveBattler][12] | (gBattleResources->bufferA[gActiveBattler][13] << 8); gAnimDisableStructPtr = (struct DisableStruct *)&gBattleResources->bufferA[gActiveBattler][16]; gTransformedPersonalities[gActiveBattler] = gAnimDisableStructPtr->transformedMonPersonality; + gTransformedOtIds[gActiveBattler] = gAnimDisableStructPtr->transformedMonOtId; gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 0; gBattlerControllerFuncs[gActiveBattler] = RecordedOpponentDoMoveAnimation; } @@ -1436,12 +1439,17 @@ 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(); } static void RecordedOpponentHandleChoosePokemon(void) { *(gBattleStruct->monToSwitchIntoId + gActiveBattler) = RecordedBattle_GetBattlerAction(RECORDED_PARTY_INDEX, gActiveBattler); + gSelectedMonPartyId = gBattleStruct->monToSwitchIntoId[gActiveBattler]; // Revival Blessing BtlController_EmitChosenMonReturnValue(BUFFER_B, *(gBattleStruct->monToSwitchIntoId + gActiveBattler), NULL); RecordedOpponentBufferExecCompleted(); } diff --git a/src/battle_controller_recorded_player.c b/src/battle_controller_recorded_player.c index 1906df8a8..8957b285a 100644 --- a/src/battle_controller_recorded_player.c +++ b/src/battle_controller_recorded_player.c @@ -7,11 +7,13 @@ #include "battle_interface.h" #include "bg.h" #include "data.h" +#include "item_menu.h" #include "item_use.h" #include "link.h" #include "main.h" #include "m4a.h" #include "palette.h" +#include "party_menu.h" #include "pokeball.h" #include "pokemon.h" #include "recorded_battle.h" @@ -1333,6 +1335,7 @@ static void RecordedPlayerHandleMoveAnimation(void) gWeatherMoveAnim = gBattleResources->bufferA[gActiveBattler][12] | (gBattleResources->bufferA[gActiveBattler][13] << 8); gAnimDisableStructPtr = (struct DisableStruct *)&gBattleResources->bufferA[gActiveBattler][16]; gTransformedPersonalities[gActiveBattler] = gAnimDisableStructPtr->transformedMonPersonality; + gTransformedOtIds[gActiveBattler] = gAnimDisableStructPtr->transformedMonOtId; gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 0; gBattlerControllerFuncs[gActiveBattler] = RecordedPlayerDoMoveAnimation; } @@ -1460,12 +1463,17 @@ 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(); } static void RecordedPlayerHandleChoosePokemon(void) { *(gBattleStruct->monToSwitchIntoId + gActiveBattler) = RecordedBattle_GetBattlerAction(RECORDED_PARTY_INDEX, gActiveBattler); + gSelectedMonPartyId = gBattleStruct->monToSwitchIntoId[gActiveBattler]; // Revival Blessing BtlController_EmitChosenMonReturnValue(BUFFER_B, *(gBattleStruct->monToSwitchIntoId + gActiveBattler), NULL); RecordedPlayerBufferExecCompleted(); } diff --git a/src/battle_controller_wally.c b/src/battle_controller_wally.c index ae20c54ec..fa1fa00fb 100644 --- a/src/battle_controller_wally.c +++ b/src/battle_controller_wally.c @@ -1115,6 +1115,7 @@ static void WallyHandleMoveAnimation(void) gWeatherMoveAnim = gBattleResources->bufferA[gActiveBattler][12] | (gBattleResources->bufferA[gActiveBattler][13] << 8); gAnimDisableStructPtr = (struct DisableStruct *)&gBattleResources->bufferA[gActiveBattler][16]; gTransformedPersonalities[gActiveBattler] = gAnimDisableStructPtr->transformedMonPersonality; + gTransformedOtIds[gActiveBattler] = gAnimDisableStructPtr->transformedMonOtId; gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 0; gBattlerControllerFuncs[gActiveBattler] = WallyDoMoveAnimation; } diff --git a/src/battle_debug.c b/src/battle_debug.c index 027be03a4..0549cf91e 100644 --- a/src/battle_debug.c +++ b/src/battle_debug.c @@ -181,6 +181,7 @@ static const u8 sText_SideStatus[] = _("Side Status"); static const u8 sText_MaxHp[] = _("HP Max"); static const u8 sText_CurrHp[] = _("HP Current"); static const u8 sText_Freeze[] = _("Freeze"); +static const u8 sText_Frostbite[] = _("Frostbite"); static const u8 sText_ToxicPoison[] = _("Toxic Poison"); static const u8 sText_ToxicCounter[] = _("Toxic Counter"); static const u8 sText_Flinch[] = _("Flinch"); @@ -258,6 +259,7 @@ static const struct BitfieldInfo sStatus1Bitfield[] = {/*Paralysis*/1, 6}, {/*Toxic Poison*/ 1, 7}, {/*Toxic Counter*/ 4, 8}, + {/*Frostbite*/ 1, 12}, }; static const struct BitfieldInfo sStatus2Bitfield[] = @@ -397,6 +399,7 @@ static const struct ListMenuItem sStatus1ListItems[] = {gText_Paralysis, 4}, {sText_ToxicPoison, 5}, {sText_ToxicCounter, 6}, + {sText_Frostbite, 7}, }; static const struct ListMenuItem sStatus2ListItems[] = @@ -774,7 +777,7 @@ static void Task_ShowAiPoints(u8 taskId) // Swap battler if it's player mon data->aiBattlerId = data->battlerId; - while (!IsBattlerAIControlled(data->aiBattlerId)) + while (!BattlerHasAi(data->aiBattlerId)) { if (++data->aiBattlerId >= gBattlersCount) data->aiBattlerId = 0; @@ -931,7 +934,7 @@ static void Task_ShowAiKnowledge(u8 taskId) // Swap battler if it's player mon data->aiBattlerId = data->battlerId; - while (!IsBattlerAIControlled(data->aiBattlerId)) + while (!BattlerHasAi(data->aiBattlerId)) { if (++data->aiBattlerId >= gBattlersCount) data->aiBattlerId = 0; diff --git a/src/battle_gfx_sfx_util.c b/src/battle_gfx_sfx_util.c index bc541f0a0..c06a7795a 100644 --- a/src/battle_gfx_sfx_util.c +++ b/src/battle_gfx_sfx_util.c @@ -398,7 +398,7 @@ void InitAndLaunchChosenStatusAnimation(bool8 isStatus2, u32 status) gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].statusAnimActive = 1; if (!isStatus2) { - if (status == STATUS1_FREEZE) + if (status == STATUS1_FREEZE || status == STATUS1_FROSTBITE) LaunchStatusAnimation(gActiveBattler, B_ANIM_STATUS_FRZ); else if (status == STATUS1_POISON || status & STATUS1_TOXIC_POISON) LaunchStatusAnimation(gActiveBattler, B_ANIM_STATUS_PSN); @@ -551,7 +551,7 @@ bool8 IsBattleSEPlaying(u8 battlerId) static void BattleLoadMonSpriteGfx(struct Pokemon *mon, u32 battlerId, bool32 opponent) { - u32 monsPersonality, currentPersonality, otId, species, paletteOffset, position; + u32 monsPersonality, currentPersonality, otId, currentOtId, species, paletteOffset, position; const void *lzPaletteData; struct Pokemon *illusionMon = GetIllusionMonPtr(battlerId); if (illusionMon != NULL) @@ -561,18 +561,26 @@ static void BattleLoadMonSpriteGfx(struct Pokemon *mon, u32 battlerId, bool32 op return; monsPersonality = GetMonData(mon, MON_DATA_PERSONALITY); + otId = GetMonData(mon, MON_DATA_OT_ID); + if (gBattleSpritesDataPtr->battlerData[battlerId].transformSpecies == SPECIES_NONE) { species = GetMonData(mon, MON_DATA_SPECIES); currentPersonality = monsPersonality; + currentOtId = otId; } else { species = gBattleSpritesDataPtr->battlerData[battlerId].transformSpecies; - currentPersonality = gTransformedPersonalities[battlerId]; + #if B_TRANSFORM_SHINY >= GEN_4 + currentPersonality = gTransformedPersonalities[battlerId]; + currentOtId = gTransformedOtIds[battlerId]; + #else + currentPersonality = monsPersonality; + currentOtId = otId; + #endif } - otId = GetMonData(mon, MON_DATA_OT_ID); position = GetBattlerPosition(battlerId); if (opponent) { @@ -592,7 +600,7 @@ static void BattleLoadMonSpriteGfx(struct Pokemon *mon, u32 battlerId, bool32 op if (gBattleSpritesDataPtr->battlerData[battlerId].transformSpecies == SPECIES_NONE) lzPaletteData = GetMonFrontSpritePal(mon); else - lzPaletteData = GetMonSpritePalFromSpeciesAndPersonality(species, otId, monsPersonality); + lzPaletteData = GetMonSpritePalFromSpeciesAndPersonality(species, currentOtId, currentPersonality); LZDecompressWram(lzPaletteData, gDecompressionBuffer); LoadPalette(gDecompressionBuffer, paletteOffset, PLTT_SIZE_4BPP); @@ -880,10 +888,18 @@ void HandleSpeciesGfxDataChange(u8 battlerAtk, u8 battlerDef, bool8 castform, bo if (GetBattlerSide(battlerAtk) == B_SIDE_PLAYER) { + #if B_TRANSFORM_SHINY >= GEN_4 if (trackEnemyPersonality) + { personalityValue = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_PERSONALITY); + otId = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_OT_ID); + } else + #endif + { personalityValue = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_PERSONALITY); + otId = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_OT_ID); + } otId = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_OT_ID); HandleLoadSpecialPokePic(FALSE, @@ -893,11 +909,19 @@ void HandleSpeciesGfxDataChange(u8 battlerAtk, u8 battlerDef, bool8 castform, bo } else { + #if B_TRANSFORM_SHINY >= GEN_4 if (trackEnemyPersonality) + { personalityValue = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_PERSONALITY); + otId = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_OT_ID); + + } else + #endif + { personalityValue = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_PERSONALITY); - otId = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_OT_ID); + otId = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_OT_ID); + } HandleLoadSpecialPokePic(TRUE, gMonSpritesGfxPtr->sprites.ptr[position], diff --git a/src/battle_interface.c b/src/battle_interface.c index 35c0e60c6..58b1d1117 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -73,6 +73,9 @@ enum HEALTHBOX_GFX_STATUS_BRN_BATTLER0, //status brn HEALTHBOX_GFX_34, HEALTHBOX_GFX_35, + HEALTHBOX_GFX_STATUS_FSB_BATTLER0, //status fsb + HEALTHBOX_GFX_116, + HEALTHBOX_GFX_117, HEALTHBOX_GFX_36, //misc [Black section] HEALTHBOX_GFX_37, //misc [Black section] HEALTHBOX_GFX_38, //misc [Black section] @@ -123,6 +126,9 @@ enum HEALTHBOX_GFX_STATUS_BRN_BATTLER1, //status2 "BRN" HEALTHBOX_GFX_84, HEALTHBOX_GFX_85, + HEALTHBOX_GFX_STATUS_FSB_BATTLER1, //status2 "FSB" + HEALTHBOX_GFX_118, + HEALTHBOX_GFX_119, HEALTHBOX_GFX_STATUS_PSN_BATTLER2, //status3 "PSN" HEALTHBOX_GFX_87, HEALTHBOX_GFX_88, @@ -138,6 +144,9 @@ enum HEALTHBOX_GFX_STATUS_BRN_BATTLER2, //status3 "BRN" HEALTHBOX_GFX_99, HEALTHBOX_GFX_100, + HEALTHBOX_GFX_STATUS_FSB_BATTLER2, //status3 "FSB" + HEALTHBOX_GFX_120, + HEALTHBOX_GFX_121, HEALTHBOX_GFX_STATUS_PSN_BATTLER3, //status4 "PSN" HEALTHBOX_GFX_102, HEALTHBOX_GFX_103, @@ -153,6 +162,9 @@ enum HEALTHBOX_GFX_STATUS_BRN_BATTLER3, //status4 "BRN" HEALTHBOX_GFX_114, HEALTHBOX_GFX_115, + HEALTHBOX_GFX_STATUS_FSB_BATTLER3, //status4 "FSB" + HEALTHBOX_GFX_122, + HEALTHBOX_GFX_123, HEALTHBOX_GFX_FRAME_END, HEALTHBOX_GFX_FRAME_END_BAR, }; @@ -186,7 +198,6 @@ static void MegaIndicator_SetVisibilities(u32 healthboxId, bool32 invisible); static void MegaIndicator_UpdateLevel(u32 healthboxId, u32 level); static void MegaIndicator_CreateSprites(u32 battlerId, u32 healthboxSpriteId); static void MegaIndicator_UpdateOamPriorities(u32 healthboxId, u32 oamPriority); -static void MegaIndicator_DestroySprites(u32 healthboxSpriteId); static void SpriteCb_MegaIndicator(struct Sprite *); static u8 GetStatusIconForBattlerId(u8, u8); @@ -691,12 +702,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(); } @@ -884,14 +900,6 @@ static void UpdateSpritePos(u8 spriteId, s16 x, s16 y) gSprites[spriteId].y = y; } -void DestoryHealthboxSprite(u8 healthboxSpriteId) -{ - MegaIndicator_DestroySprites(healthboxSpriteId); - DestroySprite(&gSprites[gSprites[healthboxSpriteId].oam.affineParam]); - DestroySprite(&gSprites[gSprites[healthboxSpriteId].hMain_HealthBarSpriteId]); - DestroySprite(&gSprites[healthboxSpriteId]); -} - void DummyBattleInterfaceFunc(u8 healthboxSpriteId, bool8 isDoubleBattleBattlerOnly) { @@ -984,8 +992,7 @@ static void UpdateLvlInHealthbox(u8 healthboxSpriteId, u8 lvl) u8 battler = gSprites[healthboxSpriteId].hMain_Battler; // Don't print Lv char if mon is mega evolved or primal reverted. - if (gBattleStruct->mega.evolvedPartyIds[GetBattlerSide(battler)] & gBitTable[gBattlerPartyIndexes[battler]] - || gBattleStruct->mega.primalRevertedPartyIds[GetBattlerSide(battler)] & gBitTable[gBattlerPartyIndexes[battler]]) + if (IsBattlerMegaEvolved(battler) || IsBattlerPrimalReverted(battler)) { objVram = ConvertIntToDecimalStringN(text, lvl, STR_CONV_MODE_LEFT_ALIGN, 3); xPos = 5 * (3 - (objVram - (text + 2))) - 1; @@ -1507,22 +1514,16 @@ static bool32 MegaIndicator_ShouldBeInvisible(u32 battlerId, u32 indicatorType) u32 side = GetBattlerSide(battlerId); if (indicatorType == INDICATOR_MEGA) { - if (gBattleStruct->mega.evolvedPartyIds[side] & gBitTable[gBattlerPartyIndexes[battlerId]]) + if (IsBattlerMegaEvolved(battlerId)) return FALSE; } else { - if (indicatorType == INDICATOR_ALPHA) - { - if (gBattleMons[battlerId].species != SPECIES_KYOGRE_PRIMAL) - return TRUE; - } - else if (indicatorType == INDICATOR_OMEGA) - { - if (gBattleMons[battlerId].species != SPECIES_GROUDON_PRIMAL) - return TRUE; - } - if (gBattleStruct->mega.primalRevertedPartyIds[side] & gBitTable[gBattlerPartyIndexes[battlerId]]) + if (indicatorType == INDICATOR_ALPHA && gBattleMons[battlerId].species != SPECIES_KYOGRE_PRIMAL) + return TRUE; + else if (indicatorType == INDICATOR_OMEGA && gBattleMons[battlerId].species != SPECIES_GROUDON_PRIMAL) + return TRUE; + if (IsBattlerPrimalReverted(battlerId)) return FALSE; } return TRUE; @@ -1540,6 +1541,9 @@ void MegaIndicator_SetVisibilities(u32 healthboxId, bool32 invisible) u8 *spriteIds = MegaIndicator_GetSpriteIds(healthboxId); u32 battlerId = gSprites[healthboxId].hMain_Battler; + if (GetSafariZoneFlag()) + return; + for (i = 0; i < INDICATOR_COUNT; i++) { if (invisible == TRUE) @@ -1599,15 +1603,6 @@ static void MegaIndicator_CreateSprites(u32 battlerId, u32 healthboxSpriteId) } } -static void MegaIndicator_DestroySprites(u32 healthboxSpriteId) -{ - u32 i; - u8 *spriteIds = MegaIndicator_GetSpriteIds(healthboxSpriteId); - - for (i = 0; i < INDICATOR_COUNT; i++) - DestroySprite(&gSprites[spriteIds[i]]); -} - static void SpriteCb_MegaIndicator(struct Sprite *sprite) { u32 battlerId = sprite->tBattler; @@ -2218,6 +2213,11 @@ static void UpdateStatusIconInHealthbox(u8 healthboxSpriteId) statusGfxPtr = GetHealthboxElementGfxPtr(GetStatusIconForBattlerId(HEALTHBOX_GFX_STATUS_FRZ_BATTLER0, battlerId)); statusPalId = PAL_STATUS_FRZ; } + else if (status & STATUS1_FROSTBITE) + { + statusGfxPtr = GetHealthboxElementGfxPtr(GetStatusIconForBattlerId(HEALTHBOX_GFX_STATUS_FSB_BATTLER0, battlerId)); + statusPalId = PAL_STATUS_FRZ; + } else if (status & STATUS1_PARALYSIS) { statusGfxPtr = GetHealthboxElementGfxPtr(GetStatusIconForBattlerId(HEALTHBOX_GFX_STATUS_PRZ_BATTLER0, battlerId)); @@ -2300,6 +2300,16 @@ static u8 GetStatusIconForBattlerId(u8 statusElementId, u8 battlerId) else ret = HEALTHBOX_GFX_STATUS_FRZ_BATTLER3; break; + case HEALTHBOX_GFX_STATUS_FSB_BATTLER0: + if (battlerId == 0) + ret = HEALTHBOX_GFX_STATUS_FSB_BATTLER0; + else if (battlerId == 1) + ret = HEALTHBOX_GFX_STATUS_FSB_BATTLER1; + else if (battlerId == 2) + ret = HEALTHBOX_GFX_STATUS_FSB_BATTLER2; + else + ret = HEALTHBOX_GFX_STATUS_FSB_BATTLER3; + break; case HEALTHBOX_GFX_STATUS_BRN_BATTLER0: if (battlerId == 0) ret = HEALTHBOX_GFX_STATUS_BRN_BATTLER0; diff --git a/src/battle_main.c b/src/battle_main.c index efbf1b819..91d5c3aa5 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -120,8 +120,7 @@ static void SpriteCB_UnusedBattleInit_Main(struct Sprite *sprite); static void TrySpecialEvolution(void); static u32 Crc32B (const u8 *data, u32 size); static u32 GeneratePartyHash(const struct Trainer *trainer, u32 i); -static void ModifyPersonalityForNature(u32 *personality, u32 newNature); -static u32 GeneratePersonalityForGender(u32 gender, u32 species); +static void CustomTrainerPartyAssignMoves(struct Pokemon *mon, const struct TrainerMonCustomized *partyEntry); EWRAM_DATA u16 gBattle_BG0_X = 0; EWRAM_DATA u16 gBattle_BG0_Y = 0; @@ -227,6 +226,7 @@ EWRAM_DATA u8 gBattlerStatusSummaryTaskId[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA u8 gBattlerInMenuId = 0; EWRAM_DATA bool8 gDoingBattleAnim = FALSE; EWRAM_DATA u32 gTransformedPersonalities[MAX_BATTLERS_COUNT] = {0}; +EWRAM_DATA u32 gTransformedOtIds[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA u8 gPlayerDpadHoldFrames = 0; EWRAM_DATA struct BattleSpriteData *gBattleSpritesDataPtr = NULL; EWRAM_DATA struct MonSpritesGfx *gMonSpritesGfxPtr = NULL; @@ -595,6 +595,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; @@ -607,21 +608,9 @@ static void CB2_InitBattleInternal(void) for (i = 0; i < PARTY_SIZE; i++) { // Player's side - targetSpecies = GetFormChangeTargetSpecies(&gPlayerParty[i], FORM_BATTLE_BEGIN, 0); - if (targetSpecies != SPECIES_NONE) - { - SetMonData(&gPlayerParty[i], MON_DATA_SPECIES, &targetSpecies); - CalculateMonStats(&gPlayerParty[i]); - TryToSetBattleFormChangeMoves(&gPlayerParty[i]); - } + TryFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_BEGIN_BATTLE); // Opponent's side - targetSpecies = GetFormChangeTargetSpecies(&gEnemyParty[i], FORM_BATTLE_BEGIN, 0); - if (targetSpecies != SPECIES_NONE) - { - SetMonData(&gEnemyParty[i], MON_DATA_SPECIES, &targetSpecies); - CalculateMonStats(&gEnemyParty[i]); - TryToSetBattleFormChangeMoves(&gEnemyParty[i]); - } + TryFormChange(i, B_SIDE_OPPONENT, FORM_CHANGE_BEGIN_BATTLE); } gBattleCommunication[MULTIUSE_STATE] = 0; @@ -1925,7 +1914,7 @@ static u32 GeneratePartyHash(const struct Trainer *trainer, u32 i) return Crc32B(buffer, n); } -static void ModifyPersonalityForNature(u32 *personality, u32 newNature) +void ModifyPersonalityForNature(u32 *personality, u32 newNature) { u32 nature = GetNatureFromPersonality(*personality); s32 diff = abs(nature - newNature); @@ -1938,7 +1927,7 @@ static void ModifyPersonalityForNature(u32 *personality, u32 newNature) *personality -= (diff * sign); } -static u32 GeneratePersonalityForGender(u32 gender, u32 species) +u32 GeneratePersonalityForGender(u32 gender, u32 species) { const struct SpeciesInfo *speciesInfo = &gSpeciesInfo[species]; if (gender == MON_MALE) @@ -1947,6 +1936,29 @@ static u32 GeneratePersonalityForGender(u32 gender, u32 species) return speciesInfo->genderRatio / 2; } +static void CustomTrainerPartyAssignMoves(struct Pokemon *mon, const struct TrainerMonCustomized *partyEntry) +{ + bool32 noMoveSet = TRUE; + u32 j; + + for (j = 0; j < MAX_MON_MOVES; ++j) + { + if (partyEntry->moves[j] != MOVE_NONE) + noMoveSet = FALSE; + } + if (noMoveSet) + { + // TODO: Figure out a default strategy when moves are not set, to generate a good moveset + return; + } + + for (j = 0; j < MAX_MON_MOVES; ++j) + { + SetMonData(mon, MON_DATA_MOVE1 + j, &partyEntry->moves[j]); + SetMonData(mon, MON_DATA_PP1 + j, &gBattleMoves[partyEntry->moves[j]].pp); + } +} + u8 CreateNPCTrainerPartyFromTrainer(struct Pokemon *party, const struct Trainer *trainer, bool32 firstTrainer, u32 battleTypeFlags) { u32 personalityValue; @@ -2049,12 +2061,7 @@ u8 CreateNPCTrainerPartyFromTrainer(struct Pokemon *party, const struct Trainer CreateMon(&party[i], partyData[i].species, partyData[i].lvl, 0, TRUE, personalityValue, otIdType, fixedOtId); SetMonData(&party[i], MON_DATA_HELD_ITEM, &partyData[i].heldItem); - // TODO: Figure out a default strategy when moves are not set, to generate a good moveset - for (j = 0; j < MAX_MON_MOVES; ++j) - { - SetMonData(&party[i], MON_DATA_MOVE1 + j, &partyData[i].moves[j]); - SetMonData(&party[i], MON_DATA_PP1 + j, &gBattleMoves[partyData[i].moves[j]].pp); - } + CustomTrainerPartyAssignMoves(&party[i], &partyData[i]); SetMonData(&party[i], MON_DATA_IVS, &(partyData[i].iv)); if (partyData[i].ev != NULL) { @@ -2111,7 +2118,13 @@ static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum, bool8 fir return 0; retVal = CreateNPCTrainerPartyFromTrainer(party, &gTrainers[trainerNum], firstTrainer, gBattleTypeFlags); - gBattleTypeFlags |= gTrainers[trainerNum].doubleBattle; + if (gBattleTypeFlags & BATTLE_TYPE_TRAINER && !(gBattleTypeFlags & (BATTLE_TYPE_FRONTIER + | BATTLE_TYPE_EREADER_TRAINER + | BATTLE_TYPE_TRAINER_HILL))) + { + gBattleTypeFlags |= gTrainers[trainerNum].doubleBattle; + } + return retVal; } void VBlankCB_Battle(void) @@ -3166,13 +3179,14 @@ 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; } gBattleStruct->swapDamageCategory = FALSE; // Photon Geyser, Shell Side Arm, Light That Burns the Sky + gSelectedMonPartyId = PARTY_SIZE; // Revival Blessing } void SwitchInClearSetData(void) @@ -3202,7 +3216,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) @@ -3285,6 +3299,9 @@ void SwitchInClearSetData(void) gBattleStruct->overwrittenAbilities[gActiveBattler] = ABILITY_NONE; + // Clear selected party ID so Revival Blessing doesn't get confused. + gSelectedMonPartyId = PARTY_SIZE; + Ai_UpdateSwitchInData(gActiveBattler); } @@ -3383,9 +3400,7 @@ void FaintClearSetData(void) gBattleMons[gActiveBattler].type3 = TYPE_MYSTERY; Ai_UpdateFaintData(gActiveBattler); - UndoFormChange(gBattlerPartyIndexes[gActiveBattler], GET_BATTLER_SIDE(gActiveBattler), FALSE); - if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) - UndoMegaEvolution(gBattlerPartyIndexes[gActiveBattler]); + TryBattleFormChange(gActiveBattler, FORM_CHANGE_FAINT); gBattleStruct->overwrittenAbilities[gActiveBattler] = ABILITY_NONE; @@ -3772,7 +3787,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]; } } @@ -3815,24 +3832,6 @@ static void TryDoEventsBeforeFirstTurn(void) } memset(gTotemBoosts, 0, sizeof(gTotemBoosts)); // erase all totem boosts just to be safe - // Primal Reversion - for (i = 0; i < gBattlersCount; i++) - { - if (GetBattlerHoldEffect(i, TRUE) == HOLD_EFFECT_PRIMAL_ORB) - { - for (j = 0; j < EVOS_PER_MON; j++) - { - if (gEvolutionTable[gBattleMons[i].species][j].targetSpecies != SPECIES_NONE - && gEvolutionTable[gBattleMons[i].species][j].method == EVO_PRIMAL_REVERSION) - { - gBattlerAttacker = i; - BattleScriptExecute(BattleScript_PrimalReversion); - return; - } - } - } - } - // Check neutralizing gas if (AbilityBattleEffects(ABILITYEFFECT_NEUTRALIZINGGAS, 0, 0, 0, 0) != 0) return; @@ -3841,6 +3840,14 @@ static void TryDoEventsBeforeFirstTurn(void) while (gBattleStruct->switchInAbilitiesCounter < gBattlersCount) { gBattlerAttacker = gBattlerByTurnOrder[gBattleStruct->switchInAbilitiesCounter++]; + + // Primal Reversion + if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_PRIMAL_ORB + && GetBattleFormChangeTargetSpecies(gBattlerAttacker, FORM_CHANGE_BATTLE_PRIMAL_REVERSION) != SPECIES_NONE) + { + BattleScriptExecute(BattleScript_PrimalReversion); + return; + } if (AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, gBattlerAttacker, 0, 0, 0) != 0) return; } @@ -3859,7 +3866,7 @@ static void TryDoEventsBeforeFirstTurn(void) gChosenActionByBattler[i] = B_ACTION_NONE; gChosenMoveByBattler[i] = MOVE_NONE; // Record party slots of player's mons that appeared in battle - if (!IsBattlerAIControlled(i)) + if (!BattlerHasAi(i)) gBattleStruct->appearedInBattle |= gBitTable[gBattlerPartyIndexes[i]]; } TurnValuesCleanUp(FALSE); @@ -3893,6 +3900,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) @@ -3985,6 +3995,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) @@ -4096,7 +4116,8 @@ static void HandleTurnActionSelectionState(void) // Do AI score computations here so we can use them in AI_TrySwitchOrUseItem if ((gBattleTypeFlags & BATTLE_TYPE_HAS_AI || IsWildMonSmart()) - && (IsBattlerAIControlled(gActiveBattler) && !(gBattleTypeFlags & BATTLE_TYPE_PALACE))) { + && (BattlerHasAi(gActiveBattler) && !(gBattleTypeFlags & BATTLE_TYPE_PALACE))) + { gBattleStruct->aiMoveOrAction[gActiveBattler] = ComputeBattleAiScores(gActiveBattler); } break; @@ -4134,6 +4155,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]++; @@ -4201,10 +4223,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) { @@ -5003,11 +5026,12 @@ 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; - if (GetWishMegaEvolutionSpecies(GetMonData(mon, MON_DATA_SPECIES), GetMonData(mon, MON_DATA_MOVE1), GetMonData(mon, MON_DATA_MOVE2), GetMonData(mon, MON_DATA_MOVE3), GetMonData(mon, MON_DATA_MOVE4))) + if (GetBattleFormChangeTargetSpecies(gActiveBattler, FORM_CHANGE_BATTLE_MEGA_EVOLUTION_MOVE) != SPECIES_NONE) BattleScriptExecute(BattleScript_WishMegaEvolution); else BattleScriptExecute(BattleScript_MegaEvolution); @@ -5357,27 +5381,37 @@ 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++) { - UndoMegaEvolution(i); - UndoFormChange(i, B_SIDE_PLAYER, FALSE); - DoBurmyFormChange(i); - } - #if B_RECALCULATE_STATS >= GEN_5 - // Recalculate the stats of every party member before the end - for (i = 0; i < PARTY_SIZE; i++) - { - if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES_OR_EGG) != SPECIES_NONE - && GetMonData(&gPlayerParty[i], MON_DATA_SPECIES_OR_EGG) != SPECIES_EGG) - { + bool8 changedForm = FALSE; + + // Appeared in battle and didn't faint + if ((gBattleStruct->appearedInBattle & gBitTable[i]) && GetMonData(&gPlayerParty[i], MON_DATA_HP, NULL) != 0) + changedForm = TryFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_END_BATTLE_TERRAIN); + + if (!changedForm) + changedForm = TryFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_END_BATTLE); + + // Clear original species field + gBattleStruct->changedSpecies[i] = SPECIES_NONE; + + #if B_RECALCULATE_STATS >= GEN_5 + // Recalculate the stats of every party member before the end + if (!changedForm) CalculateMonStats(&gPlayerParty[i]); - } + #endif + } + // Clear battle mon species to avoid a bug on the next battle that causes + // healthboxes loading incorrectly due to it trying to create a Mega Indicator + // if the previous battler would've had it. + for (i = 0; i < MAX_BATTLERS_COUNT; i++) + { + gBattleMons[i].species = SPECIES_NONE; } - #endif gBattleMainFunc = FreeResetData_ReturnToOvOrDoEvolutions; gCB2_AfterEvolution = BattleMainCB2; } diff --git a/src/battle_message.c b/src/battle_message.c index 140b8b3c4..19f6eda57 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -101,8 +101,10 @@ static const u8 sText_PkmnAlreadyPoisoned[] = _("{B_DEF_NAME_WITH_PREFIX} is alr static const u8 sText_PkmnBadlyPoisoned[] = _("{B_EFF_NAME_WITH_PREFIX} is badly\npoisoned!"); static const u8 sText_PkmnEnergyDrained[] = _("{B_DEF_NAME_WITH_PREFIX} had its\nenergy drained!"); static const u8 sText_PkmnWasBurned[] = _("{B_EFF_NAME_WITH_PREFIX} was burned!"); +static const u8 sText_PkmnGotFrostbite[] = _("{B_EFF_NAME_WITH_PREFIX} got frostbite!"); static const u8 sText_PkmnBurnedBy[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_SCR_ACTIVE_ABILITY}\nburned {B_EFF_NAME_WITH_PREFIX}!"); static const u8 sText_PkmnHurtByBurn[] = _("{B_ATK_NAME_WITH_PREFIX} is hurt\nby its burn!"); +static const u8 sText_PkmnHurtByFrostbite[] = _("{B_ATK_NAME_WITH_PREFIX} is hurt\nby its frostbite!"); static const u8 sText_PkmnAlreadyHasBurn[] = _("{B_DEF_NAME_WITH_PREFIX} already\nhas a burn."); static const u8 sText_PkmnWasFrozen[] = _("{B_EFF_NAME_WITH_PREFIX} was\nfrozen solid!"); static const u8 sText_PkmnFrozenBy[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_SCR_ACTIVE_ABILITY}\nfroze {B_EFF_NAME_WITH_PREFIX} solid!"); @@ -110,6 +112,9 @@ static const u8 sText_PkmnIsFrozen[] = _("{B_ATK_NAME_WITH_PREFIX} is\nfrozen so static const u8 sText_PkmnWasDefrosted[] = _("{B_DEF_NAME_WITH_PREFIX} was\ndefrosted!"); static const u8 sText_PkmnWasDefrosted2[] = _("{B_ATK_NAME_WITH_PREFIX} was\ndefrosted!"); static const u8 sText_PkmnWasDefrostedBy[] = _("{B_ATK_NAME_WITH_PREFIX} was\ndefrosted by {B_CURRENT_MOVE}!"); +static const u8 sText_PkmnFrostbiteHealed[] = _("{B_DEF_NAME_WITH_PREFIX}'s\nfrostbite was healed!"); +static const u8 sText_PkmnFrostbiteHealed2[] = _("{B_ATK_NAME_WITH_PREFIX}'s\nfrostbite was healed!"); +static const u8 sText_PkmnFrostbiteHealedBy[] = _("{B_ATK_NAME_WITH_PREFIX}'s {B_CURRENT_MOVE}\nhealed its frostbite!"); static const u8 sText_PkmnWasParalyzed[] = _("{B_EFF_NAME_WITH_PREFIX} is paralyzed!\nIt may be unable to move!"); static const u8 sText_PkmnWasParalyzedBy[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_SCR_ACTIVE_ABILITY}\nparalyzed {B_EFF_NAME_WITH_PREFIX}!\lIt may be unable to move!"); static const u8 sText_PkmnIsParalyzed[] = _("{B_ATK_NAME_WITH_PREFIX} is paralyzed!\nIt can't move!"); @@ -435,11 +440,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 +470,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!"); @@ -491,6 +496,7 @@ static const u8 sText_BerrySuffix[] = _(" BERRY"); static const u8 sText_PkmnsItemCuredParalysis[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_LAST_ITEM}\ncured paralysis!"); static const u8 sText_PkmnsItemCuredPoison[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_LAST_ITEM}\ncured poison!"); static const u8 sText_PkmnsItemHealedBurn[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_LAST_ITEM}\nhealed its burn!"); +static const u8 sText_PkmnsItemHealedFrostbite[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_LAST_ITEM}\nhealed its frostbite!"); static const u8 sText_PkmnsItemDefrostedIt[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_LAST_ITEM}\ndefrosted it!"); static const u8 sText_PkmnsItemWokeIt[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_LAST_ITEM}\nwoke it from its sleep!"); static const u8 sText_PkmnsItemSnappedOut[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_LAST_ITEM}\nsnapped it out of confusion!"); @@ -555,7 +561,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!"); @@ -768,6 +774,7 @@ static const u8 sText_AttackerExpelledThePoison[] = _("{B_ATK_NAME_WITH_PREFIX} static const u8 sText_AttackerShookItselfAwake[] = _("{B_ATK_NAME_WITH_PREFIX} shook itself awake!"); static const u8 sText_AttackerBrokeThroughParalysis[] = _("{B_ATK_NAME_WITH_PREFIX} gathered all its energy\nto overcome its paralysis!"); static const u8 sText_AttackerHealedItsBurn[] = _("{B_ATK_NAME_WITH_PREFIX} healed its burn with\nits sheer determination!"); +static const u8 sText_AttackerHealedItsFrostbite[] = _("{B_ATK_NAME_WITH_PREFIX} healed its frostbite with\nits sheer determination!"); static const u8 sText_AttackerMeltedTheIce[] = _("{B_ATK_NAME_WITH_PREFIX} melted the ice with\nits fiery determination!"); static const u8 sText_TargetToughedItOut[] = _("{B_DEF_NAME_WITH_PREFIX} toughed it out\nto show you its best side!"); static const u8 sText_AttackerLostElectricType[] = _("{B_ATK_NAME_WITH_PREFIX} used up all\nof its electricity!"); @@ -782,11 +789,21 @@ static const u8 sText_PrepareShellTrap[] = _("{B_ATK_NAME_WITH_PREFIX} set a she static const u8 sText_ShellTrapDidntWork[] = _("{B_ATK_NAME_WITH_PREFIX}'s shell trap didn't work!"); 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}!"); static const u8 sText_MirrorHerbCopied[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} used its {B_LAST_ITEM}\nto mirror its opponent's stat changes!"); const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { [STRINGID_MIRRORHERBCOPIED - BATTLESTRINGS_TABLE_START] = sText_MirrorHerbCopied, + [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, [STRINGID_ATTACKERGAINEDSTRENGTHFROMTHEFALLEN - BATTLESTRINGS_TABLE_START] = sText_AttackerGainedStrengthFromTheFallen, @@ -1422,6 +1439,18 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = [STRINGID_TARGETTOOHEAVY - BATTLESTRINGS_TABLE_START] = sText_TargetTooHeavy, [STRINGID_ATTACKERLOSTELECTRICTYPE - BATTLESTRINGS_TABLE_START] = sText_AttackerLostElectricType, [STRINGID_PKMNSABILITYPREVENTSABILITY - BATTLESTRINGS_TABLE_START] = sText_PkmnsAbilityPreventsAbility, + [STRINGID_PKMNHURTBYFROSTBITE - BATTLESTRINGS_TABLE_START] = sText_PkmnHurtByFrostbite, + [STRINGID_PKMNGOTFROSTBITE - BATTLESTRINGS_TABLE_START] = sText_PkmnGotFrostbite, + [STRINGID_PKMNSITEMHEALEDFROSTBITE - BATTLESTRINGS_TABLE_START] = sText_PkmnsItemHealedFrostbite, + [STRINGID_ATTACKERHEALEDITSFROSTBITE - BATTLESTRINGS_TABLE_START] = sText_AttackerHealedItsFrostbite, + [STRINGID_PKMNFROSTBITEHEALED - BATTLESTRINGS_TABLE_START] = sText_PkmnFrostbiteHealed, + [STRINGID_PKMNFROSTBITEHEALED2 - BATTLESTRINGS_TABLE_START] = sText_PkmnFrostbiteHealed2, + [STRINGID_PKMNFROSTBITEHEALEDBY - BATTLESTRINGS_TABLE_START] = sText_PkmnFrostbiteHealedBy, +}; + +const u16 gTrainerUsedItemStringIds[] = +{ + STRINGID_PLAYERUSEDITEM, STRINGID_TRAINER1USEDITEM }; const u16 gZEffectStringIds[] = @@ -1668,6 +1697,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[] = @@ -1718,6 +1748,17 @@ const u16 gGotBurnedStringIds[] = [B_MSG_STATUSED_BY_ABILITY] = STRINGID_PKMNBURNEDBY }; +const u16 gGotFrostbiteStringIds[] = +{ + [B_MSG_STATUSED] = STRINGID_PKMNGOTFROSTBITE +}; + +const u16 gFrostbiteHealedStringIds[] = +{ + [B_MSG_FROSTBITE_HEALED] = STRINGID_PKMNFROSTBITEHEALED2, + [B_MSG_FROSTBITE_HEALED_BY_MOVE] = STRINGID_PKMNFROSTBITEHEALEDBY +}; + const u16 gGotFrozenStringIds[] = { [B_MSG_STATUSED] = STRINGID_PKMNWASFROZEN, @@ -1820,16 +1861,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, @@ -1888,7 +1919,7 @@ const u16 gRoomsStringIds[] = const u16 gStatusConditionsStringIds[] = { - STRINGID_PKMNWASPOISONED, STRINGID_PKMNBADLYPOISONED, STRINGID_PKMNWASBURNED, STRINGID_PKMNWASPARALYZED, STRINGID_PKMNFELLASLEEP + STRINGID_PKMNWASPOISONED, STRINGID_PKMNBADLYPOISONED, STRINGID_PKMNWASBURNED, STRINGID_PKMNWASPARALYZED, STRINGID_PKMNFELLASLEEP, STRINGID_PKMNGOTFROSTBITE }; const u8 gText_PkmnIsEvolving[] = _("What?\n{STR_VAR_1} is evolving!"); @@ -3892,6 +3923,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 +3942,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 +3970,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 +4046,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 +4061,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; } diff --git a/src/battle_pike.c b/src/battle_pike.c index 9751d565d..37dfd9997 100644 --- a/src/battle_pike.c +++ b/src/battle_pike.c @@ -729,6 +729,7 @@ static void GetRoomInflictedStatus(void) switch (sStatusFlags) { case STATUS1_FREEZE: + case STATUS1_FROSTBITE: gSpecialVar_Result = PIKE_STATUS_FREEZE; break; case STATUS1_BURN: @@ -818,6 +819,7 @@ static bool8 DoesAbilityPreventStatus(struct Pokemon *mon, u32 status) switch (status) { case STATUS1_FREEZE: + case STATUS1_FROSTBITE: if (ability == ABILITY_MAGMA_ARMOR) ret = TRUE; break; @@ -853,6 +855,7 @@ static bool8 DoesTypePreventStatus(u16 species, u32 status) ret = TRUE; break; case STATUS1_FREEZE: + case STATUS1_FROSTBITE: if (gSpeciesInfo[species].types[0] == TYPE_ICE || gSpeciesInfo[species].types[1] == TYPE_ICE) ret = TRUE; break; @@ -913,7 +916,11 @@ static bool8 TryInflictRandomStatus(void) if (rand < 35) sStatusFlags = STATUS1_TOXIC_POISON; else if (rand < 60) + #if B_USE_FROSTBITE == TRUE + sStatusFlags = STATUS1_FROSTBITE; + #else sStatusFlags = STATUS1_FREEZE; + #endif else if (rand < 80) sStatusFlags = STATUS1_PARALYSIS; else if (rand < 90) @@ -950,6 +957,7 @@ static bool8 TryInflictRandomStatus(void) switch (sStatusFlags) { case STATUS1_FREEZE: + case STATUS1_FROSTBITE: sStatusMon = PIKE_STATUSMON_DUSCLOPS; break; case STATUS1_BURN: diff --git a/src/battle_pyramid_bag.c b/src/battle_pyramid_bag.c index d580cf680..9d5cee94a 100644 --- a/src/battle_pyramid_bag.c +++ b/src/battle_pyramid_bag.c @@ -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) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 72a332af9..615f0eb3d 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -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" @@ -60,6 +61,7 @@ #include "constants/trainers.h" #include "battle_util.h" #include "constants/pokemon.h" +#include "config/battle.h" // Helper for accessing command arguments and advancing gBattlescriptCurrInstr. // @@ -895,6 +897,7 @@ static const u32 sStatusFlagsForMoveEffects[NUM_MOVE_EFFECTS] = [MOVE_EFFECT_FREEZE] = STATUS1_FREEZE, [MOVE_EFFECT_PARALYSIS] = STATUS1_PARALYSIS, [MOVE_EFFECT_TOXIC] = STATUS1_TOXIC_POISON, + [MOVE_EFFECT_FROSTBITE] = STATUS1_FROSTBITE, [MOVE_EFFECT_CONFUSION] = STATUS2_CONFUSION, [MOVE_EFFECT_FLINCH] = STATUS2_FLINCHED, [MOVE_EFFECT_UPROAR] = STATUS2_UPROAR, @@ -918,6 +921,7 @@ static const u8 *const sMoveEffectBS_Ptrs[] = [MOVE_EFFECT_UPROAR] = BattleScript_MoveEffectUproar, [MOVE_EFFECT_PAYDAY] = BattleScript_MoveEffectPayDay, [MOVE_EFFECT_WRAP] = BattleScript_MoveEffectWrap, + [MOVE_EFFECT_FROSTBITE] = BattleScript_MoveEffectFrostbite, }; static const struct WindowTemplate sUnusedWinTemplate = @@ -978,6 +982,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 +998,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 +1010,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 +1028,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 +1042,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 +1050,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 +1076,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 +1103,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 +1154,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 +1179,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 +2607,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 +2691,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) @@ -3160,6 +3211,12 @@ void SetMoveEffect(bool32 primary, u32 certain) gMoveResultFlags |= MOVE_RESULT_DOESNT_AFFECT_FOE; } break; + case STATUS1_FROSTBITE: + if (!CanGetFrostbite(gEffectBattler)) + break; + + statusChanged = TRUE; + break; } if (statusChanged == TRUE) { @@ -3318,7 +3375,12 @@ void SetMoveEffect(bool32 primary, u32 certain) } else { - gBattleScripting.moveEffect = Random() % 3 + 3; + #if B_USE_FROSTBITE == TRUE + static const u8 sTriAttackEffects[] = { MOVE_EFFECT_BURN, MOVE_EFFECT_FROSTBITE, MOVE_EFFECT_PARALYSIS }; + #else + static const u8 sTriAttackEffects[] = { MOVE_EFFECT_BURN, MOVE_EFFECT_FREEZE, MOVE_EFFECT_PARALYSIS }; + #endif + gBattleScripting.moveEffect = RandomElement(RNG_TRI_ATTACK, sTriAttackEffects); SetMoveEffect(FALSE, 0); } break; @@ -3779,7 +3841,7 @@ void SetMoveEffect(bool32 primary, u32 certain) if (!gBattleMons[gEffectBattler].status1) { static const u8 sDireClawEffects[] = { MOVE_EFFECT_POISON, MOVE_EFFECT_PARALYSIS, MOVE_EFFECT_SLEEP }; - gBattleScripting.moveEffect = sDireClawEffects[Random() % ARRAY_COUNT(sDireClawEffects)]; + gBattleScripting.moveEffect = RandomElement(RNG_DIRE_CLAW, sDireClawEffects); SetMoveEffect(TRUE, 0); } break; @@ -4431,15 +4493,7 @@ static void Cmd_getexp(void) if (battlerId != 0xFF) { - gBattleMons[battlerId].level = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_LEVEL); - gBattleMons[battlerId].hp = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_HP); - gBattleMons[battlerId].maxHP = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_MAX_HP); - gBattleMons[battlerId].attack = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_ATK); - gBattleMons[battlerId].defense = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_DEF); - gBattleMons[battlerId].speed = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_SPEED); - gBattleMons[battlerId].spAttack = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_SPATK); - gBattleMons[battlerId].spDefense = GetMonData(&gPlayerParty[gBattleStruct->expGetterMonId], MON_DATA_SPDEF); - + CopyMonLevelAndBaseStatsToBattleMon(battlerId, &gPlayerParty[gBattleStruct->expGetterMonId]); if (gStatuses3[battlerId] & STATUS3_POWER_TRICK) SWAP(gBattleMons[battlerId].attack, gBattleMons[battlerId].defense, temp); } @@ -5534,7 +5588,6 @@ static void Cmd_moveend(void) if (gBattleMons[gBattlerTarget].status1 & STATUS1_FREEZE && gBattleMons[gBattlerTarget].hp != 0 && gBattlerAttacker != gBattlerTarget - && gSpecialStatuses[gBattlerTarget].specialDmg && (moveType == TYPE_FIRE #if B_BURN_HIT_THAW >= GEN_6 || gBattleMoves[gCurrentMove].effect == EFFECT_BURN_HIT @@ -5550,6 +5603,20 @@ static void Cmd_moveend(void) gBattlescriptCurrInstr = BattleScript_DefrostedViaFireMove; effect = TRUE; } + if (gBattleMons[gBattlerTarget].status1 & STATUS1_FROSTBITE + && gBattleMons[gBattlerTarget].hp != 0 + && gBattlerAttacker != gBattlerTarget + && gBattleMoves[originallyUsedMove].flags & FLAG_THAW_USER + && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)) + { + gBattleMons[gBattlerTarget].status1 &= ~STATUS1_FROSTBITE; + gActiveBattler = gBattlerTarget; + BtlController_EmitSetMonData(BUFFER_A, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].status1), &gBattleMons[gBattlerTarget].status1); + MarkBattlerForControllerExec(gActiveBattler); + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_FrostbiteHealedViaFireMove; + effect = TRUE; + } gBattleScripting.moveendState++; break; case MOVEEND_RECOIL: @@ -6224,28 +6291,6 @@ static void Cmd_moveend(void) } gBattleScripting.moveendState++; break; - case MOVEEND_WEATHER_FORM: - for (i = 0; i < MAX_BATTLERS_COUNT; i++) - { - switch (gBattleMons[i].species) - { - case SPECIES_CASTFORM: - case SPECIES_CASTFORM_RAINY: - case SPECIES_CASTFORM_SNOWY: - case SPECIES_CASTFORM_SUNNY: - case SPECIES_CHERRIM: - case SPECIES_CHERRIM_SUNSHINE: - effect = TryWeatherFormChange(i); - if (effect) - { - BattleScriptPushCursorAndCallback(BattleScript_WeatherFormChange); - gBattleScripting.battler = i; - gBattleStruct->formToChangeInto = effect - 1; - } - } - } - gBattleScripting.moveendState++; - break; case MOVEEND_SYMBIOSIS: for (i = 0; i < gBattlersCount; i++) { @@ -6466,10 +6511,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) @@ -6510,10 +6552,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) @@ -7036,7 +7075,7 @@ static void Cmd_switchineffects(void) gHitMarker &= ~HITMARKER_FAINTED(gActiveBattler); gSpecialStatuses[gActiveBattler].faintedHasReplacement = FALSE; - if (!IsBattlerAIControlled(gActiveBattler)) + if (!BattlerHasAi(gActiveBattler)) gBattleStruct->appearedInBattle |= gBitTable[gBattlerPartyIndexes[gActiveBattler]]; // Neutralizing Gas announces itself before hazards @@ -7667,10 +7706,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++) { @@ -7890,7 +7926,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 @@ -8574,22 +8610,6 @@ u32 IsAbilityStatusProtected(u32 battler) || IsShieldsDownProtected(battler); } -static void RecalcBattlerStats(u32 battler, struct Pokemon *mon) -{ - CalculateMonStats(mon); - gBattleMons[battler].level = GetMonData(mon, MON_DATA_LEVEL); - gBattleMons[battler].hp = GetMonData(mon, MON_DATA_HP); - gBattleMons[battler].maxHP = GetMonData(mon, MON_DATA_MAX_HP); - gBattleMons[battler].attack = GetMonData(mon, MON_DATA_ATK); - gBattleMons[battler].defense = GetMonData(mon, MON_DATA_DEF); - gBattleMons[battler].speed = GetMonData(mon, MON_DATA_SPEED); - gBattleMons[battler].spAttack = GetMonData(mon, MON_DATA_SPATK); - gBattleMons[battler].spDefense = GetMonData(mon, MON_DATA_SPDEF); - gBattleMons[battler].ability = GetMonAbility(mon); - gBattleMons[battler].type1 = gSpeciesInfo[gBattleMons[battler].species].types[0]; - gBattleMons[battler].type2 = gSpeciesInfo[gBattleMons[battler].species].types[1]; -} - u32 GetHighestStatId(u32 battlerId) { u32 i, highestId = STAT_ATK, highestStat = gBattleMons[battlerId].attack; @@ -8744,76 +8764,41 @@ 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); // Change species. if (caseId == 0) { - u16 newSpecies; if (isMega) { - gBattleStruct->mega.evolvedSpecies[battlerId] = gBattleMons[battlerId].species; - if (position == B_POSITION_PLAYER_LEFT - || (position == B_POSITION_PLAYER_RIGHT && !(gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER)))) - { - gBattleStruct->mega.playerEvolvedSpecies = gBattleStruct->mega.evolvedSpecies[battlerId]; - } - //Checks regular Mega Evolution - newSpecies = GetMegaEvolutionSpecies(gBattleStruct->mega.evolvedSpecies[battlerId], gBattleMons[battlerId].item); - //Checks Wish Mega Evolution - if (newSpecies == SPECIES_NONE) - { - newSpecies = GetWishMegaEvolutionSpecies(gBattleStruct->mega.evolvedSpecies[battlerId], - gBattleMons[battlerId].moves[0], gBattleMons[battlerId].moves[1], gBattleMons[battlerId].moves[2], gBattleMons[battlerId].moves[3]); - } + if (!TryBattleFormChange(battlerId, FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM)) + TryBattleFormChange(battlerId, FORM_CHANGE_BATTLE_MEGA_EVOLUTION_MOVE); } else - { - gBattleStruct->mega.primalRevertedSpecies[battlerId] = gBattleMons[battlerId].species; - if (position == B_POSITION_PLAYER_LEFT - || (position == B_POSITION_PLAYER_RIGHT && !(gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER)))) - { - gBattleStruct->mega.playerPrimalRevertedSpecies = gBattleStruct->mega.primalRevertedSpecies[battlerId]; - } - // Checks Primal Reversion. - newSpecies = GetPrimalReversionSpecies(gBattleStruct->mega.primalRevertedSpecies[battlerId], gBattleMons[battlerId].item); - } + TryBattleFormChange(battlerId, FORM_CHANGE_BATTLE_PRIMAL_REVERSION); - gBattleMons[battlerId].species = newSpecies; PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[battlerId].species); BtlController_EmitSetMonData(BUFFER_A, REQUEST_SPECIES_BATTLE, gBitTable[gBattlerPartyIndexes[battlerId]], sizeof(gBattleMons[battlerId].species), &gBattleMons[battlerId].species); MarkBattlerForControllerExec(battlerId); } - // Change stats. - else if (caseId == 1) - { - RecalcBattlerStats(battlerId, mon); - if (isMega) - { - gBattleStruct->mega.alreadyEvolved[position] = TRUE; - gBattleStruct->mega.evolvedPartyIds[side] |= gBitTable[gBattlerPartyIndexes[battlerId]]; - } - else - { - gBattleStruct->mega.primalRevertedPartyIds[side] |= gBitTable[gBattlerPartyIndexes[battlerId]]; - } - } // Update healthbox and elevation and play cry. else { UpdateHealthboxAttribute(gHealthboxSpriteIds[battlerId], mon, HEALTHBOX_ALL); if (side == B_SIDE_OPPONENT) SetBattlerShadowSpriteCallback(battlerId, gBattleMons[battlerId].species); + if (isMega) + gBattleStruct->mega.alreadyEvolved[position] = TRUE; } } 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++) @@ -9958,6 +9943,9 @@ static void Cmd_various(void) case STATUS1_TOXIC_POISON: gBattleScripting.moveEffect = MOVE_EFFECT_TOXIC; break; + case STATUS1_FROSTBITE: + gBattleScripting.moveEffect = MOVE_EFFECT_FROSTBITE; + break; default: gBattleScripting.moveEffect = 0; break; @@ -10126,6 +10114,8 @@ static void Cmd_various(void) gBattleCommunication[MULTISTRING_CHOOSER] = 3; else if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP) && CanSleep(gBattlerTarget)) gBattleCommunication[MULTISTRING_CHOOSER] = 4; + else if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_FROSTBITE) && CanBeFrozen(gBattlerTarget)) + gBattleCommunication[MULTISTRING_CHOOSER] = 5; else { gBattlescriptCurrInstr = cmd->failInstr; @@ -10711,15 +10701,7 @@ static void Cmd_various(void) case VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL: { VARIOUS_ARGS(const u8 *jumpInstr); - bool8 canDoPrimalReversion = FALSE; - - for (i = 0; i < EVOS_PER_MON; i++) - { - if (gEvolutionTable[gBattleMons[gActiveBattler].species][i].method == EVO_PRIMAL_REVERSION - && gEvolutionTable[gBattleMons[gActiveBattler].species][i].param == gBattleMons[gActiveBattler].item) - canDoPrimalReversion = TRUE; - } - if (!canDoPrimalReversion) + if (GetBattleFormChangeTargetSpecies(gActiveBattler, FORM_CHANGE_BATTLE_PRIMAL_REVERSION) == SPECIES_NONE) gBattlescriptCurrInstr = cmd->jumpInstr; else gBattlescriptCurrInstr = cmd->nextInstr; @@ -11183,15 +11165,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(); @@ -11224,6 +11197,83 @@ 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); + u32 side = GetBattlerSide(gBattlerAttacker); + u8 index = GetFirstFaintedPartyIndex(gBattlerAttacker); + + // Move fails if there are no battlers to revive. + if (index == PARTY_SIZE) + { + gBattlescriptCurrInstr = cmd->failInstr; + return; + } + + // Battler selected! Revive and go to next instruction. + if (gSelectedMonPartyId != PARTY_SIZE) + { + 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); + MarkBattlerForControllerExec(gBattlerAttacker); + PREPARE_SPECIES_BUFFER(gBattleTextBuff1, GetMonData(&party[gSelectedMonPartyId], MON_DATA_SPECIES)); + + // If an on-field battler is revived, it needs to be sent out again. + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && + gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)] == gSelectedMonPartyId) + { + gBattleScripting.battler = BATTLE_PARTNER(gBattlerAttacker); + gBattleCommunication[MULTIUSE_STATE] = TRUE; + } + + gSelectedMonPartyId = PARTY_SIZE; + gBattlescriptCurrInstr = cmd->nextInstr; + return; + } + + // 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[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; @@ -12294,10 +12344,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) { @@ -12879,6 +12926,7 @@ static void Cmd_transformdataexecution(void) gDisableStructs[gBattlerAttacker].disabledMove = MOVE_NONE; gDisableStructs[gBattlerAttacker].disableTimer = 0; gDisableStructs[gBattlerAttacker].transformedMonPersonality = gBattleMons[gBattlerTarget].personality; + gDisableStructs[gBattlerAttacker].transformedMonOtId = gBattleMons[gBattlerTarget].otId; gDisableStructs[gBattlerAttacker].mimickedMoves = 0; gDisableStructs[gBattlerAttacker].usedMoves = 0; @@ -13496,16 +13544,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; @@ -14133,12 +14176,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) { @@ -14322,7 +14360,7 @@ static void Cmd_cureifburnedparalysedorpoisoned(void) { CMD_ARGS(const u8 *failInstr); - if (gBattleMons[gBattlerAttacker].status1 & (STATUS1_POISON | STATUS1_BURN | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON)) + if (gBattleMons[gBattlerAttacker].status1 & (STATUS1_POISON | STATUS1_BURN | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON | STATUS1_FROSTBITE)) { gBattleMons[gBattlerAttacker].status1 = 0; gBattlescriptCurrInstr = cmd->nextInstr; @@ -14832,10 +14870,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++) { @@ -15047,7 +15082,11 @@ u16 GetSecretPowerMoveEffect(void) break; case BATTLE_TERRAIN_SNOW: case BATTLE_TERRAIN_ICE: + #if B_USE_FROSTBITE == TRUE + moveEffect = MOVE_EFFECT_FROSTBITE; + #else moveEffect = MOVE_EFFECT_FREEZE; + #endif break; case BATTLE_TERRAIN_VOLCANO: moveEffect = MOVE_EFFECT_BURN; @@ -15159,15 +15198,7 @@ static void Cmd_tryweatherformdatachange(void) { CMD_ARGS(); - u8 form; - - gBattlescriptCurrInstr = cmd->nextInstr; - form = TryWeatherFormChange(gBattleScripting.battler); - if (form) - { - BattleScriptPushCursorAndCallback(BattleScript_WeatherFormChange); - *(&gBattleStruct->formToChangeInto) = form - 1; - } + // removed in favor of new form system } // Water and Mud Sport @@ -15644,7 +15675,7 @@ static void Cmd_handleballthrow(void) if (gBattleMons[gBattlerTarget].status1 & (STATUS1_SLEEP | STATUS1_FREEZE)) odds *= 2; - if (gBattleMons[gBattlerTarget].status1 & (STATUS1_POISON | STATUS1_BURN | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON)) + if (gBattleMons[gBattlerTarget].status1 & (STATUS1_POISON | STATUS1_BURN | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON | STATUS1_FROSTBITE)) odds = (odds * 15) / 10; if (gBattleResults.catchAttempts[gLastUsedItem - FIRST_BALL] < 255) @@ -15654,7 +15685,7 @@ static void Cmd_handleballthrow(void) { BtlController_EmitBallThrowAnim(BUFFER_A, BALL_3_SHAKES_SUCCESS); MarkBattlerForControllerExec(gActiveBattler); - UndoFormChange(gBattlerPartyIndexes[gBattlerTarget], GET_BATTLER_SIDE(gBattlerTarget), FALSE); + TryBattleFormChange(gBattlerTarget, FORM_CHANGE_END_BATTLE); gBattlescriptCurrInstr = BattleScript_SuccessBallThrow; SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_POKEBALL, &gLastUsedItem); @@ -15708,7 +15739,7 @@ static void Cmd_handleballthrow(void) if (IsCriticalCapture()) gBattleSpritesDataPtr->animationData->criticalCaptureSuccess = TRUE; - UndoFormChange(gBattlerPartyIndexes[gBattlerTarget], GET_BATTLER_SIDE(gBattlerTarget), FALSE); + TryBattleFormChange(gBattlerTarget, FORM_CHANGE_END_BATTLE); gBattlescriptCurrInstr = BattleScript_SuccessBallThrow; SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_POKEBALL, &gLastUsedItem); @@ -16359,3 +16390,186 @@ static void TryUpdateRoundTurnOrder(void) } } +u8 GetFirstFaintedPartyIndex(u8 battlerId) +{ + u32 i; + u32 start = 0; + u32 end = PARTY_SIZE; + struct Pokemon *party = GetBattlerParty(battlerId); + + // Check whether partner is separate trainer. + if ((GetBattlerSide(battlerId) == B_SIDE_PLAYER && gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) + || (GetBattlerSide(battlerId) == B_SIDE_OPPONENT && gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)) + { + if (GetBattlerPosition(battlerId) == B_POSITION_OPPONENT_LEFT + || GetBattlerPosition(battlerId) == B_POSITION_PLAYER_LEFT) + { + end = PARTY_SIZE / 2; + } + else + { + start = PARTY_SIZE / 2; + } + } + + // Loop through to find fainted battler. + for (i = start; i < end; ++i) + { + u32 species = GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG); + if (species != SPECIES_NONE + && species != SPECIES_EGG + && GetMonData(&party[i], MON_DATA_HP) == 0) + { + return i; + } + } + + // 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; +} diff --git a/src/battle_tower.c b/src/battle_tower.c index a4758b930..4e16467f0 100644 --- a/src/battle_tower.c +++ b/src/battle_tower.c @@ -3103,25 +3103,38 @@ static void FillPartnerParty(u16 trainerId) case F_TRAINER_PARTY_EVERYTHING_CUSTOMIZED: { const struct TrainerMonCustomized *partyData = gTrainers[trainerId - TRAINER_CUSTOM_PARTNER].party.EverythingCustomized; + u32 otIdType = OT_ID_RANDOM_NO_SHINY; - CreateMon(&gPlayerParty[i], partyData[i].species, partyData[i].lvl, 0, TRUE, j, TRUE, otID); - SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &partyData[i].heldItem); + if (partyData[i].gender == TRAINER_MON_MALE) + j = (j & 0xFFFFFF00) | GeneratePersonalityForGender(MON_MALE, partyData[i].species); + else if (partyData[i].gender == TRAINER_MON_FEMALE) + j = (j & 0xFFFFFF00) | GeneratePersonalityForGender(MON_FEMALE, partyData[i].species); + if (partyData[i].nature != 0) + ModifyPersonalityForNature(&j, partyData[i].nature - 1); + if (partyData[i].isShiny) + { + otIdType = OT_ID_PRESET; + otID = HIHALF(j) ^ LOHALF(j); + } + + CreateMon(&gPlayerParty[i + 3], partyData[i].species, partyData[i].lvl, 0, TRUE, j, otIdType, otID); + SetMonData(&gPlayerParty[i + 3], MON_DATA_HELD_ITEM, &partyData[i].heldItem); // TODO: Figure out a default strategy when moves are not set, to generate a good moveset for (j = 0; j < MAX_MON_MOVES; ++j) { - SetMonData(&gPlayerParty[i], MON_DATA_MOVE1 + j, &partyData[i].moves[j]); - SetMonData(&gPlayerParty[i], MON_DATA_PP1 + j, &gBattleMoves[partyData[i].moves[j]].pp); + SetMonData(&gPlayerParty[i+3], MON_DATA_MOVE1 + j, &partyData[i].moves[j]); + SetMonData(&gPlayerParty[i+3], MON_DATA_PP1 + j, &gBattleMoves[partyData[i].moves[j]].pp); } - SetMonData(&gPlayerParty[i], MON_DATA_IVS, &(partyData[i].iv)); + SetMonData(&gPlayerParty[i+3], MON_DATA_IVS, &(partyData[i].iv)); if (partyData[i].ev != NULL) { - SetMonData(&gPlayerParty[i], MON_DATA_HP_EV, &(partyData[i].ev[0])); - SetMonData(&gPlayerParty[i], MON_DATA_ATK_EV, &(partyData[i].ev[1])); - SetMonData(&gPlayerParty[i], MON_DATA_DEF_EV, &(partyData[i].ev[2])); - SetMonData(&gPlayerParty[i], MON_DATA_SPATK_EV, &(partyData[i].ev[3])); - SetMonData(&gPlayerParty[i], MON_DATA_SPDEF_EV, &(partyData[i].ev[4])); - SetMonData(&gPlayerParty[i], MON_DATA_SPEED_EV, &(partyData[i].ev[5])); + SetMonData(&gPlayerParty[i+3], MON_DATA_HP_EV, &(partyData[i].ev[0])); + SetMonData(&gPlayerParty[i+3], MON_DATA_ATK_EV, &(partyData[i].ev[1])); + SetMonData(&gPlayerParty[i+3], MON_DATA_DEF_EV, &(partyData[i].ev[2])); + SetMonData(&gPlayerParty[i+3], MON_DATA_SPATK_EV, &(partyData[i].ev[3])); + SetMonData(&gPlayerParty[i+3], MON_DATA_SPDEF_EV, &(partyData[i].ev[4])); + SetMonData(&gPlayerParty[i+3], MON_DATA_SPEED_EV, &(partyData[i].ev[5])); } if (partyData[i].ability != ABILITY_NONE) { @@ -3133,19 +3146,19 @@ static void FillPartnerParty(u16 trainerId) break; } if (j < maxAbilities) - SetMonData(&gPlayerParty[i], MON_DATA_ABILITY_NUM, &j); + SetMonData(&gPlayerParty[i+3], MON_DATA_ABILITY_NUM, &j); } - SetMonData(&gPlayerParty[i], MON_DATA_FRIENDSHIP, &(partyData[i].friendship)); + SetMonData(&gPlayerParty[i+3], MON_DATA_FRIENDSHIP, &(partyData[i].friendship)); if (partyData[i].ball != ITEM_NONE) { ball = partyData[i].ball; - SetMonData(&gPlayerParty[i], MON_DATA_POKEBALL, &ball); + SetMonData(&gPlayerParty[i+3], MON_DATA_POKEBALL, &ball); } if (partyData[i].nickname != NULL) { - SetMonData(&gPlayerParty[i], MON_DATA_NICKNAME, partyData[i].nickname); + SetMonData(&gPlayerParty[i+3], MON_DATA_NICKNAME, partyData[i].nickname); } - CalculateMonStats(&gPlayerParty[i]); + CalculateMonStats(&gPlayerParty[i+3]); } } diff --git a/src/battle_tv.c b/src/battle_tv.c index 10c2144cc..f5c9f43c4 100644 --- a/src/battle_tv.c +++ b/src/battle_tv.c @@ -481,6 +481,7 @@ static const u16 sPoints_MoveEffect[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_DOUBLE_SHOCK] = 0, // TODO: Assign points [EFFECT_SPECIAL_ATTACK_UP_HIT] = 1, [EFFECT_VICTORY_DANCE] = 0, // TODO: Assign points + [EFFECT_FROSTBITE_HIT] = 1, }; static const u16 sPoints_Effectiveness[] = diff --git a/src/battle_util.c b/src/battle_util.c index e92ccfdbd..1d03e5fb0 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -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); @@ -545,98 +542,18 @@ void HandleAction_Switch(void) if (gBattleResults.playerSwitchesCounter < 255) gBattleResults.playerSwitchesCounter++; - UndoFormChange(gBattlerPartyIndexes[gBattlerAttacker], GetBattlerSide(gBattlerAttacker), TRUE); + TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_SWITCH); } 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) @@ -2564,8 +2487,16 @@ u8 DoFieldEndTurnEffects(void) gBattleStruct->turnCountersTracker++; break; case ENDTURN_WEATHER_FORM: - AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, 0, 0, 0, 0); - gBattleStruct->turnCountersTracker++; + for (i = 0; i < gBattlersCount; i++) + { + if (AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, i, 0, 0, 0)) + { + effect++; + break; + } + } + if (effect == 0) + gBattleStruct->turnCountersTracker++; break; case ENDTURN_STATUS_HEAL: for (gBattlerAttacker = 0; gBattlerAttacker < gBattlersCount; gBattlerAttacker++) @@ -2602,6 +2533,7 @@ enum ENDTURN_POISON, ENDTURN_BAD_POISON, ENDTURN_BURN, + ENDTURN_FROSTBITE, ENDTURN_NIGHTMARES, ENDTURN_CURSE, ENDTURN_WRAP, @@ -2815,6 +2747,23 @@ u8 DoBattlerEndTurnEffects(void) } gBattleStruct->turnEffectsTracker++; break; + case ENDTURN_FROSTBITE: // burn + if ((gBattleMons[gActiveBattler].status1 & STATUS1_FROSTBITE) + && gBattleMons[gActiveBattler].hp != 0) + { + MAGIC_GUARD_CHECK; + #if B_BURN_DAMAGE >= GEN_7 + gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 16; + #else + gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 8; + #endif + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + BattleScriptExecute(BattleScript_FrostbiteTurnDmg); + effect++; + } + gBattleStruct->turnEffectsTracker++; + break; case ENDTURN_NIGHTMARES: // spooky nightmares if ((gBattleMons[gActiveBattler].status2 & STATUS2_NIGHTMARE) && gBattleMons[gActiveBattler].hp != 0) @@ -3599,7 +3548,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 @@ -3705,6 +3655,17 @@ u8 AtkCanceller_UnableToUseMove(void) } effect = 2; } + if (gBattleMons[gBattlerAttacker].status1 & STATUS1_FROSTBITE && (gBattleMoves[gCurrentMove].flags & FLAG_THAW_USER)) + { + if (!(gBattleMoves[gCurrentMove].effect == EFFECT_BURN_UP && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_FIRE))) + { + gBattleMons[gBattlerAttacker].status1 &= ~STATUS1_FROSTBITE; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_MoveUsedUnfrostbite; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FROSTBITE_HEALED_BY_MOVE; + } + effect = 2; + } gBattleStruct->atkCancellerTracker++; break; case CANCELLER_POWDER_MOVE: @@ -3826,14 +3787,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) @@ -3930,10 +3886,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++) @@ -3967,12 +3920,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); } @@ -4141,7 +4089,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++) { @@ -4204,51 +4152,6 @@ static bool32 TryChangeBattleTerrain(u32 battler, u32 statusFlag, u8 *timer) return FALSE; } -static bool32 ShouldChangeFormHpBased(u32 battler) -{ - // Ability, form >, form <=, hp divided - static const u16 forms[][4] = - { - {ABILITY_ZEN_MODE, SPECIES_DARMANITAN, SPECIES_DARMANITAN_ZEN_MODE, 2}, - {ABILITY_SHIELDS_DOWN, SPECIES_MINIOR, SPECIES_MINIOR_CORE_RED, 2}, - {ABILITY_SHIELDS_DOWN, SPECIES_MINIOR_METEOR_BLUE, SPECIES_MINIOR_CORE_BLUE, 2}, - {ABILITY_SHIELDS_DOWN, SPECIES_MINIOR_METEOR_GREEN, SPECIES_MINIOR_CORE_GREEN, 2}, - {ABILITY_SHIELDS_DOWN, SPECIES_MINIOR_METEOR_INDIGO, SPECIES_MINIOR_CORE_INDIGO, 2}, - {ABILITY_SHIELDS_DOWN, SPECIES_MINIOR_METEOR_ORANGE, SPECIES_MINIOR_CORE_ORANGE, 2}, - {ABILITY_SHIELDS_DOWN, SPECIES_MINIOR_METEOR_VIOLET, SPECIES_MINIOR_CORE_VIOLET, 2}, - {ABILITY_SHIELDS_DOWN, SPECIES_MINIOR_METEOR_YELLOW, SPECIES_MINIOR_CORE_YELLOW, 2}, - {ABILITY_SCHOOLING, SPECIES_WISHIWASHI_SCHOOL, SPECIES_WISHIWASHI, 4}, - {ABILITY_GULP_MISSILE, SPECIES_CRAMORANT, SPECIES_CRAMORANT_GORGING, 2}, - {ABILITY_GULP_MISSILE, SPECIES_CRAMORANT, SPECIES_CRAMORANT_GULPING, 1}, - {ABILITY_ZEN_MODE, SPECIES_DARMANITAN_GALARIAN, SPECIES_DARMANITAN_ZEN_MODE_GALARIAN, 2}, - }; - u32 i; - u16 battlerAbility = GetBattlerAbility(battler); - - if (gBattleMons[battler].status2 & STATUS2_TRANSFORMED) - return FALSE; - - for (i = 0; i < ARRAY_COUNT(forms); i++) - { - if (battlerAbility == forms[i][0]) - { - if (gBattleMons[battler].species == forms[i][2] - && gBattleMons[battler].hp > gBattleMons[battler].maxHP / forms[i][3]) - { - gBattleMons[battler].species = forms[i][1]; - return TRUE; - } - if (gBattleMons[battler].species == forms[i][1] - && gBattleMons[battler].hp <= gBattleMons[battler].maxHP / forms[i][3]) - { - gBattleMons[battler].species = forms[i][2]; - return TRUE; - } - } - } - return FALSE; -} - static u8 ForewarnChooseMove(u32 battler) { struct Forewarn { @@ -4332,8 +4235,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; @@ -4802,8 +4704,10 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move case ABILITY_SCHOOLING: if (gBattleMons[battler].level < 20) break; + // Fallthrough + case ABILITY_ZEN_MODE: case ABILITY_SHIELDS_DOWN: - if (ShouldChangeFormHpBased(battler)) + if (TryBattleFormChange(battler, FORM_CHANGE_BATTLE_HP_PERCENT)) { BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeEnd3); effect++; @@ -4977,7 +4881,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move StringCopy(gBattleTextBuff1, gStatusConditionString_ParalysisJpn); if (gBattleMons[battler].status1 & STATUS1_BURN) StringCopy(gBattleTextBuff1, gStatusConditionString_BurnJpn); - if (gBattleMons[battler].status1 & STATUS1_FREEZE) + if (gBattleMons[battler].status1 & (STATUS1_FREEZE | STATUS1_FROSTBITE)) StringCopy(gBattleTextBuff1, gStatusConditionString_IceJpn); gBattleMons[battler].status1 = 0; @@ -5074,17 +4978,12 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move case ABILITY_SCHOOLING: if (gBattleMons[battler].level < 20) break; + // Fallthrough case ABILITY_ZEN_MODE: case ABILITY_SHIELDS_DOWN: - if ((effect = ShouldChangeFormHpBased(battler))) - BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeEnd3); - break; case ABILITY_POWER_CONSTRUCT: - if ((gBattleMons[battler].species == SPECIES_ZYGARDE || gBattleMons[battler].species == SPECIES_ZYGARDE_10) - && gBattleMons[battler].hp <= gBattleMons[battler].maxHP / 2) + if (TryBattleFormChange(battler, FORM_CHANGE_BATTLE_HP_PERCENT)) { - gBattleStruct->changedSpecies[gBattlerPartyIndexes[battler]] = gBattleMons[battler].species; - gBattleMons[battler].species = SPECIES_ZYGARDE_COMPLETE; BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeEnd3); effect++; } @@ -5104,18 +5003,9 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move } break; case ABILITY_HUNGER_SWITCH: - if (!(gBattleMons[battler].status2 & STATUS2_TRANSFORMED)) + if (TryBattleFormChange(battler, FORM_CHANGE_BATTLE_TURN_END)) { - if (gBattleMons[battler].species == SPECIES_MORPEKO) - { - gBattleMons[battler].species = SPECIES_MORPEKO_HANGRY; - BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeEnd3NoPopup); - } - else if (gBattleMons[battler].species == SPECIES_MORPEKO_HANGRY) - { - gBattleMons[battler].species = SPECIES_MORPEKO; - BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeEnd3NoPopup); - } + BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeEnd3NoPopup); effect++; } break; @@ -5799,7 +5689,6 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move { if (gBattleMons[gBattlerTarget].species == SPECIES_CRAMORANT_GORGING) { - gBattleStruct->changedSpecies[gBattlerPartyIndexes[gBattlerTarget]] = gBattleMons[gBattlerTarget].species; gBattleMons[gBattlerTarget].species = SPECIES_CRAMORANT; if (GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) { @@ -5813,7 +5702,6 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move } else if (gBattleMons[gBattlerTarget].species == SPECIES_CRAMORANT_GULPING) { - gBattleStruct->changedSpecies[gBattlerPartyIndexes[gBattlerTarget]] = gBattleMons[gBattlerTarget].species; gBattleMons[gBattlerTarget].species = SPECIES_CRAMORANT; if (GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) { @@ -5857,6 +5745,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && TARGET_TURN_DAMAGED + && IsBattlerAlive(gBattlerTarget) && (gBattleMons[gBattlerTarget].hp <= gBattleMons[gBattlerTarget].maxHP / 2) && !(TestSheerForceFlag(gBattlerAttacker, gCurrentMove))) { @@ -5935,7 +5824,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move break; case ABILITY_GULP_MISSILE: if (((gCurrentMove == MOVE_SURF && TARGET_TURN_DAMAGED) || gStatuses3[gBattlerAttacker] & STATUS3_UNDERWATER) - && (effect = ShouldChangeFormHpBased(gBattlerAttacker))) + && TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_HP_PERCENT)) { BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_AttackerFormChange; @@ -6018,7 +5907,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move } break; case ABILITY_MAGMA_ARMOR: - if (gBattleMons[battler].status1 & STATUS1_FREEZE) + if (gBattleMons[battler].status1 & (STATUS1_FREEZE | STATUS1_FROSTBITE)) { StringCopy(gBattleTextBuff1, gStatusConditionString_IceJpn); effect = 1; @@ -6041,7 +5930,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; @@ -6214,11 +6103,11 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move #else TRY_WEATHER_FORM: #endif - effect = TryWeatherFormChange(battler); - if (effect != 0) + if ((IsBattlerWeatherAffected(battler, gBattleWeather) || gBattleWeather == B_WEATHER_NONE) + && TryBattleFormChange(battler, FORM_CHANGE_BATTLE_WEATHER)) { - BattleScriptPushCursorAndCallback(BattleScript_WeatherFormChange); - *(&gBattleStruct->formToChangeInto) = effect - 1; + BattleScriptPushCursorAndCallback(BattleScript_BattlerFormChangeWithStringEnd3); + effect++; } break; case ABILITY_ICE_FACE: @@ -6551,6 +6440,20 @@ bool32 CanBeFrozen(u8 battlerId) return TRUE; } +bool32 CanGetFrostbite(u8 battlerId) +{ + u16 ability = GetBattlerAbility(battlerId); + if (IS_BATTLER_OF_TYPE(battlerId, TYPE_ICE) + || gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_SAFEGUARD + || ability == ABILITY_MAGMA_ARMOR + || ability == ABILITY_COMATOSE + || gBattleMons[battlerId].status1 & STATUS1_ANY + || IsAbilityStatusProtected(battlerId) + || IsBattlerTerrainAffected(battlerId, STATUS_FIELD_MISTY_TERRAIN)) + return FALSE; + return TRUE; +} + bool32 CanBeConfused(u8 battlerId) { if (GetBattlerAbility(battlerId) == ABILITY_OWN_TEMPO @@ -6985,6 +6888,13 @@ static u8 ItemEffectMoveEnd(u32 battlerId, u16 holdEffect) gBattlescriptCurrInstr = BattleScript_BerryCureFrzRet; effect = ITEM_STATUS_CHANGE; } + if (gBattleMons[battlerId].status1 & STATUS1_FROSTBITE && !UnnerveOn(battlerId, gLastUsedItem)) + { + gBattleMons[battlerId].status1 &= ~STATUS1_FROSTBITE; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_BerryCureFsbRet; + effect = ITEM_STATUS_CHANGE; + } break; case HOLD_EFFECT_CURE_SLP: if (gBattleMons[battlerId].status1 & STATUS1_SLEEP && !UnnerveOn(battlerId, gLastUsedItem)) @@ -6999,7 +6909,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; @@ -7033,14 +6943,14 @@ static u8 ItemEffectMoveEnd(u32 battlerId, u16 holdEffect) if (gBattleMons[battlerId].status1 & STATUS1_BURN) StringCopy(gBattleTextBuff1, gStatusConditionString_BurnJpn); - if (gBattleMons[battlerId].status1 & STATUS1_FREEZE) + if (gBattleMons[battlerId].status1 & STATUS1_FREEZE || gBattleMons[battlerId].status1 & STATUS1_FROSTBITE) StringCopy(gBattleTextBuff1, gStatusConditionString_IceJpn); if (gBattleMons[battlerId].status2 & STATUS2_CONFUSION) 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; @@ -7078,6 +6988,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; case HOLD_EFFECT_MIRROR_HERB: effect = TryConsumeMirrorHerb(battlerId, FALSE); break; @@ -7209,6 +7134,12 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) BattleScriptExecute(BattleScript_BerryCureFrzEnd2); effect = ITEM_STATUS_CHANGE; } + if (gBattleMons[battlerId].status1 & STATUS1_FROSTBITE && !UnnerveOn(battlerId, gLastUsedItem)) + { + gBattleMons[battlerId].status1 &= ~STATUS1_FROSTBITE; + BattleScriptExecute(BattleScript_BerryCureFsbEnd2); + effect = ITEM_STATUS_CHANGE; + } break; case HOLD_EFFECT_CURE_SLP: if (gBattleMons[battlerId].status1 & STATUS1_SLEEP && !UnnerveOn(battlerId, gLastUsedItem)) @@ -7244,7 +7175,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) StringCopy(gBattleTextBuff1, gStatusConditionString_BurnJpn); i++; } - if (gBattleMons[battlerId].status1 & STATUS1_FREEZE) + if (gBattleMons[battlerId].status1 & STATUS1_FREEZE || gBattleMons[battlerId].status1 & STATUS1_FROSTBITE) { StringCopy(gBattleTextBuff1, gStatusConditionString_IceJpn); i++; @@ -7259,7 +7190,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; } @@ -7320,6 +7251,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) { @@ -7355,11 +7301,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); @@ -7527,6 +7473,12 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) BattleScriptExecute(BattleScript_BerryCureFrzEnd2); effect = ITEM_STATUS_CHANGE; } + if (gBattleMons[battlerId].status1 & STATUS1_FROSTBITE && !UnnerveOn(battlerId, gLastUsedItem)) + { + gBattleMons[battlerId].status1 &= ~STATUS1_FROSTBITE; + BattleScriptExecute(BattleScript_BerryCureFsbEnd2); + effect = ITEM_STATUS_CHANGE; + } break; case HOLD_EFFECT_CURE_SLP: if (gBattleMons[battlerId].status1 & STATUS1_SLEEP && !UnnerveOn(battlerId, gLastUsedItem)) @@ -7540,7 +7492,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; } @@ -7570,7 +7522,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) StringCopy(gBattleTextBuff1, gStatusConditionString_BurnJpn); i++; } - if (gBattleMons[battlerId].status1 & STATUS1_FREEZE) + if (gBattleMons[battlerId].status1 & STATUS1_FREEZE || gBattleMons[battlerId].status1 & STATUS1_FROSTBITE) { StringCopy(gBattleTextBuff1, gStatusConditionString_IceJpn); i++; @@ -7585,7 +7537,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; } @@ -7603,6 +7555,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; case HOLD_EFFECT_MIRROR_HERB: effect = TryConsumeMirrorHerb(battlerId, TRUE); break; @@ -8233,7 +8200,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) @@ -8635,7 +8601,7 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef) basePower *= 2; break; case EFFECT_PURSUIT: - if (gActionsByTurnOrder[GetBattlerTurnOrderNum(gBattlerTarget)] == B_ACTION_SWITCH) + if (gActionsByTurnOrder[GetBattlerTurnOrderNum(battlerDef)] == B_ACTION_SWITCH) basePower *= 2; break; case EFFECT_NATURAL_GIFT: @@ -8769,12 +8735,12 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef) #if B_HIDDEN_POWER_DMG < GEN_6 u8 powerBits; - powerBits = ((gBattleMons[gBattlerAttacker].hpIV & 2) >> 1) - | ((gBattleMons[gBattlerAttacker].attackIV & 2) << 0) - | ((gBattleMons[gBattlerAttacker].defenseIV & 2) << 1) - | ((gBattleMons[gBattlerAttacker].speedIV & 2) << 2) - | ((gBattleMons[gBattlerAttacker].spAttackIV & 2) << 3) - | ((gBattleMons[gBattlerAttacker].spDefenseIV & 2) << 4); + powerBits = ((gBattleMons[battlerAtk].hpIV & 2) >> 1) + | ((gBattleMons[battlerAtk].attackIV & 2) << 0) + | ((gBattleMons[battlerAtk].defenseIV & 2) << 1) + | ((gBattleMons[battlerAtk].speedIV & 2) << 2) + | ((gBattleMons[battlerAtk].spAttackIV & 2) << 3) + | ((gBattleMons[battlerAtk].spDefenseIV & 2) << 4); basePower = (40 * powerBits) / 63 + 30; #endif @@ -8786,15 +8752,15 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef) break; case EFFECT_TERRAIN_PULSE: if ((gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) - && IsBattlerGrounded(gBattlerAttacker)) + && IsBattlerGrounded(battlerAtk)) basePower *= 2; break; case EFFECT_EXPANDING_FORCE: - if (IsBattlerTerrainAffected(gBattlerAttacker, STATUS_FIELD_PSYCHIC_TERRAIN)) + if (IsBattlerTerrainAffected(battlerAtk, STATUS_FIELD_PSYCHIC_TERRAIN)) MulModifier(&basePower, UQ_4_12(1.5)); break; case EFFECT_RISING_VOLTAGE: - if (IsBattlerTerrainAffected(gBattlerTarget, STATUS_FIELD_ELECTRIC_TERRAIN)) + if (IsBattlerTerrainAffected(battlerDef, STATUS_FIELD_ELECTRIC_TERRAIN)) basePower *= 2; break; case EFFECT_BEAT_UP: @@ -8803,7 +8769,7 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef) #endif break; case EFFECT_PSYBLADE: - if (IsBattlerTerrainAffected(gBattlerAttacker, STATUS_FIELD_ELECTRIC_TERRAIN)) + if (IsBattlerTerrainAffected(battlerAtk, STATUS_FIELD_ELECTRIC_TERRAIN)) MulModifier(&basePower, UQ_4_12(1.5)); break; } @@ -9142,7 +9108,7 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe switch (gBattleMoves[move].effect) { case EFFECT_FACADE: - if (gBattleMons[battlerAtk].status1 & (STATUS1_BURN | STATUS1_PSN_ANY | STATUS1_PARALYSIS)) + if (gBattleMons[battlerAtk].status1 & (STATUS1_BURN | STATUS1_PSN_ANY | STATUS1_PARALYSIS | STATUS1_FROSTBITE)) MulModifier(&modifier, UQ_4_12(2.0)); break; case EFFECT_BRINE: @@ -9420,10 +9386,7 @@ static bool32 CanEvolve(u32 species) for (i = 0; i < EVOS_PER_MON; i++) { - if (gEvolutionTable[species][i].method - && gEvolutionTable[species][i].method != EVO_MEGA_EVOLUTION - && gEvolutionTable[species][i].method != EVO_MOVE_MEGA_EVOLUTION - && gEvolutionTable[species][i].method != EVO_PRIMAL_REVERSION) + if (gEvolutionTable[species][i].method) return TRUE; } return FALSE; @@ -9614,6 +9577,14 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move && abilityAtk != ABILITY_GUTS) dmg = ApplyModifier(UQ_4_12(0.5), dmg); + // check frostbite + if (gBattleMons[battlerAtk].status1 & STATUS1_FROSTBITE && !IS_MOVE_PHYSICAL(move) + #if B_BURN_FACADE_DMG >= GEN_6 + && gBattleMoves[move].effect != EFFECT_FACADE + #endif + && abilityAtk != ABILITY_GUTS) + dmg = ApplyModifier(UQ_4_12(0.5), dmg); + // check sunny/rain weather if (IsBattlerWeatherAffected(battlerAtk, B_WEATHER_RAIN)) { @@ -9645,7 +9616,7 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move || (gSideStatuses[defSide] & SIDE_STATUS_AURORA_VEIL)) && abilityAtk != ABILITY_INFILTRATOR && !(isCrit) - && !gProtectStructs[gBattlerAttacker].confusionSelfDmg) + && !gProtectStructs[battlerAtk].confusionSelfDmg) { if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) MulModifier(&finalModifier, UQ_4_12(0.66)); @@ -9654,7 +9625,7 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move } // Parental Bond Second Strike - if (gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_2ND_HIT) + if (gSpecialStatuses[battlerAtk].parentalBondState == PARENTAL_BOND_2ND_HIT) { if (B_PARENTAL_BOND_DMG < GEN_7) MulModifier(&finalModifier, UQ_4_12(0.5)); @@ -9954,6 +9925,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; } @@ -10083,46 +10058,27 @@ bool32 IsPartnerMonFromSameTrainer(u8 battlerId) return TRUE; } -u16 GetMegaEvolutionSpecies(u16 preEvoSpecies, u16 heldItemId) +bool32 DoesSpeciesUseHoldItemToChangeForm(u16 species, u16 heldItemId) { u32 i; + const struct FormChange *formChanges = gFormChangeTablePointers[species]; - for (i = 0; i < EVOS_PER_MON; i++) + if (formChanges != NULL) { - if (gEvolutionTable[preEvoSpecies][i].method == EVO_MEGA_EVOLUTION - && gEvolutionTable[preEvoSpecies][i].param == heldItemId) - return gEvolutionTable[preEvoSpecies][i].targetSpecies; - } - return SPECIES_NONE; -} - -u16 GetPrimalReversionSpecies(u16 preEvoSpecies, u16 heldItemId) -{ - u32 i; - - for (i = 0; i < EVOS_PER_MON; i++) - { - if (gEvolutionTable[preEvoSpecies][i].method == EVO_PRIMAL_REVERSION - && gEvolutionTable[preEvoSpecies][i].param == heldItemId) - return gEvolutionTable[preEvoSpecies][i].targetSpecies; - } - return SPECIES_NONE; -} - -u16 GetWishMegaEvolutionSpecies(u16 preEvoSpecies, u16 moveId1, u16 moveId2, u16 moveId3, u16 moveId4) -{ - u32 i, par; - - for (i = 0; i < EVOS_PER_MON; i++) - { - if (gEvolutionTable[preEvoSpecies][i].method == EVO_MOVE_MEGA_EVOLUTION) + for (i = 0; formChanges[i].method != FORM_CHANGE_TERMINATOR; i++) { - par = gEvolutionTable[preEvoSpecies][i].param; - if (par == moveId1 || par == moveId2 || par == moveId3 || par == moveId4) - return gEvolutionTable[preEvoSpecies][i].targetSpecies; + switch (formChanges[i].method) + { + case FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM: + case FORM_CHANGE_BATTLE_PRIMAL_REVERSION: + case FORM_CHANGE_ITEM_HOLD: + if (formChanges[i].param1 == heldItemId) + return TRUE; + break; + } } } - return SPECIES_NONE; + return FALSE; } bool32 CanMegaEvolve(u8 battlerId) @@ -10165,7 +10121,7 @@ bool32 CanMegaEvolve(u8 battlerId) itemId = GetMonData(mon, MON_DATA_HELD_ITEM); // Check if there is an entry in the evolution table for regular Mega Evolution. - if (GetMegaEvolutionSpecies(species, itemId) != SPECIES_NONE) + if (GetBattleFormChangeTargetSpecies(battlerId, FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM) != SPECIES_NONE) { #if DEBUG_BATTLE_MENU == TRUE if (gBattleStruct->debugHoldEffects[battlerId]) @@ -10183,85 +10139,162 @@ bool32 CanMegaEvolve(u8 battlerId) } // Check if there is an entry in the evolution table for Wish Mega Evolution. - if (GetWishMegaEvolutionSpecies(species, GetMonData(mon, MON_DATA_MOVE1), GetMonData(mon, MON_DATA_MOVE2), GetMonData(mon, MON_DATA_MOVE3), GetMonData(mon, MON_DATA_MOVE4))) + if (GetBattleFormChangeTargetSpecies(battlerId, FORM_CHANGE_BATTLE_MEGA_EVOLUTION_MOVE) != SPECIES_NONE) return TRUE; // No checks passed, the mon CAN'T mega evolve. return FALSE; } -void UndoMegaEvolution(u32 monId) +bool32 IsBattlerMegaEvolved(u8 battlerId) { - u16 baseSpecies = GET_BASE_SPECIES_ID(GetMonData(&gPlayerParty[monId], MON_DATA_SPECIES)); - - if (gBattleStruct->mega.evolvedPartyIds[B_SIDE_PLAYER] & gBitTable[monId]) - { - gBattleStruct->mega.evolvedPartyIds[B_SIDE_PLAYER] &= ~(gBitTable[monId]); - SetMonData(&gPlayerParty[monId], MON_DATA_SPECIES, &baseSpecies); - CalculateMonStats(&gPlayerParty[monId]); - } - else if (gBattleStruct->mega.primalRevertedPartyIds[B_SIDE_PLAYER] & gBitTable[monId]) - { - gBattleStruct->mega.primalRevertedPartyIds[B_SIDE_PLAYER] &= ~(gBitTable[monId]); - SetMonData(&gPlayerParty[monId], MON_DATA_SPECIES, &baseSpecies); - CalculateMonStats(&gPlayerParty[monId]); - } - // While not exactly a mega evolution, Zygarde follows the same rules. - else if (GetMonData(&gPlayerParty[monId], MON_DATA_SPECIES, NULL) == SPECIES_ZYGARDE_COMPLETE) - { - SetMonData(&gPlayerParty[monId], MON_DATA_SPECIES, &gBattleStruct->changedSpecies[monId]); - gBattleStruct->changedSpecies[monId] = 0; - CalculateMonStats(&gPlayerParty[monId]); - } + // While Transform does copy stats and visuals, it shouldn't be counted as true Mega Evolution. + if (gBattleMons[battlerId].status2 & STATUS2_TRANSFORMED) + return FALSE; + return (gSpeciesInfo[gBattleMons[battlerId].species].flags & SPECIES_FLAG_MEGA_EVOLUTION); } -void UndoFormChange(u32 monId, u32 side, bool32 isSwitchingOut) +bool32 IsBattlerPrimalReverted(u8 battlerId) { - u32 i, currSpecies, targetSpecies; - struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; - static const u16 species[][3] = - { - // Changed Form ID Default Form ID Should change on switch - {SPECIES_EISCUE_NOICE_FACE, SPECIES_EISCUE, TRUE}, - {SPECIES_MIMIKYU_BUSTED, SPECIES_MIMIKYU, FALSE}, - {SPECIES_GRENINJA_ASH, SPECIES_GRENINJA_BATTLE_BOND, FALSE}, - {SPECIES_MELOETTA_PIROUETTE, SPECIES_MELOETTA, FALSE}, - {SPECIES_AEGISLASH_BLADE, SPECIES_AEGISLASH, TRUE}, - {SPECIES_DARMANITAN_ZEN_MODE, SPECIES_DARMANITAN, TRUE}, - {SPECIES_MINIOR, SPECIES_MINIOR_CORE_RED, TRUE}, - {SPECIES_MINIOR_METEOR_BLUE, SPECIES_MINIOR_CORE_BLUE, TRUE}, - {SPECIES_MINIOR_METEOR_GREEN, SPECIES_MINIOR_CORE_GREEN, TRUE}, - {SPECIES_MINIOR_METEOR_INDIGO, SPECIES_MINIOR_CORE_INDIGO, TRUE}, - {SPECIES_MINIOR_METEOR_ORANGE, SPECIES_MINIOR_CORE_ORANGE, TRUE}, - {SPECIES_MINIOR_METEOR_VIOLET, SPECIES_MINIOR_CORE_VIOLET, TRUE}, - {SPECIES_MINIOR_METEOR_YELLOW, SPECIES_MINIOR_CORE_YELLOW, TRUE}, - {SPECIES_WISHIWASHI_SCHOOL, SPECIES_WISHIWASHI, TRUE}, - {SPECIES_CRAMORANT_GORGING, SPECIES_CRAMORANT, TRUE}, - {SPECIES_CRAMORANT_GULPING, SPECIES_CRAMORANT, TRUE}, - {SPECIES_MORPEKO_HANGRY, SPECIES_MORPEKO, TRUE}, - {SPECIES_DARMANITAN_ZEN_MODE_GALARIAN, SPECIES_DARMANITAN_GALARIAN, TRUE}, - }; + // While Transform does copy stats and visuals, it shouldn't be counted as true Primal Revesion. + if (gBattleMons[battlerId].status2 & STATUS2_TRANSFORMED) + return FALSE; + return (gSpeciesInfo[gBattleMons[battlerId].species].flags & SPECIES_FLAG_PRIMAL_REVERSION); +} - currSpecies = GetMonData(&party[monId], MON_DATA_SPECIES, NULL); - for (i = 0; i < ARRAY_COUNT(species); i++) +// Returns SPECIES_NONE if no form change is possible +u16 GetBattleFormChangeTargetSpecies(u8 battlerId, u16 method) +{ + u32 i, j; + u16 targetSpecies = SPECIES_NONE; + u16 species = gBattleMons[battlerId].species; + const struct FormChange *formChanges = gFormChangeTablePointers[species]; + u16 heldItem; + u32 ability; + + if (formChanges != NULL) { - if (currSpecies == species[i][0] && (!isSwitchingOut || species[i][2] == TRUE)) + heldItem = gBattleMons[battlerId].item; + ability = GetBattlerAbility(battlerId); + + for (i = 0; formChanges[i].method != FORM_CHANGE_TERMINATOR; i++) { - SetMonData(&party[monId], MON_DATA_SPECIES, &species[i][1]); - CalculateMonStats(&party[monId]); - break; + if (method == formChanges[i].method && species != formChanges[i].targetSpecies) + { + switch (method) + { + case FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM: + case FORM_CHANGE_BATTLE_PRIMAL_REVERSION: + if (heldItem == formChanges[i].param1) + targetSpecies = formChanges[i].targetSpecies; + break; + case FORM_CHANGE_BATTLE_MEGA_EVOLUTION_MOVE: + if (gBattleMons[battlerId].moves[0] == formChanges[i].param1 + || gBattleMons[battlerId].moves[1] == formChanges[i].param1 + || gBattleMons[battlerId].moves[2] == formChanges[i].param1 + || gBattleMons[battlerId].moves[3] == formChanges[i].param1) + targetSpecies = formChanges[i].targetSpecies; + break; + case FORM_CHANGE_BATTLE_SWITCH: + targetSpecies = formChanges[i].targetSpecies; + break; + case FORM_CHANGE_BATTLE_HP_PERCENT: + if (formChanges[i].param1 == GetBattlerAbility(battlerId)) + { + // We multiply by 100 to make sure that integer division doesn't mess with the health check. + u32 hpCheck = gBattleMons[battlerId].hp * 100 * 100 / gBattleMons[battlerId].maxHP; + switch(formChanges[i].param2) + { + case HP_HIGHER_THAN: + if (hpCheck > formChanges[i].param3 * 100) + targetSpecies = formChanges[i].targetSpecies; + break; + case HP_LOWER_EQ_THAN: + if (hpCheck <= formChanges[i].param3 * 100) + targetSpecies = formChanges[i].targetSpecies; + break; + } + } + break; + case FORM_CHANGE_BATTLE_WEATHER: + if (gBattleWeather & formChanges[i].param1 + || (gBattleWeather == B_WEATHER_NONE && formChanges[i].param1 == B_WEATHER_NONE)) + targetSpecies = formChanges[i].targetSpecies; + break; + case FORM_CHANGE_BATTLE_TURN_END: + if (formChanges[i].param1 == GetBattlerAbility(battlerId)) + targetSpecies = formChanges[i].targetSpecies; + break; + } + } } } - if (!isSwitchingOut) + + return targetSpecies; +} + +bool32 CanBattlerFormChange(u8 battlerId, u16 method) +{ + // Can't change form if transformed. + if (gBattleMons[battlerId].status2 & STATUS2_TRANSFORMED + && B_TRANSFORM_FORM_CHANGES >= GEN_5) + return FALSE; + // Mega Evolved Pokémon should always revert to normal upon fainting or ending the battle. + if (IsBattlerMegaEvolved(battlerId) && (method == FORM_CHANGE_FAINT || method == FORM_CHANGE_END_BATTLE)) + return TRUE; + else if (IsBattlerPrimalReverted(battlerId) && (method == FORM_CHANGE_END_BATTLE)) + return TRUE; + return DoesSpeciesHaveFormChangeMethod(gBattleMons[battlerId].species, method); +} + +bool32 TryBattleFormChange(u8 battlerId, u16 method) +{ + u8 monId = gBattlerPartyIndexes[battlerId]; + u8 side = GET_BATTLER_SIDE(battlerId); + struct Pokemon *party = GetBattlerParty(battlerId); + u16 targetSpecies; + + if (!CanBattlerFormChange(battlerId, method)) + return FALSE; + + targetSpecies = GetBattleFormChangeTargetSpecies(battlerId, method); + if (targetSpecies == SPECIES_NONE) + targetSpecies = GetFormChangeTargetSpecies(&party[monId], method, 0); + if (targetSpecies != SPECIES_NONE) { - targetSpecies = GetFormChangeTargetSpecies(&party[monId], FORM_BATTLE_END, 0); - if (targetSpecies != SPECIES_NONE) + // Saves the original species on the first form change for the player. + if (side == B_SIDE_PLAYER && gBattleStruct->changedSpecies[monId] == SPECIES_NONE) + gBattleStruct->changedSpecies[monId] = gBattleMons[battlerId].species; + + TryToSetBattleFormChangeMoves(&party[monId], method); + SetMonData(&party[monId], MON_DATA_SPECIES, &targetSpecies); + gBattleMons[battlerId].species = targetSpecies; + RecalcBattlerStats(battlerId, &party[monId]); + return TRUE; + } + else if (gBattleStruct->changedSpecies[monId] != SPECIES_NONE) + { + bool8 restoreSpecies = FALSE; + + // Mega Evolved Pokémon should always revert to normal upon fainting or ending the battle, so no need to add it to the form change tables. + if (IsBattlerMegaEvolved(battlerId) && (method == FORM_CHANGE_FAINT || method == FORM_CHANGE_END_BATTLE)) + restoreSpecies = TRUE; + + // Unlike Megas, Primal Reversion isn't canceled on fainting. + else if (IsBattlerPrimalReverted(battlerId) && (method == FORM_CHANGE_END_BATTLE)) + restoreSpecies = TRUE; + + if (restoreSpecies) { - SetMonData(&party[monId], MON_DATA_SPECIES, &targetSpecies); - CalculateMonStats(&party[monId]); - TryToSetBattleFormChangeMoves(&party[monId]); + // Reverts the original species + TryToSetBattleFormChangeMoves(&party[monId], method); + SetMonData(&party[monId], MON_DATA_SPECIES, &gBattleStruct->changedSpecies[monId]); + RecalcBattlerStats(battlerId, &party[monId]); + return TRUE; } } + + return FALSE; } bool32 DoBattlersShareType(u32 battler1, u32 battler2) @@ -10292,24 +10325,10 @@ bool32 CanBattlerGetOrLoseItem(u8 battlerId, u16 itemId) // Mail can be stolen now if (itemId == ITEM_ENIGMA_BERRY_E_READER) return FALSE; - // Primal Reversion inducing items cannot be lost if pokemon's base species can undergo primal reversion with it. - else if (holdEffect == HOLD_EFFECT_PRIMAL_ORB && (GetPrimalReversionSpecies(GET_BASE_SPECIES_ID(species), itemId) != SPECIES_NONE)) + else if (DoesSpeciesUseHoldItemToChangeForm(species, itemId)) return FALSE; - // Mega stone cannot be lost if pokemon's base species can mega evolve with it. - else if (holdEffect == HOLD_EFFECT_MEGA_STONE && (GetMegaEvolutionSpecies(GET_BASE_SPECIES_ID(species), itemId) != SPECIES_NONE)) - return FALSE; - else if (GET_BASE_SPECIES_ID(species) == SPECIES_GIRATINA && itemId == ITEM_GRISEOUS_ORB) - return FALSE; - else if (GET_BASE_SPECIES_ID(species) == SPECIES_GENESECT && holdEffect == HOLD_EFFECT_DRIVE) - return FALSE; - else if (GET_BASE_SPECIES_ID(species) == SPECIES_SILVALLY && holdEffect == HOLD_EFFECT_MEMORY) - return FALSE; - else if (GET_BASE_SPECIES_ID(species) == SPECIES_ARCEUS && holdEffect == HOLD_EFFECT_PLATE) - return FALSE; -#ifdef HOLD_EFFECT_Z_CRYSTAL else if (holdEffect == HOLD_EFFECT_Z_CRYSTAL) return FALSE; -#endif else return TRUE; } @@ -10353,10 +10372,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)]]; @@ -10481,17 +10497,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) @@ -10642,18 +10647,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 } } } @@ -10707,8 +10714,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 } @@ -10832,46 +10839,6 @@ bool32 TryRoomService(u8 battlerId) } } -void DoBurmyFormChange(u32 monId) -{ - u16 newSpecies, currSpecies; - struct Pokemon *party = gPlayerParty; - - currSpecies = GetMonData(&party[monId], MON_DATA_SPECIES, NULL); - - if ((GET_BASE_SPECIES_ID(currSpecies) == SPECIES_BURMY) - && (gBattleStruct->appearedInBattle & gBitTable[monId]) // Burmy appeared in battle - && GetMonData(&party[monId], MON_DATA_HP, NULL) != 0) // Burmy isn't fainted - { - switch (gBattleTerrain) - { - case BATTLE_TERRAIN_GRASS: - case BATTLE_TERRAIN_LONG_GRASS: - case BATTLE_TERRAIN_POND: - case BATTLE_TERRAIN_MOUNTAIN: - case BATTLE_TERRAIN_PLAIN: - newSpecies = SPECIES_BURMY; - break; - case BATTLE_TERRAIN_CAVE: - case BATTLE_TERRAIN_SAND: - newSpecies = SPECIES_BURMY_SANDY_CLOAK; - break; - case BATTLE_TERRAIN_BUILDING: - newSpecies = SPECIES_BURMY_TRASH_CLOAK; - break; - default: // Don't change form if last battle was water-related - newSpecies = SPECIES_NONE; - break; - } - - if (newSpecies != SPECIES_NONE) - { - SetMonData(&party[monId], MON_DATA_SPECIES, &newSpecies); - CalculateMonStats(&party[monId]); - } - } -} - bool32 BlocksPrankster(u16 move, u8 battlerPrankster, u8 battlerDef, bool32 checkTarget) { #if B_PRANKSTER_DARK_TYPES >= GEN_7 @@ -10964,3 +10931,48 @@ static void SetRandomMultiHitCounter() gMultiHitCounter = 5 - (Random() & 1); } } + +void CopyMonLevelAndBaseStatsToBattleMon(u32 battler, struct Pokemon *mon) +{ + gBattleMons[battler].level = GetMonData(mon, MON_DATA_LEVEL); + gBattleMons[battler].hp = GetMonData(mon, MON_DATA_HP); + gBattleMons[battler].maxHP = GetMonData(mon, MON_DATA_MAX_HP); + gBattleMons[battler].attack = GetMonData(mon, MON_DATA_ATK); + gBattleMons[battler].defense = GetMonData(mon, MON_DATA_DEF); + gBattleMons[battler].speed = GetMonData(mon, MON_DATA_SPEED); + gBattleMons[battler].spAttack = GetMonData(mon, MON_DATA_SPATK); + gBattleMons[battler].spDefense = GetMonData(mon, MON_DATA_SPDEF); +} + +void CopyMonAbilityAndTypesToBattleMon(u32 battler, struct Pokemon *mon) +{ + gBattleMons[battler].ability = GetMonAbility(mon); + gBattleMons[battler].type1 = gSpeciesInfo[gBattleMons[battler].species].types[0]; + gBattleMons[battler].type2 = gSpeciesInfo[gBattleMons[battler].species].types[1]; + gBattleMons[battler].type3 = TYPE_MYSTERY; +} + +void RecalcBattlerStats(u32 battler, struct Pokemon *mon) +{ + CalculateMonStats(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; +} + diff --git a/src/battle_z_move.c b/src/battle_z_move.c index 104a44daa..f435253c7 100644 --- a/src/battle_z_move.c +++ b/src/battle_z_move.c @@ -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; } } diff --git a/src/cable_car.c b/src/cable_car.c index 4eb4c3080..7d18df7b7 100644 --- a/src/cable_car.c +++ b/src/cable_car.c @@ -27,9 +27,11 @@ #define STATE_END 0xFF -#define TAG_CABLE_CAR 1 -#define TAG_DOOR 2 -#define TAG_CABLE 3 +enum { + TAG_CABLE_CAR = 1, + TAG_DOOR, + TAG_CABLE, +}; struct CableCar { @@ -62,8 +64,8 @@ struct CableCar u16 *groundTilemap; u16 *treesTilemap; u16 *bgMountainsTilemap; - const u16 *pylonHookTilemapEntries; - u8 *pylonStemTilemap; + const u16 *pylonTopTilemap; + u16 *pylonPoleTilemap; }; static EWRAM_DATA struct CableCar *sCableCar = NULL; @@ -129,24 +131,11 @@ static const struct BgTemplate sBgTemplates[4] = { }, }; -static const u8 sGround_Tilemap[] = INCBIN_U8("graphics/cable_car/ground.bin.lz"); -static const u8 sTrees_Tilemap[] = INCBIN_U8("graphics/cable_car/trees.bin.lz"); -static const u8 sBgMountains_Tilemap[] = INCBIN_U8("graphics/cable_car/bg_mountains.bin.lz"); - -static const u16 sPylonHook_TilemapEntries[] = { - 0x3000, - 0x3001, - 0x3002, - 0x3003, - 0x3004, - 0x3005, - 0x3006, - 0x3007, - 0x3008, - 0x3009, -}; - -static const u8 sPylonStems_Tilemap[] = INCBIN_U8("graphics/cable_car/pylons.bin.lz"); +static const u16 sGround_Tilemap[] = INCBIN_U16("graphics/cable_car/ground.bin.lz"); +static const u16 sTrees_Tilemap[] = INCBIN_U16("graphics/cable_car/trees.bin.lz"); +static const u16 sBgMountains_Tilemap[] = INCBIN_U16("graphics/cable_car/bg_mountains.bin.lz"); +static const u16 sPylonTop_Tilemap[] = INCBIN_U16("graphics/cable_car/pylon_top.bin"); +static const u16 sPylonPole_Tilemap[] = INCBIN_U16("graphics/cable_car/pylon_pole.bin.lz"); static const struct CompressedSpriteSheet sSpriteSheets[] = { { gCableCar_Gfx, 0x800, TAG_CABLE_CAR }, @@ -299,8 +288,8 @@ static void CB2_LoadCableCar(void) sCableCar->groundTilemap = malloc_and_decompress(sGround_Tilemap, &sizeOut); sCableCar->treesTilemap = malloc_and_decompress(sTrees_Tilemap, &sizeOut); sCableCar->bgMountainsTilemap = malloc_and_decompress(sBgMountains_Tilemap, &sizeOut); - sCableCar->pylonStemTilemap = malloc_and_decompress(sPylonStems_Tilemap, &sizeOut); - sCableCar->pylonHookTilemapEntries = sPylonHook_TilemapEntries; + sCableCar->pylonPoleTilemap = malloc_and_decompress(sPylonPole_Tilemap, &sizeOut); + sCableCar->pylonTopTilemap = sPylonTop_Tilemap; DecompressAndCopyTileDataToVram(0, gCableCarBg_Gfx, 0, 0, 0); gMain.state++; break; @@ -335,8 +324,8 @@ static void CB2_LoadCableCar(void) case 6: CopyToBgTilemapBufferRect_ChangePalette(1, sCableCar->treesTilemap, 0, 17, 32, 15, 17); CopyToBgTilemapBufferRect_ChangePalette(2, sCableCar->bgMountainsTilemap, 0, 0, 30, 20, 17); - CopyToBgTilemapBufferRect_ChangePalette(3, sCableCar->pylonHookTilemapEntries, 0, 0, 5, 2, 17); - CopyToBgTilemapBufferRect_ChangePalette(3, sCableCar->pylonStemTilemap, 0, 2, 2, 20, 17); + CopyToBgTilemapBufferRect_ChangePalette(3, sCableCar->pylonTopTilemap, 0, 0, 5, 2, 17); + CopyToBgTilemapBufferRect_ChangePalette(3, sCableCar->pylonPoleTilemap, 0, 2, 2, 20, 17); gMain.state++; break; case 7: @@ -404,8 +393,8 @@ static void CB2_EndCableCar(void) UnsetBgTilemapBuffer(2); UnsetBgTilemapBuffer(3); ResetBgsAndClearDma3BusyFlags(0); - sCableCar->pylonHookTilemapEntries = NULL; - FREE_AND_SET_NULL(sCableCar->pylonStemTilemap); + sCableCar->pylonTopTilemap = NULL; + FREE_AND_SET_NULL(sCableCar->pylonPoleTilemap); FREE_AND_SET_NULL(sCableCar->bgMountainsTilemap); FREE_AND_SET_NULL(sCableCar->treesTilemap); FREE_AND_SET_NULL(sCableCar->groundTilemap); @@ -514,8 +503,8 @@ static void Task_AnimateBgGoingUp(u8 taskId) FillBgTilemapBufferRect(3, 0, 2, 0, 1, 2, 17); break; case 16: - CopyToBgTilemapBufferRect_ChangePalette(3, sCableCar->pylonHookTilemapEntries, 0, 0, 5, 2, 17); - CopyToBgTilemapBufferRect_ChangePalette(3, sCableCar->pylonStemTilemap, 0, 2, 2, 30, 17); + CopyToBgTilemapBufferRect_ChangePalette(3, sCableCar->pylonTopTilemap, 0, 0, 5, 2, 17); + CopyToBgTilemapBufferRect_ChangePalette(3, sCableCar->pylonPoleTilemap, 0, 2, 2, 30, 17); sCableCar->bg3VerticalOffset = 64; break; } @@ -542,7 +531,7 @@ static void Task_AnimateBgGoingDown(u8 taskId) switch (sCableCar->bg3HorizontalOffset) { case 176: - CopyToBgTilemapBufferRect_ChangePalette(3, sCableCar->pylonStemTilemap, 0, 2, 2, 30, 17); + CopyToBgTilemapBufferRect_ChangePalette(3, sCableCar->pylonPoleTilemap, 0, 2, 2, 30, 17); break; case 16: FillBgTilemapBufferRect(3, 0, 2, 0, 3, 2, 17); @@ -550,14 +539,14 @@ static void Task_AnimateBgGoingDown(u8 taskId) sCableCar->bg3VerticalOffset = 192; break; case 32: - FillBgTilemapBufferRect(3, sCableCar->pylonHookTilemapEntries[2], 2, 0, 1, 1, 17); - FillBgTilemapBufferRect(3, sCableCar->pylonHookTilemapEntries[3], 3, 0, 1, 1, 17); - FillBgTilemapBufferRect(3, sCableCar->pylonHookTilemapEntries[7], 2, 1, 1, 1, 17); - FillBgTilemapBufferRect(3, sCableCar->pylonHookTilemapEntries[8], 3, 1, 1, 1, 17); + FillBgTilemapBufferRect(3, sCableCar->pylonTopTilemap[2], 2, 0, 1, 1, 17); + FillBgTilemapBufferRect(3, sCableCar->pylonTopTilemap[3], 3, 0, 1, 1, 17); + FillBgTilemapBufferRect(3, sCableCar->pylonTopTilemap[7], 2, 1, 1, 1, 17); + FillBgTilemapBufferRect(3, sCableCar->pylonTopTilemap[8], 3, 1, 1, 1, 17); break; case 40: - FillBgTilemapBufferRect(3, sCableCar->pylonHookTilemapEntries[4], 4, 0, 1, 1, 17); - FillBgTilemapBufferRect(3, sCableCar->pylonHookTilemapEntries[9], 4, 1, 1, 1, 17); + FillBgTilemapBufferRect(3, sCableCar->pylonTopTilemap[4], 4, 0, 1, 1, 17); + FillBgTilemapBufferRect(3, sCableCar->pylonTopTilemap[9], 4, 1, 1, 1, 17); break; } } diff --git a/src/contest.c b/src/contest.c index 047f13526..eadf960a2 100644 --- a/src/contest.c +++ b/src/contest.c @@ -5500,7 +5500,7 @@ static void ContestBG_FillBoxWithTile(u8 bg, u16 firstTileNum, u8 x, u8 y, u8 wi static bool32 Contest_RunTextPrinters(void) { RunTextPrinters(); - return IsTextPrinterActive(4); + return IsTextPrinterActive(WIN_GENERAL_TEXT); } static void Contest_SetBgCopyFlags(u32 flagIndex) diff --git a/src/data/battle_anim.h b/src/data/battle_anim.h index b1f158310..46293e3a0 100644 --- a/src/data/battle_anim.h +++ b/src/data/battle_anim.h @@ -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}, diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 64ce24686..9473bae71 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -121,7 +121,11 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] = [MOVE_ICE_PUNCH] = { - .effect = EFFECT_FREEZE_HIT, + #if B_USE_FROSTBITE == TRUE + .effect = EFFECT_FROSTBITE_HIT, + #else + .effect = EFFECT_FREEZE_HIT, + #endif .power = 75, .type = TYPE_ICE, .accuracy = 100, @@ -982,7 +986,13 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] = #else .power = 95, #endif - .effect = EFFECT_FREEZE_HIT, + // The following effect is also relevant in battle_pike.c + // If you cherry-pick this to use something other than the config, make sure to update it there too + #if B_USE_FROSTBITE == TRUE + .effect = EFFECT_FROSTBITE_HIT, + #else + .effect = EFFECT_FREEZE_HIT, + #endif .type = TYPE_ICE, .accuracy = 100, .pp = 10, @@ -1001,7 +1011,11 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] = #else .power = 120, #endif - .effect = EFFECT_FREEZE_HIT, + #if B_USE_FROSTBITE == TRUE + .effect = EFFECT_FROSTBITE_HIT, + #else + .effect = EFFECT_FREEZE_HIT, + #endif .type = TYPE_ICE, .accuracy = 70, .pp = 5, @@ -3062,7 +3076,11 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] = [MOVE_POWDER_SNOW] = { - .effect = EFFECT_FREEZE_HIT, + #if B_USE_FROSTBITE == TRUE + .effect = EFFECT_FROSTBITE_HIT, + #else + .effect = EFFECT_FREEZE_HIT, + #endif .power = 40, .type = TYPE_ICE, .accuracy = 100, @@ -7177,6 +7195,11 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] = #else .flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_SHEER_FORCE_BOOST | FLAG_STRONG_JAW_BOOST, #endif + #if B_USE_FROSTBITE == TRUE + .argument = STATUS1_FROSTBITE, + #else + .argument = STATUS1_FREEZE, + #endif .effect = EFFECT_FLINCH_STATUS, .power = 65, .type = TYPE_ICE, @@ -7186,7 +7209,6 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] = .target = MOVE_TARGET_SELECTED, .priority = 0, .split = SPLIT_PHYSICAL, - .argument = STATUS1_FREEZE, .zMoveEffect = Z_EFFECT_NONE, }, @@ -7884,7 +7906,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] = .accuracy = 100, .pp = 5, .secondaryEffectChance = 10, - .target = MOVE_TARGET_BOTH, + .target = MOVE_TARGET_SELECTED, .priority = 0, .flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_SHEER_FORCE_BOOST, .split = SPLIT_SPECIAL, @@ -12354,7 +12376,11 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] = [MOVE_FREEZING_GLARE] = { .power = 90, - .effect = EFFECT_FREEZE_HIT, + #if B_USE_FROSTBITE == TRUE + .effect = EFFECT_FROSTBITE_HIT, + #else + .effect = EFFECT_FREEZE_HIT, + #endif .type = TYPE_PSYCHIC, .accuracy = 100, .pp = 10, @@ -13048,7 +13074,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] = [MOVE_REVIVAL_BLESSING] = { - .effect = EFFECT_PLACEHOLDER, // EFFECT_REVIVAL_BLESSING + .effect = EFFECT_REVIVAL_BLESSING, .power = 0, .type = TYPE_NORMAL, .accuracy = 0, diff --git a/src/data/graphics/items.h b/src/data/graphics/items.h index ce4ecf608..9ef79b2c9 100644 --- a/src/data/graphics/items.h +++ b/src/data/graphics/items.h @@ -645,6 +645,15 @@ const u32 gItemIconPalette_RibbonSweet[] = INCBIN_U32("graphics/items/icon_palet const u32 gItemIcon_Everstone[] = INCBIN_U32("graphics/items/icons/everstone.4bpp.lz"); const u32 gItemIconPalette_Everstone[] = INCBIN_U32("graphics/items/icon_palettes/everstone.gbapal.lz"); +const u32 gItemIcon_BlackAugurite[] = INCBIN_U32("graphics/items/icons/black_augurite.4bpp.lz"); +const u32 gItemIconPalette_BlackAugurite[] = INCBIN_U32("graphics/items/icon_palettes/black_augurite.gbapal.lz"); + +const u32 gItemIcon_LinkingCord[] = INCBIN_U32("graphics/items/icons/linking_cord.4bpp.lz"); +const u32 gItemIconPalette_LinkingCord[] = INCBIN_U32("graphics/items/icon_palettes/linking_cord.gbapal.lz"); + +const u32 gItemIcon_PeatBlock[] = INCBIN_U32("graphics/items/icons/peat_block.4bpp.lz"); +const u32 gItemIconPalette_PeatBlock[] = INCBIN_U32("graphics/items/icon_palettes/peat_block.gbapal.lz"); + // Nectars const u32 gItemIcon_RedNectar[] = INCBIN_U32("graphics/items/icons/red_nectar.4bpp.lz"); @@ -1989,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"); diff --git a/src/data/item_icon_table.h b/src/data/item_icon_table.h index 9e4b56777..05a878281 100644 --- a/src/data/item_icon_table.h +++ b/src/data/item_icon_table.h @@ -840,6 +840,10 @@ const u32 *const gItemIconTable[ITEMS_COUNT + 1][2] = [ITEM_ADAMANT_CRYSTAL] = {gItemIcon_AdamantCrystal, gItemIconPalette_AdamantCrystal}, [ITEM_GRISEOUS_CORE] = {gItemIcon_GriseousCore, gItemIconPalette_GriseousCore}, [ITEM_LUSTROUS_GLOBE] = {gItemIcon_LustrousGlobe, gItemIconPalette_LustrousGlobe}, + [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}, }; diff --git a/src/data/items.h b/src/data/items.h index 82e41901c..1831f11d0 100644 --- a/src/data/items.h +++ b/src/data/items.h @@ -20,9 +20,8 @@ const struct Item gItems[] = .price = 200, .description = sPokeBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_POKE_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_POKE_BALL - FIRST_BALL, }, @@ -33,9 +32,8 @@ const struct Item gItems[] = .price = 600, .description = sGreatBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_GREAT_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_GREAT_BALL - FIRST_BALL, }, @@ -46,9 +44,8 @@ const struct Item gItems[] = .price = 800, .description = sUltraBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_ULTRA_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_ULTRA_BALL - FIRST_BALL, }, @@ -59,9 +56,8 @@ const struct Item gItems[] = .price = 0, .description = sMasterBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_MASTER_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_MASTER_BALL - FIRST_BALL, }, @@ -72,9 +68,8 @@ const struct Item gItems[] = .price = 20, .description = sPremierBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_PREMIER_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_PREMIER_BALL - FIRST_BALL, }, @@ -85,9 +80,8 @@ const struct Item gItems[] = .price = 300, .description = sHealBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_HEAL_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_HEAL_BALL - FIRST_BALL, }, @@ -98,9 +92,8 @@ const struct Item gItems[] = .price = 1000, .description = sNetBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_NET_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_NET_BALL - FIRST_BALL, }, @@ -111,9 +104,8 @@ const struct Item gItems[] = .price = 1000, .description = sNestBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_NEST_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_NEST_BALL - FIRST_BALL, }, @@ -124,9 +116,8 @@ const struct Item gItems[] = .price = 1000, .description = sDiveBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_DIVE_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_DIVE_BALL - FIRST_BALL, }, @@ -137,9 +128,8 @@ const struct Item gItems[] = .price = 1000, .description = sDuskBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_DUSK_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_DUSK_BALL - FIRST_BALL, }, @@ -150,9 +140,8 @@ const struct Item gItems[] = .price = 1000, .description = sTimerBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_TIMER_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_TIMER_BALL - FIRST_BALL, }, @@ -163,9 +152,8 @@ const struct Item gItems[] = .price = 1000, .description = sQuickBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_QUICK_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_QUICK_BALL - FIRST_BALL, }, @@ -176,9 +164,8 @@ const struct Item gItems[] = .price = 1000, .description = sRepeatBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_REPEAT_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_REPEAT_BALL - FIRST_BALL, }, @@ -189,9 +176,8 @@ const struct Item gItems[] = .price = 1000, .description = sLuxuryBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_LUXURY_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_LUXURY_BALL - FIRST_BALL, }, @@ -202,9 +188,8 @@ const struct Item gItems[] = .price = 0, .description = sLevelBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_LEVEL_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_LEVEL_BALL - FIRST_BALL, }, @@ -215,9 +200,8 @@ const struct Item gItems[] = .price = 0, .description = sLureBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_LURE_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_LURE_BALL - FIRST_BALL, }, @@ -228,9 +212,8 @@ const struct Item gItems[] = .price = 0, .description = sMoonBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_MOON_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_MOON_BALL - FIRST_BALL, }, @@ -241,9 +224,8 @@ const struct Item gItems[] = .price = 0, .description = sFriendBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_FRIEND_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_FRIEND_BALL - FIRST_BALL, }, @@ -254,9 +236,8 @@ const struct Item gItems[] = .price = 0, .description = sLoveBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_LOVE_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_LOVE_BALL - FIRST_BALL, }, @@ -267,9 +248,8 @@ const struct Item gItems[] = .price = 0, .description = sFastBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_FAST_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_FAST_BALL - FIRST_BALL, }, @@ -280,9 +260,8 @@ const struct Item gItems[] = .price = 0, .description = sHeavyBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_HEAVY_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_HEAVY_BALL - FIRST_BALL, }, @@ -293,9 +272,8 @@ const struct Item gItems[] = .price = 0, .description = sDreamBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_DREAM_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_DREAM_BALL - FIRST_BALL, }, @@ -306,9 +284,8 @@ const struct Item gItems[] = .price = 0, .description = sSafariBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_SAFARI_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_SAFARI_BALL - FIRST_BALL, }, @@ -319,9 +296,8 @@ const struct Item gItems[] = .price = 0, .description = sSportBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_SPORT_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_SPORT_BALL - FIRST_BALL, }, @@ -332,9 +308,8 @@ const struct Item gItems[] = .price = 0, .description = sParkBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_PARK_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_PARK_BALL - FIRST_BALL, }, @@ -345,9 +320,8 @@ const struct Item gItems[] = .price = 0, .description = sBeastBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_BEAST_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_BEAST_BALL - FIRST_BALL, }, @@ -358,9 +332,8 @@ const struct Item gItems[] = .price = 0, .description = sCherishBallDesc, .pocket = POCKET_POKE_BALLS, - .type = ITEM_CHERISH_BALL - FIRST_BALL, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_PokeBall, + .type = ITEM_USE_BAG_MENU, + .battleUsage = EFFECT_ITEM_THROW_BALL, .secondaryId = ITEM_CHERISH_BALL - FIRST_BALL, }, @@ -376,8 +349,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_RESTORE_HP, .flingPower = 30, }, @@ -391,8 +363,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_RESTORE_HP, .flingPower = 30, }, @@ -406,8 +377,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_RESTORE_HP, .flingPower = 30, }, @@ -421,8 +391,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_RESTORE_HP, .flingPower = 30, }, @@ -436,8 +405,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_HEAL_AND_CURE_STATUS, .flingPower = 30, }, @@ -450,8 +418,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_REVIVE, .flingPower = 30, }, @@ -464,8 +431,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_REVIVE, .flingPower = 30, }, @@ -479,8 +445,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_RESTORE_HP, .flingPower = 30, }, @@ -494,8 +459,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_RESTORE_HP, .flingPower = 30, }, @@ -509,8 +473,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_RESTORE_HP, .flingPower = 30, }, @@ -524,8 +487,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_RESTORE_HP, .flingPower = 30, }, @@ -538,8 +500,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_RESTORE_HP, .flingPower = 30, }, @@ -552,8 +513,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_RESTORE_HP, .flingPower = 30, }, @@ -566,8 +526,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_RESTORE_HP, .flingPower = 30, }, @@ -580,8 +539,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_REVIVE, .flingPower = 30, }, @@ -594,8 +552,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 30, }, @@ -608,8 +565,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 30, }, @@ -622,8 +578,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 30, }, @@ -636,8 +591,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 30, }, @@ -650,8 +604,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 30, }, @@ -664,8 +617,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 30, }, @@ -677,10 +629,9 @@ const struct Item gItems[] = .holdEffectParam = 10, .description = sEtherDesc, .pocket = POCKET_ITEMS, - .type = ITEM_USE_PARTY_MENU, + .type = ITEM_USE_PARTY_MENU_MOVES, .fieldUseFunc = ItemUseOutOfBattle_PPRecovery, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_PPRecovery, + .battleUsage = EFFECT_ITEM_RESTORE_PP, .flingPower = 30, }, @@ -692,10 +643,9 @@ const struct Item gItems[] = .holdEffectParam = 255, .description = sMaxEtherDesc, .pocket = POCKET_ITEMS, - .type = ITEM_USE_PARTY_MENU, + .type = ITEM_USE_PARTY_MENU_MOVES, .fieldUseFunc = ItemUseOutOfBattle_PPRecovery, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_PPRecovery, + .battleUsage = EFFECT_ITEM_RESTORE_PP, .flingPower = 30, }, @@ -709,8 +659,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_PPRecovery, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_PPRecovery, + .battleUsage = EFFECT_ITEM_RESTORE_PP, .flingPower = 30, }, @@ -724,8 +673,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_PPRecovery, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_PPRecovery, + .battleUsage = EFFECT_ITEM_RESTORE_PP, .flingPower = 30, }, @@ -740,8 +688,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_RESTORE_HP, .flingPower = 30, }, @@ -767,8 +714,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_RESTORE_HP, .flingPower = 30, }, @@ -781,8 +727,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_REVIVE, .flingPower = 30, }, @@ -797,8 +742,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 30, }, @@ -811,8 +755,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 30, }, @@ -825,8 +768,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 30, }, @@ -839,8 +781,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 30, }, @@ -853,8 +794,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 30, }, @@ -867,8 +807,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 30, }, @@ -881,8 +820,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 30, }, @@ -895,8 +833,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 30, }, @@ -1454,8 +1391,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 30, }, @@ -1468,8 +1404,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 30, }, @@ -1482,8 +1417,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 30, }, @@ -1618,17 +1552,19 @@ const struct Item gItems[] = // X Items +#define X_ITEM_STAGES (B_X_ITEMS_BUFF >= GEN_7) ? 2 : 1 + [ITEM_X_ATTACK] = { .name = _("X Attack"), .itemId = ITEM_X_ATTACK, .price = 1000, + .holdEffectParam = X_ITEM_STAGES, .description = sXAttackDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_StatIncrease, + .battleUsage = EFFECT_ITEM_INCREASE_STAT, .flingPower = 30, }, @@ -1637,12 +1573,12 @@ const struct Item gItems[] = .name = _("X Defense"), .itemId = ITEM_X_DEFENSE, .price = 2000, + .holdEffectParam = X_ITEM_STAGES, .description = sXDefenseDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_StatIncrease, + .battleUsage = EFFECT_ITEM_INCREASE_STAT, .flingPower = 30, }, @@ -1651,12 +1587,12 @@ const struct Item gItems[] = .name = _("X Sp. Atk"), .itemId = ITEM_X_SP_ATK, .price = 1000, + .holdEffectParam = X_ITEM_STAGES, .description = sXSpAtkDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_StatIncrease, + .battleUsage = EFFECT_ITEM_INCREASE_STAT, .flingPower = 30, }, @@ -1665,12 +1601,12 @@ const struct Item gItems[] = .name = _("X Sp. Def"), .itemId = ITEM_X_SP_DEF, .price = 2000, + .holdEffectParam = X_ITEM_STAGES, .description = sXSpDefDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_StatIncrease, + .battleUsage = EFFECT_ITEM_INCREASE_STAT, .flingPower = 30, }, @@ -1679,12 +1615,12 @@ const struct Item gItems[] = .name = _("X Speed"), .itemId = ITEM_X_SPEED, .price = 1000, + .holdEffectParam = X_ITEM_STAGES, .description = sXSpeedDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_StatIncrease, + .battleUsage = EFFECT_ITEM_INCREASE_STAT, .flingPower = 30, }, @@ -1693,12 +1629,12 @@ const struct Item gItems[] = .name = _("X Accuracy"), .itemId = ITEM_X_ACCURACY, .price = 1000, + .holdEffectParam = X_ITEM_STAGES, .description = sXAccuracyDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_StatIncrease, + .battleUsage = EFFECT_ITEM_INCREASE_STAT, .flingPower = 30, }, @@ -1711,8 +1647,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_StatIncrease, + .battleUsage = EFFECT_ITEM_SET_FOCUS_ENERGY, .flingPower = 30, }, @@ -1725,8 +1660,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_StatIncrease, + .battleUsage = EFFECT_ITEM_SET_MIST, .flingPower = 30, }, @@ -1739,8 +1673,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_Escape, + .battleUsage = EFFECT_ITEM_ESCAPE, .flingPower = 30, }, @@ -1753,8 +1686,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_Escape, + .battleUsage = EFFECT_ITEM_ESCAPE, .flingPower = 30, }, @@ -1767,8 +1699,7 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_Escape, + .battleUsage = EFFECT_ITEM_ESCAPE, .flingPower = 30, }, @@ -1781,11 +1712,12 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, - .battleUsage = ITEM_B_USE_OTHER, - .battleUseFunc = ItemUseInBattle_StatIncrease, // Todo + .battleUsage = EFFECT_ITEM_INCREASE_ALL_STATS, .flingPower = 30, }, +#undef X_ITEM_STAGES + // Treasures [ITEM_BOTTLE_CAP] = @@ -3193,7 +3125,6 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_FormChange_ConsumedOnUse, - .secondaryId = FORM_ITEM_USE, .flingPower = 10, }, @@ -3207,7 +3138,6 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_FormChange_ConsumedOnUse, - .secondaryId = FORM_ITEM_USE, .flingPower = 10, }, @@ -3221,7 +3151,6 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_FormChange_ConsumedOnUse, - .secondaryId = FORM_ITEM_USE, .flingPower = 10, }, @@ -3235,7 +3164,6 @@ const struct Item gItems[] = .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_FormChange_ConsumedOnUse, - .secondaryId = FORM_ITEM_USE, .flingPower = 10, }, @@ -6874,8 +6802,7 @@ const struct Item gItems[] = .pocket = POCKET_BERRIES, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 10, }, @@ -6889,8 +6816,7 @@ const struct Item gItems[] = .pocket = POCKET_BERRIES, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 10, }, @@ -6904,8 +6830,7 @@ const struct Item gItems[] = .pocket = POCKET_BERRIES, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 10, }, @@ -6919,8 +6844,7 @@ const struct Item gItems[] = .pocket = POCKET_BERRIES, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 10, }, @@ -6934,8 +6858,7 @@ const struct Item gItems[] = .pocket = POCKET_BERRIES, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 10, }, @@ -6948,10 +6871,9 @@ const struct Item gItems[] = .holdEffectParam = 10, .description = sLeppaBerryDesc, .pocket = POCKET_BERRIES, - .type = ITEM_USE_PARTY_MENU, + .type = ITEM_USE_PARTY_MENU_MOVES, .fieldUseFunc = ItemUseOutOfBattle_PPRecovery, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_PPRecovery, + .battleUsage = EFFECT_ITEM_RESTORE_PP, .flingPower = 10, }, @@ -6966,8 +6888,7 @@ const struct Item gItems[] = .pocket = POCKET_BERRIES, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_RESTORE_HP, .flingPower = 10, }, @@ -6981,8 +6902,7 @@ const struct Item gItems[] = .pocket = POCKET_BERRIES, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 10, }, @@ -6996,8 +6916,7 @@ const struct Item gItems[] = .pocket = POCKET_BERRIES, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_CURE_STATUS, .flingPower = 10, }, @@ -7017,8 +6936,7 @@ const struct Item gItems[] = .pocket = POCKET_BERRIES, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_Medicine, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_Medicine, + .battleUsage = EFFECT_ITEM_RESTORE_HP, .flingPower = 10, }, @@ -7794,8 +7712,7 @@ const struct Item gItems[] = .pocket = POCKET_BERRIES, .type = ITEM_USE_BAG_MENU, // Type handled by ItemUseOutOfBattle_EnigmaBerry .fieldUseFunc = ItemUseOutOfBattle_EnigmaBerry, - .battleUsage = ITEM_B_USE_MEDICINE, - .battleUseFunc = ItemUseInBattle_EnigmaBerry, + .battleUsage = EFFECT_ITEM_ENIGMA_BERRY_EREADER, .flingPower = 10, }, @@ -7807,6 +7724,7 @@ const struct Item gItems[] = .itemId = ITEM_TM01_FOCUS_PUNCH, .price = 3000, .description = sTM01Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7818,6 +7736,7 @@ const struct Item gItems[] = .itemId = ITEM_TM02_DRAGON_CLAW, .price = 3000, .description = sTM02Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7829,6 +7748,7 @@ const struct Item gItems[] = .itemId = ITEM_TM03_WATER_PULSE, .price = 3000, .description = sTM03Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7840,6 +7760,7 @@ const struct Item gItems[] = .itemId = ITEM_TM04_CALM_MIND, .price = 3000, .description = sTM04Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7851,6 +7772,7 @@ const struct Item gItems[] = .itemId = ITEM_TM05_ROAR, .price = 1000, .description = sTM05Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7862,6 +7784,7 @@ const struct Item gItems[] = .itemId = ITEM_TM06_TOXIC, .price = 3000, .description = sTM06Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7873,6 +7796,7 @@ const struct Item gItems[] = .itemId = ITEM_TM07_HAIL, .price = 3000, .description = sTM07Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7884,6 +7808,7 @@ const struct Item gItems[] = .itemId = ITEM_TM08_BULK_UP, .price = 3000, .description = sTM08Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7895,6 +7820,7 @@ const struct Item gItems[] = .itemId = ITEM_TM09_BULLET_SEED, .price = 3000, .description = sTM09Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7906,6 +7832,7 @@ const struct Item gItems[] = .itemId = ITEM_TM10_HIDDEN_POWER, .price = 3000, .description = sTM10Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7917,6 +7844,7 @@ const struct Item gItems[] = .itemId = ITEM_TM11_SUNNY_DAY, .price = 2000, .description = sTM11Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7928,6 +7856,7 @@ const struct Item gItems[] = .itemId = ITEM_TM12_TAUNT, .price = 3000, .description = sTM12Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7939,6 +7868,7 @@ const struct Item gItems[] = .itemId = ITEM_TM13_ICE_BEAM, .price = 3000, .description = sTM13Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7950,6 +7880,7 @@ const struct Item gItems[] = .itemId = ITEM_TM14_BLIZZARD, .price = 5500, .description = sTM14Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7961,6 +7892,7 @@ const struct Item gItems[] = .itemId = ITEM_TM15_HYPER_BEAM, .price = 7500, .description = sTM15Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7972,6 +7904,7 @@ const struct Item gItems[] = .itemId = ITEM_TM16_LIGHT_SCREEN, .price = 3000, .description = sTM16Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7983,6 +7916,7 @@ const struct Item gItems[] = .itemId = ITEM_TM17_PROTECT, .price = 3000, .description = sTM17Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -7994,6 +7928,7 @@ const struct Item gItems[] = .itemId = ITEM_TM18_RAIN_DANCE, .price = 2000, .description = sTM18Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8005,6 +7940,7 @@ const struct Item gItems[] = .itemId = ITEM_TM19_GIGA_DRAIN, .price = 3000, .description = sTM19Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8016,6 +7952,7 @@ const struct Item gItems[] = .itemId = ITEM_TM20_SAFEGUARD, .price = 3000, .description = sTM20Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8027,6 +7964,7 @@ const struct Item gItems[] = .itemId = ITEM_TM21_FRUSTRATION, .price = 1000, .description = sTM21Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8038,6 +7976,7 @@ const struct Item gItems[] = .itemId = ITEM_TM22_SOLAR_BEAM, .price = 3000, .description = sTM22Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8049,6 +7988,7 @@ const struct Item gItems[] = .itemId = ITEM_TM23_IRON_TAIL, .price = 3000, .description = sTM23Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8060,6 +8000,7 @@ const struct Item gItems[] = .itemId = ITEM_TM24_THUNDERBOLT, .price = 3000, .description = sTM24Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8071,6 +8012,7 @@ const struct Item gItems[] = .itemId = ITEM_TM25_THUNDER, .price = 5500, .description = sTM25Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8082,6 +8024,7 @@ const struct Item gItems[] = .itemId = ITEM_TM26_EARTHQUAKE, .price = 3000, .description = sTM26Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8093,6 +8036,7 @@ const struct Item gItems[] = .itemId = ITEM_TM27_RETURN, .price = 1000, .description = sTM27Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8104,6 +8048,7 @@ const struct Item gItems[] = .itemId = ITEM_TM28_DIG, .price = 2000, .description = sTM28Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8115,6 +8060,7 @@ const struct Item gItems[] = .itemId = ITEM_TM29_PSYCHIC, .price = 2000, .description = sTM29Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8126,6 +8072,7 @@ const struct Item gItems[] = .itemId = ITEM_TM30_SHADOW_BALL, .price = 3000, .description = sTM30Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8137,6 +8084,7 @@ const struct Item gItems[] = .itemId = ITEM_TM31_BRICK_BREAK, .price = 3000, .description = sTM31Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8148,6 +8096,7 @@ const struct Item gItems[] = .itemId = ITEM_TM32_DOUBLE_TEAM, .price = 2000, .description = sTM32Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8159,6 +8108,7 @@ const struct Item gItems[] = .itemId = ITEM_TM33_REFLECT, .price = 3000, .description = sTM33Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8170,6 +8120,7 @@ const struct Item gItems[] = .itemId = ITEM_TM34_SHOCK_WAVE, .price = 3000, .description = sTM34Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8181,6 +8132,7 @@ const struct Item gItems[] = .itemId = ITEM_TM35_FLAMETHROWER, .price = 3000, .description = sTM35Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8192,6 +8144,7 @@ const struct Item gItems[] = .itemId = ITEM_TM36_SLUDGE_BOMB, .price = 1000, .description = sTM36Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8203,6 +8156,7 @@ const struct Item gItems[] = .itemId = ITEM_TM37_SANDSTORM, .price = 2000, .description = sTM37Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8214,6 +8168,7 @@ const struct Item gItems[] = .itemId = ITEM_TM38_FIRE_BLAST, .price = 5500, .description = sTM38Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8225,6 +8180,7 @@ const struct Item gItems[] = .itemId = ITEM_TM39_ROCK_TOMB, .price = 3000, .description = sTM39Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8236,6 +8192,7 @@ const struct Item gItems[] = .itemId = ITEM_TM40_AERIAL_ACE, .price = 3000, .description = sTM40Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8247,6 +8204,7 @@ const struct Item gItems[] = .itemId = ITEM_TM41_TORMENT, .price = 3000, .description = sTM41Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8258,6 +8216,7 @@ const struct Item gItems[] = .itemId = ITEM_TM42_FACADE, .price = 3000, .description = sTM42Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8269,6 +8228,7 @@ const struct Item gItems[] = .itemId = ITEM_TM43_SECRET_POWER, .price = 3000, .description = sTM43Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8280,6 +8240,7 @@ const struct Item gItems[] = .itemId = ITEM_TM44_REST, .price = 3000, .description = sTM44Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8291,6 +8252,7 @@ const struct Item gItems[] = .itemId = ITEM_TM45_ATTRACT, .price = 3000, .description = sTM45Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8302,6 +8264,7 @@ const struct Item gItems[] = .itemId = ITEM_TM46_THIEF, .price = 3000, .description = sTM46Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8313,6 +8276,7 @@ const struct Item gItems[] = .itemId = ITEM_TM47_STEEL_WING, .price = 3000, .description = sTM47Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8324,6 +8288,7 @@ const struct Item gItems[] = .itemId = ITEM_TM48_SKILL_SWAP, .price = 3000, .description = sTM48Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8335,6 +8300,7 @@ const struct Item gItems[] = .itemId = ITEM_TM49_SNATCH, .price = 3000, .description = sTM49Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8346,6 +8312,7 @@ const struct Item gItems[] = .itemId = ITEM_TM50_OVERHEAT, .price = 3000, .description = sTM50Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8357,6 +8324,7 @@ const struct Item gItems[] = .itemId = ITEM_TM51, .price = 3000, .description = sTM51Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8368,6 +8336,7 @@ const struct Item gItems[] = .itemId = ITEM_TM52, .price = 3000, .description = sTM52Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8379,6 +8348,7 @@ const struct Item gItems[] = .itemId = ITEM_TM53, .price = 3000, .description = sTM53Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8390,6 +8360,7 @@ const struct Item gItems[] = .itemId = ITEM_TM54, .price = 3000, .description = sTM54Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8401,6 +8372,7 @@ const struct Item gItems[] = .itemId = ITEM_TM55, .price = 3000, .description = sTM55Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8412,6 +8384,7 @@ const struct Item gItems[] = .itemId = ITEM_TM56, .price = 3000, .description = sTM56Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8423,6 +8396,7 @@ const struct Item gItems[] = .itemId = ITEM_TM57, .price = 3000, .description = sTM57Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8434,6 +8408,7 @@ const struct Item gItems[] = .itemId = ITEM_TM58, .price = 3000, .description = sTM58Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8445,6 +8420,7 @@ const struct Item gItems[] = .itemId = ITEM_TM59, .price = 3000, .description = sTM59Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8456,6 +8432,7 @@ const struct Item gItems[] = .itemId = ITEM_TM60, .price = 3000, .description = sTM60Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8467,6 +8444,7 @@ const struct Item gItems[] = .itemId = ITEM_TM61, .price = 3000, .description = sTM61Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8478,6 +8456,7 @@ const struct Item gItems[] = .itemId = ITEM_TM62, .price = 3000, .description = sTM62Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8489,6 +8468,7 @@ const struct Item gItems[] = .itemId = ITEM_TM63, .price = 3000, .description = sTM63Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8500,6 +8480,7 @@ const struct Item gItems[] = .itemId = ITEM_TM64, .price = 3000, .description = sTM64Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8511,6 +8492,7 @@ const struct Item gItems[] = .itemId = ITEM_TM65, .price = 3000, .description = sTM65Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8522,6 +8504,7 @@ const struct Item gItems[] = .itemId = ITEM_TM66, .price = 3000, .description = sTM66Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8533,6 +8516,7 @@ const struct Item gItems[] = .itemId = ITEM_TM67, .price = 3000, .description = sTM67Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8544,6 +8528,7 @@ const struct Item gItems[] = .itemId = ITEM_TM68, .price = 3000, .description = sTM68Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8555,6 +8540,7 @@ const struct Item gItems[] = .itemId = ITEM_TM69, .price = 3000, .description = sTM69Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8566,6 +8552,7 @@ const struct Item gItems[] = .itemId = ITEM_TM70, .price = 3000, .description = sTM70Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8577,6 +8564,7 @@ const struct Item gItems[] = .itemId = ITEM_TM71, .price = 3000, .description = sTM71Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8588,6 +8576,7 @@ const struct Item gItems[] = .itemId = ITEM_TM72, .price = 3000, .description = sTM72Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8599,6 +8588,7 @@ const struct Item gItems[] = .itemId = ITEM_TM73, .price = 3000, .description = sTM73Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8610,6 +8600,7 @@ const struct Item gItems[] = .itemId = ITEM_TM74, .price = 3000, .description = sTM74Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8621,6 +8612,7 @@ const struct Item gItems[] = .itemId = ITEM_TM75, .price = 3000, .description = sTM75Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8632,6 +8624,7 @@ const struct Item gItems[] = .itemId = ITEM_TM76, .price = 3000, .description = sTM76Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8643,6 +8636,7 @@ const struct Item gItems[] = .itemId = ITEM_TM77, .price = 3000, .description = sTM77Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8654,6 +8648,7 @@ const struct Item gItems[] = .itemId = ITEM_TM78, .price = 3000, .description = sTM78Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8665,6 +8660,7 @@ const struct Item gItems[] = .itemId = ITEM_TM79, .price = 3000, .description = sTM79Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8676,6 +8672,7 @@ const struct Item gItems[] = .itemId = ITEM_TM80, .price = 3000, .description = sTM80Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8687,6 +8684,7 @@ const struct Item gItems[] = .itemId = ITEM_TM81, .price = 3000, .description = sTM81Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8698,6 +8696,7 @@ const struct Item gItems[] = .itemId = ITEM_TM82, .price = 3000, .description = sTM82Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8709,6 +8708,7 @@ const struct Item gItems[] = .itemId = ITEM_TM83, .price = 3000, .description = sTM83Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8720,6 +8720,7 @@ const struct Item gItems[] = .itemId = ITEM_TM84, .price = 3000, .description = sTM84Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8731,6 +8732,7 @@ const struct Item gItems[] = .itemId = ITEM_TM85, .price = 3000, .description = sTM85Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8742,6 +8744,7 @@ const struct Item gItems[] = .itemId = ITEM_TM86, .price = 3000, .description = sTM86Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8753,6 +8756,7 @@ const struct Item gItems[] = .itemId = ITEM_TM87, .price = 3000, .description = sTM87Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8764,6 +8768,7 @@ const struct Item gItems[] = .itemId = ITEM_TM88, .price = 3000, .description = sTM88Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8775,6 +8780,7 @@ const struct Item gItems[] = .itemId = ITEM_TM89, .price = 3000, .description = sTM89Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8786,6 +8792,7 @@ const struct Item gItems[] = .itemId = ITEM_TM90, .price = 3000, .description = sTM90Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8797,6 +8804,7 @@ const struct Item gItems[] = .itemId = ITEM_TM91, .price = 3000, .description = sTM91Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8808,6 +8816,7 @@ const struct Item gItems[] = .itemId = ITEM_TM92, .price = 3000, .description = sTM92Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8819,6 +8828,7 @@ const struct Item gItems[] = .itemId = ITEM_TM93, .price = 3000, .description = sTM93Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8830,6 +8840,7 @@ const struct Item gItems[] = .itemId = ITEM_TM94, .price = 3000, .description = sTM94Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8841,6 +8852,7 @@ const struct Item gItems[] = .itemId = ITEM_TM95, .price = 3000, .description = sTM95Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8852,6 +8864,7 @@ const struct Item gItems[] = .itemId = ITEM_TM96, .price = 3000, .description = sTM96Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8863,6 +8876,7 @@ const struct Item gItems[] = .itemId = ITEM_TM97, .price = 3000, .description = sTM97Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8874,6 +8888,7 @@ const struct Item gItems[] = .itemId = ITEM_TM98, .price = 3000, .description = sTM98Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8885,6 +8900,7 @@ const struct Item gItems[] = .itemId = ITEM_TM99, .price = 3000, .description = sTM99Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -8896,6 +8912,7 @@ const struct Item gItems[] = .itemId = ITEM_TM100, .price = 3000, .description = sTM100Desc, + .importance = I_REUSABLE_TMS, .pocket = POCKET_TM_HM, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_TMHM, @@ -9071,7 +9088,6 @@ const struct Item gItems[] = .pocket = POCKET_KEY_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_FormChange, - .secondaryId = FORM_ITEM_USE, }, [ITEM_REVEAL_GLASS] = @@ -9083,7 +9099,6 @@ const struct Item gItems[] = .pocket = POCKET_KEY_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_FormChange, - .secondaryId = FORM_ITEM_USE, }, [ITEM_DNA_SPLICERS] = @@ -9093,9 +9108,8 @@ const struct Item gItems[] = .price = 0, .description = sDNASplicersDesc, .pocket = POCKET_KEY_ITEMS, - .type = ITEM_USE_PARTY_MENU, - .fieldUseFunc = ItemUseOutOfBattle_FormChange, - .secondaryId = FORM_ITEM_USE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo: ItemUseOutOfBattle_FormChange_Fusion }, [ITEM_ZYGARDE_CUBE] = @@ -9119,7 +9133,6 @@ const struct Item gItems[] = .pocket = POCKET_KEY_ITEMS, .type = ITEM_USE_PARTY_MENU, .fieldUseFunc = ItemUseOutOfBattle_FormChange, - .secondaryId = FORM_ITEM_USE, }, [ITEM_N_SOLARIZER] = @@ -9129,9 +9142,8 @@ const struct Item gItems[] = .price = 0, .description = sNSolarizerDesc, .pocket = POCKET_KEY_ITEMS, - .type = ITEM_USE_PARTY_MENU, - .fieldUseFunc = ItemUseOutOfBattle_FormChange, - .secondaryId = FORM_ITEM_USE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo: ItemUseOutOfBattle_FormChange_Fusion }, [ITEM_N_LUNARIZER] = @@ -9141,9 +9153,8 @@ const struct Item gItems[] = .price = 0, .description = sNLunarizerDesc, .pocket = POCKET_KEY_ITEMS, - .type = ITEM_USE_PARTY_MENU, - .fieldUseFunc = ItemUseOutOfBattle_FormChange, - .secondaryId = FORM_ITEM_USE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo: ItemUseOutOfBattle_FormChange_Fusion }, [ITEM_REINS_OF_UNITY] = @@ -9153,9 +9164,8 @@ const struct Item gItems[] = .price = 0, .description = sReinsOfUnityDesc, .pocket = POCKET_KEY_ITEMS, - .type = ITEM_USE_PARTY_MENU, - .fieldUseFunc = ItemUseOutOfBattle_FormChange, - .secondaryId = FORM_ITEM_USE, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo: ItemUseOutOfBattle_FormChange_Fusion }, // Battle Mechanic Key Items @@ -10283,4 +10293,53 @@ const struct Item gItems[] = .fieldUseFunc = ItemUseOutOfBattle_CannotUse, .flingPower = 60, }, + + [ITEM_BLACK_AUGURITE] = + { + .name = _("BlackAugurite"), + .itemId = ITEM_BLACK_AUGURITE, + .price = 8000, + .description = sBlackAuguriteDesc, + .pocket = POCKET_ITEMS, + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, + .flingPower = 30, + }, + + [ITEM_LINKING_CORD] = + { + .name = _("Linking Cord"), + .itemId = ITEM_LINKING_CORD, + .price = 8000, + .description = sLinkingCordDesc, + .pocket = POCKET_ITEMS, + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, + .flingPower = 30, + }, + + [ITEM_PEAT_BLOCK] = + { + .name = _("Peat Block"), + .itemId = ITEM_PEAT_BLOCK, + .price = 10000, + .description = sPeatBlockDesc, + .pocket = POCKET_ITEMS, + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, + .flingPower = 30, + }, + + [ITEM_BERSERK_GENE] = + { + .name = _("Berserk Gene"), + .itemId = ITEM_BERSERK_GENE, + .price = 20, + .holdEffect = HOLD_EFFECT_BERSERK_GENE, + .description = sBerserkGene, + .pocket = POCKET_ITEMS, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + .flingPower = 10, + }, }; diff --git a/src/data/party_menu.h b/src/data/party_menu.h index 4a06fa135..e7ebf9893 100644 --- a/src/data/party_menu.h +++ b/src/data/party_menu.h @@ -1054,7 +1054,7 @@ static const union AnimCmd sSpriteAnim_StatusFaint[] = ANIMCMD_END }; -static const union AnimCmd sSpriteAnim_Blank[] = +static const union AnimCmd sSpriteAnim_StatusFrostbite[] = { ANIMCMD_FRAME(28, 0), ANIMCMD_END @@ -1069,7 +1069,7 @@ static const union AnimCmd *const sSpriteTemplate_StatusCondition[] = sSpriteAnim_StatusBurn, sSpriteAnim_StatusPokerus, sSpriteAnim_StatusFaint, - sSpriteAnim_Blank + sSpriteAnim_StatusFrostbite }; static const struct CompressedSpriteSheet sSpriteSheet_StatusIcons = diff --git a/src/data/pokemon/evolution.h b/src/data/pokemon/evolution.h index b76e83a73..86ef6dbe5 100644 --- a/src/data/pokemon/evolution.h +++ b/src/data/pokemon/evolution.h @@ -2,22 +2,16 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = { [SPECIES_BULBASAUR] = {{EVO_LEVEL, 16, SPECIES_IVYSAUR}}, [SPECIES_IVYSAUR] = {{EVO_LEVEL, 32, SPECIES_VENUSAUR}}, - [SPECIES_VENUSAUR] = {{EVO_MEGA_EVOLUTION, ITEM_VENUSAURITE, SPECIES_VENUSAUR_MEGA}}, [SPECIES_CHARMANDER] = {{EVO_LEVEL, 16, SPECIES_CHARMELEON}}, [SPECIES_CHARMELEON] = {{EVO_LEVEL, 36, SPECIES_CHARIZARD}}, - [SPECIES_CHARIZARD] = {{EVO_MEGA_EVOLUTION, ITEM_CHARIZARDITE_X, SPECIES_CHARIZARD_MEGA_X}, - {EVO_MEGA_EVOLUTION, ITEM_CHARIZARDITE_Y, SPECIES_CHARIZARD_MEGA_Y}}, [SPECIES_SQUIRTLE] = {{EVO_LEVEL, 16, SPECIES_WARTORTLE}}, [SPECIES_WARTORTLE] = {{EVO_LEVEL, 36, SPECIES_BLASTOISE}}, - [SPECIES_BLASTOISE] = {{EVO_MEGA_EVOLUTION, ITEM_BLASTOISINITE, SPECIES_BLASTOISE_MEGA}}, [SPECIES_CATERPIE] = {{EVO_LEVEL, 7, SPECIES_METAPOD}}, [SPECIES_METAPOD] = {{EVO_LEVEL, 10, SPECIES_BUTTERFREE}}, [SPECIES_WEEDLE] = {{EVO_LEVEL, 7, SPECIES_KAKUNA}}, [SPECIES_KAKUNA] = {{EVO_LEVEL, 10, SPECIES_BEEDRILL}}, - [SPECIES_BEEDRILL] = {{EVO_MEGA_EVOLUTION, ITEM_BEEDRILLITE, SPECIES_BEEDRILL_MEGA}}, [SPECIES_PIDGEY] = {{EVO_LEVEL, 18, SPECIES_PIDGEOTTO}}, [SPECIES_PIDGEOTTO] = {{EVO_LEVEL, 36, SPECIES_PIDGEOT}}, - [SPECIES_PIDGEOT] = {{EVO_MEGA_EVOLUTION, ITEM_PIDGEOTITE, SPECIES_PIDGEOT_MEGA}}, [SPECIES_RATTATA] = {{EVO_LEVEL, 20, SPECIES_RATICATE}}, [SPECIES_SPEAROW] = {{EVO_LEVEL, 20, SPECIES_FEAROW}}, [SPECIES_EKANS] = {{EVO_LEVEL, 22, SPECIES_ARBOK}}, @@ -47,19 +41,20 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = [SPECIES_POLIWHIRL] = {{EVO_ITEM, ITEM_WATER_STONE, SPECIES_POLIWRATH}, {EVO_TRADE_ITEM, ITEM_KINGS_ROCK, SPECIES_POLITOED}}, [SPECIES_ABRA] = {{EVO_LEVEL, 16, SPECIES_KADABRA}}, - [SPECIES_KADABRA] = {{EVO_TRADE, 0, SPECIES_ALAKAZAM}}, - [SPECIES_ALAKAZAM] = {{EVO_MEGA_EVOLUTION, ITEM_ALAKAZITE, SPECIES_ALAKAZAM_MEGA}}, + [SPECIES_KADABRA] = {{EVO_TRADE, 0, SPECIES_ALAKAZAM}, + {EVO_ITEM, ITEM_LINKING_CORD, SPECIES_ALAKAZAM}}, [SPECIES_MACHOP] = {{EVO_LEVEL, 28, SPECIES_MACHOKE}}, - [SPECIES_MACHOKE] = {{EVO_TRADE, 0, SPECIES_MACHAMP}}, + [SPECIES_MACHOKE] = {{EVO_TRADE, 0, SPECIES_MACHAMP}, + {EVO_ITEM, ITEM_LINKING_CORD, SPECIES_MACHAMP}}, [SPECIES_BELLSPROUT] = {{EVO_LEVEL, 21, SPECIES_WEEPINBELL}}, [SPECIES_WEEPINBELL] = {{EVO_ITEM, ITEM_LEAF_STONE, SPECIES_VICTREEBEL}}, [SPECIES_TENTACOOL] = {{EVO_LEVEL, 30, SPECIES_TENTACRUEL}}, [SPECIES_GEODUDE] = {{EVO_LEVEL, 25, SPECIES_GRAVELER}}, - [SPECIES_GRAVELER] = {{EVO_TRADE, 0, SPECIES_GOLEM}}, + [SPECIES_GRAVELER] = {{EVO_TRADE, 0, SPECIES_GOLEM}, + {EVO_ITEM, ITEM_LINKING_CORD, SPECIES_GOLEM}}, [SPECIES_PONYTA] = {{EVO_LEVEL, 40, SPECIES_RAPIDASH}}, [SPECIES_SLOWPOKE] = {{EVO_LEVEL, 37, SPECIES_SLOWBRO}, {EVO_TRADE_ITEM, ITEM_KINGS_ROCK, SPECIES_SLOWKING}}, - [SPECIES_SLOWBRO] = {{EVO_MEGA_EVOLUTION, ITEM_SLOWBRONITE, SPECIES_SLOWBRO_MEGA}}, [SPECIES_MAGNEMITE] = {{EVO_LEVEL, 30, SPECIES_MAGNETON}}, #if P_GEN_4_POKEMON == TRUE [SPECIES_MAGNETON] = {{EVO_MAPSEC, MAPSEC_NEW_MAUVILLE, SPECIES_MAGNEZONE}, @@ -70,8 +65,8 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = [SPECIES_GRIMER] = {{EVO_LEVEL, 38, SPECIES_MUK}}, [SPECIES_SHELLDER] = {{EVO_ITEM, ITEM_WATER_STONE, SPECIES_CLOYSTER}}, [SPECIES_GASTLY] = {{EVO_LEVEL, 25, SPECIES_HAUNTER}}, - [SPECIES_HAUNTER] = {{EVO_TRADE, 0, SPECIES_GENGAR}}, - [SPECIES_GENGAR] = {{EVO_MEGA_EVOLUTION, ITEM_GENGARITE, SPECIES_GENGAR_MEGA}}, + [SPECIES_HAUNTER] = {{EVO_TRADE, 0, SPECIES_GENGAR}, + {EVO_ITEM, ITEM_LINKING_CORD, SPECIES_GENGAR}}, [SPECIES_ONIX] = {{EVO_TRADE_ITEM, ITEM_METAL_COAT, SPECIES_STEELIX}}, [SPECIES_DROWZEE] = {{EVO_LEVEL, 26, SPECIES_HYPNO}}, [SPECIES_KRABBY] = {{EVO_LEVEL, 28, SPECIES_KINGLER}}, @@ -92,19 +87,17 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = #if P_GEN_4_POKEMON == TRUE [SPECIES_TANGELA] = {{EVO_MOVE, MOVE_ANCIENT_POWER, SPECIES_TANGROWTH}}, #endif - [SPECIES_KANGASKHAN] = {{EVO_MEGA_EVOLUTION, ITEM_KANGASKHANITE, SPECIES_KANGASKHAN_MEGA}}, [SPECIES_HORSEA] = {{EVO_LEVEL, 32, SPECIES_SEADRA}}, [SPECIES_SEADRA] = {{EVO_TRADE_ITEM, ITEM_DRAGON_SCALE, SPECIES_KINGDRA}}, [SPECIES_GOLDEEN] = {{EVO_LEVEL, 33, SPECIES_SEAKING}}, [SPECIES_STARYU] = {{EVO_ITEM, ITEM_WATER_STONE, SPECIES_STARMIE}}, - [SPECIES_SCYTHER] = {{EVO_TRADE_ITEM, ITEM_METAL_COAT, SPECIES_SCIZOR}}, + [SPECIES_SCYTHER] = {{EVO_TRADE_ITEM, ITEM_METAL_COAT, SPECIES_SCIZOR}, + {EVO_ITEM, ITEM_BLACK_AUGURITE, SPECIES_KLEAVOR}}, #if P_GEN_4_POKEMON == TRUE [SPECIES_ELECTABUZZ] = {{EVO_TRADE_ITEM, ITEM_ELECTIRIZER, SPECIES_ELECTIVIRE}}, [SPECIES_MAGMAR] = {{EVO_TRADE_ITEM, ITEM_MAGMARIZER, SPECIES_MAGMORTAR}}, #endif - [SPECIES_PINSIR] = {{EVO_MEGA_EVOLUTION, ITEM_PINSIRITE, SPECIES_PINSIR_MEGA}}, [SPECIES_MAGIKARP] = {{EVO_LEVEL, 20, SPECIES_GYARADOS}}, - [SPECIES_GYARADOS] = {{EVO_MEGA_EVOLUTION, ITEM_GYARADOSITE, SPECIES_GYARADOS_MEGA}}, [SPECIES_EEVEE] = {{EVO_ITEM, ITEM_THUNDER_STONE, SPECIES_JOLTEON}, {EVO_ITEM, ITEM_WATER_STONE, SPECIES_VAPOREON}, {EVO_ITEM, ITEM_FIRE_STONE, SPECIES_FLAREON}, @@ -123,11 +116,8 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = [SPECIES_PORYGON] = {{EVO_TRADE_ITEM, ITEM_UPGRADE, SPECIES_PORYGON2}}, [SPECIES_OMANYTE] = {{EVO_LEVEL, 40, SPECIES_OMASTAR}}, [SPECIES_KABUTO] = {{EVO_LEVEL, 40, SPECIES_KABUTOPS}}, - [SPECIES_AERODACTYL] = {{EVO_MEGA_EVOLUTION, ITEM_AERODACTYLITE, SPECIES_AERODACTYL_MEGA}}, [SPECIES_DRATINI] = {{EVO_LEVEL, 30, SPECIES_DRAGONAIR}}, [SPECIES_DRAGONAIR] = {{EVO_LEVEL, 55, SPECIES_DRAGONITE}}, - [SPECIES_MEWTWO] = {{EVO_MEGA_EVOLUTION, ITEM_MEWTWONITE_X, SPECIES_MEWTWO_MEGA_X}, - {EVO_MEGA_EVOLUTION, ITEM_MEWTWONITE_Y, SPECIES_MEWTWO_MEGA_Y}}, [SPECIES_CHIKORITA] = {{EVO_LEVEL, 16, SPECIES_BAYLEEF}}, [SPECIES_BAYLEEF] = {{EVO_LEVEL, 32, SPECIES_MEGANIUM}}, [SPECIES_CYNDAQUIL] = {{EVO_LEVEL, 14, SPECIES_QUILAVA}}, @@ -149,7 +139,6 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = [SPECIES_NATU] = {{EVO_LEVEL, 25, SPECIES_XATU}}, [SPECIES_MAREEP] = {{EVO_LEVEL, 15, SPECIES_FLAAFFY}}, [SPECIES_FLAAFFY] = {{EVO_LEVEL, 30, SPECIES_AMPHAROS}}, - [SPECIES_AMPHAROS] = {{EVO_MEGA_EVOLUTION, ITEM_AMPHAROSITE, SPECIES_AMPHAROS_MEGA}}, [SPECIES_MARILL] = {{EVO_LEVEL, 18, SPECIES_AZUMARILL}}, [SPECIES_HOPPIP] = {{EVO_LEVEL, 18, SPECIES_SKIPLOOM}}, [SPECIES_SKIPLOOM] = {{EVO_LEVEL, 27, SPECIES_JUMPLUFF}}, @@ -167,10 +156,7 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = #if P_GEN_4_POKEMON == TRUE [SPECIES_GLIGAR] = {{EVO_ITEM_HOLD_NIGHT, ITEM_RAZOR_FANG, SPECIES_GLISCOR}}, #endif - [SPECIES_STEELIX] = {{EVO_MEGA_EVOLUTION, ITEM_STEELIXITE, SPECIES_STEELIX_MEGA}}, [SPECIES_SNUBBULL] = {{EVO_LEVEL, 23, SPECIES_GRANBULL}}, - [SPECIES_SCIZOR] = {{EVO_MEGA_EVOLUTION, ITEM_SCIZORITE, SPECIES_SCIZOR_MEGA}}, - [SPECIES_HERACROSS] = {{EVO_MEGA_EVOLUTION, ITEM_HERACRONITE, SPECIES_HERACROSS_MEGA}}, #if P_GEN_4_POKEMON == TRUE [SPECIES_SNEASEL] = {{EVO_ITEM_HOLD_NIGHT, ITEM_RAZOR_CLAW, SPECIES_WEAVILE}}, #endif @@ -182,7 +168,6 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = #endif [SPECIES_REMORAID] = {{EVO_LEVEL, 25, SPECIES_OCTILLERY}}, [SPECIES_HOUNDOUR] = {{EVO_LEVEL, 24, SPECIES_HOUNDOOM}}, - [SPECIES_HOUNDOOM] = {{EVO_MEGA_EVOLUTION, ITEM_HOUNDOOMINITE, SPECIES_HOUNDOOM_MEGA}}, [SPECIES_PHANPY] = {{EVO_LEVEL, 25, SPECIES_DONPHAN}}, #if P_GEN_4_POKEMON == TRUE [SPECIES_PORYGON2] = {{EVO_TRADE_ITEM, ITEM_DUBIOUS_DISC, SPECIES_PORYGON_Z}}, @@ -195,16 +180,12 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = [SPECIES_MAGBY] = {{EVO_LEVEL, 30, SPECIES_MAGMAR}}, [SPECIES_LARVITAR] = {{EVO_LEVEL, 30, SPECIES_PUPITAR}}, [SPECIES_PUPITAR] = {{EVO_LEVEL, 55, SPECIES_TYRANITAR}}, - [SPECIES_TYRANITAR] = {{EVO_MEGA_EVOLUTION, ITEM_TYRANITARITE, SPECIES_TYRANITAR_MEGA}}, [SPECIES_TREECKO] = {{EVO_LEVEL, 16, SPECIES_GROVYLE}}, [SPECIES_GROVYLE] = {{EVO_LEVEL, 36, SPECIES_SCEPTILE}}, - [SPECIES_SCEPTILE] = {{EVO_MEGA_EVOLUTION, ITEM_SCEPTILITE, SPECIES_SCEPTILE_MEGA}}, [SPECIES_TORCHIC] = {{EVO_LEVEL, 16, SPECIES_COMBUSKEN}}, [SPECIES_COMBUSKEN] = {{EVO_LEVEL, 36, SPECIES_BLAZIKEN}}, - [SPECIES_BLAZIKEN] = {{EVO_MEGA_EVOLUTION, ITEM_BLAZIKENITE, SPECIES_BLAZIKEN_MEGA}}, [SPECIES_MUDKIP] = {{EVO_LEVEL, 16, SPECIES_MARSHTOMP}}, [SPECIES_MARSHTOMP] = {{EVO_LEVEL, 36, SPECIES_SWAMPERT}}, - [SPECIES_SWAMPERT] = {{EVO_MEGA_EVOLUTION, ITEM_SWAMPERTITE, SPECIES_SWAMPERT_MEGA}}, [SPECIES_POOCHYENA] = {{EVO_LEVEL, 18, SPECIES_MIGHTYENA}}, [SPECIES_ZIGZAGOON] = {{EVO_LEVEL, 20, SPECIES_LINOONE}}, [SPECIES_WURMPLE] = {{EVO_LEVEL_SILCOON, 7, SPECIES_SILCOON}, @@ -227,20 +208,16 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = #if P_GEN_4_POKEMON == TRUE [SPECIES_NOSEPASS] = {{EVO_MAPSEC, MAPSEC_NEW_MAUVILLE, SPECIES_PROBOPASS}}, #endif - [SPECIES_SABLEYE] = {{EVO_MEGA_EVOLUTION, ITEM_SABLENITE, SPECIES_SABLEYE_MEGA}}, [SPECIES_BARBOACH] = {{EVO_LEVEL, 30, SPECIES_WHISCASH}}, [SPECIES_CORPHISH] = {{EVO_LEVEL, 30, SPECIES_CRAWDAUNT}}, [SPECIES_FEEBAS] = {{EVO_BEAUTY, 170, SPECIES_MILOTIC}, {EVO_TRADE_ITEM, ITEM_PRISM_SCALE, SPECIES_MILOTIC}}, [SPECIES_CARVANHA] = {{EVO_LEVEL, 30, SPECIES_SHARPEDO}}, - [SPECIES_SHARPEDO] = {{EVO_MEGA_EVOLUTION, ITEM_SHARPEDONITE, SPECIES_SHARPEDO_MEGA}}, [SPECIES_TRAPINCH] = {{EVO_LEVEL, 35, SPECIES_VIBRAVA}}, [SPECIES_VIBRAVA] = {{EVO_LEVEL, 45, SPECIES_FLYGON}}, [SPECIES_MAKUHITA] = {{EVO_LEVEL, 24, SPECIES_HARIYAMA}}, [SPECIES_ELECTRIKE] = {{EVO_LEVEL, 26, SPECIES_MANECTRIC}}, - [SPECIES_MANECTRIC] = {{EVO_MEGA_EVOLUTION, ITEM_MANECTITE, SPECIES_MANECTRIC_MEGA}}, [SPECIES_NUMEL] = {{EVO_LEVEL, 33, SPECIES_CAMERUPT}}, - [SPECIES_CAMERUPT] = {{EVO_MEGA_EVOLUTION, ITEM_CAMERUPTITE, SPECIES_CAMERUPT_MEGA}}, [SPECIES_SPHEAL] = {{EVO_LEVEL, 32, SPECIES_SEALEO}}, [SPECIES_SEALEO] = {{EVO_LEVEL, 44, SPECIES_WALREIN}}, [SPECIES_CACNEA] = {{EVO_LEVEL, 32, SPECIES_CACTURNE}}, @@ -249,14 +226,10 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = {EVO_ITEM_FEMALE, ITEM_DAWN_STONE, SPECIES_FROSLASS} #endif }, - [SPECIES_GLALIE] = {{EVO_MEGA_EVOLUTION, ITEM_GLALITITE, SPECIES_GLALIE_MEGA}}, [SPECIES_AZURILL] = {{EVO_FRIENDSHIP, 0, SPECIES_MARILL}}, [SPECIES_SPOINK] = {{EVO_LEVEL, 32, SPECIES_GRUMPIG}}, - [SPECIES_MAWILE] = {{EVO_MEGA_EVOLUTION, ITEM_MAWILITE, SPECIES_MAWILE_MEGA}}, [SPECIES_MEDITITE] = {{EVO_LEVEL, 37, SPECIES_MEDICHAM}}, - [SPECIES_MEDICHAM] = {{EVO_MEGA_EVOLUTION, ITEM_MEDICHAMITE, SPECIES_MEDICHAM_MEGA}}, [SPECIES_SWABLU] = {{EVO_LEVEL, 35, SPECIES_ALTARIA}}, - [SPECIES_ALTARIA] = {{EVO_MEGA_EVOLUTION, ITEM_ALTARIANITE, SPECIES_ALTARIA_MEGA}}, [SPECIES_WYNAUT] = {{EVO_LEVEL, 15, SPECIES_WOBBUFFET}}, [SPECIES_DUSKULL] = {{EVO_LEVEL, 37, SPECIES_DUSCLOPS}}, #if P_GEN_4_POKEMON == TRUE @@ -270,12 +243,9 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = [SPECIES_LOUDRED] = {{EVO_LEVEL, 40, SPECIES_EXPLOUD}}, [SPECIES_CLAMPERL] = {{EVO_TRADE_ITEM, ITEM_DEEP_SEA_TOOTH, SPECIES_HUNTAIL}, {EVO_TRADE_ITEM, ITEM_DEEP_SEA_SCALE, SPECIES_GOREBYSS}}, - [SPECIES_ABSOL] = {{EVO_MEGA_EVOLUTION, ITEM_ABSOLITE, SPECIES_ABSOL_MEGA}}, [SPECIES_SHUPPET] = {{EVO_LEVEL, 37, SPECIES_BANETTE}}, - [SPECIES_BANETTE] = {{EVO_MEGA_EVOLUTION, ITEM_BANETTITE, SPECIES_BANETTE_MEGA}}, [SPECIES_ARON] = {{EVO_LEVEL, 32, SPECIES_LAIRON}}, [SPECIES_LAIRON] = {{EVO_LEVEL, 42, SPECIES_AGGRON}}, - [SPECIES_AGGRON] = {{EVO_MEGA_EVOLUTION, ITEM_AGGRONITE, SPECIES_AGGRON_MEGA}}, [SPECIES_LILEEP] = {{EVO_LEVEL, 40, SPECIES_CRADILY}}, [SPECIES_ANORITH] = {{EVO_LEVEL, 40, SPECIES_ARMALDO}}, [SPECIES_RALTS] = {{EVO_LEVEL, 20, SPECIES_KIRLIA}}, @@ -284,19 +254,10 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = {EVO_ITEM_MALE, ITEM_DAWN_STONE, SPECIES_GALLADE} #endif }, - [SPECIES_GARDEVOIR] = {{EVO_MEGA_EVOLUTION, ITEM_GARDEVOIRITE, SPECIES_GARDEVOIR_MEGA}}, [SPECIES_BAGON] = {{EVO_LEVEL, 30, SPECIES_SHELGON}}, [SPECIES_SHELGON] = {{EVO_LEVEL, 50, SPECIES_SALAMENCE}}, - [SPECIES_SALAMENCE] = {{EVO_MEGA_EVOLUTION, ITEM_SALAMENCITE, SPECIES_SALAMENCE_MEGA}}, [SPECIES_BELDUM] = {{EVO_LEVEL, 20, SPECIES_METANG}}, [SPECIES_METANG] = {{EVO_LEVEL, 45, SPECIES_METAGROSS}}, - [SPECIES_METAGROSS] = {{EVO_MEGA_EVOLUTION, ITEM_METAGROSSITE, SPECIES_METAGROSS_MEGA}}, - [SPECIES_LATIAS] = {{EVO_MEGA_EVOLUTION, ITEM_LATIASITE, SPECIES_LATIAS_MEGA}}, - [SPECIES_LATIOS] = {{EVO_MEGA_EVOLUTION, ITEM_LATIOSITE, SPECIES_LATIOS_MEGA}}, - [SPECIES_KYOGRE] = {{EVO_PRIMAL_REVERSION, ITEM_BLUE_ORB, SPECIES_KYOGRE_PRIMAL}}, - [SPECIES_GROUDON] = {{EVO_PRIMAL_REVERSION, ITEM_RED_ORB, SPECIES_GROUDON_PRIMAL}}, - [SPECIES_RAYQUAZA] = {{EVO_MOVE_MEGA_EVOLUTION, MOVE_DRAGON_ASCENT, SPECIES_RAYQUAZA_MEGA}}, - #if P_GEN_4_POKEMON == TRUE // Gens 4-7 [SPECIES_TURTWIG] = {{EVO_LEVEL, 18, SPECIES_GROTLE}}, @@ -311,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}, @@ -322,7 +283,6 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = [SPECIES_SHELLOS] = {{EVO_LEVEL, 30, SPECIES_GASTRODON}}, [SPECIES_DRIFLOON] = {{EVO_LEVEL, 28, SPECIES_DRIFBLIM}}, [SPECIES_BUNEARY] = {{EVO_FRIENDSHIP, 0, SPECIES_LOPUNNY}}, - [SPECIES_LOPUNNY] = {{EVO_MEGA_EVOLUTION, ITEM_LOPUNNITE, SPECIES_LOPUNNY_MEGA}}, [SPECIES_GLAMEOW] = {{EVO_LEVEL, 38, SPECIES_PURUGLY}}, [SPECIES_CHINGLING] = {{EVO_FRIENDSHIP_NIGHT, 0, SPECIES_CHIMECHO}}, [SPECIES_STUNKY] = {{EVO_LEVEL, 34, SPECIES_SKUNTANK}}, @@ -332,18 +292,14 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = [SPECIES_HAPPINY] = {{EVO_ITEM_HOLD_DAY, ITEM_OVAL_STONE, SPECIES_CHANSEY}}, [SPECIES_GIBLE] = {{EVO_LEVEL, 24, SPECIES_GABITE}}, [SPECIES_GABITE] = {{EVO_LEVEL, 48, SPECIES_GARCHOMP}}, - [SPECIES_GARCHOMP] = {{EVO_MEGA_EVOLUTION, ITEM_GARCHOMPITE, SPECIES_GARCHOMP_MEGA}}, [SPECIES_MUNCHLAX] = {{EVO_FRIENDSHIP, 0, SPECIES_SNORLAX}}, [SPECIES_RIOLU] = {{EVO_FRIENDSHIP_DAY, 0, SPECIES_LUCARIO}}, - [SPECIES_LUCARIO] = {{EVO_MEGA_EVOLUTION, ITEM_LUCARIONITE, SPECIES_LUCARIO_MEGA}}, [SPECIES_HIPPOPOTAS] = {{EVO_LEVEL, 34, SPECIES_HIPPOWDON}}, [SPECIES_SKORUPI] = {{EVO_LEVEL, 40, SPECIES_DRAPION}}, [SPECIES_CROAGUNK] = {{EVO_LEVEL, 37, SPECIES_TOXICROAK}}, [SPECIES_FINNEON] = {{EVO_LEVEL, 31, SPECIES_LUMINEON}}, [SPECIES_MANTYKE] = {{EVO_SPECIFIC_MON_IN_PARTY, SPECIES_REMORAID, SPECIES_MANTINE}}, [SPECIES_SNOVER] = {{EVO_LEVEL, 40, SPECIES_ABOMASNOW}}, - [SPECIES_ABOMASNOW] = {{EVO_MEGA_EVOLUTION, ITEM_ABOMASITE, SPECIES_ABOMASNOW_MEGA}}, - [SPECIES_GALLADE] = {{EVO_MEGA_EVOLUTION, ITEM_GALLADITE, SPECIES_GALLADE_MEGA}}, #endif #if P_GEN_5_POKEMON == TRUE [SPECIES_SNIVY] = {{EVO_LEVEL, 17, SPECIES_SERVINE}}, @@ -364,12 +320,13 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = [SPECIES_TRANQUILL] = {{EVO_LEVEL, 32, SPECIES_UNFEZANT}}, [SPECIES_BLITZLE] = {{EVO_LEVEL, 27, SPECIES_ZEBSTRIKA}}, [SPECIES_ROGGENROLA] = {{EVO_LEVEL, 25, SPECIES_BOLDORE}}, - [SPECIES_BOLDORE] = {{EVO_TRADE, 0, SPECIES_GIGALITH}}, + [SPECIES_BOLDORE] = {{EVO_TRADE, 0, SPECIES_GIGALITH}, + {EVO_ITEM, ITEM_LINKING_CORD, SPECIES_GIGALITH}}, [SPECIES_WOOBAT] = {{EVO_FRIENDSHIP, 0, SPECIES_SWOOBAT}}, [SPECIES_DRILBUR] = {{EVO_LEVEL, 31, SPECIES_EXCADRILL}}, - [SPECIES_AUDINO] = {{EVO_MEGA_EVOLUTION, ITEM_AUDINITE, SPECIES_AUDINO_MEGA}}, [SPECIES_TIMBURR] = {{EVO_LEVEL, 25, SPECIES_GURDURR}}, - [SPECIES_GURDURR] = {{EVO_TRADE, 0, SPECIES_CONKELDURR}}, + [SPECIES_GURDURR] = {{EVO_TRADE, 0, SPECIES_CONKELDURR}, + {EVO_ITEM, ITEM_LINKING_CORD, SPECIES_CONKELDURR}}, [SPECIES_TYMPOLE] = {{EVO_LEVEL, 25, SPECIES_PALPITOAD}}, [SPECIES_PALPITOAD] = {{EVO_LEVEL, 36, SPECIES_SEISMITOAD}}, [SPECIES_SEWADDLE] = {{EVO_LEVEL, 20, SPECIES_SWADLOON}}, @@ -454,11 +411,12 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = [SPECIES_AMAURA] = {{EVO_LEVEL_NIGHT, 39, SPECIES_AURORUS}}, [SPECIES_GOOMY] = {{EVO_LEVEL, 40, SPECIES_SLIGGOO}}, [SPECIES_SLIGGOO] = {{EVO_LEVEL_RAIN, 50, SPECIES_GOODRA}}, - [SPECIES_PHANTUMP] = {{EVO_TRADE, 0, SPECIES_TREVENANT}}, - [SPECIES_PUMPKABOO] = {{EVO_TRADE, 0, SPECIES_GOURGEIST}}, + [SPECIES_PHANTUMP] = {{EVO_TRADE, 0, SPECIES_TREVENANT}, + {EVO_ITEM, ITEM_LINKING_CORD, SPECIES_TREVENANT}}, + [SPECIES_PUMPKABOO] = {{EVO_TRADE, 0, SPECIES_GOURGEIST}, + {EVO_ITEM, ITEM_LINKING_CORD, SPECIES_GOURGEIST}}, [SPECIES_BERGMITE] = {{EVO_LEVEL, 37, SPECIES_AVALUGG}}, [SPECIES_NOIBAT] = {{EVO_LEVEL, 48, SPECIES_NOIVERN}}, - [SPECIES_DIANCIE] = {{EVO_MEGA_EVOLUTION, ITEM_DIANCITE, SPECIES_DIANCIE_MEGA}}, #endif #if P_GEN_7_POKEMON == TRUE [SPECIES_ROWLET] = {{EVO_LEVEL, 17, SPECIES_DARTRIX}}, @@ -552,7 +510,8 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = [SPECIES_DIGLETT_ALOLAN] = {{EVO_LEVEL, 26, SPECIES_DUGTRIO_ALOLAN}}, [SPECIES_MEOWTH_ALOLAN] = {{EVO_FRIENDSHIP, 28, SPECIES_PERSIAN_ALOLAN}}, [SPECIES_GEODUDE_ALOLAN] = {{EVO_LEVEL, 25, SPECIES_GRAVELER_ALOLAN}}, - [SPECIES_GRAVELER_ALOLAN] = {{EVO_TRADE, 0, SPECIES_GOLEM_ALOLAN}}, + [SPECIES_GRAVELER_ALOLAN] = {{EVO_TRADE, 0, SPECIES_GOLEM_ALOLAN}, + {EVO_ITEM, ITEM_LINKING_CORD, SPECIES_GOLEM_ALOLAN}}, [SPECIES_GRIMER_ALOLAN] = {{EVO_LEVEL, 38, SPECIES_MUK_ALOLAN}}, #if P_GEN_8_POKEMON == TRUE [SPECIES_MEOWTH_GALARIAN] = {{EVO_LEVEL, 28, SPECIES_PERRSERKER}}, @@ -593,14 +552,18 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] = [SPECIES_FLOETTE_ORANGE_FLOWER] = {{EVO_ITEM, ITEM_SHINY_STONE, SPECIES_FLORGES_ORANGE_FLOWER}}, [SPECIES_FLOETTE_BLUE_FLOWER] = {{EVO_ITEM, ITEM_SHINY_STONE, SPECIES_FLORGES_BLUE_FLOWER}}, [SPECIES_FLOETTE_WHITE_FLOWER] = {{EVO_ITEM, ITEM_SHINY_STONE, SPECIES_FLORGES_WHITE_FLOWER}}, - [SPECIES_PUMPKABOO_SMALL] = {{EVO_TRADE, 0, SPECIES_GOURGEIST_SMALL}}, - [SPECIES_PUMPKABOO_LARGE] = {{EVO_TRADE, 0, SPECIES_GOURGEIST_LARGE}}, - [SPECIES_PUMPKABOO_SUPER] = {{EVO_TRADE, 0, SPECIES_GOURGEIST_SUPER}}, + [SPECIES_PUMPKABOO_SMALL] = {{EVO_TRADE, 0, SPECIES_GOURGEIST_SMALL}, + {EVO_ITEM, ITEM_LINKING_CORD, SPECIES_GOURGEIST_SMALL}}, + [SPECIES_PUMPKABOO_LARGE] = {{EVO_TRADE, 0, SPECIES_GOURGEIST_LARGE}, + {EVO_ITEM, ITEM_LINKING_CORD, SPECIES_GOURGEIST_LARGE}}, + [SPECIES_PUMPKABOO_SUPER] = {{EVO_TRADE, 0, SPECIES_GOURGEIST_SUPER}, + {EVO_ITEM, ITEM_LINKING_CORD, SPECIES_GOURGEIST_SUPER}}, #endif #if P_GEN_7_POKEMON == TRUE [SPECIES_ROCKRUFF_OWN_TEMPO] = {{EVO_LEVEL_DUSK, 25, SPECIES_LYCANROC_DUSK}}, #endif #if P_GEN_8_POKEMON == TRUE [SPECIES_SINISTEA_ANTIQUE] = {{EVO_ITEM, ITEM_CHIPPED_POT, SPECIES_POLTEAGEIST_ANTIQUE}}, + [SPECIES_URSARING] = {{EVO_ITEM_NIGHT, ITEM_PEAT_BLOCK, SPECIES_URSALUNA}}, #endif }; diff --git a/src/data/pokemon/form_change_table_pointers.h b/src/data/pokemon/form_change_table_pointers.h index 62afeb2e0..daeaa9cbb 100644 --- a/src/data/pokemon/form_change_table_pointers.h +++ b/src/data/pokemon/form_change_table_pointers.h @@ -1,6 +1,107 @@ const struct FormChange *const gFormChangeTablePointers[NUM_SPECIES] = { + [SPECIES_VENUSAUR] = sVenusaurFormChangeTable, + [SPECIES_VENUSAUR_MEGA] = sVenusaurFormChangeTable, + [SPECIES_CHARIZARD] = sCharizardFormChangeTable, + [SPECIES_CHARIZARD_MEGA_X] = sCharizardFormChangeTable, + [SPECIES_CHARIZARD_MEGA_Y] = sCharizardFormChangeTable, + [SPECIES_BLASTOISE] = sBlastoiseFormChangeTable, + [SPECIES_BLASTOISE_MEGA] = sBlastoiseFormChangeTable, + [SPECIES_BEEDRILL] = sBeedrillFormChangeTable, + [SPECIES_BEEDRILL_MEGA] = sBeedrillFormChangeTable, + [SPECIES_PIDGEOT] = sPidgeotFormChangeTable, + [SPECIES_PIDGEOT_MEGA] = sPidgeotFormChangeTable, + [SPECIES_ALAKAZAM] = sAlakazamFormChangeTable, + [SPECIES_ALAKAZAM_MEGA] = sAlakazamFormChangeTable, + [SPECIES_SLOWBRO] = sSlowbroFormChangeTable, + [SPECIES_SLOWBRO_MEGA] = sSlowbroFormChangeTable, + [SPECIES_GENGAR] = sGengarFormChangeTable, + [SPECIES_GENGAR_MEGA] = sGengarFormChangeTable, + [SPECIES_KANGASKHAN] = sKangaskhanFormChangeTable, + [SPECIES_KANGASKHAN_MEGA] = sKangaskhanFormChangeTable, + [SPECIES_PINSIR] = sPinsirFormChangeTable, + [SPECIES_PINSIR_MEGA] = sPinsirFormChangeTable, + [SPECIES_GYARADOS] = sGyaradosFormChangeTable, + [SPECIES_GYARADOS_MEGA] = sGyaradosFormChangeTable, + [SPECIES_AERODACTYL] = sAerodactylFormChangeTable, + [SPECIES_AERODACTYL_MEGA] = sAerodactylFormChangeTable, + [SPECIES_MEWTWO] = sMewtwoFormChangeTable, + [SPECIES_MEWTWO_MEGA_X] = sMewtwoFormChangeTable, + [SPECIES_MEWTWO_MEGA_Y] = sMewtwoFormChangeTable, + [SPECIES_AMPHAROS] = sAmpharosFormChangeTable, + [SPECIES_AMPHAROS_MEGA] = sAmpharosFormChangeTable, + [SPECIES_STEELIX] = sSteelixFormChangeTable, + [SPECIES_STEELIX_MEGA] = sSteelixFormChangeTable, + [SPECIES_SCIZOR] = sScizorFormChangeTable, + [SPECIES_SCIZOR_MEGA] = sScizorFormChangeTable, + [SPECIES_HERACROSS] = sHeracrossFormChangeTable, + [SPECIES_HERACROSS_MEGA] = sHeracrossFormChangeTable, + [SPECIES_HOUNDOOM] = sHoundoomFormChangeTable, + [SPECIES_HOUNDOOM_MEGA] = sHoundoomFormChangeTable, + [SPECIES_TYRANITAR] = sTyranitarFormChangeTable, + [SPECIES_TYRANITAR_MEGA] = sTyranitarFormChangeTable, + [SPECIES_SCEPTILE] = sSceptileFormChangeTable, + [SPECIES_SCEPTILE_MEGA] = sSceptileFormChangeTable, + [SPECIES_BLAZIKEN] = sBlazikenFormChangeTable, + [SPECIES_BLAZIKEN_MEGA] = sBlazikenFormChangeTable, + [SPECIES_SWAMPERT] = sSwampertFormChangeTable, + [SPECIES_SWAMPERT_MEGA] = sSwampertFormChangeTable, + [SPECIES_SABLEYE] = sSableyeFormChangeTable, + [SPECIES_SABLEYE_MEGA] = sSableyeFormChangeTable, + [SPECIES_SHARPEDO] = sSharpedoFormChangeTable, + [SPECIES_SHARPEDO_MEGA] = sSharpedoFormChangeTable, + [SPECIES_MANECTRIC] = sManectricFormChangeTable, + [SPECIES_MANECTRIC_MEGA] = sManectricFormChangeTable, + [SPECIES_CAMERUPT] = sCameruptFormChangeTable, + [SPECIES_CAMERUPT_MEGA] = sCameruptFormChangeTable, + [SPECIES_GLALIE] = sGlalieFormChangeTable, + [SPECIES_GLALIE_MEGA] = sGlalieFormChangeTable, + [SPECIES_MAWILE] = sMawileFormChangeTable, + [SPECIES_MAWILE_MEGA] = sMawileFormChangeTable, + [SPECIES_MEDICHAM] = sMedichamFormChangeTable, + [SPECIES_MEDICHAM_MEGA] = sMedichamFormChangeTable, + [SPECIES_ALTARIA] = sAltariaFormChangeTable, + [SPECIES_ALTARIA_MEGA] = sAltariaFormChangeTable, + [SPECIES_ABSOL] = sAbsolFormChangeTable, + [SPECIES_ABSOL_MEGA] = sAbsolFormChangeTable, + [SPECIES_CASTFORM] = sCastformFormChangeTable, + [SPECIES_CASTFORM_SUNNY] = sCastformFormChangeTable, + [SPECIES_CASTFORM_RAINY] = sCastformFormChangeTable, + [SPECIES_CASTFORM_SNOWY] = sCastformFormChangeTable, + [SPECIES_BANETTE] = sBanetteFormChangeTable, + [SPECIES_BANETTE_MEGA] = sBanetteFormChangeTable, + [SPECIES_AGGRON] = sAggronFormChangeTable, + [SPECIES_AGGRON_MEGA] = sAggronFormChangeTable, + [SPECIES_GARDEVOIR] = sGardevoirFormChangeTable, + [SPECIES_GARDEVOIR_MEGA] = sGardevoirFormChangeTable, + [SPECIES_SALAMENCE] = sSalamenceFormChangeTable, + [SPECIES_SALAMENCE_MEGA] = sSalamenceFormChangeTable, + [SPECIES_METAGROSS] = sMetagrossFormChangeTable, + [SPECIES_METAGROSS_MEGA] = sMetagrossFormChangeTable, + [SPECIES_LATIAS] = sLatiasFormChangeTable, + [SPECIES_LATIAS_MEGA] = sLatiasFormChangeTable, + [SPECIES_LATIOS] = sLatiosFormChangeTable, + [SPECIES_LATIOS_MEGA] = sLatiosFormChangeTable, + [SPECIES_KYOGRE] = sKyogreFormChangeTable, + [SPECIES_KYOGRE_PRIMAL] = sKyogreFormChangeTable, + [SPECIES_GROUDON] = sGroudonFormChangeTable, + [SPECIES_GROUDON_PRIMAL] = sGroudonFormChangeTable, + [SPECIES_RAYQUAZA] = sRayquazaFormChangeTable, + [SPECIES_RAYQUAZA_MEGA] = sRayquazaFormChangeTable, #if P_GEN_4_POKEMON == TRUE + [SPECIES_BURMY] = sBurmyFormChangeTable, + [SPECIES_BURMY_SANDY_CLOAK] = sBurmyFormChangeTable, + [SPECIES_BURMY_TRASH_CLOAK] = sBurmyFormChangeTable, + [SPECIES_LOPUNNY] = sLopunnyFormChangeTable, + [SPECIES_LOPUNNY_MEGA] = sLopunnyFormChangeTable, + [SPECIES_GARCHOMP] = sGarchompFormChangeTable, + [SPECIES_GARCHOMP_MEGA] = sGarchompFormChangeTable, + [SPECIES_LUCARIO] = sLucarioFormChangeTable, + [SPECIES_LUCARIO_MEGA] = sLucarioFormChangeTable, + [SPECIES_ABOMASNOW] = sAbomasnowFormChangeTable, + [SPECIES_ABOMASNOW_MEGA] = sAbomasnowFormChangeTable, + [SPECIES_GALLADE] = sGalladeFormChangeTable, + [SPECIES_GALLADE_MEGA] = sGalladeFormChangeTable, [SPECIES_DIALGA] = sDialgaFormChangeTable, [SPECIES_DIALGA_ORIGIN] = sDialgaFormChangeTable, [SPECIES_PALKIA] = sPalkiaFormChangeTable, @@ -29,6 +130,12 @@ const struct FormChange *const gFormChangeTablePointers[NUM_SPECIES] = [SPECIES_ARCEUS_FAIRY] = sArceusFormChangeTable, #endif #if P_GEN_5_POKEMON == TRUE + [SPECIES_AUDINO] = sAudinoFormChangeTable, + [SPECIES_AUDINO_MEGA] = sAudinoFormChangeTable, + [SPECIES_DARMANITAN] = sDarmanitanFormChangeTable, + [SPECIES_DARMANITAN_ZEN_MODE] = sDarmanitanFormChangeTable, + [SPECIES_DARMANITAN_GALARIAN] = sDarmanitanGalarianFormChangeTable, + [SPECIES_DARMANITAN_ZEN_MODE_GALARIAN] = sDarmanitanGalarianFormChangeTable, [SPECIES_TORNADUS] = sTornadusFormChangeTable, [SPECIES_TORNADUS_THERIAN] = sTornadusFormChangeTable, [SPECIES_THUNDURUS] = sThundurusFormChangeTable, @@ -37,6 +144,8 @@ const struct FormChange *const gFormChangeTablePointers[NUM_SPECIES] = [SPECIES_LANDORUS_THERIAN] = sLandorusFormChangeTable, [SPECIES_KELDEO] = sKeldeoFormChangeTable, [SPECIES_KELDEO_RESOLUTE] = sKeldeoFormChangeTable, + [SPECIES_MELOETTA] = sMeloettaFormChangeTable, + [SPECIES_MELOETTA_PIROUETTE] = sMeloettaFormChangeTable, [SPECIES_GENESECT] = sGenesectFormChangeTable, [SPECIES_GENESECT_DOUSE_DRIVE] = sGenesectFormChangeTable, [SPECIES_GENESECT_SHOCK_DRIVE] = sGenesectFormChangeTable, @@ -44,8 +153,17 @@ const struct FormChange *const gFormChangeTablePointers[NUM_SPECIES] = [SPECIES_GENESECT_CHILL_DRIVE] = sGenesectFormChangeTable, #endif #if P_GEN_6_POKEMON == TRUE + [SPECIES_GRENINJA_BATTLE_BOND] = sGreninjaBattleBondFormChangeTable, + [SPECIES_GRENINJA_ASH] = sGreninjaBattleBondFormChangeTable, + [SPECIES_AEGISLASH] = sAegislashFormChangeTable, + [SPECIES_AEGISLASH_BLADE] = sAegislashFormChangeTable, [SPECIES_XERNEAS] = sXerneasFormChangeTable, [SPECIES_XERNEAS_ACTIVE] = sXerneasFormChangeTable, + [SPECIES_ZYGARDE_10_POWER_CONSTRUCT] = sZygardePowerConstructFormChangeTable, + [SPECIES_ZYGARDE_50_POWER_CONSTRUCT] = sZygardePowerConstructFormChangeTable, + [SPECIES_ZYGARDE_COMPLETE] = sZygardePowerConstructFormChangeTable, + [SPECIES_DIANCIE] = sDiancieFormChangeTable, + [SPECIES_DIANCIE_MEGA] = sDiancieFormChangeTable, [SPECIES_HOOPA] = sHoopaFormChangeTable, [SPECIES_HOOPA_UNBOUND] = sHoopaFormChangeTable, #endif @@ -54,6 +172,8 @@ const struct FormChange *const gFormChangeTablePointers[NUM_SPECIES] = [SPECIES_ORICORIO_POM_POM] = sOricorioFormChangeTable, [SPECIES_ORICORIO_PAU] = sOricorioFormChangeTable, [SPECIES_ORICORIO_SENSU] = sOricorioFormChangeTable, + [SPECIES_WISHIWASHI] = sWishiwashiFormChangeTable, + [SPECIES_WISHIWASHI_SCHOOL] = sWishiwashiFormChangeTable, [SPECIES_SILVALLY] = sSilvallyFormChangeTable, [SPECIES_SILVALLY_BUG] = sSilvallyFormChangeTable, [SPECIES_SILVALLY_DARK] = sSilvallyFormChangeTable, @@ -72,8 +192,31 @@ const struct FormChange *const gFormChangeTablePointers[NUM_SPECIES] = [SPECIES_SILVALLY_ROCK] = sSilvallyFormChangeTable, [SPECIES_SILVALLY_STEEL] = sSilvallyFormChangeTable, [SPECIES_SILVALLY_WATER] = sSilvallyFormChangeTable, + [SPECIES_MIMIKYU] = sMimikyuFormChangeTable, + [SPECIES_MIMIKYU_BUSTED] = sMimikyuFormChangeTable, + [SPECIES_MINIOR] = sMiniorRedFormChangeTable, + [SPECIES_MINIOR_CORE_RED] = sMiniorRedFormChangeTable, + [SPECIES_MINIOR_METEOR_BLUE] = sMiniorBlueFormChangeTable, + [SPECIES_MINIOR_CORE_BLUE] = sMiniorBlueFormChangeTable, + [SPECIES_MINIOR_METEOR_GREEN] = sMiniorGreenFormChangeTable, + [SPECIES_MINIOR_CORE_GREEN] = sMiniorGreenFormChangeTable, + [SPECIES_MINIOR_METEOR_INDIGO] = sMiniorIndigoFormChangeTable, + [SPECIES_MINIOR_CORE_INDIGO] = sMiniorIndigoFormChangeTable, + [SPECIES_MINIOR_METEOR_ORANGE] = sMiniorOrangeFormChangeTable, + [SPECIES_MINIOR_CORE_ORANGE] = sMiniorOrangeFormChangeTable, + [SPECIES_MINIOR_METEOR_VIOLET] = sMiniorVioletFormChangeTable, + [SPECIES_MINIOR_CORE_VIOLET] = sMiniorVioletFormChangeTable, + [SPECIES_MINIOR_METEOR_YELLOW] = sMiniorYellowFormChangeTable, + [SPECIES_MINIOR_CORE_YELLOW] = sMiniorYellowFormChangeTable, #endif #if P_GEN_8_POKEMON == TRUE + [SPECIES_CRAMORANT] = sCramorantFormChangeTable, + [SPECIES_CRAMORANT_GULPING] = sCramorantFormChangeTable, + [SPECIES_CRAMORANT_GORGING] = sCramorantFormChangeTable, + [SPECIES_EISCUE] = sEiscueFormChangeTable, + [SPECIES_EISCUE_NOICE_FACE] = sEiscueFormChangeTable, + [SPECIES_MORPEKO] = sMorpekoFormChangeTable, + [SPECIES_MORPEKO_HANGRY] = sMorpekoFormChangeTable, [SPECIES_ZACIAN] = sZacianFormChangeTable, [SPECIES_ZACIAN_CROWNED_SWORD] = sZacianFormChangeTable, [SPECIES_ZAMAZENTA] = sZamazentaFormChangeTable, diff --git a/src/data/pokemon/form_change_tables.h b/src/data/pokemon/form_change_tables.h index 723bda4b2..c4ade7b9a 100644 --- a/src/data/pokemon/form_change_tables.h +++ b/src/data/pokemon/form_change_tables.h @@ -1,211 +1,582 @@ -/* -FORM_ITEM_HOLD: - Form change activates when the specified item is given to or taken from the selected Pokémon. - Alternatively, form change activates when the specified item is is given to or taken from - the selected Pokémon that has a particular ability. - param1 = item to hold - param2 = ability to check for, optional +static const struct FormChange sVenusaurFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_VENUSAUR_MEGA, ITEM_VENUSAURITE}, + {FORM_CHANGE_TERMINATOR}, +}; -FORM_ITEM_USE: - Form change activates when the item is used on the selected Pokémon. - param1 = item to use - param2 = DAY if form change activates in the daytime, optional - NIGHT if form change activates at nighttime, optional +static const struct FormChange sCharizardFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_CHARIZARD_MEGA_X, ITEM_CHARIZARDITE_X}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_CHARIZARD_MEGA_Y, ITEM_CHARIZARDITE_Y}, + {FORM_CHANGE_TERMINATOR}, +}; -FORM_MOVE: - Form change activates when the Pokémon learns or forgets the move. - param1 = move to check for - param2 = WHEN_LEARNED if form change activates when move is forgotten - WHEN_FORGOTTEN if form change activates when move is learned +static const struct FormChange sBlastoiseFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_BLASTOISE_MEGA, ITEM_BLASTOISINITE}, + {FORM_CHANGE_TERMINATOR}, +}; -FORM_WITHDRAW: - Form change activates when the Pokémon is withdrawn from the PC or Daycare. - no parameters +static const struct FormChange sBeedrillFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_BEEDRILL_MEGA, ITEM_BEEDRILLITE}, + {FORM_CHANGE_TERMINATOR}, +}; -FORM_BATTLE_BEGIN: - Form change activates when the Pokémon is sent out at the beginning of a battle - param1 = item to hold, optional - param2 = a move that will be replaced, optional - param3 = a new move to replace it with, optional +static const struct FormChange sPidgeotFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_PIDGEOT_MEGA, ITEM_PIDGEOTITE}, + {FORM_CHANGE_TERMINATOR}, +}; -FORM_BATTLE_END: - Form change activates at the end of a battle - param1 = item to hold, optional - param2 = a move that will be replaced, optional - param3 = a new move to replace it with, optional -*/ +static const struct FormChange sAlakazamFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_ALAKAZAM_MEGA, ITEM_ALAKAZITE}, + {FORM_CHANGE_TERMINATOR}, +}; -// FORM_MOVE param2 Arguments -#define WHEN_LEARNED 0 -#define WHEN_FORGOTTEN 1 +static const struct FormChange sSlowbroFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SLOWBRO_MEGA, ITEM_SLOWBRONITE}, + {FORM_CHANGE_TERMINATOR}, +}; -// FORM_ITEM_USE param2 Arguments -#define DAY 1 -#define NIGHT 2 +static const struct FormChange sGengarFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_GENGAR_MEGA, ITEM_GENGARITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sKangaskhanFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_KANGASKHAN_MEGA, ITEM_KANGASKHANITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sPinsirFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_PINSIR_MEGA, ITEM_PINSIRITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sGyaradosFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_GYARADOS_MEGA, ITEM_GYARADOSITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sAerodactylFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_AERODACTYL_MEGA, ITEM_AERODACTYLITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sMewtwoFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_MEWTWO_MEGA_X, ITEM_MEWTWONITE_X}, + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_MEWTWO_MEGA_Y, ITEM_MEWTWONITE_Y}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sAmpharosFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_AMPHAROS_MEGA, ITEM_AMPHAROSITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sSteelixFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_STEELIX_MEGA, ITEM_STEELIXITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sScizorFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SCIZOR_MEGA, ITEM_SCIZORITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sHeracrossFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_HERACROSS_MEGA, ITEM_HERACRONITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sHoundoomFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_HOUNDOOM_MEGA, ITEM_HOUNDOOMINITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sTyranitarFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_TYRANITAR_MEGA, ITEM_TYRANITARITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sSceptileFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SCEPTILE_MEGA, ITEM_SCEPTILITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sBlazikenFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_BLAZIKEN_MEGA, ITEM_BLAZIKENITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sSwampertFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SWAMPERT_MEGA, ITEM_SWAMPERTITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sSableyeFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SABLEYE_MEGA, ITEM_SABLENITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sSharpedoFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SHARPEDO_MEGA, ITEM_SHARPEDONITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sManectricFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_MANECTRIC_MEGA, ITEM_MANECTITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sCameruptFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_CAMERUPT_MEGA, ITEM_CAMERUPTITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sGlalieFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_GLALIE_MEGA, ITEM_GLALITITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sMawileFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_MAWILE_MEGA, ITEM_MAWILITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sMedichamFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_MEDICHAM_MEGA, ITEM_MEDICHAMITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sAltariaFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_ALTARIA_MEGA, ITEM_ALTARIANITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sAbsolFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_ABSOL_MEGA, ITEM_ABSOLITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sCastformFormChangeTable[] = { + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CASTFORM_SUNNY, B_WEATHER_SUN}, + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CASTFORM_RAINY, B_WEATHER_RAIN}, + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CASTFORM_SNOWY, B_WEATHER_HAIL}, + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CASTFORM, ~(B_WEATHER_SUN | B_WEATHER_RAIN | B_WEATHER_HAIL)}, + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CASTFORM, B_WEATHER_NONE}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_CASTFORM}, + {FORM_CHANGE_FAINT, SPECIES_CASTFORM}, + {FORM_CHANGE_END_BATTLE, SPECIES_CASTFORM}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sBanetteFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_BANETTE_MEGA, ITEM_BANETTITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sAggronFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_AGGRON_MEGA, ITEM_AGGRONITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sGardevoirFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_GARDEVOIR_MEGA, ITEM_GARDEVOIRITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sSalamenceFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_SALAMENCE_MEGA, ITEM_SALAMENCITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sMetagrossFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_METAGROSS_MEGA, ITEM_METAGROSSITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sLatiasFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_LATIAS_MEGA, ITEM_LATIASITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sLatiosFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_LATIOS_MEGA, ITEM_LATIOSITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sKyogreFormChangeTable[] = { + {FORM_CHANGE_BATTLE_PRIMAL_REVERSION, SPECIES_KYOGRE_PRIMAL, ITEM_BLUE_ORB}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sGroudonFormChangeTable[] = { + {FORM_CHANGE_BATTLE_PRIMAL_REVERSION, SPECIES_GROUDON_PRIMAL, ITEM_RED_ORB}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sRayquazaFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_MOVE, SPECIES_RAYQUAZA_MEGA, MOVE_DRAGON_ASCENT}, + {FORM_CHANGE_TERMINATOR}, +}; #if P_GEN_4_POKEMON == TRUE +static const struct FormChange sBurmyFormChangeTable[] = { + {FORM_CHANGE_END_BATTLE_TERRAIN, SPECIES_BURMY, BATTLE_TERRAIN_GRASS}, + {FORM_CHANGE_END_BATTLE_TERRAIN, SPECIES_BURMY, BATTLE_TERRAIN_LONG_GRASS}, + {FORM_CHANGE_END_BATTLE_TERRAIN, SPECIES_BURMY, BATTLE_TERRAIN_POND}, + {FORM_CHANGE_END_BATTLE_TERRAIN, SPECIES_BURMY, BATTLE_TERRAIN_MOUNTAIN}, + {FORM_CHANGE_END_BATTLE_TERRAIN, SPECIES_BURMY, BATTLE_TERRAIN_PLAIN}, + {FORM_CHANGE_END_BATTLE_TERRAIN, SPECIES_BURMY_SANDY_CLOAK, BATTLE_TERRAIN_CAVE}, + {FORM_CHANGE_END_BATTLE_TERRAIN, SPECIES_BURMY_SANDY_CLOAK, BATTLE_TERRAIN_SAND}, + {FORM_CHANGE_END_BATTLE_TERRAIN, SPECIES_BURMY_TRASH_CLOAK, BATTLE_TERRAIN_BUILDING}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sCherrimFormChangeTable[] = { + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CHERRIM_SUNSHINE, B_WEATHER_SUN}, + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CHERRIM, ~B_WEATHER_SUN}, + {FORM_CHANGE_BATTLE_WEATHER, SPECIES_CHERRIM, B_WEATHER_NONE}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_CHERRIM}, + {FORM_CHANGE_FAINT, SPECIES_CHERRIM}, + {FORM_CHANGE_END_BATTLE, SPECIES_CHERRIM}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sLopunnyFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_LOPUNNY_MEGA, ITEM_LOPUNNITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sGarchompFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_GARCHOMP_MEGA, ITEM_GARCHOMPITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sLucarioFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_LUCARIO_MEGA, ITEM_LUCARIONITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sAbomasnowFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_ABOMASNOW_MEGA, ITEM_ABOMASITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sGalladeFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_GALLADE_MEGA, ITEM_GALLADITE}, + {FORM_CHANGE_TERMINATOR}, +}; + static const struct FormChange sDialgaFormChangeTable[] = { - {FORM_ITEM_HOLD, SPECIES_DIALGA, ITEM_NONE}, - {FORM_ITEM_HOLD, SPECIES_DIALGA_ORIGIN, ITEM_ADAMANT_CRYSTAL}, - {FORM_CHANGE_END}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_DIALGA, ITEM_NONE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_DIALGA_ORIGIN, ITEM_ADAMANT_CRYSTAL}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sPalkiaFormChangeTable[] = { - {FORM_ITEM_HOLD, SPECIES_PALKIA, ITEM_NONE}, - {FORM_ITEM_HOLD, SPECIES_PALKIA_ORIGIN, ITEM_LUSTROUS_GLOBE}, - {FORM_CHANGE_END}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_PALKIA, ITEM_NONE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_PALKIA_ORIGIN, ITEM_LUSTROUS_GLOBE}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sGiratinaFormChangeTable[] = { - {FORM_ITEM_HOLD, SPECIES_GIRATINA, ITEM_NONE}, - {FORM_ITEM_HOLD, SPECIES_GIRATINA_ORIGIN, ITEM_GRISEOUS_CORE}, - {FORM_CHANGE_END}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_GIRATINA, ITEM_NONE}, +#if I_GRISEOUS_ORB_FORM_CHANGE < GEN_9 + {FORM_CHANGE_ITEM_HOLD, SPECIES_GIRATINA_ORIGIN, ITEM_GRISEOUS_ORB}, +#endif + {FORM_CHANGE_ITEM_HOLD, SPECIES_GIRATINA_ORIGIN, ITEM_GRISEOUS_CORE}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sShayminFormChangeTable[] = { - {FORM_ITEM_USE, SPECIES_SHAYMIN_SKY, ITEM_GRACIDEA, DAY}, - // {FORM_WITHDRAW, SPECIES_SHAYMIN}, - {FORM_CHANGE_END}, + {FORM_CHANGE_ITEM_USE, SPECIES_SHAYMIN_SKY, ITEM_GRACIDEA, DAY}, + // {FORM_CHANGE_WITHDRAW, SPECIES_SHAYMIN}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sArceusFormChangeTable[] = { - {FORM_ITEM_HOLD, SPECIES_ARCEUS, ITEM_NONE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_FIGHTING, ITEM_FIST_PLATE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_FIGHTING, ITEM_FIGHTINIUM_Z, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_FLYING, ITEM_SKY_PLATE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_FLYING, ITEM_FLYINIUM_Z, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_POISON, ITEM_TOXIC_PLATE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_POISON, ITEM_POISONIUM_Z, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_ROCK, ITEM_STONE_PLATE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_ROCK, ITEM_ROCKIUM_Z, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_GROUND, ITEM_EARTH_PLATE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_GROUND, ITEM_GROUNDIUM_Z, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_BUG, ITEM_INSECT_PLATE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_BUG, ITEM_BUGINIUM_Z, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_GHOST, ITEM_SPOOKY_PLATE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_GHOST, ITEM_GHOSTIUM_Z, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_STEEL, ITEM_IRON_PLATE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_STEEL, ITEM_STEELIUM_Z, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_FIRE, ITEM_FLAME_PLATE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_FIRE, ITEM_FIRIUM_Z, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_WATER, ITEM_SPLASH_PLATE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_WATER, ITEM_WATERIUM_Z, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_GRASS, ITEM_MEADOW_PLATE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_GRASS, ITEM_GRASSIUM_Z, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_ELECTRIC, ITEM_ZAP_PLATE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_ELECTRIC, ITEM_ELECTRIUM_Z, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_PSYCHIC, ITEM_MIND_PLATE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_PSYCHIC, ITEM_PSYCHIUM_Z, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_ICE, ITEM_ICICLE_PLATE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_ICE, ITEM_ICIUM_Z, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_DRAGON, ITEM_DRACO_PLATE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_DRAGON, ITEM_DRAGONIUM_Z, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_DARK, ITEM_DREAD_PLATE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_DARK, ITEM_DARKINIUM_Z, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_FAIRY, ITEM_PIXIE_PLATE, ABILITY_MULTITYPE}, - {FORM_ITEM_HOLD, SPECIES_ARCEUS_FAIRY, ITEM_FAIRIUM_Z, ABILITY_MULTITYPE}, - {FORM_CHANGE_END}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS, ITEM_NONE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_FIGHTING, ITEM_FIST_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_FIGHTING, ITEM_FIGHTINIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_FLYING, ITEM_SKY_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_FLYING, ITEM_FLYINIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_POISON, ITEM_TOXIC_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_POISON, ITEM_POISONIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_ROCK, ITEM_STONE_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_ROCK, ITEM_ROCKIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_GROUND, ITEM_EARTH_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_GROUND, ITEM_GROUNDIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_BUG, ITEM_INSECT_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_BUG, ITEM_BUGINIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_GHOST, ITEM_SPOOKY_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_GHOST, ITEM_GHOSTIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_STEEL, ITEM_IRON_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_STEEL, ITEM_STEELIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_FIRE, ITEM_FLAME_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_FIRE, ITEM_FIRIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_WATER, ITEM_SPLASH_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_WATER, ITEM_WATERIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_GRASS, ITEM_MEADOW_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_GRASS, ITEM_GRASSIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_ELECTRIC, ITEM_ZAP_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_ELECTRIC, ITEM_ELECTRIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_PSYCHIC, ITEM_MIND_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_PSYCHIC, ITEM_PSYCHIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_ICE, ITEM_ICICLE_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_ICE, ITEM_ICIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_DRAGON, ITEM_DRACO_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_DRAGON, ITEM_DRAGONIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_DARK, ITEM_DREAD_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_DARK, ITEM_DARKINIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_FAIRY, ITEM_PIXIE_PLATE, ABILITY_MULTITYPE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_ARCEUS_FAIRY, ITEM_FAIRIUM_Z, ABILITY_MULTITYPE}, + {FORM_CHANGE_TERMINATOR}, }; #endif #if P_GEN_5_POKEMON == TRUE +static const struct FormChange sAudinoFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_AUDINO_MEGA, ITEM_AUDINITE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sDarmanitanFormChangeTable[] = { + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_DARMANITAN, ABILITY_ZEN_MODE, HP_HIGHER_THAN, 50}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_DARMANITAN_ZEN_MODE, ABILITY_ZEN_MODE, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_FAINT, SPECIES_DARMANITAN}, + {FORM_CHANGE_END_BATTLE, SPECIES_DARMANITAN}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sDarmanitanGalarianFormChangeTable[] = { + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_DARMANITAN_GALARIAN, ABILITY_ZEN_MODE, HP_HIGHER_THAN, 50}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_DARMANITAN_ZEN_MODE_GALARIAN, ABILITY_ZEN_MODE, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_FAINT, SPECIES_DARMANITAN_GALARIAN}, + {FORM_CHANGE_END_BATTLE, SPECIES_DARMANITAN_GALARIAN}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sMeloettaFormChangeTable[] = { + {FORM_CHANGE_FAINT, SPECIES_MELOETTA}, + {FORM_CHANGE_END_BATTLE, SPECIES_MELOETTA}, + {FORM_CHANGE_TERMINATOR}, +}; + static const struct FormChange sTornadusFormChangeTable[] = { - {FORM_ITEM_USE, SPECIES_TORNADUS_THERIAN, ITEM_REVEAL_GLASS}, - {FORM_ITEM_USE, SPECIES_TORNADUS, ITEM_REVEAL_GLASS}, - {FORM_CHANGE_END}, + {FORM_CHANGE_ITEM_USE, SPECIES_TORNADUS_THERIAN, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_ITEM_USE, SPECIES_TORNADUS, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sThundurusFormChangeTable[] = { - {FORM_ITEM_USE, SPECIES_THUNDURUS_THERIAN, ITEM_REVEAL_GLASS}, - {FORM_ITEM_USE, SPECIES_THUNDURUS, ITEM_REVEAL_GLASS}, - {FORM_CHANGE_END}, + {FORM_CHANGE_ITEM_USE, SPECIES_THUNDURUS_THERIAN, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_ITEM_USE, SPECIES_THUNDURUS, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sLandorusFormChangeTable[] = { - {FORM_ITEM_USE, SPECIES_LANDORUS_THERIAN, ITEM_REVEAL_GLASS}, - {FORM_ITEM_USE, SPECIES_LANDORUS, ITEM_REVEAL_GLASS}, - {FORM_CHANGE_END}, + {FORM_CHANGE_ITEM_USE, SPECIES_LANDORUS_THERIAN, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_ITEM_USE, SPECIES_LANDORUS, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sKeldeoFormChangeTable[] = { - // {FORM_MOVE, SPECIES_KELDEO_RESOLUTE, MOVE_SECRET_SWORD, WHEN_LEARNED}, - // {FORM_MOVE, SPECIES_KELDEO, MOVE_SECRET_SWORD, WHEN_FORGOTTEN}, - {FORM_CHANGE_END}, + // {FORM_CHANGE_MOVE, SPECIES_KELDEO_RESOLUTE, MOVE_SECRET_SWORD, WHEN_LEARNED}, + // {FORM_CHANGE_MOVE, SPECIES_KELDEO, MOVE_SECRET_SWORD, WHEN_FORGOTTEN}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sGenesectFormChangeTable[] = { - {FORM_ITEM_HOLD, SPECIES_GENESECT, ITEM_NONE}, - {FORM_ITEM_HOLD, SPECIES_GENESECT_DOUSE_DRIVE, ITEM_DOUSE_DRIVE}, - {FORM_ITEM_HOLD, SPECIES_GENESECT_SHOCK_DRIVE, ITEM_SHOCK_DRIVE}, - {FORM_ITEM_HOLD, SPECIES_GENESECT_BURN_DRIVE, ITEM_BURN_DRIVE}, - {FORM_ITEM_HOLD, SPECIES_GENESECT_CHILL_DRIVE, ITEM_CHILL_DRIVE}, - {FORM_CHANGE_END}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_GENESECT, ITEM_NONE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_GENESECT_DOUSE_DRIVE, ITEM_DOUSE_DRIVE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_GENESECT_SHOCK_DRIVE, ITEM_SHOCK_DRIVE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_GENESECT_BURN_DRIVE, ITEM_BURN_DRIVE}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_GENESECT_CHILL_DRIVE, ITEM_CHILL_DRIVE}, + {FORM_CHANGE_TERMINATOR}, }; #endif #if P_GEN_6_POKEMON == TRUE +static const struct FormChange sGreninjaBattleBondFormChangeTable[] = { + {FORM_CHANGE_FAINT, SPECIES_GRENINJA_BATTLE_BOND}, + {FORM_CHANGE_END_BATTLE, SPECIES_GRENINJA_BATTLE_BOND}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sAegislashFormChangeTable[] = { + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_AEGISLASH}, + {FORM_CHANGE_FAINT, SPECIES_AEGISLASH}, + {FORM_CHANGE_END_BATTLE, SPECIES_AEGISLASH}, + {FORM_CHANGE_TERMINATOR}, +}; + static const struct FormChange sXerneasFormChangeTable[] = { - {FORM_BATTLE_BEGIN, SPECIES_XERNEAS_ACTIVE}, - {FORM_BATTLE_END, SPECIES_XERNEAS, }, - {FORM_CHANGE_END}, + {FORM_CHANGE_BEGIN_BATTLE, SPECIES_XERNEAS_ACTIVE}, + {FORM_CHANGE_END_BATTLE, SPECIES_XERNEAS, }, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sZygardePowerConstructFormChangeTable[] = { + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_ZYGARDE_COMPLETE, ABILITY_POWER_CONSTRUCT, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_FAINT}, + {FORM_CHANGE_END_BATTLE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sDiancieFormChangeTable[] = { + {FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM, SPECIES_DIANCIE_MEGA, ITEM_DIANCITE}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sHoopaFormChangeTable[] = { - {FORM_ITEM_USE, SPECIES_HOOPA_UNBOUND, ITEM_PRISON_BOTTLE, SPECIES_HOOPA}, - // {FORM_WITHDRAW, SPECIES_HOOPA}, - {FORM_CHANGE_END}, + {FORM_CHANGE_ITEM_USE, SPECIES_HOOPA_UNBOUND, ITEM_PRISON_BOTTLE, SPECIES_HOOPA}, + {FORM_CHANGE_WITHDRAW, SPECIES_HOOPA}, + {FORM_CHANGE_TERMINATOR}, }; #endif #if P_GEN_7_POKEMON == TRUE static const struct FormChange sOricorioFormChangeTable[] = { - {FORM_ITEM_USE, SPECIES_ORICORIO, ITEM_RED_NECTAR}, - {FORM_ITEM_USE, SPECIES_ORICORIO_POM_POM, ITEM_YELLOW_NECTAR}, - {FORM_ITEM_USE, SPECIES_ORICORIO_PAU, ITEM_PINK_NECTAR}, - {FORM_ITEM_USE, SPECIES_ORICORIO_SENSU, ITEM_PURPLE_NECTAR}, - {FORM_CHANGE_END}, + {FORM_CHANGE_ITEM_USE, SPECIES_ORICORIO, ITEM_RED_NECTAR}, + {FORM_CHANGE_ITEM_USE, SPECIES_ORICORIO_POM_POM, ITEM_YELLOW_NECTAR}, + {FORM_CHANGE_ITEM_USE, SPECIES_ORICORIO_PAU, ITEM_PINK_NECTAR}, + {FORM_CHANGE_ITEM_USE, SPECIES_ORICORIO_SENSU, ITEM_PURPLE_NECTAR}, + {FORM_CHANGE_TERMINATOR}, +}; +static const struct FormChange sWishiwashiFormChangeTable[] = { + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_WISHIWASHI_SCHOOL, ABILITY_SCHOOLING, HP_HIGHER_THAN, 25}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_WISHIWASHI, ABILITY_SCHOOLING, HP_LOWER_EQ_THAN, 25}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_WISHIWASHI}, + {FORM_CHANGE_FAINT, SPECIES_WISHIWASHI}, + {FORM_CHANGE_END_BATTLE, SPECIES_WISHIWASHI}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sSilvallyFormChangeTable[] = { - {FORM_ITEM_HOLD, SPECIES_SILVALLY, ITEM_NONE, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_FIGHTING, ITEM_FIGHTING_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_FLYING, ITEM_FLYING_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_POISON, ITEM_POISON_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_GROUND, ITEM_GROUND_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_ROCK, ITEM_ROCK_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_BUG, ITEM_BUG_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_GHOST, ITEM_GHOST_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_STEEL, ITEM_STEEL_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_FIRE, ITEM_FIRE_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_WATER, ITEM_WATER_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_GRASS, ITEM_GRASS_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_ELECTRIC, ITEM_ELECTRIC_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_PSYCHIC, ITEM_PSYCHIC_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_ICE, ITEM_ICE_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_DRAGON, ITEM_DRAGON_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_DARK, ITEM_DARK_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_ITEM_HOLD, SPECIES_SILVALLY_FAIRY, ITEM_FAIRY_MEMORY, ABILITY_RKS_SYSTEM}, - {FORM_CHANGE_END}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY, ITEM_NONE, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_FIGHTING, ITEM_FIGHTING_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_FLYING, ITEM_FLYING_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_POISON, ITEM_POISON_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_GROUND, ITEM_GROUND_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_ROCK, ITEM_ROCK_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_BUG, ITEM_BUG_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_GHOST, ITEM_GHOST_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_STEEL, ITEM_STEEL_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_FIRE, ITEM_FIRE_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_WATER, ITEM_WATER_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_GRASS, ITEM_GRASS_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_ELECTRIC, ITEM_ELECTRIC_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_PSYCHIC, ITEM_PSYCHIC_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_ICE, ITEM_ICE_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_DRAGON, ITEM_DRAGON_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_DARK, ITEM_DARK_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_ITEM_HOLD, SPECIES_SILVALLY_FAIRY, ITEM_FAIRY_MEMORY, ABILITY_RKS_SYSTEM}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sMimikyuFormChangeTable[] = { + {FORM_CHANGE_FAINT, SPECIES_MIMIKYU}, + {FORM_CHANGE_END_BATTLE, SPECIES_MIMIKYU}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sMiniorRedFormChangeTable[] = { + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR, ABILITY_SHIELDS_DOWN, HP_HIGHER_THAN, 50}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_CORE_RED, ABILITY_SHIELDS_DOWN, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_RED}, + {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_RED}, + {FORM_CHANGE_END_BATTLE, SPECIES_MINIOR_CORE_RED}, + {FORM_CHANGE_TERMINATOR}, +}; +static const struct FormChange sMiniorBlueFormChangeTable[] = { + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_METEOR_BLUE, ABILITY_SHIELDS_DOWN, HP_HIGHER_THAN, 50}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_CORE_BLUE, ABILITY_SHIELDS_DOWN, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_BLUE}, + {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_BLUE}, + {FORM_CHANGE_END_BATTLE, SPECIES_MINIOR_CORE_BLUE}, + {FORM_CHANGE_TERMINATOR}, +}; +static const struct FormChange sMiniorGreenFormChangeTable[] = { + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_METEOR_GREEN, ABILITY_SHIELDS_DOWN, HP_HIGHER_THAN, 50}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_CORE_GREEN, ABILITY_SHIELDS_DOWN, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_GREEN}, + {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_GREEN}, + {FORM_CHANGE_END_BATTLE, SPECIES_MINIOR_CORE_GREEN}, + {FORM_CHANGE_TERMINATOR}, +}; +static const struct FormChange sMiniorIndigoFormChangeTable[] = { + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_METEOR_INDIGO, ABILITY_SHIELDS_DOWN, HP_HIGHER_THAN, 50}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_CORE_INDIGO, ABILITY_SHIELDS_DOWN, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_INDIGO}, + {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_INDIGO}, + {FORM_CHANGE_END_BATTLE, SPECIES_MINIOR_CORE_INDIGO}, + {FORM_CHANGE_TERMINATOR}, +}; +static const struct FormChange sMiniorOrangeFormChangeTable[] = { + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_METEOR_ORANGE, ABILITY_SHIELDS_DOWN, HP_HIGHER_THAN, 50}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_CORE_ORANGE, ABILITY_SHIELDS_DOWN, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_ORANGE}, + {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_ORANGE}, + {FORM_CHANGE_END_BATTLE, SPECIES_MINIOR_CORE_ORANGE}, + {FORM_CHANGE_TERMINATOR}, +}; +static const struct FormChange sMiniorVioletFormChangeTable[] = { + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_METEOR_VIOLET, ABILITY_SHIELDS_DOWN, HP_HIGHER_THAN, 50}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_CORE_VIOLET, ABILITY_SHIELDS_DOWN, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_VIOLET}, + {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_VIOLET}, + {FORM_CHANGE_END_BATTLE, SPECIES_MINIOR_CORE_VIOLET}, + {FORM_CHANGE_TERMINATOR}, +}; +static const struct FormChange sMiniorYellowFormChangeTable[] = { + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_METEOR_YELLOW, ABILITY_SHIELDS_DOWN, HP_HIGHER_THAN, 50}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_MINIOR_CORE_YELLOW, ABILITY_SHIELDS_DOWN, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MINIOR_CORE_YELLOW}, + {FORM_CHANGE_FAINT, SPECIES_MINIOR_CORE_YELLOW}, + {FORM_CHANGE_END_BATTLE, SPECIES_MINIOR_CORE_YELLOW}, + {FORM_CHANGE_TERMINATOR}, }; #endif #if P_GEN_8_POKEMON == TRUE +static const struct FormChange sCramorantFormChangeTable[] = { + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_CRAMORANT_GULPING, ABILITY_GULP_MISSILE, HP_HIGHER_THAN, 50}, + {FORM_CHANGE_BATTLE_HP_PERCENT, SPECIES_CRAMORANT_GORGING, ABILITY_GULP_MISSILE, HP_LOWER_EQ_THAN, 50}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_CRAMORANT}, + {FORM_CHANGE_FAINT, SPECIES_CRAMORANT}, + {FORM_CHANGE_END_BATTLE, SPECIES_CRAMORANT}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sEiscueFormChangeTable[] = { + {FORM_CHANGE_FAINT, SPECIES_EISCUE}, + {FORM_CHANGE_END_BATTLE, SPECIES_EISCUE}, + {FORM_CHANGE_TERMINATOR}, +}; + +static const struct FormChange sMorpekoFormChangeTable[] = { + {FORM_CHANGE_BATTLE_TURN_END, SPECIES_MORPEKO_HANGRY, ABILITY_HUNGER_SWITCH}, + {FORM_CHANGE_BATTLE_TURN_END, SPECIES_MORPEKO , ABILITY_HUNGER_SWITCH}, + {FORM_CHANGE_BATTLE_SWITCH, SPECIES_MORPEKO}, + {FORM_CHANGE_FAINT, SPECIES_MORPEKO}, + {FORM_CHANGE_END_BATTLE, SPECIES_MORPEKO}, + {FORM_CHANGE_TERMINATOR}, +}; + static const struct FormChange sZacianFormChangeTable[] = { - {FORM_BATTLE_BEGIN, SPECIES_ZACIAN_CROWNED_SWORD, ITEM_RUSTED_SWORD, MOVE_IRON_HEAD, MOVE_BEHEMOTH_BLADE}, - {FORM_BATTLE_END, SPECIES_ZACIAN, ITEM_RUSTED_SWORD, MOVE_BEHEMOTH_BLADE, MOVE_IRON_HEAD}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BEGIN_BATTLE, SPECIES_ZACIAN_CROWNED_SWORD, ITEM_RUSTED_SWORD, MOVE_IRON_HEAD, MOVE_BEHEMOTH_BLADE}, + {FORM_CHANGE_END_BATTLE, SPECIES_ZACIAN, ITEM_RUSTED_SWORD, MOVE_BEHEMOTH_BLADE, MOVE_IRON_HEAD}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sZamazentaFormChangeTable[] = { - {FORM_BATTLE_BEGIN, SPECIES_ZAMAZENTA_CROWNED_SHIELD, ITEM_RUSTED_SHIELD, MOVE_IRON_HEAD, MOVE_BEHEMOTH_BASH}, - {FORM_BATTLE_END, SPECIES_ZAMAZENTA, ITEM_RUSTED_SHIELD, MOVE_BEHEMOTH_BASH, MOVE_IRON_HEAD}, - {FORM_CHANGE_END}, + {FORM_CHANGE_BEGIN_BATTLE, SPECIES_ZAMAZENTA_CROWNED_SHIELD, ITEM_RUSTED_SHIELD, MOVE_IRON_HEAD, MOVE_BEHEMOTH_BASH}, + {FORM_CHANGE_END_BATTLE, SPECIES_ZAMAZENTA, ITEM_RUSTED_SHIELD, MOVE_BEHEMOTH_BASH, MOVE_IRON_HEAD}, + {FORM_CHANGE_TERMINATOR}, }; static const struct FormChange sEnamorusFormChangeTable[] = { - {FORM_ITEM_USE, SPECIES_ENAMORUS, ITEM_REVEAL_GLASS}, - {FORM_ITEM_USE, SPECIES_ENAMORUS_THERIAN, ITEM_REVEAL_GLASS}, - {FORM_CHANGE_END}, + {FORM_CHANGE_ITEM_USE, SPECIES_ENAMORUS, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_ITEM_USE, SPECIES_ENAMORUS_THERIAN, ITEM_REVEAL_GLASS}, + {FORM_CHANGE_TERMINATOR}, }; #endif diff --git a/src/data/pokemon/item_effects.h b/src/data/pokemon/item_effects.h index 607f57814..087c6db0c 100644 --- a/src/data/pokemon/item_effects.h +++ b/src/data/pokemon/item_effects.h @@ -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, @@ -556,6 +554,9 @@ const u8 *const gItemEffectTable[ITEMS_COUNT] = [ITEM_MALICIOUS_ARMOR] = gItemEffect_EvoItem, [ITEM_SCROLL_OF_DARKNESS] = gItemEffect_EvoItem, [ITEM_SCROLL_OF_WATERS] = gItemEffect_EvoItem, + [ITEM_BLACK_AUGURITE] = gItemEffect_EvoItem, + [ITEM_LINKING_CORD] = gItemEffect_EvoItem, + [ITEM_PEAT_BLOCK] = gItemEffect_EvoItem, // Berries [ITEM_CHERI_BERRY] = gItemEffect_CheriBerry, diff --git a/src/data/pokemon/species_info.h b/src/data/pokemon/species_info.h index 7b60f1b1a..6e99e6f34 100644 --- a/src/data/pokemon/species_info.h +++ b/src/data/pokemon/species_info.h @@ -22202,7 +22202,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .abilities = {ABILITY_PRIMORDIAL_SEA, ABILITY_PRIMORDIAL_SEA}, .bodyColor = BODY_COLOR_BLUE, .noFlip = FALSE, - .flags = SPECIES_FLAG_LEGENDARY, + .flags = SPECIES_FLAG_LEGENDARY | SPECIES_FLAG_PRIMAL_REVERSION, }, [SPECIES_GROUDON_PRIMAL] = @@ -22225,7 +22225,7 @@ const struct SpeciesInfo gSpeciesInfo[] = .abilities = {ABILITY_DESOLATE_LAND, ABILITY_DESOLATE_LAND}, .bodyColor = BODY_COLOR_RED, .noFlip = FALSE, - .flags = SPECIES_FLAG_LEGENDARY, + .flags = SPECIES_FLAG_LEGENDARY | SPECIES_FLAG_PRIMAL_REVERSION, }, [SPECIES_RATTATA_ALOLAN] = diff --git a/src/data/text/item_descriptions.h b/src/data/text/item_descriptions.h index da15f001c..dddf8552f 100644 --- a/src/data/text/item_descriptions.h +++ b/src/data/text/item_descriptions.h @@ -1300,6 +1300,21 @@ static const u8 sEverstoneDesc[] = _( "item that prevents\n" "evolution."); +static const u8 sBlackAuguriteDesc[] = _( + "A black stone that\n" + "makes some Pokémon\n" + "evolve.");; + +static const u8 sLinkingCordDesc[] = _( + "A mysterious string\n" + "that makes some\n" + "Pokémon evolve."); + +static const u8 sPeatBlockDesc[] = _( + "A block of material\n" + "that makes some\n" + "Pokémon evolve."); + // Nectars static const u8 sRedNectarDesc[] = _( "Flower nectar that\n" @@ -3892,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."); diff --git a/src/data/text/move_descriptions.h b/src/data/text/move_descriptions.h index c2b7e0b23..f950c2a1a 100644 --- a/src/data/text/move_descriptions.h +++ b/src/data/text/move_descriptions.h @@ -38,7 +38,11 @@ static const u8 sFirePunchDescription[] = _( static const u8 sIcePunchDescription[] = _( "An icy punch that may\n" +#if B_USE_FROSTBITE == TRUE + "leave the foe with frostbite."); +#else "freeze the foe."); +#endif static const u8 sThunderPunchDescription[] = _( "An electrified punch that\n" @@ -238,11 +242,19 @@ static const u8 sSurfDescription[] = _( static const u8 sIceBeamDescription[] = _( "Blasts the foe with an icy\n" +#if B_USE_FROSTBITE == TRUE + "beam. May cause frostbite."); +#else "beam that may freeze it."); +#endif static const u8 sBlizzardDescription[] = _( "Hits the foe with an icy\n" +#if B_USE_FROSTBITE == TRUE + "storm. May cause frostbite."); +#else "storm that may freeze it."); +#endif static const u8 sPsybeamDescription[] = _( "Fires a peculiar ray that\n" @@ -2931,7 +2943,11 @@ static const u8 sDragonEnergyDescription[] = _( static const u8 sFreezingGlareDescription[] = _( "Shoots psychic power from\n" +#if B_USE_FROSTBITE == TRUE + "the eyes. May frostbite."); +#else "the eyes. May freeze the foe."); +#endif static const u8 sFieryWrathDescription[] = _( "An attack fueled by your\n" diff --git a/src/daycare.c b/src/daycare.c index 803c0cacf..077ef499a 100644 --- a/src/daycare.c +++ b/src/daycare.c @@ -20,6 +20,7 @@ #include "list_menu.h" #include "overworld.h" #include "item.h" +#include "constants/form_change_types.h" #include "constants/items.h" #include "constants/moves.h" #include "constants/region_map_sections.h" @@ -255,8 +256,9 @@ static u16 TakeSelectedPokemonFromDaycare(struct DaycareMon *daycareMon) species = GetBoxMonData(&daycareMon->mon, MON_DATA_SPECIES); BoxMonToMon(&daycareMon->mon, &pokemon); - newSpecies = GetFormChangeTargetSpecies(&pokemon, FORM_WITHDRAW, 0); - if (newSpecies != SPECIES_NONE) { + newSpecies = GetFormChangeTargetSpecies(&pokemon, FORM_CHANGE_WITHDRAW, 0); + if (newSpecies != SPECIES_NONE) + { SetMonData(&pokemon, MON_DATA_SPECIES, &newSpecies); CalculateMonStats(&pokemon); species = newSpecies; diff --git a/src/easy_chat.c b/src/easy_chat.c index 6595e0a10..12a3a0808 100644 --- a/src/easy_chat.c +++ b/src/easy_chat.c @@ -5109,7 +5109,7 @@ static bool8 IsEasyChatGroupUnlocked(u8 groupId) switch (groupId) { case EC_GROUP_TRENDY_SAYING: - return FlagGet(FLAG_SYS_HIPSTER_MEET); + return FlagGet(FLAG_UNLOCKED_TRENDY_SAYINGS); case EC_GROUP_EVENTS: case EC_GROUP_MOVE_1: case EC_GROUP_MOVE_2: @@ -5425,80 +5425,99 @@ void BufferDeepLinkPhrase(void) CopyEasyChatWord(gStringVar2, easyChatWord); } -static bool8 IsAdditionalPhraseUnlocked(u8 additionalPhraseId) +/* + ### Trendy Sayings + + Not to be confused with Dewford Town's "trendy phrase". + + This is a group of easy chat words (EC_GROUP_TRENDY_SAYING) that are normally inaccessible. + They can be unlocked either through Mystery Event (where they're referred to as "rare" words) + or from the "Hipster" variety of the Mauville Old Man. The Hipster can unlock one word each + time he is received via record mixing (and once if he is the player's default Old Man). + + Which words have been unlocked is saved in the unlockedTrendySayings bitfield in SaveBlock1 + + Unlocked trendy saying words are only accessible if the flag FLAG_UNLOCKED_TRENDY_SAYINGS is set. + It's set any time the player talks to the Hipster, but is not apparently set by Mystery Event, + meaning trendy saying words unlocked via Mystery Event may not be available until the player has + talked to the Hipster. +*/ +static bool8 IsTrendySayingUnlocked(u8 wordIndex) { - int byteOffset = additionalPhraseId / 8; - int shift = additionalPhraseId % 8; - return (gSaveBlock1Ptr->additionalPhrases[byteOffset] >> shift) & 1; + int byteOffset = wordIndex / 8; + int shift = wordIndex % 8; + return (gSaveBlock1Ptr->unlockedTrendySayings[byteOffset] >> shift) & 1; } -void UnlockAdditionalPhrase(u8 additionalPhraseId) +void UnlockTrendySaying(u8 wordIndex) { - if (additionalPhraseId < NUM_ADDITIONAL_PHRASES) + if (wordIndex < NUM_TRENDY_SAYINGS) { - int byteOffset = additionalPhraseId / 8; - int shift = additionalPhraseId % 8; - gSaveBlock1Ptr->additionalPhrases[byteOffset] |= 1 << shift; + int byteOffset = wordIndex / 8; + int shift = wordIndex % 8; + gSaveBlock1Ptr->unlockedTrendySayings[byteOffset] |= 1 << shift; } } -static u8 GetNumAdditionalPhrasesUnlocked(void) +static u8 GetNumTrendySayingsUnlocked(void) { u8 i; - u8 numAdditionalPhrasesUnlocked; + u8 numUnlocked; - for (i = 0, numAdditionalPhrasesUnlocked = 0; i < NUM_ADDITIONAL_PHRASES; i++) + for (i = 0, numUnlocked = 0; i < NUM_TRENDY_SAYINGS; i++) { - if (IsAdditionalPhraseUnlocked(i)) - numAdditionalPhrasesUnlocked++; + if (IsTrendySayingUnlocked(i)) + numUnlocked++; } - return numAdditionalPhrasesUnlocked; + return numUnlocked; } -u16 GetNewHipsterPhraseToTeach(void) +u16 UnlockRandomTrendySaying(void) { u16 i; - u16 additionalPhraseId; - u8 numAdditionalPhrasesUnlocked = GetNumAdditionalPhrasesUnlocked(); - if (numAdditionalPhrasesUnlocked == NUM_ADDITIONAL_PHRASES) + u16 numToSkip; + u8 numUnlocked = GetNumTrendySayingsUnlocked(); + if (numUnlocked == NUM_TRENDY_SAYINGS) return EC_EMPTY_WORD; - additionalPhraseId = Random() % (NUM_ADDITIONAL_PHRASES - numAdditionalPhrasesUnlocked); - for (i = 0; i < NUM_ADDITIONAL_PHRASES; i++) + numToSkip = Random() % (NUM_TRENDY_SAYINGS - numUnlocked); + for (i = 0; i < NUM_TRENDY_SAYINGS; i++) { - if (!IsAdditionalPhraseUnlocked(i)) + if (!IsTrendySayingUnlocked(i)) { - if (additionalPhraseId) + if (numToSkip) { - additionalPhraseId--; + // Skip the first n locked words, as determined by the Random call above. + numToSkip--; } else { - UnlockAdditionalPhrase(i); + UnlockTrendySaying(i); return EC_WORD(EC_GROUP_TRENDY_SAYING, i); } } } + // Would only be reached if there are no new words to teach, which is handled at the start. return EC_EMPTY_WORD; } // Unused -u16 GetRandomTaughtHipsterPhrase(void) +static u16 GetRandomUnlockedTrendySaying(void) { u16 i; - u16 additionalPhraseId = GetNumAdditionalPhrasesUnlocked(); - if (additionalPhraseId == 0) + u16 n = GetNumTrendySayingsUnlocked(); + if (n == 0) return EC_EMPTY_WORD; - additionalPhraseId = Random() % additionalPhraseId; - for (i = 0; i < NUM_ADDITIONAL_PHRASES; i++) + n = Random() % n; + for (i = 0; i < NUM_TRENDY_SAYINGS; i++) { - if (IsAdditionalPhraseUnlocked(i)) + if (IsTrendySayingUnlocked(i)) { - if (additionalPhraseId) - additionalPhraseId--; + if (n) + n--; else return EC_WORD(EC_GROUP_TRENDY_SAYING, i); } @@ -5569,10 +5588,10 @@ void InitEasyChatPhrases(void) // Mauville old man data is corrupted, which is initialized directly after // this function is called when starting a new game. for (i = 0; i < 64; i++) - gSaveBlock1Ptr->additionalPhrases[i] = 0; + gSaveBlock1Ptr->unlockedTrendySayings[i] = 0; #else - for (i = 0; i < ARRAY_COUNT(gSaveBlock1Ptr->additionalPhrases); i++) - gSaveBlock1Ptr->additionalPhrases[i] = 0; + for (i = 0; i < ARRAY_COUNT(gSaveBlock1Ptr->unlockedTrendySayings); i++) + gSaveBlock1Ptr->unlockedTrendySayings[i] = 0; #endif } @@ -5611,7 +5630,7 @@ static void SetUnlockedEasyChatGroups(void) sWordData->unlockedGroupIds[sWordData->numUnlockedGroups++] = EC_GROUP_MOVE_2; } - if (FlagGet(FLAG_SYS_HIPSTER_MEET)) + if (FlagGet(FLAG_UNLOCKED_TRENDY_SAYINGS)) sWordData->unlockedGroupIds[sWordData->numUnlockedGroups++] = EC_GROUP_TRENDY_SAYING; if (IsNationalPokedexEnabled()) @@ -5800,7 +5819,7 @@ static bool8 IsEasyChatIndexAndGroupUnlocked(u16 wordIndex, u8 groupId) case EC_GROUP_MOVE_2: return TRUE; case EC_GROUP_TRENDY_SAYING: - return IsAdditionalPhraseUnlocked(wordIndex); + return IsTrendySayingUnlocked(wordIndex); default: return gEasyChatGroups[groupId].wordData.words[wordIndex].enabled; } diff --git a/src/event_object_movement.c b/src/event_object_movement.c index ccb6143bc..329482e31 100644 --- a/src/event_object_movement.c +++ b/src/event_object_movement.c @@ -132,9 +132,9 @@ static void SetObjectEventDynamicGraphicsId(struct ObjectEvent *); static void RemoveObjectEventInternal(struct ObjectEvent *); static u16 GetObjectEventFlagIdByObjectEventId(u8); static void UpdateObjectEventVisibility(struct ObjectEvent *, struct Sprite *); -static void MakeSpriteTemplateFromObjectEventTemplate(struct ObjectEventTemplate *, struct SpriteTemplate *, const struct SubspriteTable **); +static void MakeSpriteTemplateFromObjectEventTemplate(const struct ObjectEventTemplate *, struct SpriteTemplate *, const struct SubspriteTable **); static void GetObjectEventMovingCameraOffset(s16 *, s16 *); -static struct ObjectEventTemplate *GetObjectEventTemplateByLocalIdAndMap(u8, u8, u8); +static const struct ObjectEventTemplate *GetObjectEventTemplateByLocalIdAndMap(u8, u8, u8); static void LoadObjectEventPalette(u16); static void RemoveObjectEventIfOutsideView(struct ObjectEvent *); static void SpawnObjectEventOnReturnToField(u8, s16, s16); @@ -148,7 +148,7 @@ static void SpriteCB_CameraObject(struct Sprite *); static void CameraObject_0(struct Sprite *); static void CameraObject_1(struct Sprite *); static void CameraObject_2(struct Sprite *); -static struct ObjectEventTemplate *FindObjectEventTemplateByLocalId(u8, struct ObjectEventTemplate *, u8); +static const struct ObjectEventTemplate *FindObjectEventTemplateByLocalId(u8, const struct ObjectEventTemplate *, u8); static void ClearObjectEventMovement(struct ObjectEvent *, struct Sprite *); static void ObjectEventSetSingleMovement(struct ObjectEvent *, struct Sprite *, u8); static void SetSpriteDataForNormalStep(struct Sprite *, u8, u8); @@ -1268,7 +1268,7 @@ static u8 GetObjectEventIdByLocalId(u8 localId) return OBJECT_EVENTS_COUNT; } -static u8 InitObjectEventStateFromTemplate(struct ObjectEventTemplate *template, u8 mapNum, u8 mapGroup) +static u8 InitObjectEventStateFromTemplate(const struct ObjectEventTemplate *template, u8 mapNum, u8 mapGroup) { struct ObjectEvent *objectEvent; u8 objectEventId; @@ -1399,7 +1399,7 @@ void RemoveAllObjectEventsExceptPlayer(void) } } -static u8 TrySetupObjectEventSprite(struct ObjectEventTemplate *objectEventTemplate, struct SpriteTemplate *spriteTemplate, u8 mapNum, u8 mapGroup, s16 cameraX, s16 cameraY) +static u8 TrySetupObjectEventSprite(const struct ObjectEventTemplate *objectEventTemplate, struct SpriteTemplate *spriteTemplate, u8 mapNum, u8 mapGroup, s16 cameraX, s16 cameraY) { u8 spriteId; u8 paletteSlot; @@ -1459,7 +1459,7 @@ static u8 TrySetupObjectEventSprite(struct ObjectEventTemplate *objectEventTempl return objectEventId; } -static u8 TrySpawnObjectEventTemplate(struct ObjectEventTemplate *objectEventTemplate, u8 mapNum, u8 mapGroup, s16 cameraX, s16 cameraY) +static u8 TrySpawnObjectEventTemplate(const struct ObjectEventTemplate *objectEventTemplate, u8 mapNum, u8 mapGroup, s16 cameraX, s16 cameraY) { u8 objectEventId; struct SpriteTemplate spriteTemplate; @@ -1513,7 +1513,7 @@ u8 SpawnSpecialObjectEventParameterized(u8 graphicsId, u8 movementBehavior, u8 l u8 TrySpawnObjectEvent(u8 localId, u8 mapNum, u8 mapGroup) { - struct ObjectEventTemplate *objectEventTemplate; + const struct ObjectEventTemplate *objectEventTemplate; s16 cameraX, cameraY; objectEventTemplate = GetObjectEventTemplateByLocalIdAndMap(localId, mapNum, mapGroup); @@ -1543,7 +1543,7 @@ static void CopyObjectGraphicsInfoToSpriteTemplate_WithMovementType(u16 graphics CopyObjectGraphicsInfoToSpriteTemplate(graphicsId, sMovementTypeCallbacks[movementType], spriteTemplate, subspriteTables); } -static void MakeSpriteTemplateFromObjectEventTemplate(struct ObjectEventTemplate *objectEventTemplate, struct SpriteTemplate *spriteTemplate, const struct SubspriteTable **subspriteTables) +static void MakeSpriteTemplateFromObjectEventTemplate(const struct ObjectEventTemplate *objectEventTemplate, struct SpriteTemplate *spriteTemplate, const struct SubspriteTable **subspriteTables) { CopyObjectGraphicsInfoToSpriteTemplate_WithMovementType(objectEventTemplate->graphicsId, objectEventTemplate->movementType, spriteTemplate, subspriteTables); } @@ -2375,7 +2375,7 @@ const u8 *GetObjectEventScriptPointerByObjectEventId(u8 objectEventId) static u16 GetObjectEventFlagIdByLocalIdAndMap(u8 localId, u8 mapNum, u8 mapGroup) { - struct ObjectEventTemplate *obj = GetObjectEventTemplateByLocalIdAndMap(localId, mapNum, mapGroup); + const struct ObjectEventTemplate *obj = GetObjectEventTemplateByLocalIdAndMap(localId, mapNum, mapGroup); #ifdef UBFIX // BUG: The function may return NULL, and attempting to read from NULL may freeze the game using modern compilers. if (obj == NULL) @@ -2422,9 +2422,9 @@ u8 GetObjectEventBerryTreeId(u8 objectEventId) return gObjectEvents[objectEventId].trainerRange_berryTreeId; } -static struct ObjectEventTemplate *GetObjectEventTemplateByLocalIdAndMap(u8 localId, u8 mapNum, u8 mapGroup) +static const struct ObjectEventTemplate *GetObjectEventTemplateByLocalIdAndMap(u8 localId, u8 mapNum, u8 mapGroup) { - struct ObjectEventTemplate *templates; + const struct ObjectEventTemplate *templates; const struct MapHeader *mapHeader; u8 count; @@ -2442,7 +2442,7 @@ static struct ObjectEventTemplate *GetObjectEventTemplateByLocalIdAndMap(u8 loca return FindObjectEventTemplateByLocalId(localId, templates, count); } -static struct ObjectEventTemplate *FindObjectEventTemplateByLocalId(u8 localId, struct ObjectEventTemplate *templates, u8 count) +static const struct ObjectEventTemplate *FindObjectEventTemplateByLocalId(u8 localId, const struct ObjectEventTemplate *templates, u8 count) { u8 i; diff --git a/src/field_control_avatar.c b/src/field_control_avatar.c index 96e9173c9..a1575ba00 100644 --- a/src/field_control_avatar.c +++ b/src/field_control_avatar.c @@ -61,8 +61,8 @@ static s8 GetWarpEventAtMapPosition(struct MapHeader *, struct MapPosition *); static void SetupWarp(struct MapHeader *, s8, struct MapPosition *); static bool8 TryDoorWarp(struct MapPosition *, u16, u8); static s8 GetWarpEventAtPosition(struct MapHeader *, u16, u16, u8); -static u8 *GetCoordEventScriptAtPosition(struct MapHeader *, u16, u16, u8); -static struct BgEvent *GetBackgroundEventAtPosition(struct MapHeader *, u16, u16, u8); +static const u8 *GetCoordEventScriptAtPosition(struct MapHeader *, u16, u16, u8); +static const struct BgEvent *GetBackgroundEventAtPosition(struct MapHeader *, u16, u16, u8); static bool8 TryStartCoordEventScript(struct MapPosition *); static bool8 TryStartWarpEventScript(struct MapPosition *, u16); static bool8 TryStartMiscWalkingScripts(u16); @@ -334,7 +334,7 @@ static const u8 *GetInteractedObjectEventScript(struct MapPosition *position, u8 static const u8 *GetInteractedBackgroundEventScript(struct MapPosition *position, u8 metatileBehavior, u8 direction) { - struct BgEvent *bgEvent = GetBackgroundEventAtPosition(&gMapHeader, position->x - MAP_OFFSET, position->y - MAP_OFFSET, position->elevation); + const struct BgEvent *bgEvent = GetBackgroundEventAtPosition(&gMapHeader, position->x - MAP_OFFSET, position->y - MAP_OFFSET, position->elevation); if (bgEvent == NULL) return NULL; @@ -516,7 +516,7 @@ static bool8 TryStartStepBasedScript(struct MapPosition *position, u16 metatileB static bool8 TryStartCoordEventScript(struct MapPosition *position) { - u8 *script = GetCoordEventScriptAtPosition(&gMapHeader, position->x - MAP_OFFSET, position->y - MAP_OFFSET, position->elevation); + const u8 *script = GetCoordEventScriptAtPosition(&gMapHeader, position->x - MAP_OFFSET, position->y - MAP_OFFSET, position->elevation); if (script == NULL) return FALSE; @@ -565,11 +565,13 @@ static bool8 TryStartStepCountScript(u16 metatileBehavior) if (!(gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_FORCED_MOVE) && !MetatileBehavior_IsForcedMovementTile(metatileBehavior)) { + #if OW_POISON_DAMAGE < GEN_5 if (UpdatePoisonStepCounter() == TRUE) { ScriptContext_SetupScript(EventScript_FieldPoison); return TRUE; } + #endif if (ShouldEggHatch()) { IncrementGameStat(GAME_STAT_HATCHED_EGGS); @@ -883,7 +885,7 @@ static bool8 TryDoorWarp(struct MapPosition *position, u16 metatileBehavior, u8 static s8 GetWarpEventAtPosition(struct MapHeader *mapHeader, u16 x, u16 y, u8 elevation) { s32 i; - struct WarpEvent *warpEvent = mapHeader->events->warps; + const struct WarpEvent *warpEvent = mapHeader->events->warps; u8 warpCount = mapHeader->events->warpCount; for (i = 0; i < warpCount; i++, warpEvent++) @@ -897,7 +899,7 @@ static s8 GetWarpEventAtPosition(struct MapHeader *mapHeader, u16 x, u16 y, u8 e return WARP_ID_NONE; } -static u8 *TryRunCoordEventScript(struct CoordEvent *coordEvent) +static const u8 *TryRunCoordEventScript(const struct CoordEvent *coordEvent) { if (coordEvent != NULL) { @@ -917,10 +919,10 @@ static u8 *TryRunCoordEventScript(struct CoordEvent *coordEvent) return NULL; } -static u8 *GetCoordEventScriptAtPosition(struct MapHeader *mapHeader, u16 x, u16 y, u8 elevation) +static const u8 *GetCoordEventScriptAtPosition(struct MapHeader *mapHeader, u16 x, u16 y, u8 elevation) { s32 i; - struct CoordEvent *coordEvents = mapHeader->events->coordEvents; + const struct CoordEvent *coordEvents = mapHeader->events->coordEvents; u8 coordEventCount = mapHeader->events->coordEventCount; for (i = 0; i < coordEventCount; i++) @@ -929,7 +931,7 @@ static u8 *GetCoordEventScriptAtPosition(struct MapHeader *mapHeader, u16 x, u16 { if (coordEvents[i].elevation == elevation || coordEvents[i].elevation == 0) { - u8 *script = TryRunCoordEventScript(&coordEvents[i]); + const u8 *script = TryRunCoordEventScript(&coordEvents[i]); if (script != NULL) return script; } @@ -938,15 +940,15 @@ static u8 *GetCoordEventScriptAtPosition(struct MapHeader *mapHeader, u16 x, u16 return NULL; } -u8 *GetCoordEventScriptAtMapPosition(struct MapPosition *position) +const u8 *GetCoordEventScriptAtMapPosition(struct MapPosition *position) { return GetCoordEventScriptAtPosition(&gMapHeader, position->x - MAP_OFFSET, position->y - MAP_OFFSET, position->elevation); } -static struct BgEvent *GetBackgroundEventAtPosition(struct MapHeader *mapHeader, u16 x, u16 y, u8 elevation) +static const struct BgEvent *GetBackgroundEventAtPosition(struct MapHeader *mapHeader, u16 x, u16 y, u8 elevation) { u8 i; - struct BgEvent *bgEvents = mapHeader->events->bgEvents; + const struct BgEvent *bgEvents = mapHeader->events->bgEvents; u8 bgEventCount = mapHeader->events->bgEventCount; for (i = 0; i < bgEventCount; i++) diff --git a/src/field_poison.c b/src/field_poison.c index f254a6d14..202be30e2 100644 --- a/src/field_poison.c +++ b/src/field_poison.c @@ -15,6 +15,7 @@ #include "task.h" #include "trainer_hill.h" #include "constants/field_poison.h" +#include "constants/form_change_types.h" #include "constants/party_menu.h" static bool32 IsMonValidSpecies(struct Pokemon *pokemon) @@ -44,7 +45,9 @@ static void FaintFromFieldPoison(u8 partyIdx) struct Pokemon *pokemon = &gPlayerParty[partyIdx]; u32 status = STATUS1_NONE; +#if OW_POISON_DAMAGE < GEN_4 AdjustFriendship(pokemon, FRIENDSHIP_EVENT_FAINT_FIELD_PSN); +#endif SetMonData(pokemon, MON_DATA_STATUS, &status); GetMonData(pokemon, MON_DATA_NICKNAME, gStringVar1); StringGet_Nickname(gStringVar1); @@ -53,7 +56,11 @@ static void FaintFromFieldPoison(u8 partyIdx) static bool32 MonFaintedFromPoison(u8 partyIdx) { struct Pokemon *pokemon = &gPlayerParty[partyIdx]; +#if OW_POISON_DAMAGE < GEN_4 if (IsMonValidSpecies(pokemon) && GetMonData(pokemon, MON_DATA_HP) == 0 && GetAilmentFromStatus(GetMonData(pokemon, MON_DATA_STATUS)) == AILMENT_PSN) +#else + if (IsMonValidSpecies(pokemon) && GetMonData(pokemon, MON_DATA_HP) == 1 && GetAilmentFromStatus(GetMonData(pokemon, MON_DATA_STATUS)) == AILMENT_PSN) +#endif return TRUE; return FALSE; @@ -127,8 +134,16 @@ s32 DoPoisonFieldEffect(void) { // Apply poison damage hp = GetMonData(pokemon, MON_DATA_HP); + #if OW_POISON_DAMAGE < GEN_4 if (hp == 0 || --hp == 0) + { + TryFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_FAINT); numFainted++; + } + #else + if (hp == 1 || --hp == 1) + numFainted++; + #endif SetMonData(pokemon, MON_DATA_HP, &hp); numPoisoned++; diff --git a/src/fieldmap.c b/src/fieldmap.c index 89d6b602c..df4db47b5 100644 --- a/src/fieldmap.c +++ b/src/fieldmap.c @@ -36,7 +36,7 @@ struct BackupMapLayout gBackupMapLayout; static const struct ConnectionFlags sDummyConnectionFlags = {0}; static void InitMapLayoutData(struct MapHeader *mapHeader); -static void InitBackupMapLayoutData(u16 *map, u16 width, u16 height); +static void InitBackupMapLayoutData(const u16 *map, u16 width, u16 height); static void FillSouthConnection(struct MapHeader const *mapHeader, struct MapHeader const *connectedMapHeader, s32 offset); static void FillNorthConnection(struct MapHeader const *mapHeader, struct MapHeader const *connectedMapHeader, s32 offset); static void FillWestConnection(struct MapHeader const *mapHeader, struct MapHeader const *connectedMapHeader, s32 offset); @@ -44,14 +44,14 @@ static void FillEastConnection(struct MapHeader const *mapHeader, struct MapHead static void InitBackupMapLayoutConnections(struct MapHeader *mapHeader); static void LoadSavedMapView(void); static bool8 SkipCopyingMetatileFromSavedMap(u16 *mapBlock, u16 mapWidth, u8 yMode); -static struct MapConnection *GetIncomingConnection(u8 direction, int x, int y); -static bool8 IsPosInIncomingConnectingMap(u8 direction, int x, int y, struct MapConnection *connection); +static const struct MapConnection *GetIncomingConnection(u8 direction, int x, int y); +static bool8 IsPosInIncomingConnectingMap(u8 direction, int x, int y, const struct MapConnection *connection); static bool8 IsCoordInIncomingConnectingMap(int coord, int srcMax, int destMax, int offset); #define GetBorderBlockAt(x, y)({ \ u16 block; \ int i; \ - u16 *border = gMapHeader.mapLayout->border; \ + const u16 *border = gMapHeader.mapLayout->border; /* Unused, they read it again below */ \ \ i = (x + 1) & 1; \ i += ((y + 1) & 1) * 2; \ @@ -63,7 +63,7 @@ static bool8 IsCoordInIncomingConnectingMap(int coord, int srcMax, int destMax, #define GetMapGridBlockAt(x, y) (AreCoordsWithinMapGridBounds(x, y) ? gBackupMapLayout.map[x + gBackupMapLayout.width * y] : GetBorderBlockAt(x, y)) -struct MapHeader const *const GetMapHeaderFromConnection(struct MapConnection *connection) +const struct MapHeader *const GetMapHeaderFromConnection(const struct MapConnection *connection) { return Overworld_GetMapHeaderByGroupAndId(connection->mapGroup, connection->mapNum); } @@ -116,7 +116,7 @@ static void InitMapLayoutData(struct MapHeader *mapHeader) } } -static void InitBackupMapLayoutData(u16 *map, u16 width, u16 height) +static void InitBackupMapLayoutData(const u16 *map, u16 width, u16 height) { u16 *dest; int y; @@ -133,7 +133,7 @@ static void InitBackupMapLayoutData(u16 *map, u16 width, u16 height) static void InitBackupMapLayoutConnections(struct MapHeader *mapHeader) { int count; - struct MapConnection *connection; + const struct MapConnection *connection; int i; if (mapHeader->connections) @@ -171,7 +171,7 @@ static void InitBackupMapLayoutConnections(struct MapHeader *mapHeader) static void FillConnection(int x, int y, struct MapHeader const *connectedMapHeader, int x2, int y2, int width, int height) { int i; - u16 *src; + const u16 *src; u16 *dest; int mapWidth; @@ -619,7 +619,7 @@ bool32 CanCameraMoveInDirection(int direction) return TRUE; } -static void SetPositionFromConnection(struct MapConnection *connection, int direction, int x, int y) +static void SetPositionFromConnection(const struct MapConnection *connection, int direction, int x, int y) { struct MapHeader const *mapHeader; mapHeader = GetMapHeaderFromConnection(connection); @@ -647,7 +647,7 @@ static void SetPositionFromConnection(struct MapConnection *connection, int dire bool8 CameraMove(int x, int y) { int direction; - struct MapConnection *connection; + const struct MapConnection *connection; int old_x, old_y; gCamera.active = FALSE; direction = GetPostCameraMoveMapBorderId(x, y); @@ -675,11 +675,11 @@ bool8 CameraMove(int x, int y) return gCamera.active; } -static struct MapConnection *GetIncomingConnection(u8 direction, int x, int y) +static const struct MapConnection *GetIncomingConnection(u8 direction, int x, int y) { int count; int i; - struct MapConnection *connection; + const struct MapConnection *connection; const struct MapConnections *connections = gMapHeader.connections; #ifdef UBFIX // UB: Multiple possible null dereferences @@ -696,7 +696,7 @@ static struct MapConnection *GetIncomingConnection(u8 direction, int x, int y) return NULL; } -static bool8 IsPosInIncomingConnectingMap(u8 direction, int x, int y, struct MapConnection *connection) +static bool8 IsPosInIncomingConnectingMap(u8 direction, int x, int y, const struct MapConnection *connection) { struct MapHeader const *mapHeader; mapHeader = GetMapHeaderFromConnection(connection); @@ -737,7 +737,7 @@ static int IsCoordInConnectingMap(int coord, int max) return FALSE; } -static int IsPosInConnectingMap(struct MapConnection *connection, int x, int y) +static int IsPosInConnectingMap(const struct MapConnection *connection, int x, int y) { struct MapHeader const *mapHeader; mapHeader = GetMapHeaderFromConnection(connection); @@ -753,10 +753,10 @@ static int IsPosInConnectingMap(struct MapConnection *connection, int x, int y) return FALSE; } -struct MapConnection *GetMapConnectionAtPos(s16 x, s16 y) +const struct MapConnection *GetMapConnectionAtPos(s16 x, s16 y) { int count; - struct MapConnection *connection; + const struct MapConnection *connection; int i; u8 direction; if (!gMapHeader.connections) diff --git a/src/item.c b/src/item.c index db24cb82e..2c6937244 100644 --- a/src/item.c +++ b/src/item.c @@ -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_FROSTBITE: + 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 | STATUS1_FROSTBITE; + 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; +} diff --git a/src/item_menu.c b/src/item_menu.c index 4c66b0923..2a382b064 100755 --- a/src/item_menu.c +++ b/src/item_menu.c @@ -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) diff --git a/src/item_use.c b/src/item_use.c index dbdcc16d6..2f703a3a9 100644 --- a/src/item_use.c +++ b/src/item_use.c @@ -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}; @@ -380,7 +382,7 @@ static bool8 ItemfinderCheckForHiddenItems(const struct MapEvents *events, u8 ta static bool8 IsHiddenItemPresentAtCoords(const struct MapEvents *events, s16 x, s16 y) { u8 bgEventCount = events->bgEventCount; - struct BgEvent *bgEvent = events->bgEvents; + const struct BgEvent *bgEvent = events->bgEvents; int i; for (i = 0; i < bgEventCount; i++) @@ -396,7 +398,7 @@ static bool8 IsHiddenItemPresentAtCoords(const struct MapEvents *events, s16 x, return FALSE; } -static bool8 IsHiddenItemPresentInConnection(struct MapConnection *connection, int x, int y) +static bool8 IsHiddenItemPresentInConnection(const struct MapConnection *connection, int x, int y) { u16 localX, localY; @@ -461,7 +463,7 @@ static void CheckForHiddenItemsInMapConnection(u8 taskId) || var2 > y || y >= height) { - struct MapConnection *conn = GetMapConnectionAtPos(x, y); + const struct MapConnection *conn = GetMapConnectionAtPos(x, y); if (conn && IsHiddenItemPresentInConnection(conn, x, y) == TRUE) SetDistanceOfClosestHiddenItem(taskId, x - playerX, y - playerY); } @@ -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; } } @@ -1183,7 +1245,7 @@ void ItemUseOutOfBattle_EnigmaBerry(u8 taskId) case ITEM_EFFECT_CURE_POISON: case ITEM_EFFECT_CURE_SLEEP: case ITEM_EFFECT_CURE_BURN: - case ITEM_EFFECT_CURE_FREEZE: + case ITEM_EFFECT_CURE_FREEZE_FROSTBITE: case ITEM_EFFECT_CURE_PARALYSIS: case ITEM_EFFECT_CURE_ALL_STATUS: case ITEM_EFFECT_ATK_EV: @@ -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; diff --git a/src/mauville_old_man.c b/src/mauville_old_man.c index 90e3671cc..9bec5fd08 100644 --- a/src/mauville_old_man.c +++ b/src/mauville_old_man.c @@ -88,7 +88,7 @@ static void SetupHipster(void) struct MauvilleManHipster *hipster = &gSaveBlock1Ptr->oldMan.hipster; hipster->id = MAUVILLE_MAN_HIPSTER; - hipster->alreadySpoken = FALSE; + hipster->taughtWord = FALSE; hipster->language = gGameLanguage; } @@ -225,27 +225,28 @@ void PlayBardSong(void) ScriptContext_Stop(); } -void GetHipsterSpokenFlag(void) +void HasHipsterTaughtWord(void) { - gSpecialVar_Result = (&gSaveBlock1Ptr->oldMan.hipster)->alreadySpoken; + gSpecialVar_Result = (&gSaveBlock1Ptr->oldMan.hipster)->taughtWord; } -void SetHipsterSpokenFlag(void) +void SetHipsterTaughtWord(void) { - (&gSaveBlock1Ptr->oldMan.hipster)->alreadySpoken = TRUE; + (&gSaveBlock1Ptr->oldMan.hipster)->taughtWord = TRUE; } void HipsterTryTeachWord(void) { - u16 phrase = GetNewHipsterPhraseToTeach(); + u16 word = UnlockRandomTrendySaying(); - if (phrase == EC_EMPTY_WORD) + if (word == EC_EMPTY_WORD) { + // All words already unlocked gSpecialVar_Result = FALSE; } else { - CopyEasyChatWord(gStringVar1, phrase); + CopyEasyChatWord(gStringVar1, word); gSpecialVar_Result = TRUE; } } @@ -369,7 +370,7 @@ static void ResetBardFlag(void) static void ResetHipsterFlag(void) { - (&gSaveBlock1Ptr->oldMan.hipster)->alreadySpoken = FALSE; + (&gSaveBlock1Ptr->oldMan.hipster)->taughtWord = FALSE; } static void ResetTraderFlag(void) diff --git a/src/mystery_event_script.c b/src/mystery_event_script.c index 124ababa4..b146bbab3 100644 --- a/src/mystery_event_script.c +++ b/src/mystery_event_script.c @@ -293,7 +293,7 @@ bool8 MEScrCmd_givenationaldex(struct ScriptContext *ctx) bool8 MEScrCmd_addrareword(struct ScriptContext *ctx) { - UnlockAdditionalPhrase(ScriptReadByte(ctx)); + UnlockTrendySaying(ScriptReadByte(ctx)); StringExpandPlaceholders(gStringVar4, gText_MysteryEventRareWord); ctx->mStatus = MEVENT_STATUS_SUCCESS; return FALSE; diff --git a/src/overworld.c b/src/overworld.c index 6b63a60d5..2e9959b87 100644 --- a/src/overworld.c +++ b/src/overworld.c @@ -156,7 +156,7 @@ static void InitMenuBasedScript(const u8 *); static void LoadCableClubPlayer(s32, s32, struct CableClubPlayer *); static bool32 IsCableClubPlayerUnfrozen(struct CableClubPlayer *); static bool32 CanCableClubPlayerPressStart(struct CableClubPlayer *); -static u8 *TryGetTileEventScript(struct CableClubPlayer *); +static const u8 *TryGetTileEventScript(struct CableClubPlayer *); static bool32 PlayerIsAtSouthExit(struct CableClubPlayer *); static const u8 *TryInteractWithPlayer(struct CableClubPlayer *); static u16 KeyInterCB_DeferToRecvQueue(u32); @@ -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. @@ -487,7 +506,7 @@ void LoadObjEventTemplatesFromHeader(void) void LoadSaveblockObjEventScripts(void) { - struct ObjectEventTemplate *mapHeaderObjTemplates = gMapHeader.events->objectEvents; + const struct ObjectEventTemplate *mapHeaderObjTemplates = gMapHeader.events->objectEvents; struct ObjectEventTemplate *savObjTemplates = gSaveBlock1Ptr->objectEventTemplates; s32 i; @@ -2719,7 +2738,7 @@ static bool32 CanCableClubPlayerPressStart(struct CableClubPlayer *player) return FALSE; } -static u8 *TryGetTileEventScript(struct CableClubPlayer *player) +static const u8 *TryGetTileEventScript(struct CableClubPlayer *player) { if (player->movementMode != MOVEMENT_MODE_SCRIPTED) return FACING_NONE; diff --git a/src/party_menu.c b/src/party_menu.c index 9185657a7..773495a4d 100755 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -66,6 +66,7 @@ #include "constants/battle.h" #include "constants/battle_frontier.h" #include "constants/field_effects.h" +#include "constants/form_change_types.h" #include "constants/item_effects.h" #include "constants/items.h" #include "constants/moves.h" @@ -390,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); @@ -480,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" @@ -1354,6 +1358,24 @@ static void HandleChooseMonSelection(u8 taskId, s8 *slotPtr) TryEnterMonForMinigame(taskId, (u8)*slotPtr); } break; + case PARTY_ACTION_CHOOSE_FAINTED_MON: + { + u8 partyId = GetPartyIdFromBattleSlot((u8)*slotPtr); + if (GetMonData(&gPlayerParty[*slotPtr], MON_DATA_HP) > 0 + || GetMonData(&gPlayerParty[*slotPtr], MON_DATA_SPECIES_OR_EGG) == SPECIES_EGG + || ((gBattleTypeFlags & BATTLE_TYPE_MULTI) && partyId >= (PARTY_SIZE / 2))) + { + // Can't select if egg, alive, or doesn't belong to you + PlaySE(SE_FAILURE); + } + else + { + PlaySE(SE_SELECT); + gSelectedMonPartyId = partyId; + Task_ClosePartyMenu(taskId); + } + break; + } default: case PARTY_ACTION_ABILITY_PREVENTS: case PARTY_ACTION_SWITCHING: @@ -1379,6 +1401,7 @@ static void HandleChooseMonCancel(u8 taskId, s8 *slotPtr) switch (gPartyMenu.action) { case PARTY_ACTION_SEND_OUT: + case PARTY_ACTION_CHOOSE_FAINTED_MON: PlaySE(SE_FAILURE); break; case PARTY_ACTION_SWITCH: @@ -1919,6 +1942,8 @@ u8 GetAilmentFromStatus(u32 status) return AILMENT_FRZ; if (status & STATUS1_BURN) return AILMENT_BRN; + if (status & STATUS1_FROSTBITE) + return AILMENT_FSB; return AILMENT_NONE; } @@ -4282,12 +4307,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; @@ -4298,7 +4318,7 @@ static bool8 IsHPRecoveryItem(u16 item) return FALSE; } -static void GetMedicineItemEffectMessage(u16 item) +static void GetMedicineItemEffectMessage(u16 item, u32 statusCured) { switch (GetItemEffectType(item)) { @@ -4311,8 +4331,11 @@ static void GetMedicineItemEffectMessage(u16 item) case ITEM_EFFECT_CURE_BURN: StringExpandPlaceholders(gStringVar4, gText_PkmnBurnHealed); break; - case ITEM_EFFECT_CURE_FREEZE: - StringExpandPlaceholders(gStringVar4, gText_PkmnThawedOut); + case ITEM_EFFECT_CURE_FREEZE_FROSTBITE: + if (statusCured & STATUS1_FREEZE) + StringExpandPlaceholders(gStringVar4, gText_PkmnThawedOut); + if (statusCured & STATUS1_FROSTBITE) + StringExpandPlaceholders(gStringVar4, gText_PkmnFrostbiteHealed); break; case ITEM_EFFECT_CURE_PARALYSIS: StringExpandPlaceholders(gStringVar4, gText_PkmnCuredOfParalysis); @@ -4377,18 +4400,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) @@ -4397,6 +4496,7 @@ void ItemUseCB_Medicine(u8 taskId, TaskFunc task) struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId]; u16 item = gSpecialVar_ItemId; bool8 canHeal, cannotUse; + u32 oldStatus = GetMonData(mon, MON_DATA_STATUS); if (NotUsingHPEVItemOnShedinja(mon, item) == FALSE) { @@ -4411,7 +4511,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) @@ -4449,7 +4549,7 @@ void ItemUseCB_Medicine(u8 taskId, TaskFunc task) else { GetMonNickname(mon, gStringVar1); - GetMedicineItemEffectMessage(item); + GetMedicineItemEffectMessage(item, oldStatus); DisplayPartyMenuMessage(gStringVar4, TRUE); ScheduleBgCopyTilemapToVram(2); gTasks[taskId].func = task; @@ -4672,7 +4772,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); @@ -4788,25 +4888,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 { @@ -4817,11 +4911,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) @@ -4832,34 +4926,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, 0); + DisplayPartyMenuMessage(gStringVar4, TRUE); + ScheduleBgCopyTilemapToVram(2); + gTasks[taskId].func = Task_ClosePartyMenuAfterText; + } } } @@ -4973,7 +5091,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); @@ -5173,7 +5291,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 @@ -5440,7 +5558,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; @@ -5507,7 +5625,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); @@ -5620,7 +5738,7 @@ static void Task_TryItemUseFormChange(u8 taskId) bool32 TryItemUseFormChange(u8 taskId, TaskFunc task) { struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId]; - u16 targetSpecies = GetFormChangeTargetSpecies(mon, ItemId_GetSecondaryId(gSpecialVar_ItemId), gSpecialVar_ItemId); + u16 targetSpecies = GetFormChangeTargetSpecies(mon, FORM_CHANGE_ITEM_USE, gSpecialVar_ItemId); if (targetSpecies != SPECIES_NONE) { @@ -5655,7 +5773,7 @@ void ItemUseCB_FormChange_ConsumedOnUse(u8 taskId, TaskFunc task) } void TryItemHoldFormChange(struct Pokemon *mon) { - u16 targetSpecies = GetFormChangeTargetSpecies(mon, FORM_ITEM_HOLD, 0); + u16 targetSpecies = GetFormChangeTargetSpecies(mon, FORM_CHANGE_ITEM_HOLD, 0); if (targetSpecies != SPECIES_NONE) { PlayCry_NormalNoDucking(targetSpecies, 0, CRY_VOLUME_RS, CRY_VOLUME_RS); @@ -5672,16 +5790,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; @@ -5703,7 +5823,7 @@ u8 GetItemEffectType(u16 item) else if (statusCure == ITEM3_BURN) return ITEM_EFFECT_CURE_BURN; else if (statusCure == ITEM3_FREEZE) - return ITEM_EFFECT_CURE_FREEZE; + return ITEM_EFFECT_CURE_FREEZE_FROSTBITE; else if (statusCure == ITEM3_PARALYSIS) return ITEM_EFFECT_CURE_PARALYSIS; else if (statusCure == ITEM3_CONFUSION) diff --git a/src/pokemon.c b/src/pokemon.c index f9f7d811d..ec63332fe 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -42,6 +42,7 @@ #include "constants/battle_frontier.h" #include "constants/battle_move_effects.h" #include "constants/battle_script_commands.h" +#include "constants/form_change_types.h" #include "constants/hold_effects.h" #include "constants/item_effects.h" #include "constants/items.h" @@ -1919,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 }, @@ -4138,13 +4139,14 @@ void CalculateMonStats(struct Pokemon *mon) { if (currentHP == 0 && oldMaxHP == 0) currentHP = newMaxHP; - else if (currentHP != 0) { - // BUG: currentHP is unintentionally able to become <= 0 after the instruction below. This causes the pomeg berry glitch. - currentHP += newMaxHP - oldMaxHP; - #ifdef BUGFIX + else if (currentHP != 0) + { + if (newMaxHP > oldMaxHP) + currentHP += newMaxHP - oldMaxHP; if (currentHP <= 0) currentHP = 1; - #endif + if (currentHP > newMaxHP) + currentHP = newMaxHP; } else return; @@ -4235,6 +4237,17 @@ void SetMonMoveSlot(struct Pokemon *mon, u16 move, u8 slot) SetMonData(mon, MON_DATA_PP1 + slot, &gBattleMoves[move].pp); } +static void SetMonMoveSlot_KeepPP(struct Pokemon *mon, u16 move, u8 slot) +{ + u8 ppBonuses = GetMonData(mon, MON_DATA_PP_BONUSES, NULL); + u8 currPP = GetMonData(mon, MON_DATA_PP1 + slot, NULL); + u8 newPP = CalculatePPWithBonus(move, ppBonuses, slot); + u8 finalPP = min(currPP, newPP); + + SetMonData(mon, MON_DATA_MOVE1 + slot, &move); + SetMonData(mon, MON_DATA_PP1 + slot, &finalPP); +} + void SetBattleMonMoveSlot(struct BattlePokemon *mon, u16 move, u8 slot) { mon->moves[slot] = move; @@ -5736,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++) @@ -5793,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: @@ -5879,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) @@ -5915,27 +5809,16 @@ 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) retVal = FALSE; - if ((itemEffect[i] & ITEM3_FREEZE) && HealStatusConditions(mon, partyIndex, STATUS1_FREEZE, battlerId) == 0) + if ((itemEffect[i] & ITEM3_FREEZE) && HealStatusConditions(mon, partyIndex, STATUS1_FREEZE | STATUS1_FROSTBITE, battlerId) == 0) 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) @@ -5984,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; @@ -6010,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; } @@ -6022,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 @@ -6081,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); @@ -6134,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; } } @@ -6160,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; } } @@ -6220,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; @@ -6246,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; } @@ -6812,6 +6643,11 @@ u16 GetEvolutionTargetSpecies(struct Pokemon *mon, u8 mode, u16 evolutionItem, s if (GetMonGender(mon) == MON_MALE && gEvolutionTable[species][i].param == evolutionItem) targetSpecies = gEvolutionTable[species][i].targetSpecies; break; + case EVO_ITEM_NIGHT: + RtcCalcLocalTime(); + if (gLocalTime.hours >= 0 && gLocalTime.hours < 12 && gEvolutionTable[species][i].param == evolutionItem) + targetSpecies = gEvolutionTable[species][i].targetSpecies; + break; } } break; @@ -8488,18 +8324,18 @@ u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *boxMon, u16 method, u32 heldItem = GetBoxMonData(boxMon, MON_DATA_HELD_ITEM, NULL); ability = GetAbilityBySpecies(species, GetBoxMonData(boxMon, MON_DATA_ABILITY_NUM, NULL)); - for (i = 0; formChanges[i].method != FORM_CHANGE_END; i++) + for (i = 0; formChanges[i].method != FORM_CHANGE_TERMINATOR; i++) { if (method == formChanges[i].method && species != formChanges[i].targetSpecies) { switch (method) { - case FORM_ITEM_HOLD: + case FORM_CHANGE_ITEM_HOLD: if ((heldItem == formChanges[i].param1 || formChanges[i].param1 == ITEM_NONE) && (ability == formChanges[i].param2 || formChanges[i].param2 == ABILITY_NONE)) targetSpecies = formChanges[i].targetSpecies; break; - case FORM_ITEM_USE: + case FORM_CHANGE_ITEM_USE: if (arg == formChanges[i].param1) { switch (formChanges[i].param2) @@ -8520,14 +8356,23 @@ u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *boxMon, u16 method, u32 } } break; - case FORM_MOVE: + case FORM_CHANGE_MOVE: if (BoxMonKnowsMove(boxMon, formChanges[i].param1) != formChanges[i].param2) targetSpecies = formChanges[i].targetSpecies; break; - case FORM_BATTLE_BEGIN: - case FORM_BATTLE_END: + case FORM_CHANGE_BEGIN_BATTLE: + case FORM_CHANGE_END_BATTLE: if (heldItem == formChanges[i].param1 || formChanges[i].param1 == ITEM_NONE) targetSpecies = formChanges[i].targetSpecies; + break; + case FORM_CHANGE_END_BATTLE_TERRAIN: + if (gBattleTerrain == formChanges[i].param1) + targetSpecies = formChanges[i].targetSpecies; + break; + case FORM_CHANGE_WITHDRAW: + case FORM_CHANGE_FAINT: + targetSpecies = formChanges[i].targetSpecies; + break; } } } @@ -8536,6 +8381,23 @@ u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *boxMon, u16 method, u32 return targetSpecies; } +bool32 DoesSpeciesHaveFormChangeMethod(u16 species, u16 method) +{ + u32 i, j; + const struct FormChange *formChanges = gFormChangeTablePointers[species]; + + if (formChanges != NULL) + { + for (i = 0; formChanges[i].method != FORM_CHANGE_TERMINATOR; i++) + { + if (method == formChanges[i].method && species != formChanges[i].targetSpecies) + return TRUE; + } + } + + return FALSE; +} + u16 MonTryLearningNewMoveEvolution(struct Pokemon *mon, bool8 firstMove) { u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL); @@ -8618,20 +8480,47 @@ bool32 ShouldShowFemaleDifferences(u16 species, u32 personality) return (gSpeciesInfo[species].flags & SPECIES_FLAG_GENDER_DIFFERENCE) && GetGenderFromSpeciesAndPersonality(species, personality) == MON_FEMALE; } -void TryToSetBattleFormChangeMoves(struct Pokemon *mon) +bool32 TryFormChange(u32 monId, u32 side, u16 method) +{ + struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; + u16 targetSpecies; + + if (GetMonData(&party[monId], MON_DATA_SPECIES_OR_EGG, 0) == SPECIES_NONE + || GetMonData(&party[monId], MON_DATA_SPECIES_OR_EGG, 0) == SPECIES_EGG) + return FALSE; + + targetSpecies = GetFormChangeTargetSpecies(&party[monId], method, 0); + + if (targetSpecies == SPECIES_NONE && gBattleStruct != NULL) + targetSpecies = gBattleStruct->changedSpecies[monId]; + + if (targetSpecies != SPECIES_NONE) + { + TryToSetBattleFormChangeMoves(&party[monId], method); + SetMonData(&party[monId], MON_DATA_SPECIES, &targetSpecies); + CalculateMonStats(&party[monId]); + return TRUE; + } + + return FALSE; +} + +void TryToSetBattleFormChangeMoves(struct Pokemon *mon, u16 method) { int i, j; u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL); const struct FormChange *formChanges = gFormChangeTablePointers[species]; - u8 ppBonuses = GetMonData(mon, MON_DATA_PP_BONUSES, NULL); - if (formChanges == NULL) + if (formChanges == NULL + || (method != FORM_CHANGE_BEGIN_BATTLE && method != FORM_CHANGE_END_BATTLE)) return; - for (i = 0; formChanges[i].method != FORM_CHANGE_END; i++) + for (i = 0; formChanges[i].method != FORM_CHANGE_TERMINATOR; i++) { - if ((formChanges[i].method == FORM_BATTLE_BEGIN || formChanges[i].method == FORM_BATTLE_END) - && formChanges[i].param2 && formChanges[i].param3 && formChanges[i].targetSpecies == species) + if (formChanges[i].method == method + && formChanges[i].param2 + && formChanges[i].param3 + && formChanges[i].targetSpecies != species) { u16 originalMove = formChanges[i].param2; u16 newMove = formChanges[i].param3; @@ -8639,20 +8528,9 @@ void TryToSetBattleFormChangeMoves(struct Pokemon *mon) for (j = 0; j < MAX_MON_MOVES; j++) { u16 currMove = GetMonData(mon, MON_DATA_MOVE1 + j, NULL); - u8 totalPp = gBattleMoves[currMove].pp; // Get current move's max PP - u8 currPp = GetMonData(mon, MON_DATA_PP1 + j, NULL); // Get current move's remaining PP - u8 diffPp = totalPp - currPp; // Current move's PP difference - u8 finalPp = gBattleMoves[newMove].pp - diffPp; // Apply the PP difference to the new move - if (currMove == originalMove) - { - if (finalPp > gBattleMoves[newMove].pp) - finalPp = 0; - SetMonMoveSlot(mon, newMove, j); - SetMonData(mon, MON_DATA_PP1 + j, &finalPp); - } + SetMonMoveSlot_KeepPP(mon, newMove, j); } - SetMonData(mon, MON_DATA_PP_BONUSES, &ppBonuses); break; } } diff --git a/src/pokemon_storage_system.c b/src/pokemon_storage_system.c index 7d9f71f55..1224a7dbe 100644 --- a/src/pokemon_storage_system.c +++ b/src/pokemon_storage_system.c @@ -36,6 +36,7 @@ #include "trig.h" #include "walda_phrase.h" #include "window.h" +#include "constants/form_change_types.h" #include "constants/items.h" #include "constants/moves.h" #include "constants/rgb.h" @@ -6893,7 +6894,7 @@ static void ReshowDisplayMon(void) void SetMonFormPSS(struct BoxPokemon *boxMon) { - u16 targetSpecies = GetFormChangeTargetSpeciesBoxMon(boxMon, FORM_ITEM_HOLD, 0); + u16 targetSpecies = GetFormChangeTargetSpeciesBoxMon(boxMon, FORM_CHANGE_ITEM_HOLD, 0); if (targetSpecies != SPECIES_NONE) { SetBoxMonData(boxMon, MON_DATA_SPECIES, &targetSpecies); diff --git a/src/pokemon_summary_screen.c b/src/pokemon_summary_screen.c index 331307626..f7106b875 100644 --- a/src/pokemon_summary_screen.c +++ b/src/pokemon_summary_screen.c @@ -1112,6 +1112,10 @@ static const union AnimCmd sSpriteAnim_StatusFaint[] = { ANIMCMD_FRAME(24, 0, FALSE, FALSE), ANIMCMD_END }; +static const union AnimCmd sSpriteAnim_StatusFrostbite[] = { + ANIMCMD_FRAME(28, 0, FALSE, FALSE), + ANIMCMD_END +}; static const union AnimCmd *const sSpriteAnimTable_StatusCondition[] = { sSpriteAnim_StatusPoison, sSpriteAnim_StatusParalyzed, @@ -1120,11 +1124,12 @@ static const union AnimCmd *const sSpriteAnimTable_StatusCondition[] = { sSpriteAnim_StatusBurn, sSpriteAnim_StatusPokerus, sSpriteAnim_StatusFaint, + sSpriteAnim_StatusFrostbite, }; static const struct CompressedSpriteSheet sStatusIconsSpriteSheet = { .data = gStatusGfx_Icons, - .size = 0x380, + .size = 0x400, .tag = TAG_MON_STATUS }; static const struct CompressedSpritePalette sStatusIconsSpritePalette = diff --git a/src/random.c b/src/random.c index e59b56387..14983e776 100644 --- a/src/random.c +++ b/src/random.c @@ -38,9 +38,12 @@ u32 RandomUniform(enum RandomTag tag, u32 lo, u32 hi); __attribute__((weak, alias("RandomWeightedArrayDefault"))) u32 RandomWeightedArray(enum RandomTag tag, u32 sum, u32 n, const u8 *weights); +__attribute__((weak, alias("RandomElementArrayDefault"))) +const void *RandomElementArray(enum RandomTag tag, const void *array, size_t size, size_t count); + u32 RandomUniformDefault(enum RandomTag tag, u32 lo, u32 hi) { - return lo + (((hi - lo) * Random()) >> 16); + return lo + (((hi - lo + 1) * Random()) >> 16); } u32 RandomWeightedArrayDefault(enum RandomTag tag, u32 sum, u32 n, const u8 *weights) @@ -55,3 +58,8 @@ u32 RandomWeightedArrayDefault(enum RandomTag tag, u32 sum, u32 n, const u8 *wei } return n - 1; } + +const void *RandomElementArrayDefault(enum RandomTag tag, const void *array, size_t size, size_t count) +{ + return (const u8 *)array + size * RandomUniformDefault(tag, 0, count - 1); +} diff --git a/src/script_pokemon_util.c b/src/script_pokemon_util.c index 15d5b2e5d..34f75ef8e 100755 --- a/src/script_pokemon_util.c +++ b/src/script_pokemon_util.c @@ -72,7 +72,7 @@ u8 ScriptGiveMon(u16 species, u8 level, u16 item, u32 unused1, u32 unused2, u8 u SetMonData(&mon, MON_DATA_HELD_ITEM, heldItem); // In case a mon with a form changing item is given. Eg: SPECIES_ARCEUS with ITEM_SPLASH_PLATE will transform into SPECIES_ARCEUS_WATER upon gifted. - targetSpecies = GetFormChangeTargetSpecies(&mon, FORM_ITEM_HOLD, 0); + targetSpecies = GetFormChangeTargetSpecies(&mon, FORM_CHANGE_ITEM_HOLD, 0); if (targetSpecies != SPECIES_NONE) { SetMonData(&mon, MON_DATA_SPECIES, &targetSpecies); diff --git a/src/shop.c b/src/shop.c index 8fea1e117..b4978f063 100644 --- a/src/shop.c +++ b/src/shop.c @@ -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); diff --git a/src/strings.c b/src/strings.c index 8815212e0..eb7bb8ba1 100644 --- a/src/strings.c +++ b/src/strings.c @@ -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?"); @@ -412,6 +414,7 @@ const u8 gText_PkmnCuredOfPoison[] = _("{STR_VAR_1} was cured of its\npoisoning. const u8 gText_PkmnCuredOfParalysis[] = _("{STR_VAR_1} was cured of\nparalysis.{PAUSE_UNTIL_PRESS}"); const u8 gText_PkmnWokeUp2[] = _("{STR_VAR_1} woke up.{PAUSE_UNTIL_PRESS}"); const u8 gText_PkmnBurnHealed[] = _("{STR_VAR_1}'s burn was healed.{PAUSE_UNTIL_PRESS}"); +const u8 gText_PkmnFrostbiteHealed[] = _("{STR_VAR_1}'s frostbite was healed.{PAUSE_UNTIL_PRESS}"); const u8 gText_PkmnThawedOut[] = _("{STR_VAR_1} was thawed out.{PAUSE_UNTIL_PRESS}"); const u8 gText_PPWasRestored[] = _("PP was restored.{PAUSE_UNTIL_PRESS}"); const u8 gText_PkmnRegainhedHealth[] = _("{STR_VAR_1} regained health.{PAUSE_UNTIL_PRESS}"); // Unused @@ -1191,7 +1194,11 @@ const u8 gText_PsychUp48BP[] = _("PSYCH UP{CLEAR_TO 0x4E}48BP"); const u8 gText_IcePunch48BP[] = _("ICE PUNCH{CLEAR_TO 0x4E}48BP"); const u8 gText_ThunderPunch48BP[] = _("THUNDERPUNCH{CLEAR_TO 0x4E}48BP"); const u8 gText_FirePunch48BP[] = _("FIRE PUNCH{CLEAR_TO 0x4E}48BP"); +#if OW_POISON_DAMAGE < GEN_4 const u8 gText_PkmnFainted_FldPsn[] = _("{STR_VAR_1} fainted…\p\n"); +#else +const u8 gText_PkmnFainted_FldPsn[] = _("{STR_VAR_1} survived the poisoning.\nThe poison faded away!\p"); +#endif const u8 gText_Marco[] = _("MARCO"); const u8 gText_TrainerCardName[] = _("NAME: "); const u8 gText_TrainerCardIDNo[] = _("IDNo."); diff --git a/src/trainer_hill.c b/src/trainer_hill.c index f6ee9e818..2995a2cb2 100644 --- a/src/trainer_hill.c +++ b/src/trainer_hill.c @@ -685,7 +685,8 @@ static u16 GetMetatileForFloor(u8 floorId, u32 x, u32 y, u32 floorWidth) // floo void GenerateTrainerHillFloorLayout(u16 *mapArg) { s32 y, x; - u16 *src, *dst; + const u16 *src; + u16 *dst; u8 mapId = GetCurrentTrainerHillMapId(); if (mapId == TRAINER_HILL_ENTRANCE) diff --git a/src/wild_encounter.c b/src/wild_encounter.c index d228b87a1..ef668c3a1 100644 --- a/src/wild_encounter.c +++ b/src/wild_encounter.c @@ -1097,7 +1097,11 @@ static void ApplyCleanseTagEncounterRateMod(u32 *encRate) bool8 TryDoDoubleWildBattle(void) { +#if B_DOUBLE_WILD_REQUIRE_2_MONS == TRUE if (GetSafariZoneFlag() || GetMonsStateToDoubles() != PLAYER_HAS_TWO_USABLE_MONS) +#else + if (GetSafariZoneFlag()) +#endif return FALSE; #if B_FLAG_FORCE_DOUBLE_WILD != 0 else if (FlagGet(B_FLAG_FORCE_DOUBLE_WILD)) diff --git a/test/ability_contrary.c b/test/ability_contrary.c index 7fd902280..33cfa7ce8 100644 --- a/test/ability_contrary.c +++ b/test/ability_contrary.c @@ -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!"); diff --git a/test/ability_download.c b/test/ability_download.c index 132c0eb5b..d83d90196 100644 --- a/test/ability_download.c +++ b/test/ability_download.c @@ -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); diff --git a/test/ability_hunger_switch.c b/test/ability_hunger_switch.c new file mode 100644 index 000000000..9250ae85a --- /dev/null +++ b/test/ability_hunger_switch.c @@ -0,0 +1,25 @@ +#include "global.h" +#include "test_battle.h" + +SINGLE_BATTLE_TEST("Hunger Switch switches Morpeko's forms at the end of the turn") +{ + u16 species; + PARAMETRIZE { species = SPECIES_MORPEKO; } + PARAMETRIZE { species = SPECIES_MORPEKO_HANGRY; } + GIVEN { + ASSUME(P_GEN_8_POKEMON == TRUE); + PLAYER(species) { Speed(2); }; + OPPONENT(SPECIES_WOBBUFFET) { Speed(1); }; + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); } + } SCENE { + MESSAGE("Morpeko used Celebrate!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + } THEN { + if (species == SPECIES_MORPEKO) + EXPECT_EQ(player->species, SPECIES_MORPEKO_HANGRY); + else + EXPECT_EQ(player->species, SPECIES_MORPEKO); + } +} diff --git a/test/ability_intimidate.c b/test/ability_intimidate.c index a891f9af8..40804cbb1 100644 --- a/test/ability_intimidate.c +++ b/test/ability_intimidate.c @@ -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); diff --git a/test/ability_magic_bounce.c b/test/ability_magic_bounce.c index d52b93c4a..848f632ab 100644 --- a/test/ability_magic_bounce.c +++ b/test/ability_magic_bounce.c @@ -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!"); } } diff --git a/test/ability_oblivious.c b/test/ability_oblivious.c index 0708845ed..efe2901ec 100644 --- a/test/ability_oblivious.c +++ b/test/ability_oblivious.c @@ -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!"); } } diff --git a/test/ability_schooling.c b/test/ability_schooling.c new file mode 100644 index 000000000..03a5303f0 --- /dev/null +++ b/test/ability_schooling.c @@ -0,0 +1,111 @@ +#include "global.h" +#include "test_battle.h" + +SINGLE_BATTLE_TEST("Schooling switches Level 20+ Wishiwashi's form when HP is 25-percent or less at the end of the turn") +{ + u16 level; + PARAMETRIZE { level = 19; } + PARAMETRIZE { level = 20; } + + GIVEN { + ASSUME(P_GEN_7_POKEMON == TRUE); + ASSUME(gSpeciesInfo[SPECIES_WISHIWASHI].baseHP == gSpeciesInfo[SPECIES_WISHIWASHI_SCHOOL].baseHP); + PLAYER(SPECIES_WISHIWASHI) + { + Level(level); + HP(GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP) / 2); + Ability(ABILITY_SCHOOLING); + }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_SUPER_FANG); } + } SCENE { + if (level >= 20) + { + ABILITY_POPUP(player, ABILITY_SCHOOLING); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + } + MESSAGE("Wishiwashi used Celebrate!"); + MESSAGE("Foe Wobbuffet used Super Fang!"); + HP_BAR(player); + if (level >= 20) + { + ABILITY_POPUP(player, ABILITY_SCHOOLING); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + } + } THEN { + EXPECT_EQ(player->species, SPECIES_WISHIWASHI); + } +} + +SINGLE_BATTLE_TEST("Schooling switches Level 20+ Wishiwashi's form when HP is over 25-percent before the first turn") +{ + u16 level; + bool32 overQuarterHP; + PARAMETRIZE { level = 19; overQuarterHP = FALSE; } + PARAMETRIZE { level = 20; overQuarterHP = FALSE; } + PARAMETRIZE { level = 19; overQuarterHP = TRUE; } + PARAMETRIZE { level = 20; overQuarterHP = TRUE; } + + GIVEN { + ASSUME(P_GEN_7_POKEMON == TRUE); + ASSUME(gSpeciesInfo[SPECIES_WISHIWASHI].baseHP == gSpeciesInfo[SPECIES_WISHIWASHI_SCHOOL].baseHP); + PLAYER(SPECIES_WISHIWASHI) + { + Level(level); + HP(GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP) / (overQuarterHP ? 2 : 4)); + Ability(ABILITY_SCHOOLING); + }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); } + } SCENE { + if (level >= 20 && overQuarterHP) + { + ABILITY_POPUP(player, ABILITY_SCHOOLING); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + } + MESSAGE("Wishiwashi used Celebrate!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + } THEN { + if (level >= 20 && overQuarterHP) + EXPECT_EQ(player->species, SPECIES_WISHIWASHI_SCHOOL); + else + EXPECT_EQ(player->species, SPECIES_WISHIWASHI); + } +} + +SINGLE_BATTLE_TEST("Schooling switches Level 20+ Wishiwashi's form when HP is healed above 25-percent") +{ + u16 level; + PARAMETRIZE { level = 19; } + PARAMETRIZE { level = 20; } + + GIVEN { + ASSUME(P_GEN_7_POKEMON == TRUE); + ASSUME(gSpeciesInfo[SPECIES_WISHIWASHI].baseHP == gSpeciesInfo[SPECIES_WISHIWASHI_SCHOOL].baseHP); + PLAYER(SPECIES_WISHIWASHI) + { + Level(level); + HP(GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP) / 4); + Ability(ABILITY_SCHOOLING); + }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_HEAL_PULSE); } + } SCENE { + MESSAGE("Wishiwashi used Celebrate!"); + MESSAGE("Foe Wobbuffet used Heal Pulse!"); + HP_BAR(player); + if (level >= 20) + { + ABILITY_POPUP(player, ABILITY_SCHOOLING); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + } + } THEN { + if (level >= 20) + EXPECT_EQ(player->species, SPECIES_WISHIWASHI_SCHOOL); + else + EXPECT_EQ(player->species, SPECIES_WISHIWASHI); + } +} diff --git a/test/ability_speed_boost.c b/test/ability_speed_boost.c index b3e128931..39219a5cc 100644 --- a/test/ability_speed_boost.c +++ b/test/ability_speed_boost.c @@ -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); }; diff --git a/test/ability_volt_absorb.c b/test/ability_volt_absorb.c index bef35e2b4..18902eaa2 100644 --- a/test/ability_volt_absorb.c +++ b/test/ability_volt_absorb.c @@ -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!"); } } diff --git a/test/ability_zen_mode.c b/test/ability_zen_mode.c new file mode 100644 index 000000000..f18f6d659 --- /dev/null +++ b/test/ability_zen_mode.c @@ -0,0 +1,93 @@ +#include "global.h" +#include "test_battle.h" + +SINGLE_BATTLE_TEST("Zen Mode switches Darmanitan's form when HP is half or less at the end of the turn") +{ + u16 standardSpecies, zenSpecies; + PARAMETRIZE { standardSpecies = SPECIES_DARMANITAN; zenSpecies = SPECIES_DARMANITAN_ZEN_MODE; } + PARAMETRIZE { standardSpecies = SPECIES_DARMANITAN_GALARIAN; zenSpecies = SPECIES_DARMANITAN_ZEN_MODE_GALARIAN; } + + GIVEN { + ASSUME(P_GEN_5_POKEMON == TRUE); + ASSUME(gSpeciesInfo[standardSpecies].baseHP == 105); + ASSUME(gSpeciesInfo[zenSpecies].baseHP == 105); + PLAYER(standardSpecies) + { + Ability(ABILITY_ZEN_MODE); + HP((GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP) / 2) + 1); + }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_TACKLE); } + } SCENE { + MESSAGE("Darmanitan used Celebrate!"); + MESSAGE("Foe Wobbuffet used Tackle!"); + HP_BAR(player); + ABILITY_POPUP(player, ABILITY_ZEN_MODE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + } THEN { + ASSUME(player->hp <= player->maxHP / 2); + EXPECT_EQ(player->species, zenSpecies); + } +} + +SINGLE_BATTLE_TEST("Zen Mode switches Darmanitan's form when HP is half or less before the first turn") +{ + u16 standardSpecies, zenSpecies; + PARAMETRIZE { standardSpecies = SPECIES_DARMANITAN; zenSpecies = SPECIES_DARMANITAN_ZEN_MODE; } + PARAMETRIZE { standardSpecies = SPECIES_DARMANITAN_GALARIAN; zenSpecies = SPECIES_DARMANITAN_ZEN_MODE_GALARIAN; } + + GIVEN { + ASSUME(P_GEN_5_POKEMON == TRUE); + ASSUME(gSpeciesInfo[standardSpecies].baseHP == 105); + ASSUME(gSpeciesInfo[zenSpecies].baseHP == 105); + PLAYER(standardSpecies) + { + Ability(ABILITY_ZEN_MODE); + HP(GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP) / 2); + }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); } + } SCENE { + ABILITY_POPUP(player, ABILITY_ZEN_MODE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + MESSAGE("Darmanitan used Celebrate!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + } THEN { + EXPECT_LE(player->hp, player->maxHP / 2); + EXPECT_EQ(player->species, zenSpecies); + } +} + +SINGLE_BATTLE_TEST("Zen Mode switches Darmanitan's form when HP is healed above half") +{ + u16 standardSpecies, zenSpecies; + PARAMETRIZE { standardSpecies = SPECIES_DARMANITAN; zenSpecies = SPECIES_DARMANITAN_ZEN_MODE; } + PARAMETRIZE { standardSpecies = SPECIES_DARMANITAN_GALARIAN; zenSpecies = SPECIES_DARMANITAN_ZEN_MODE_GALARIAN; } + + GIVEN { + ASSUME(P_GEN_5_POKEMON == TRUE); + ASSUME(gSpeciesInfo[standardSpecies].baseHP == 105); + ASSUME(gSpeciesInfo[zenSpecies].baseHP == 105); + PLAYER(standardSpecies) + { + Ability(ABILITY_ZEN_MODE); + HP(GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP) / 2); + }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_HEAL_PULSE); } + } SCENE { + ABILITY_POPUP(player, ABILITY_ZEN_MODE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + MESSAGE("Darmanitan used Celebrate!"); + MESSAGE("Foe Wobbuffet used Heal Pulse!"); + HP_BAR(player); + ABILITY_POPUP(player, ABILITY_ZEN_MODE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + } THEN { + EXPECT_GT(player->hp, player->maxHP / 2); + EXPECT_EQ(player->species, standardSpecies); + } +} diff --git a/test/form_change.c b/test/form_change.c new file mode 100644 index 000000000..74ba2b75f --- /dev/null +++ b/test/form_change.c @@ -0,0 +1,119 @@ +#include "global.h" +#include "test_battle.h" + +SINGLE_BATTLE_TEST("Xerneas changes into Active Form upon battle start") +{ + GIVEN { + ASSUME(P_GEN_6_POKEMON == TRUE); + PLAYER(SPECIES_XERNEAS); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); } + } THEN { + EXPECT_EQ(player->species, SPECIES_XERNEAS_ACTIVE); + } +} + +SINGLE_BATTLE_TEST("Zacian changes into its Crowned Form when holding the Rusted Sword upon battle start") +{ + u16 item; + PARAMETRIZE { item = ITEM_NONE; } + PARAMETRIZE { item = ITEM_RUSTED_SWORD; } + GIVEN { + ASSUME(P_GEN_8_POKEMON == TRUE); + PLAYER(SPECIES_ZACIAN) { Item(item); }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); } + } THEN { + if (item == ITEM_NONE) + EXPECT_EQ(player->species, SPECIES_ZACIAN); + else + EXPECT_EQ(player->species, SPECIES_ZACIAN_CROWNED_SWORD); + } +} + +SINGLE_BATTLE_TEST("Zacian's Iron Head becomes Behemoth Blade upon form change") +{ + GIVEN { + ASSUME(P_GEN_8_POKEMON == TRUE); + PLAYER(SPECIES_ZACIAN) { Item(ITEM_RUSTED_SWORD); Moves(MOVE_IRON_HEAD, MOVE_CELEBRATE); }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); } + } THEN { + ASSUME(player->species == SPECIES_ZACIAN_CROWNED_SWORD); // Assumes form change worked. + EXPECT_EQ(player->moves[0], MOVE_BEHEMOTH_BLADE); + } +} + +SINGLE_BATTLE_TEST("Zamazenta changes into its Crowned Form when holding the Rusted Shield upon battle start") +{ + u16 item; + PARAMETRIZE { item = ITEM_NONE; } + PARAMETRIZE { item = ITEM_RUSTED_SHIELD; } + GIVEN { + ASSUME(P_GEN_8_POKEMON == TRUE); + PLAYER(SPECIES_ZAMAZENTA) { Item(item); }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); } + } THEN { + if (item == ITEM_NONE) + EXPECT_EQ(player->species, SPECIES_ZAMAZENTA); + else + EXPECT_EQ(player->species, SPECIES_ZAMAZENTA_CROWNED_SHIELD); + } +} + +SINGLE_BATTLE_TEST("Zamazenta's Iron Head becomes Behemoth Bash upon form change") +{ + GIVEN { + ASSUME(P_GEN_8_POKEMON == TRUE); + PLAYER(SPECIES_ZAMAZENTA) { Item(ITEM_RUSTED_SHIELD); Moves(MOVE_IRON_HEAD, MOVE_CELEBRATE); }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); } + } THEN { + ASSUME(player->species == SPECIES_ZAMAZENTA_CROWNED_SHIELD); // Assumes form change worked. + EXPECT_EQ(player->moves[0], MOVE_BEHEMOTH_BASH); + } +} + +SINGLE_BATTLE_TEST("Aegislash reverts to Shield Form upon switching out") +{ + GIVEN { + ASSUME(P_GEN_6_POKEMON == TRUE); + PLAYER(SPECIES_AEGISLASH); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + TURN { SWITCH(player, 1); } + TURN { SWITCH(player, 0); } + } SCENE { + ABILITY_POPUP(player, ABILITY_STANCE_CHANGE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + MESSAGE("Aegislash used Tackle!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + } THEN { + EXPECT_EQ(player->species, SPECIES_AEGISLASH); + } +} + +SINGLE_BATTLE_TEST("Aegislash reverts to Shield Form upon fainting") +{ + GIVEN { + ASSUME(P_GEN_6_POKEMON == TRUE); + PLAYER(SPECIES_AEGISLASH) { HP(1); }; + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_GUST); SEND_OUT(player, 1);} + } SCENE { + MESSAGE("Foe Wobbuffet used Gust!"); + MESSAGE("Aegislash fainted!"); + } THEN { + EXPECT_EQ(GetMonData(&PLAYER_PARTY[0], MON_DATA_SPECIES), SPECIES_AEGISLASH); + } +} diff --git a/test/hold_effect_berserk_gene.c b/test/hold_effect_berserk_gene.c new file mode 100644 index 000000000..361d14861 --- /dev/null +++ b/test/hold_effect_berserk_gene.c @@ -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); + } +} diff --git a/test/item_effect_increase_stat.c b/test/item_effect_increase_stat.c new file mode 100644 index 000000000..b459e3ac8 --- /dev/null +++ b/test/item_effect_increase_stat.c @@ -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); + } +} diff --git a/test/item_effect_restore_hp.c b/test/item_effect_restore_hp.c new file mode 100644 index 000000000..971ec2400 --- /dev/null +++ b/test/item_effect_restore_hp.c @@ -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); + } +} diff --git a/test/item_effect_restore_pp.c b/test/item_effect_restore_pp.c new file mode 100644 index 000000000..234d4ae4e --- /dev/null +++ b/test/item_effect_restore_pp.c @@ -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); + } +} diff --git a/test/move.c b/test/move.c index 9ad336330..9e23c2bd0 100644 --- a/test/move.c +++ b/test/move.c @@ -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); diff --git a/test/move_effect_attack_down.c b/test/move_effect_attack_down.c index 6333bbea1..0df14f701 100644 --- a/test/move_effect_attack_down.c +++ b/test/move_effect_attack_down.c @@ -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); diff --git a/test/move_effect_attack_up.c b/test/move_effect_attack_up.c index 7b57fa0d2..4978d03f9 100644 --- a/test/move_effect_attack_up.c +++ b/test/move_effect_attack_up.c @@ -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); diff --git a/test/move_effect_attack_up_user_ally.c b/test/move_effect_attack_up_user_ally.c index e98df30d8..e920752de 100644 --- a/test/move_effect_attack_up_user_ally.c +++ b/test/move_effect_attack_up_user_ally.c @@ -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); diff --git a/test/move_effect_burn_up.c b/test/move_effect_burn_up.c new file mode 100644 index 000000000..a53b1afa8 --- /dev/null +++ b/test/move_effect_burn_up.c @@ -0,0 +1,53 @@ +#include "global.h" +#include "test_battle.h" + +ASSUMPTIONS +{ + ASSUME(gBattleMoves[MOVE_BURN_UP].effect == EFFECT_BURN_UP); + ASSUME(gSpeciesInfo[SPECIES_WOBBUFFET].types[0] != TYPE_FIRE || gSpeciesInfo[SPECIES_WOBBUFFET].types[1] != TYPE_FIRE); + ASSUME(gSpeciesInfo[SPECIES_CYNDAQUIL].types[0] == TYPE_FIRE || gSpeciesInfo[SPECIES_CYNDAQUIL].types[1] == TYPE_FIRE); +} + +SINGLE_BATTLE_TEST("Burn Up user loses its Fire-type") +{ + GIVEN { + PLAYER(SPECIES_CYNDAQUIL); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_BURN_UP); } + TURN { MOVE(player, MOVE_BURN_UP); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BURN_UP, player); + MESSAGE("Cyndaquil burned itself out!"); + MESSAGE("Cyndaquil used Burn Up!"); + MESSAGE("But it failed!"); + } +} + +SINGLE_BATTLE_TEST("Burn Up fails if the user isn't a Fire-type") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_BURN_UP); } + } SCENE { + NONE_OF { ANIMATION(ANIM_TYPE_MOVE, MOVE_BURN_UP, player); } + MESSAGE("Wobbuffet used Burn Up!"); + MESSAGE("But it failed!"); + } +} + +SINGLE_BATTLE_TEST("Burn Up user loses its Fire-type if enemy faints") +{ + GIVEN { + PLAYER(SPECIES_CYNDAQUIL); + OPPONENT(SPECIES_WOBBUFFET) { HP(1); } + } WHEN { + TURN { MOVE(player, MOVE_BURN_UP); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BURN_UP, player); + HP_BAR(opponent, hp: 0); + MESSAGE("Cyndaquil burned itself out!"); + } +} diff --git a/test/move_effect_defense_down.c b/test/move_effect_defense_down.c index 6e5a45e84..9ecd1c25f 100644 --- a/test/move_effect_defense_down.c +++ b/test/move_effect_defense_down.c @@ -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); diff --git a/test/move_effect_defense_up.c b/test/move_effect_defense_up.c index 8db9a7f7e..492ce7bc9 100644 --- a/test/move_effect_defense_up.c +++ b/test/move_effect_defense_up.c @@ -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); diff --git a/test/move_effect_defog.c b/test/move_effect_defog.c index e9e55d57f..751ddf60f 100644 --- a/test/move_effect_defog.c +++ b/test/move_effect_defog.c @@ -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!"); } } } diff --git a/test/move_effect_dire_claw.c b/test/move_effect_dire_claw.c index f02555df3..2212c3cb0 100644 --- a/test/move_effect_dire_claw.c +++ b/test/move_effect_dire_claw.c @@ -6,21 +6,14 @@ ASSUMPTIONS ASSUME(gBattleMoves[MOVE_DIRE_CLAW].effect == EFFECT_DIRE_CLAW); } -// found by brute-force -#define RNG_SLEEP 0xcb0 -#define RNG_POISON 0x2BE -#define RNG_PARALYSIS 5 - SINGLE_BATTLE_TEST("Dire Claw can inflict poison, paralysis or sleep") { u8 statusAnim; - u32 rng; - KNOWN_FAILING; - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PSN; rng = RNG_POISON; } - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; } - PARAMETRIZE { statusAnim = B_ANIM_STATUS_SLP; rng = RNG_SLEEP; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_PSN; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_SLP; } + PASSES_RANDOMLY(1, 3, RNG_DIRE_CLAW); GIVEN { - RNGSeed(rng); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -48,15 +41,14 @@ SINGLE_BATTLE_TEST("Dire Claw cannot poison/paralyze poison/electric types respe u16 species; u32 rng; #if B_PARALYZE_ELECTRIC >= GEN_6 - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; species = SPECIES_RAICHU; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = MOVE_EFFECT_PARALYSIS; species = SPECIES_RAICHU; } #endif // B_PARALYZE_ELECTRIC - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PSN; rng = RNG_POISON; species = SPECIES_ARBOK;} + PARAMETRIZE { statusAnim = B_ANIM_STATUS_PSN; rng = MOVE_EFFECT_POISON; species = SPECIES_ARBOK;} GIVEN { - RNGSeed(rng); PLAYER(SPECIES_WOBBUFFET); OPPONENT(species); } WHEN { - TURN { MOVE(player, MOVE_DIRE_CLAW); } + TURN { MOVE(player, MOVE_DIRE_CLAW, WITH_RNG(RNG_DIRE_CLAW, rng)); } TURN {} } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_DIRE_CLAW, player); @@ -76,21 +68,20 @@ SINGLE_BATTLE_TEST("Dire Claw cannot poison/paralyze/cause to fall asleep pokemo u8 statusAnim; u16 species, ability; u32 rng; - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; species = SPECIES_RAICHU; ability = ABILITY_LIGHTNING_ROD; } - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; species = SPECIES_JOLTEON; ability = ABILITY_VOLT_ABSORB; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = MOVE_EFFECT_PARALYSIS; species = SPECIES_RAICHU; ability = ABILITY_LIGHTNING_ROD; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = MOVE_EFFECT_PARALYSIS; species = SPECIES_JOLTEON; ability = ABILITY_VOLT_ABSORB; } #if P_GEN_4_POKEMON == TRUE - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; species = SPECIES_ELECTIVIRE; ability = ABILITY_MOTOR_DRIVE; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = MOVE_EFFECT_PARALYSIS; species = SPECIES_ELECTIVIRE; ability = ABILITY_MOTOR_DRIVE; } #endif // P_GEN_4_POKEMON - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PSN; rng = RNG_POISON; species = SPECIES_ZANGOOSE; ability = ABILITY_IMMUNITY; } - PARAMETRIZE { statusAnim = B_ANIM_STATUS_SLP; rng = RNG_SLEEP; species = SPECIES_VIGOROTH; ability = ABILITY_VITAL_SPIRIT; } - PARAMETRIZE { statusAnim = B_ANIM_STATUS_SLP; rng = RNG_SLEEP; species = SPECIES_HYPNO; ability = ABILITY_INSOMNIA; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_PSN; rng = MOVE_EFFECT_POISON; species = SPECIES_ZANGOOSE; ability = ABILITY_IMMUNITY; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_SLP; rng = MOVE_EFFECT_SLEEP; species = SPECIES_VIGOROTH; ability = ABILITY_VITAL_SPIRIT; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_SLP; rng = MOVE_EFFECT_SLEEP; species = SPECIES_HYPNO; ability = ABILITY_INSOMNIA; } GIVEN { - RNGSeed(rng); PLAYER(SPECIES_WOBBUFFET); OPPONENT(species) {Ability(ability);} } WHEN { - TURN { MOVE(player, MOVE_DIRE_CLAW); } + TURN { MOVE(player, MOVE_DIRE_CLAW, WITH_RNG(RNG_DIRE_CLAW, rng)); } TURN {} } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_DIRE_CLAW, player); @@ -112,15 +103,14 @@ SINGLE_BATTLE_TEST("Dire Claw cannot poison/paralyze/cause to fall asleep a mon { u8 statusAnim; u32 rng; - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PSN; rng = RNG_POISON; } - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; } - PARAMETRIZE { statusAnim = B_ANIM_STATUS_SLP; rng = RNG_SLEEP; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_PSN; rng = MOVE_EFFECT_POISON; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = MOVE_EFFECT_PARALYSIS; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_SLP; rng = MOVE_EFFECT_SLEEP; } GIVEN { - RNGSeed(rng); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET) {Status1(STATUS1_BURN);} } WHEN { - TURN { MOVE(player, MOVE_DIRE_CLAW); } + TURN { MOVE(player, MOVE_DIRE_CLAW, WITH_RNG(RNG_DIRE_CLAW, rng)); } TURN {} } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_DIRE_CLAW, player); diff --git a/test/move_effect_double_shock.c b/test/move_effect_double_shock.c new file mode 100644 index 000000000..c3651c403 --- /dev/null +++ b/test/move_effect_double_shock.c @@ -0,0 +1,53 @@ +#include "global.h" +#include "test_battle.h" + +ASSUMPTIONS +{ + ASSUME(gBattleMoves[MOVE_DOUBLE_SHOCK].effect == EFFECT_DOUBLE_SHOCK); + ASSUME(gSpeciesInfo[SPECIES_WOBBUFFET].types[0] != TYPE_ELECTRIC || gSpeciesInfo[SPECIES_WOBBUFFET].types[1] != TYPE_ELECTRIC); + ASSUME(gSpeciesInfo[SPECIES_PIKACHU].types[0] == TYPE_ELECTRIC || gSpeciesInfo[SPECIES_PIKACHU].types[1] == TYPE_ELECTRIC); +} + +SINGLE_BATTLE_TEST("Double Shock user loses its Electric-type") +{ + GIVEN { + PLAYER(SPECIES_PIKACHU); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_DOUBLE_SHOCK); } + TURN { MOVE(player, MOVE_DOUBLE_SHOCK); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DOUBLE_SHOCK, player); + MESSAGE("Pikachu used up all of its electricity!"); + MESSAGE("Pikachu used Double Shock!"); + MESSAGE("But it failed!"); + } +} + +SINGLE_BATTLE_TEST("Double Shock fails if the user isn't an Electric-type") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_DOUBLE_SHOCK); } + } SCENE { + NONE_OF { ANIMATION(ANIM_TYPE_MOVE, MOVE_DOUBLE_SHOCK, player); } + MESSAGE("Wobbuffet used Double Shock!"); + MESSAGE("But it failed!"); + } +} + +SINGLE_BATTLE_TEST("Double Shock user loses its Electric-type if enemy faints") +{ + GIVEN { + PLAYER(SPECIES_PIKACHU); + OPPONENT(SPECIES_WOBBUFFET) { HP(1); } + } WHEN { + TURN { MOVE(player, MOVE_DOUBLE_SHOCK); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DOUBLE_SHOCK, player); + HP_BAR(opponent, hp: 0); + MESSAGE("Pikachu used up all of its electricity!"); + } +} diff --git a/test/move_effect_revival_blessing.c b/test/move_effect_revival_blessing.c new file mode 100644 index 000000000..6bc76ec85 --- /dev/null +++ b/test/move_effect_revival_blessing.c @@ -0,0 +1,117 @@ +#include "global.h" +#include "test_battle.h" + +// Note: Since these tests are recorded battle, they don't test the right battle controller +// behaviors. These have been tested in-game, in double, in multi, and in link battles. AI will always +// revive their first fainted party member in order. + +#define MOVE_MESSAGE(name) \ + do { \ + if (B_EXPANDED_MOVE_NAMES == FALSE) \ + MESSAGE(name" used RevivlBlesng!"); \ + else \ + MESSAGE(name" used Revival Blessing!"); \ + } while (0); \ + +ASSUMPTIONS +{ + ASSUME(gBattleMoves[MOVE_REVIVAL_BLESSING].effect == EFFECT_REVIVAL_BLESSING); +} + +SINGLE_BATTLE_TEST("Revival Blessing revives a chosen fainted party member for the player") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET) { HP(0); } + PLAYER(SPECIES_WYNAUT) { HP(0); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_REVIVAL_BLESSING); SEND_OUT(player, 2); } + } SCENE { + MOVE_MESSAGE("Wobbuffet") + MESSAGE("Wynaut was revived and is ready to fight again!"); + } +} + +SINGLE_BATTLE_TEST("Revival Blessing revives a fainted party member for an opponent") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_RAICHU); + OPPONENT(SPECIES_PICHU) { HP(0); } + OPPONENT(SPECIES_PIKACHU) { HP(0); } + } WHEN { + TURN { MOVE(opponent, MOVE_REVIVAL_BLESSING); SEND_OUT(opponent, 1); } + } SCENE { + MOVE_MESSAGE("Foe Raichu") + MESSAGE("Pichu was revived and is ready to fight again!"); + } +} + +SINGLE_BATTLE_TEST("Revival Blessing fails if no party members are fainted") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_REVIVAL_BLESSING); } + } SCENE { + MOVE_MESSAGE("Wobbuffet") + MESSAGE("But it failed!"); + } +} + +// Note: There isn't a good way to test multi battles at the moment, but +// this PASSES in game! +TO_DO_BATTLE_TEST("Revival Blessing cannot revive a partner's party member"); +// DOUBLE_BATTLE_TEST("Revival Blessing cannot revive a partner's party member") +// { +// struct BattlePokemon *user; +// gBattleTypeFlags |= BATTLE_TYPE_TWO_OPPONENTS; +// PARAMETRIZE { user = opponentLeft; } +// PARAMETRIZE { user = opponentRight; } +// GIVEN { +// ASSUME((gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) != FALSE); +// PLAYER(SPECIES_WOBBUFFET); +// PLAYER(SPECIES_WOBBUFFET); +// OPPONENT(SPECIES_WOBBUFFET); +// OPPONENT(SPECIES_WOBBUFFET); +// OPPONENT(SPECIES_WOBBUFFET); +// OPPONENT(SPECIES_WYNAUT); +// OPPONENT(SPECIES_WYNAUT) { HP(0); } +// OPPONENT(SPECIES_WYNAUT); +// } WHEN { +// TURN { MOVE(user, MOVE_REVIVAL_BLESSING); } +// } SCENE { +// if (user == opponentLeft) { +// MOVE_MESSAGE(Foe Wobbuffet) +// MESSAGE("But it failed!"); +// } else { +// MOVE_MESSAGE(Foe Wynaut) +// MESSAGE("Wynaut was revived and is ready to fight again!"); +// } +// } +// } + +// Note: The test runner gets upset about "sending out" a battler on the field, +// but this PASSES in game! +TO_DO_BATTLE_TEST("Revived battlers still lose their turn"); +// DOUBLE_BATTLE_TEST("Revived battlers still lose their turn") +// { +// GIVEN { +// PLAYER(SPECIES_WOBBUFFET); +// PLAYER(SPECIES_WYNAUT); +// OPPONENT(SPECIES_WOBBUFFET); +// OPPONENT(SPECIES_WYNAUT) { HP(1); } +// } WHEN { +// TURN { MOVE(playerLeft, MOVE_TACKLE, target: opponentRight); +// MOVE(opponentLeft, MOVE_REVIVAL_BLESSING); +// SEND_OUT(opponentLeft, 1); } +// } SCENE { +// MESSAGE("Wobbuffet used Tackle!"); +// MESSAGE("Foe Wynaut fainted!"); +// MOVE_MESSAGE("Foe Wobbuffet") +// MESSAGE("Wynaut was revived and is ready to fight again!"); +// NOT { MESSAGE("Wynaut used Celebrate!"); } +// } +// } diff --git a/test/move_effect_special_attack_down.c b/test/move_effect_special_attack_down.c index a20b8558e..0511692d4 100644 --- a/test/move_effect_special_attack_down.c +++ b/test/move_effect_special_attack_down.c @@ -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); diff --git a/test/move_effect_special_attack_up_3.c b/test/move_effect_special_attack_up_3.c index f7e7e11d1..ad53bedb9 100644 --- a/test/move_effect_special_attack_up_3.c +++ b/test/move_effect_special_attack_up_3.c @@ -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); diff --git a/test/move_effect_stockpile.c b/test/move_effect_stockpile.c index 0530355ef..bd0d3a113 100644 --- a/test/move_effect_stockpile.c +++ b/test/move_effect_stockpile.c @@ -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!"); diff --git a/test/move_effect_tri_attack.c b/test/move_effect_tri_attack.c index 9bfacdb98..c3fbfaace 100644 --- a/test/move_effect_tri_attack.c +++ b/test/move_effect_tri_attack.c @@ -6,21 +6,14 @@ ASSUMPTIONS ASSUME(gBattleMoves[MOVE_TRI_ATTACK].effect == EFFECT_TRI_ATTACK); } -// found by brute-force -#define RNG_PARALYSIS 0xcb0 -#define RNG_BURN 0x2BE -#define RNG_FREEZE 5 - SINGLE_BATTLE_TEST("Tri Attack can inflict paralysis, burn or freeze") { u8 statusAnim; - u32 rng; - KNOWN_FAILING; - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; } - PARAMETRIZE { statusAnim = B_ANIM_STATUS_BRN; rng = RNG_BURN; } - PARAMETRIZE { statusAnim = B_ANIM_STATUS_FRZ; rng = RNG_FREEZE; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_BRN; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_FRZ; } + PASSES_RANDOMLY(1, 3, RNG_TRI_ATTACK); GIVEN { - RNGSeed(rng); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -48,16 +41,15 @@ SINGLE_BATTLE_TEST("Tri Attack cannot paralyze/burn/freeze electric/fire/ice typ u16 species; u32 rng; #if B_PARALYZE_ELECTRIC >= GEN_6 - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; species = SPECIES_RAICHU;} + PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = MOVE_EFFECT_PARALYSIS; species = SPECIES_RAICHU;} #endif // B_PARALYZE_ELECTRIC - PARAMETRIZE { statusAnim = B_ANIM_STATUS_BRN; rng = RNG_BURN; species = SPECIES_ARCANINE; } - PARAMETRIZE { statusAnim = B_ANIM_STATUS_FRZ; rng = RNG_FREEZE; species = SPECIES_GLALIE; } + 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; } GIVEN { - RNGSeed(rng); PLAYER(SPECIES_WOBBUFFET); OPPONENT(species); } WHEN { - TURN { MOVE(player, MOVE_TRI_ATTACK); } + TURN { MOVE(player, MOVE_TRI_ATTACK, WITH_RNG(RNG_TRI_ATTACK, rng)); } TURN {} } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_TRI_ATTACK, player); @@ -80,23 +72,22 @@ SINGLE_BATTLE_TEST("Tri Attack cannot paralyze/burn/freeze pokemon with abilitie u8 statusAnim; u16 species, ability; u32 rng; - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; species = SPECIES_RAICHU; ability = ABILITY_LIGHTNING_ROD; } - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; species = SPECIES_JOLTEON; ability = ABILITY_VOLT_ABSORB; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = MOVE_EFFECT_PARALYSIS; species = SPECIES_RAICHU; ability = ABILITY_LIGHTNING_ROD; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = MOVE_EFFECT_PARALYSIS; species = SPECIES_JOLTEON; ability = ABILITY_VOLT_ABSORB; } #if P_GEN_4_POKEMON == TRUE - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; species = SPECIES_ELECTIVIRE; ability = ABILITY_MOTOR_DRIVE; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = MOVE_EFFECT_PARALYSIS; species = SPECIES_ELECTIVIRE; ability = ABILITY_MOTOR_DRIVE; } #endif // P_GEN_4_POKEMON #if P_GEN_7_POKEMON == TRUE - PARAMETRIZE { statusAnim = B_ANIM_STATUS_BRN; rng = RNG_BURN; species = SPECIES_DEWPIDER; ability = ABILITY_WATER_BUBBLE; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_BRN; rng = MOVE_EFFECT_BURN; species = SPECIES_DEWPIDER; ability = ABILITY_WATER_BUBBLE; } #endif // P_GEN_7_POKEMON - PARAMETRIZE { statusAnim = B_ANIM_STATUS_BRN; rng = RNG_BURN; species = SPECIES_SEAKING; ability = ABILITY_WATER_VEIL; } - PARAMETRIZE { statusAnim = B_ANIM_STATUS_FRZ; rng = RNG_FREEZE; species = SPECIES_CAMERUPT; ability = ABILITY_MAGMA_ARMOR; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_BRN; rng = MOVE_EFFECT_BURN; species = SPECIES_SEAKING; ability = ABILITY_WATER_VEIL; } + PARAMETRIZE { statusAnim = B_ANIM_STATUS_FRZ; rng = MOVE_EFFECT_FREEZE; species = SPECIES_CAMERUPT; ability = ABILITY_MAGMA_ARMOR; } GIVEN { - RNGSeed(rng); PLAYER(SPECIES_WOBBUFFET); OPPONENT(species) {Ability(ability);} } WHEN { - TURN { MOVE(player, MOVE_TRI_ATTACK); } + TURN { MOVE(player, MOVE_TRI_ATTACK, WITH_RNG(RNG_TRI_ATTACK, rng)); } TURN {} } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_TRI_ATTACK, player); @@ -118,15 +109,14 @@ SINGLE_BATTLE_TEST("Tri Attack cannot paralyze/burn/freeze a mon which is alread { u8 statusAnim; u32 rng; - PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = RNG_PARALYSIS; } - PARAMETRIZE { statusAnim = B_ANIM_STATUS_BRN; rng = RNG_BURN; } - PARAMETRIZE { statusAnim = B_ANIM_STATUS_FRZ; rng = RNG_FREEZE; } + 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; } GIVEN { - RNGSeed(rng); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET) {Status1(STATUS1_SLEEP);} } WHEN { - TURN { MOVE(player, MOVE_TRI_ATTACK); } + TURN { MOVE(player, MOVE_TRI_ATTACK, WITH_RNG(RNG_TRI_ATTACK, rng)); } TURN {} } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_TRI_ATTACK, player); diff --git a/test/random.c b/test/random.c index abaf4a4f8..39f587c06 100644 --- a/test/random.c +++ b/test/random.c @@ -34,6 +34,17 @@ TEST("RandomWeighted generates 0..n-1") } } +TEST("RandomElement generates an element") +{ + u32 i; + static const u8 es[4] = { 1, 2, 4, 8 }; + for (i = 0; i < 1024; i++) + { + u32 e = *(const u8 *)RandomElementArrayDefault(RNG_NONE, es, sizeof(es[0]), ARRAY_COUNT(es)); + EXPECT(e == 1 || e == 2 || e == 4 || e == 8); + } +} + TEST("RandomUniform generates uniform distribution") { u32 i, error; @@ -42,7 +53,7 @@ TEST("RandomUniform generates uniform distribution") memset(distribution, 0, sizeof(distribution)); for (i = 0; i < 4096; i++) { - u32 r = RandomUniformDefault(RNG_NONE, 0, ARRAY_COUNT(distribution)); + u32 r = RandomUniformDefault(RNG_NONE, 0, ARRAY_COUNT(distribution) - 1); EXPECT(0 <= r && r < ARRAY_COUNT(distribution)); distribution[r]++; } @@ -79,3 +90,23 @@ TEST("RandomWeighted generates distribution in proportion to the weights") EXPECT_LT(error, UQ_4_12(0.025)); } + +TEST("RandomElement generates a uniform distribution") +{ + u32 i, error; + static const u8 es[4] = { 1, 2, 4, 8 }; + u16 distribution[9]; + + memset(distribution, 0, sizeof(distribution)); + for (i = 0; i < 4096; i++) + { + u32 e = *(const u8 *)RandomElementArrayDefault(RNG_NONE, es, sizeof(es[0]), ARRAY_COUNT(es)); + distribution[e]++; + } + + error = 0; + for (i = 0; i < ARRAY_COUNT(es); i++) + error += abs(UQ_4_12(0.25) - distribution[es[i]]); + + EXPECT_LT(error, UQ_4_12(0.025)); +} diff --git a/test/status1.c b/test/status1.c index f4d3c7d94..c244b9a60 100644 --- a/test/status1.c +++ b/test/status1.c @@ -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; diff --git a/test/status_frostbite.c b/test/status_frostbite.c new file mode 100644 index 000000000..f03447821 --- /dev/null +++ b/test/status_frostbite.c @@ -0,0 +1,96 @@ +#include "global.h" +#include "test_battle.h" + +SINGLE_BATTLE_TEST("Frostbite reduces the special attack by 50 percent") +{ + s16 reducedDamage; + s16 normaleDamage; + + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Status1(STATUS1_FROSTBITE); } + } WHEN { + TURN { MOVE(opponent, MOVE_SWIFT); MOVE(player, MOVE_FLAME_WHEEL); } + TURN { MOVE(opponent, MOVE_SWIFT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SWIFT, opponent); + HP_BAR(player, captureDamage: &reducedDamage); + ANIMATION(ANIM_TYPE_MOVE, MOVE_FLAME_WHEEL, player); + HP_BAR(opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SWIFT, opponent); + HP_BAR(player, captureDamage: &normaleDamage); + } THEN { EXPECT_EQ(reducedDamage * 2, normaleDamage); } +} + +SINGLE_BATTLE_TEST("Frostbite deals 1/16 damage to effected pokemon") +{ + s16 frostbiteDamage; + + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Status1(STATUS1_FROSTBITE); } + } WHEN { + TURN { } + } SCENE { + MESSAGE("Foe Wobbuffet is hurt by its frostbite!"); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_FRZ, opponent); + HP_BAR(opponent, captureDamage: &frostbiteDamage); + } THEN { EXPECT_EQ(frostbiteDamage, opponent->maxHP / 16); } +} + +SINGLE_BATTLE_TEST("Frostbite is healed if hit with a thawing move") +{ + u32 move; + + PARAMETRIZE { move = MOVE_FLAME_WHEEL; } + PARAMETRIZE { move = MOVE_SACRED_FIRE; } + PARAMETRIZE { move = MOVE_FLARE_BLITZ; } + PARAMETRIZE { move = MOVE_FUSION_FLARE; } + PARAMETRIZE { move = MOVE_EMBER; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Status1(STATUS1_FROSTBITE); } + } WHEN { + TURN { MOVE(player, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, player); + if (move == MOVE_EMBER) { + NONE_OF { + MESSAGE("Foe Wobbuffet's frostbite was healed!"); + } + } else { + MESSAGE("Foe Wobbuffet's frostbite was healed!"); + } + } +} + +SINGLE_BATTLE_TEST("Frostbite is healed when the user uses a thawing move") +{ + u32 move; + + PARAMETRIZE { move = MOVE_FLAME_WHEEL; } + PARAMETRIZE { move = MOVE_SACRED_FIRE; } + PARAMETRIZE { move = MOVE_FLARE_BLITZ; } + PARAMETRIZE { move = MOVE_FUSION_FLARE; } + PARAMETRIZE { move = MOVE_EMBER; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_FROSTBITE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, player); + HP_BAR(opponent); + if (move == MOVE_EMBER) { + MESSAGE("Wobbuffet is hurt by its frostbite!"); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_FRZ, player); + } else { + NONE_OF { + MESSAGE("Wobbuffet is hurt by its frostbite!"); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_FRZ, player); + } + } + } +} diff --git a/test/terrain_electric.c b/test/terrain_electric.c new file mode 100644 index 000000000..e9c34ef92 --- /dev/null +++ b/test/terrain_electric.c @@ -0,0 +1,92 @@ +#include "global.h" +#include "test_battle.h" + +SINGLE_BATTLE_TEST("Electric Terrain protects grounded battlers from falling asleep") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_CLAYDOL) { Ability(ABILITY_LEVITATE); } + } WHEN { + TURN { MOVE(player, MOVE_ELECTRIC_TERRAIN); MOVE(opponent, MOVE_SPORE); } + TURN { MOVE(player, MOVE_SPORE); } + } SCENE { + MESSAGE("Wobbuffet used ElctrcTrrain!"); + MESSAGE("Foe Claydol used Spore!"); + MESSAGE("Wobbuffet surrounds itself with electrified terrain!"); + MESSAGE("Wobbuffet used Spore!"); + MESSAGE("Foe Claydol fell asleep!"); + STATUS_ICON(opponent, sleep: TRUE); + } +} + +SINGLE_BATTLE_TEST("Electric Terrain activates Electric Seed and Mimicry") +{ + GIVEN { + ASSUME(P_GEN_8_POKEMON == TRUE); + ASSUME(gItems[ITEM_ELECTRIC_SEED].holdEffect == HOLD_EFFECT_SEEDS); + ASSUME(gItems[ITEM_ELECTRIC_SEED].holdEffectParam == HOLD_EFFECT_PARAM_ELECTRIC_TERRAIN); + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_ELECTRIC_SEED); } + OPPONENT(SPECIES_STUNFISK_GALARIAN) { Ability(ABILITY_MIMICRY); } + } WHEN { + 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!"); + ABILITY_POPUP(opponent); + MESSAGE("Foe Stunfisk's type changed to Electr!"); + } FINALLY { + EXPECT_EQ(gBattleMons[B_POSITION_OPPONENT_LEFT].type1, TYPE_ELECTRIC); + } +} + +SINGLE_BATTLE_TEST("Electric Terrain increases power of Electric-type moves by 30/50 percent", s16 damage) +{ + bool32 terrain; + PARAMETRIZE { terrain = FALSE; } + PARAMETRIZE { terrain = TRUE; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + if (terrain) + TURN { MOVE(player, MOVE_ELECTRIC_TERRAIN); } + TURN { MOVE(player, MOVE_THUNDER_SHOCK); } + } SCENE { + MESSAGE("Wobbuffet used ThunderShock!"); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + if (B_TERRAIN_TYPE_BOOST >= GEN_8) + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.3), results[1].damage); + else + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage); + } +} + +SINGLE_BATTLE_TEST("Electric Terrain lasts for 5 turns") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_ELECTRIC_TERRAIN); } + TURN {} + TURN {} + TURN {} + TURN {} + } SCENE { + MESSAGE("Foe Wobbuffet used Celebrate!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIC_TERRAIN, player); + MESSAGE("An electric current runs across the battlefield!"); + + MESSAGE("Wobbuffet used Celebrate!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + + MESSAGE("Wobbuffet used Celebrate!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + + MESSAGE("Wobbuffet used Celebrate!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + + MESSAGE("The electricity disappeared from the battlefield."); + } +} diff --git a/test/terrain_grassy.c b/test/terrain_grassy.c index 77f8a9927..7668c49bd 100644 --- a/test/terrain_grassy.c +++ b/test/terrain_grassy.c @@ -15,5 +15,101 @@ SINGLE_BATTLE_TEST("Grassy Terrain recovers 1/16th HP at end of turn") } } -TO_DO_BATTLE_TEST("Grassy Terrain increases power of Grass-type moves by 30/50 percent") -TO_DO_BATTLE_TEST("Grassy Terrain decreases power of Earthquake, Magnitude and Bulldoze by 50 percent") +SINGLE_BATTLE_TEST("Grassy Terrain activates Grassy Seed and Mimicry") +{ + GIVEN { + ASSUME(P_GEN_8_POKEMON == TRUE); + ASSUME(gItems[ITEM_GRASSY_SEED].holdEffect == HOLD_EFFECT_SEEDS); + ASSUME(gItems[ITEM_GRASSY_SEED].holdEffectParam == HOLD_EFFECT_PARAM_GRASSY_TERRAIN); + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_GRASSY_SEED); } + OPPONENT(SPECIES_STUNFISK_GALARIAN) { Ability(ABILITY_MIMICRY); } + } WHEN { + 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!"); + ABILITY_POPUP(opponent); + MESSAGE("Foe Stunfisk's type changed to Grass!"); + } FINALLY { + EXPECT_EQ(gBattleMons[B_POSITION_OPPONENT_LEFT].type1, TYPE_GRASS); + } +} + +SINGLE_BATTLE_TEST("Grassy Terrain increases power of Grass-type moves by 30/50 percent", s16 damage) +{ + bool32 terrain; + PARAMETRIZE { terrain = FALSE; } + PARAMETRIZE { terrain = TRUE; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + if (terrain) + TURN { MOVE(player, MOVE_GRASSY_TERRAIN); } + TURN { MOVE(player, MOVE_ABSORB); } + } SCENE { + MESSAGE("Wobbuffet used Absorb!"); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + if (B_TERRAIN_TYPE_BOOST >= GEN_8) + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.3), results[1].damage); + else + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage); + } +} + +// Magnitude is not tested because its damage is variable. +SINGLE_BATTLE_TEST("Grassy Terrain decreases power of Earthquake and Bulldoze by 50 percent", s16 damage) +{ + bool32 terrain; + u16 move; + PARAMETRIZE { terrain = FALSE; move = MOVE_EARTHQUAKE; } // 0 + PARAMETRIZE { terrain = TRUE; move = MOVE_EARTHQUAKE; } // 1 + PARAMETRIZE { terrain = FALSE; move = MOVE_BULLDOZE; } // 2 + PARAMETRIZE { terrain = TRUE; move = MOVE_BULLDOZE; } // 3 + GIVEN { + ASSUME(gBattleMoves[MOVE_EARTHQUAKE].effect == EFFECT_EARTHQUAKE); + ASSUME(gBattleMoves[MOVE_BULLDOZE].effect == EFFECT_BULLDOZE); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + if (terrain) + TURN { MOVE(player, MOVE_GRASSY_TERRAIN); } + TURN { MOVE(player, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage); + EXPECT_MUL_EQ(results[2].damage, Q_4_12(0.5), results[3].damage); + } +} + +SINGLE_BATTLE_TEST("Grassy Terrain lasts for 5 turns") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_GRASSY_TERRAIN); } + TURN {} + TURN {} + TURN {} + TURN {} + } SCENE { + MESSAGE("Foe Wobbuffet used Celebrate!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_GRASSY_TERRAIN, player); + MESSAGE("Grass grew to cover the battlefield!"); + + MESSAGE("Wobbuffet used Celebrate!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + + MESSAGE("Wobbuffet used Celebrate!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + + MESSAGE("Wobbuffet used Celebrate!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + + MESSAGE("The grass disappeared from the battlefield."); + } +} diff --git a/test/terrain_misty.c b/test/terrain_misty.c new file mode 100644 index 000000000..4f8793d9d --- /dev/null +++ b/test/terrain_misty.c @@ -0,0 +1,109 @@ +#include "global.h" +#include "test_battle.h" + +SINGLE_BATTLE_TEST("Misty Terrain protects grounded battlers from non-volatile status conditions") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_CLAYDOL) { Ability(ABILITY_LEVITATE); } + } WHEN { + TURN { MOVE(player, MOVE_MISTY_TERRAIN); MOVE(opponent, MOVE_TOXIC); } + TURN { MOVE(player, MOVE_TOXIC); } + } SCENE { + MESSAGE("Wobbuffet used MistyTerrain!"); + MESSAGE("Foe Claydol used Toxic!"); + MESSAGE("Wobbuffet surrounds itself with a protective mist!"); + NOT { STATUS_ICON(opponent, badPoison: TRUE); } + MESSAGE("Wobbuffet used Toxic!"); + STATUS_ICON(opponent, badPoison: TRUE); + } +} + +SINGLE_BATTLE_TEST("Misty Terrain activates Misty Seed and Mimicry") +{ + GIVEN { + ASSUME(P_GEN_8_POKEMON == TRUE); + ASSUME(gItems[ITEM_MISTY_SEED].holdEffect == HOLD_EFFECT_SEEDS); + ASSUME(gItems[ITEM_MISTY_SEED].holdEffectParam == HOLD_EFFECT_PARAM_MISTY_TERRAIN); + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_MISTY_SEED); } + OPPONENT(SPECIES_STUNFISK_GALARIAN) { Ability(ABILITY_MIMICRY); } + } WHEN { + TURN { MOVE(player, MOVE_MISTY_TERRAIN); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Using Misty Seed, the Sp. Def of Wobbuffet rose!"); + ABILITY_POPUP(opponent); + MESSAGE("Foe Stunfisk's type changed to Fairy!"); + } FINALLY { + EXPECT_EQ(gBattleMons[B_POSITION_OPPONENT_LEFT].type1, TYPE_FAIRY); + } +} + +SINGLE_BATTLE_TEST("Misty Terrain does not increase the power of Fairy-type moves", s16 damage) +{ + bool32 terrain; + PARAMETRIZE { terrain = FALSE; } + PARAMETRIZE { terrain = TRUE; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + if (terrain) + TURN { MOVE(player, MOVE_MISTY_TERRAIN); } + TURN { MOVE(player, MOVE_MOONBLAST); } + } SCENE { + MESSAGE("Wobbuffet used Moonblast!"); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + } +} + +SINGLE_BATTLE_TEST("Misty Terrain decreases power of Dragon-type moves by 50 percent", s16 damage) +{ + bool32 terrain; + PARAMETRIZE { terrain = FALSE; } + PARAMETRIZE { terrain = TRUE; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + if (terrain) + TURN { MOVE(player, MOVE_MISTY_TERRAIN); } + TURN { MOVE(player, MOVE_DRAGON_CLAW); } + } SCENE { + MESSAGE("Wobbuffet used Dragon Claw!"); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage); + } +} + +SINGLE_BATTLE_TEST("Misty Terrain lasts for 5 turns") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_MISTY_TERRAIN); } + TURN {} + TURN {} + TURN {} + TURN {} + } SCENE { + MESSAGE("Foe Wobbuffet used Celebrate!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_MISTY_TERRAIN, player); + MESSAGE("Mist swirled about the battlefield!"); + + MESSAGE("Wobbuffet used Celebrate!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + + MESSAGE("Wobbuffet used Celebrate!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + + MESSAGE("Wobbuffet used Celebrate!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + + MESSAGE("The mist disappeared from the battlefield."); + } +} diff --git a/test/terrain_psychic.c b/test/terrain_psychic.c new file mode 100644 index 000000000..3ecfa99e0 --- /dev/null +++ b/test/terrain_psychic.c @@ -0,0 +1,167 @@ +#include "global.h" +#include "test_battle.h" + +SINGLE_BATTLE_TEST("Psychic Terrain protects grounded battlers from priority moves") +{ + GIVEN { + PLAYER(SPECIES_CLAYDOL) { Ability(ABILITY_LEVITATE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_PSYCHIC_TERRAIN); } + TURN { MOVE(player, MOVE_QUICK_ATTACK); MOVE(opponent, MOVE_QUICK_ATTACK); } + } SCENE { + MESSAGE("Claydol used PsychcTrrain!"); + MESSAGE("Claydol cannot use Quick Attack!"); + NOT { HP_BAR(opponent); } + MESSAGE("Foe Wobbuffet used Quick Attack!"); + HP_BAR(player); + } +} + +SINGLE_BATTLE_TEST("Psychic Terrain activates Psychic Seed and Mimicry") +{ + GIVEN { + ASSUME(P_GEN_8_POKEMON == TRUE); + ASSUME(gItems[ITEM_PSYCHIC_SEED].holdEffect == HOLD_EFFECT_SEEDS); + ASSUME(gItems[ITEM_PSYCHIC_SEED].holdEffectParam == HOLD_EFFECT_PARAM_PSYCHIC_TERRAIN); + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_PSYCHIC_SEED); } + OPPONENT(SPECIES_STUNFISK_GALARIAN) { Ability(ABILITY_MIMICRY); } + } WHEN { + TURN { MOVE(player, MOVE_PSYCHIC_TERRAIN); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Using Psychic Seed, the Sp. Def of Wobbuffet rose!"); + ABILITY_POPUP(opponent); + MESSAGE("Foe Stunfisk's type changed to Psychc!"); + } FINALLY { + EXPECT_EQ(gBattleMons[B_POSITION_OPPONENT_LEFT].type1, TYPE_PSYCHIC); + } +} + +SINGLE_BATTLE_TEST("Psychic Terrain increases power of Psychic-type moves by 30/50 percent", s16 damage) +{ + bool32 terrain; + PARAMETRIZE { terrain = FALSE; } + PARAMETRIZE { terrain = TRUE; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + if (terrain) + TURN { MOVE(player, MOVE_PSYCHIC_TERRAIN); } + TURN { MOVE(player, MOVE_CONFUSION); } + } SCENE { + MESSAGE("Wobbuffet used Confusion!"); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + if (B_TERRAIN_TYPE_BOOST >= GEN_8) + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.3), results[1].damage); + else + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage); + } +} + +SINGLE_BATTLE_TEST("Psychic Terrain doesn't block priority moves that target the user", s16 damage) +{ + GIVEN { + PLAYER(SPECIES_SABLEYE) { Ability(ABILITY_PRANKSTER); HP(1); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_PSYCHIC_TERRAIN); } + TURN { MOVE(player, MOVE_RECOVER); } + } SCENE { + MESSAGE("Sableye used PsychcTrrain!"); + MESSAGE("Sableye used Recover!"); + HP_BAR(player); + } +} + +SINGLE_BATTLE_TEST("Psychic Terrain doesn't block priority moves that target all battlers", s16 damage) +{ + KNOWN_FAILING; + GIVEN { + PLAYER(SPECIES_SABLEYE) { Ability(ABILITY_PRANKSTER); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_PSYCHIC_TERRAIN); } + TURN { MOVE(player, MOVE_HAZE); } + } SCENE { + MESSAGE("Sableye used PsychcTrrain!"); + MESSAGE("Sableye used Haze!"); + } +} + +SINGLE_BATTLE_TEST("Psychic Terrain doesn't block priority moves that target all opponents", s16 damage) +{ + KNOWN_FAILING; + GIVEN { + PLAYER(SPECIES_SABLEYE) { Ability(ABILITY_PRANKSTER); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_PSYCHIC_TERRAIN); } + TURN { MOVE(player, MOVE_SPIKES); } + } SCENE { + MESSAGE("Sableye used PsychcTrrain!"); + MESSAGE("Sableye used Spikes!"); + } +} + +DOUBLE_BATTLE_TEST("Psychic Terrain doesn't block priority moves that target allies", s16 damage) +{ + GIVEN { + PLAYER(SPECIES_SABLEYE) { Ability(ABILITY_PRANKSTER); } + PLAYER(SPECIES_WOBBUFFET) { HP(1); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerLeft, MOVE_PSYCHIC_TERRAIN); } + TURN { MOVE(playerLeft, MOVE_HEAL_PULSE, target: playerRight); } + } SCENE { + MESSAGE("Sableye used PsychcTrrain!"); + MESSAGE("Sableye used Heal Pulse!"); + } +} + +SINGLE_BATTLE_TEST("Psychic Terrain doesn't block priority field moves", s16 damage) +{ + KNOWN_FAILING; + GIVEN { + PLAYER(SPECIES_SABLEYE) { Ability(ABILITY_PRANKSTER); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_PSYCHIC_TERRAIN); } + TURN { MOVE(player, MOVE_SUNNY_DAY); } + } SCENE { + MESSAGE("Sableye used PsychcTrrain!"); + MESSAGE("Sableye used Sunny Day!"); + } +} + +SINGLE_BATTLE_TEST("Psychic Terrain lasts for 5 turns") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_PSYCHIC_TERRAIN); } + TURN {} + TURN {} + TURN {} + TURN {} + } SCENE { + MESSAGE("Foe Wobbuffet used Celebrate!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PSYCHIC_TERRAIN, player); + MESSAGE("The battlefield got weird!"); + + MESSAGE("Wobbuffet used Celebrate!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + + MESSAGE("Wobbuffet used Celebrate!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + + MESSAGE("Wobbuffet used Celebrate!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + + MESSAGE("The weirdness disappeared from the battlefield."); + } +} diff --git a/test/test_battle.h b/test/test_battle.h index 0e0464254..432e33fa8 100644 --- a/test/test_battle.h +++ b/test/test_battle.h @@ -303,13 +303,14 @@ * The inference process is naive, if your test contains anything that * modifies the speed of a battler you should specify them explicitly. * - * MOVE(battler, move | moveSlot:, [megaEvolve:], [hit:], [criticalHit:], [target:], [allowed:]) + * MOVE(battler, move | moveSlot:, [megaEvolve:], [hit:], [criticalHit:], [target:], [allowed:], [WITH_RNG(tag, value]) * Used when the battler chooses Fight. Either the move ID or move slot * must be specified. megaEvolve: TRUE causes the battler to Mega Evolve * if able, hit: FALSE causes the move to miss, criticalHit: TRUE causes * the move to land a critical hit, target: is used in double battles to * choose the target (when necessary), and allowed: FALSE is used to - * reject an illegal move e.g. a Disabled one. + * reject an illegal move e.g. a Disabled one. WITH_RNG allows the move + * to specify an explicit outcome for an RNG tag. * MOVE(playerLeft, MOVE_TACKLE, target: opponentRight); * If the battler does not have an explicit Moves specified the moveset * will be populated based on the MOVEs it uses. @@ -333,6 +334,13 @@ * via Switch, e.g. after fainting or due to a U-turn. * SEND_OUT(player, 1); * + * USE_ITEM(battler, itemId, [partyIndex:], [move:]) + * Used when the battler chooses to use an item from the Bag. The item + * ID must be specified, and party index and move slot if applicable, e.g: + * USE_ITEM(player, ITEM_X_ATTACK); + * USE_ITEM(player, ITEM_POTION, partyIndex: 0); + * USE_ITEM(player, ITEM_LEPPA_BERRY, partyIndex: 0, move: MOVE_TACKLE); + * * SCENE * Contains an abridged description of the UI during the THEN. The order * of the description must match too, e.g. @@ -518,8 +526,7 @@ struct QueuedMessageEvent struct QueuedStatusEvent { u32 battlerId:3; - u32 mask:8; - u32 unused_01:21; + u32 mask:29; }; struct QueuedEvent @@ -538,11 +545,18 @@ struct QueuedEvent } as; }; +struct TurnRNG +{ + u16 tag; + u16 value; +}; + struct BattlerTurn { u8 hit:2; u8 criticalHit:2; u8 secondaryEffect:2; + struct TurnRNG rng; }; struct BattleTestData @@ -757,6 +771,8 @@ enum { TURN_CLOSED, TURN_OPEN, TURN_CLOSING }; #define SWITCH(battler, partyIndex) Switch(__LINE__, battler, partyIndex) #define SKIP_TURN(battler) SkipTurn(__LINE__, battler) #define SEND_OUT(battler, partyIndex) SendOut(__LINE__, battler, partyIndex) +#define USE_ITEM(battler, ...) UseItem(__LINE__, battler, (struct ItemContext) { APPEND_TRUE(__VA_ARGS__) }) +#define WITH_RNG(tag, value) rng: ((struct TurnRNG) { tag, value }) struct MoveContext { @@ -777,6 +793,18 @@ struct MoveContext u16 explicitAllowed:1; struct BattlePokemon *target; bool8 explicitTarget; + struct TurnRNG rng; + bool8 explicitRNG; +}; + +struct ItemContext +{ + u16 itemId; + u16 explicitItemId:1; + u16 partyIndex; + u16 explicitPartyIndex:1; + u16 move; + u16 explicitMove:1; }; void OpenTurn(u32 sourceLine); @@ -785,7 +813,7 @@ void Move(u32 sourceLine, struct BattlePokemon *, struct MoveContext); void ForcedMove(u32 sourceLine, struct BattlePokemon *); void Switch(u32 sourceLine, struct BattlePokemon *, u32 partyIndex); void SkipTurn(u32 sourceLine, struct BattlePokemon *); - +void UseItem(u32 sourceLine, struct BattlePokemon *, struct ItemContext); void SendOut(u32 sourceLine, struct BattlePokemon *, u32 partyIndex); /* Scene */ @@ -843,6 +871,7 @@ struct StatusEventContext bool8 freeze:1; bool8 paralysis:1; bool8 badPoison:1; + bool8 frostbite:1; }; void OpenQueueGroup(u32 sourceLine, enum QueueGroupType); diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c index d869bf2e5..95c451308 100644 --- a/test/test_runner_battle.c +++ b/test/test_runner_battle.c @@ -3,6 +3,7 @@ #include "battle_anim.h" #include "battle_controllers.h" #include "characters.h" +#include "item_menu.h" #include "main.h" #include "malloc.h" #include "random.h" @@ -292,6 +293,20 @@ static void BattleTest_Run(void *data) u32 RandomUniform(enum RandomTag tag, u32 lo, u32 hi) { + const struct BattlerTurn *turn = NULL; + u32 default_ = hi; + + if (gCurrentTurnActionNumber < gBattlersCount) + { + u32 battlerId = gBattlerByTurnOrder[gCurrentTurnActionNumber]; + turn = &DATA.battleRecordTurns[gBattleResults.battleTurnCounter][battlerId]; + } + + if (turn && turn->rng.tag == tag) + { + default_ = turn->rng.value; + } + if (tag == STATE->rngTag) { u32 n = hi - lo + 1; @@ -308,7 +323,7 @@ u32 RandomUniform(enum RandomTag tag, u32 lo, u32 hi) return STATE->runTrial + lo; } - return hi; + return default_; } u32 RandomWeightedArray(enum RandomTag tag, u32 sum, u32 n, const u8 *weights) @@ -322,28 +337,35 @@ u32 RandomWeightedArray(enum RandomTag tag, u32 sum, u32 n, const u8 *weights) turn = &DATA.battleRecordTurns[gBattleResults.battleTurnCounter][battlerId]; } - switch (tag) + if (turn && turn->rng.tag == tag) { - case RNG_ACCURACY: - ASSUME(n == 2); - if (turn && turn->hit) - return turn->hit - 1; - default_ = TRUE; - break; + default_ = turn->rng.value; + } + else + { + switch (tag) + { + case RNG_ACCURACY: + ASSUME(n == 2); + if (turn && turn->hit) + return turn->hit - 1; + default_ = TRUE; + break; - case RNG_CRITICAL_HIT: - ASSUME(n == 2); - if (turn && turn->criticalHit) - return turn->criticalHit - 1; - default_ = FALSE; - break; + case RNG_CRITICAL_HIT: + ASSUME(n == 2); + if (turn && turn->criticalHit) + return turn->criticalHit - 1; + default_ = FALSE; + break; - case RNG_SECONDARY_EFFECT: - ASSUME(n == 2); - if (turn && turn->secondaryEffect) - return turn->secondaryEffect - 1; - default_ = TRUE; - break; + case RNG_SECONDARY_EFFECT: + ASSUME(n == 2); + if (turn && turn->secondaryEffect) + return turn->secondaryEffect - 1; + default_ = TRUE; + break; + } } if (tag == STATE->rngTag) @@ -365,6 +387,52 @@ u32 RandomWeightedArray(enum RandomTag tag, u32 sum, u32 n, const u8 *weights) return default_; } +const void *RandomElementArray(enum RandomTag tag, const void *array, size_t size, size_t count) +{ + const struct BattlerTurn *turn = NULL; + u32 index = count-1; + + if (gCurrentTurnActionNumber < gBattlersCount) + { + u32 battlerId = gBattlerByTurnOrder[gCurrentTurnActionNumber]; + turn = &DATA.battleRecordTurns[gBattleResults.battleTurnCounter][battlerId]; + } + + if (turn && turn->rng.tag == tag) + { + u32 element; + for (index = 0; index < count; index++) + { + memcpy(&element, (const u8 *)array + size * index, size); + if (element == turn->rng.value) + break; + } + if (index == count) + { + // TODO: Incorporate the line number. + const char *filename = gTestRunnerState.test->filename; + Test_ExitWithResult(TEST_RESULT_ERROR, "%s: RandomElement illegal value requested: %d", filename, turn->rng.value); + } + } + + if (tag == STATE->rngTag) + { + if (STATE->trials == 1) + { + STATE->trials = count; + PrintTestName(); + } + else if (STATE->trials != count) + { + Test_ExitWithResult(TEST_RESULT_ERROR, "RandomElement called with inconsistent trials %d and %d", STATE->trials, count); + } + STATE->trialRatio = Q_4_12(1) / count; + index = STATE->runTrial; + } + + return (const u8 *)array + size * index; +} + static s32 TryAbilityPopUp(s32 i, s32 n, u32 battlerId, u32 ability) { struct QueuedAbilityEvent *event; @@ -1014,9 +1082,12 @@ void Ability_(u32 sourceLine, u32 ability) void Level_(u32 sourceLine, u32 level) { // TODO: Preserve any explicitly-set stats. + u32 species = GetMonData(DATA.currentMon, MON_DATA_SPECIES); INVALID_IF(!DATA.currentMon, "Level outside of PLAYER/OPPONENT"); INVALID_IF(level == 0 || level > MAX_LEVEL, "Illegal level: %d", level); SetMonData(DATA.currentMon, MON_DATA_LEVEL, &level); + SetMonData(DATA.currentMon, MON_DATA_EXP, &gExperienceTables[gSpeciesInfo[species].growthRate][level]); + CalculateMonStats(DATA.currentMon); } void MaxHP_(u32 sourceLine, u32 maxHP) @@ -1184,6 +1255,9 @@ void BattleTest_CheckBattleRecordActionType(u32 battlerId, u32 recordIndex, u32 case B_ACTION_SWITCH: actualMacro = "SWITCH"; break; + case B_ACTION_USE_ITEM: + actualMacro = "USE_ITEM"; + break; } break; case RECORDED_PARTY_INDEX: @@ -1357,6 +1431,8 @@ void Move(u32 sourceLine, struct BattlePokemon *battler, struct MoveContext ctx) DATA.battleRecordTurns[DATA.turns][battlerId].criticalHit = 1 + ctx.criticalHit; if (ctx.explicitSecondaryEffect) DATA.battleRecordTurns[DATA.turns][battlerId].secondaryEffect = 1 + ctx.secondaryEffect; + if (ctx.explicitRNG) + DATA.battleRecordTurns[DATA.turns][battlerId].rng = ctx.rng; if (!(DATA.actionBattlers & (1 << battlerId))) { @@ -1439,6 +1515,40 @@ void SendOut(u32 sourceLine, struct BattlePokemon *battler, u32 partyIndex) DATA.currentMonIndexes[battlerId] = partyIndex; } +void UseItem(u32 sourceLine, struct BattlePokemon *battler, struct ItemContext ctx) +{ + s32 i; + s32 battlerId = battler - gBattleMons; + bool32 requirePartyIndex = ItemId_GetType(ctx.itemId) == ITEM_USE_PARTY_MENU || ItemId_GetType(ctx.itemId) == ITEM_USE_PARTY_MENU_MOVES; + // Check general bad use. + INVALID_IF(DATA.turnState == TURN_CLOSED, "USE_ITEM outside TURN"); + INVALID_IF(DATA.actionBattlers & (1 << battlerId), "Multiple battler actions"); + INVALID_IF(ctx.itemId >= ITEMS_COUNT, "Illegal item: %d", ctx.itemId); + // Check party menu items. + INVALID_IF(requirePartyIndex && !ctx.explicitPartyIndex, "%S requires explicit party index", ItemId_GetName(ctx.itemId)); + INVALID_IF(requirePartyIndex && ctx.partyIndex >= ((battlerId & BIT_SIDE) == B_SIDE_PLAYER ? DATA.playerPartySize : DATA.opponentPartySize), \ + "USE_ITEM to invalid party index"); + // Check move slot items. + if (ItemId_GetType(ctx.itemId) == ITEM_USE_PARTY_MENU_MOVES) + { + INVALID_IF(!ctx.explicitMove, "%S requires an explicit move", ItemId_GetName(ctx.itemId)); + for (i = 0; i < MAX_MON_MOVES; i++) + { + if (GetMonData(CurrentMon(battlerId), MON_DATA_MOVE1 + i, NULL) == ctx.move) + break; + } + INVALID_IF(i == MAX_MON_MOVES, "USE_ITEM on invalid move: %d", ctx.move); + } + PushBattlerAction(sourceLine, battlerId, RECORDED_ACTION_TYPE, B_ACTION_USE_ITEM); + PushBattlerAction(sourceLine, battlerId, RECORDED_ITEM_ID, (ctx.itemId >> 8) & 0xFF); + PushBattlerAction(sourceLine, battlerId, RECORDED_ITEM_ID, ctx.itemId & 0xFF); + if (ctx.explicitPartyIndex) + gBattleStruct->itemPartyIndex[battlerId] = ctx.partyIndex; + if (ctx.explicitMove) + gBattleStruct->itemPartyIndex[battlerId] = i; + DATA.actionBattlers |= 1 << battlerId; +} + static const char *const sQueueGroupTypeMacros[] = { [QUEUE_GROUP_NONE] = NULL, @@ -1610,6 +1720,8 @@ void QueueStatus(u32 sourceLine, struct BattlePokemon *battler, struct StatusEve mask = STATUS1_PARALYSIS; else if (ctx.badPoison) mask = STATUS1_TOXIC_POISON; + else if (ctx.frostbite) + mask = STATUS1_FROSTBITE; else mask = ctx.status1; diff --git a/test/trainer_control.c b/test/trainer_control.c index 307942207..2a21dcdf6 100644 --- a/test/trainer_control.c +++ b/test/trainer_control.c @@ -81,7 +81,7 @@ TEST("CreateNPCTrainerPartyForTrainer generates customized Pokémon") EXPECT(GetMonData(&testParty[0], MON_DATA_HELD_ITEM, 0) == ITEM_ASSAULT_VEST); EXPECT(GetMonData(&testParty[1], MON_DATA_HELD_ITEM, 0) == ITEM_NONE); - + EXPECT(GetMonData(&testParty[0], MON_DATA_HP_IV, 0) == 25); EXPECT(GetMonData(&testParty[0], MON_DATA_ATK_IV, 0) == 26); EXPECT(GetMonData(&testParty[0], MON_DATA_DEF_IV, 0) == 27);