From 7b7c66bc56491f264d57ff946deab8ebda820b53 Mon Sep 17 00:00:00 2001 From: cawtds Date: Sun, 9 Jun 2024 19:55:37 +0200 Subject: [PATCH] various updates: fixed switch in ability message, gulpmissile, explosion... --- asm/macros/battle_script.inc | 4 + data/battle_scripts_1.s | 52 ++++------ include/battle_scripts.h | 4 +- include/battle_util.h | 2 +- include/constants/form_change_types.h | 3 + src/battle_message.c | 2 +- src/battle_script_commands.c | 140 ++++++++++++++++++++------ src/battle_util.c | 136 +++++++++++++++---------- src/data/battle_move_effects.h | 2 +- src/data/pokemon/form_change_tables.h | 1 + 10 files changed, 225 insertions(+), 121 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 4cb2c526b..0906e0b5c 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1637,6 +1637,10 @@ .macro trygulpmissile callnative BS_TryGulpMissile .endm + + .macro tryactivategulpmissile + callnative BS_TryActivateGulpMissile + .endm .macro tryquash failInstr:req callnative BS_TryQuash diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index b17b1a47a..be3883368 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -3118,43 +3118,23 @@ BattleScript_EffectExplosion:: attackcanceler attackstring ppreduce -@ Below jumps to BattleScript_DampStopsExplosion if it fails (only way it can) tryexplosion - waitstate -BattleScript_EffectExplosion_AnimDmgFaintAttacker: - call BattleScript_EffectExplosion_AnimDmgRet - moveendall setatkhptozero - tryfaintmon BS_ATTACKER - end - -BattleScript_EffectMindBlown:: - attackcanceler - attackstring - ppreduce - jumpifbyte CMP_GREATER_THAN, sB_ANIM_TARGETS_HIT, 0, BattleScript_EffectMindBlown_NoHpLoss - jumpifabilitypresent ABILITY_DAMP, BattleScript_MindBlownDamp - jumpifmorethanhalfHP BS_ATTACKER, BattleScript_EffectMindBlown_HpDown - setbyte sMULTIHIT_EFFECT, 0 @ Note to faint the attacker - instanthpdrop BS_ATTACKER waitstate - goto BattleScript_EffectExplosion_AnimDmgFaintAttacker -BattleScript_EffectMindBlown_NoHpLoss: - jumpifbyte CMP_EQUAL, sMULTIHIT_EFFECT, 0, BattleScript_EffectExplosion_AnimDmgFaintAttacker - goto BattleScript_EffectMindBlown_AnimDmgNoFaint -BattleScript_MindBlownDamp: - copybyte gBattlerTarget, gBattlerAbility - goto BattleScript_DampStopsExplosion -BattleScript_EffectMindBlown_HpDown: - setbyte sMULTIHIT_EFFECT, 1 @ Note to not faint the attacker - jumpifability BS_ATTACKER, ABILITY_MAGIC_GUARD, BattleScript_EffectMindBlown_AnimDmgNoFaint - dmg_1_2_attackerhp + jumpiffainted BS_TARGET, TRUE, BattleScript_MoveEnd + accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE + goto BattleScript_HitFromCritCalc + +BattleScript_FaintAttackerForExplosion:: + tryfaintmon BS_ATTACKER + return + +BattleScript_MaxHp50Recoil:: + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER - waitstate -BattleScript_EffectMindBlown_AnimDmgNoFaint: - call BattleScript_EffectExplosion_AnimDmgRet - goto BattleScript_MoveEnd + tryfaintmon BS_ATTACKER + return BattleScript_PreserveMissedBitDoMoveAnim: bichalfword gMoveResultFlags, MOVE_RESULT_MISSED @@ -5574,6 +5554,7 @@ BattleScript_EffectCamouflage:: BattleScript_FaintAttacker:: tryillusionoff BS_ATTACKER + tryactivategulpmissile playfaintcry BS_ATTACKER pause B_WAIT_TIME_LONG dofaintanimation BS_ATTACKER @@ -5586,6 +5567,7 @@ BattleScript_FaintAttacker:: BattleScript_FaintTarget:: tryillusionoff BS_TARGET + tryactivategulpmissile playfaintcry BS_TARGET pause B_WAIT_TIME_LONG dofaintanimation BS_TARGET @@ -7397,6 +7379,12 @@ BattleScript_TargetBurnHeal:: updatestatusicon BS_TARGET return +BattleScript_TargetPoisonHealed:: + printstring STRINGID_PASTELVEILENTERS + waitmessage B_WAIT_TIME_LONG + updatestatusicon BS_TARGET + return + BattleScript_MoveEffectSleep:: statusanimation BS_EFFECT_BATTLER printfromtable gFellAsleepStringIds diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 9ff8e1b99..62eb1671a 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -396,6 +396,8 @@ extern const u8 BattleScript_MoveEffectCoreEnforcer[]; extern const u8 BattleScript_MoveEffectIncinerate[]; extern const u8 BattleScript_MoveEffectBugBite[]; extern const u8 BattleScript_BothCanNoLongerEscape[]; +extern const u8 BattleScript_FaintAttackerForExplosion[]; +extern const u8 BattleScript_MaxHp50Recoil[]; extern const u8 BattleScript_RemoveFireType[]; extern const u8 BattleScript_RemoveElectricType[]; extern const u8 BattleScript_RemoveGenericType[]; @@ -592,6 +594,7 @@ extern const u8 BattleScript_CurseTurnDmg[]; extern const u8 BattleScript_TargetPRLZHeal[]; extern const u8 BattleScript_TargetWokeUp[]; extern const u8 BattleScript_TargetBurnHeal[]; +extern const u8 BattleScript_TargetPoisonHealed[]; extern const u8 BattleScript_MoveEffectSleep[]; extern const u8 BattleScript_YawnMakesAsleep[]; extern const u8 BattleScript_MoveEffectPoison[]; @@ -1204,7 +1207,6 @@ extern const u8 BattleScript_EffectLaserFocus[]; extern const u8 BattleScript_EffectMagneticFlux[]; extern const u8 BattleScript_EffectGearUp[]; extern const u8 BattleScript_EffectStrengthSap[]; -extern const u8 BattleScript_EffectMindBlown[]; extern const u8 BattleScript_EffectPurify[]; extern const u8 BattleScript_FailIfNotArgType[]; extern const u8 BattleScript_EffectShoreUp[]; diff --git a/include/battle_util.h b/include/battle_util.h index 46de190e0..1271ce469 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -118,7 +118,7 @@ extern const uq4_12_t gTypeEffectivenessTable[NUMBER_OF_MON_TYPES][NUMBER_OF_MON void HandleAction_UseMove(void); void HandleAction_Switch(void); void HandleAction_UseItem(void); -bool8 TryRunFromBattle(u8 battler); +bool32 TryRunFromBattle(u32 battler); void HandleAction_Run(void); void HandleAction_WatchesCarefully(void); void HandleAction_SafariZoneBallThrow(void); diff --git a/include/constants/form_change_types.h b/include/constants/form_change_types.h index 51325baf2..30bb54d02 100644 --- a/include/constants/form_change_types.h +++ b/include/constants/form_change_types.h @@ -120,4 +120,7 @@ // param1: status #define FORM_CHANGE_STATUS 20 +// Form change that activates after move is used. Currently only used for activating Gulp Missile. +#define FORM_CHANGE_HIT_BY_MOVE 21 + #endif // GUARD_CONSTANTS_FORM_CHANGE_TYPES_H diff --git a/src/battle_message.c b/src/battle_message.c index 1d1ac3162..922d53b1e 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -738,7 +738,7 @@ static const u8 sText_BeingHitChargedPkmnWithPower[] = _("Being hit by {B_CURREN static const u8 sText_SunlightActivatedAbility[] = _("The harsh sunlight activated\n{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_LAST_ABILITY}!"); static const u8 sText_StatWasHeightened[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_BUFF1} was heightened!"); static const u8 sText_ElectricTerrainActivatedAbility[] = _("The Electric Terrain activated\n{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_LAST_ABILITY}!"); -static const u8 sText_AbilityWeakenedSurroundingMonsStat[] = _("{B_ATK_NAME_WITH_PREFIX}'s {B_ATK_ABILITY}\nweakened the {B_BUFF1} of\lall surrounding Pokémon!\p"); +static const u8 sText_AbilityWeakenedSurroundingMonsStat[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_SCR_ACTIVE_ABILITY}\nweakened the {B_BUFF1} of\lall surrounding Pokémon!\p"); static const u8 sText_AttackerGainedStrengthFromTheFallen[] = _("{B_ATK_NAME_WITH_PREFIX} gained strength\nfrom the fallen!"); static const u8 sText_PrepareShellTrap[] = _("{B_ATK_NAME_WITH_PREFIX} set a shell trap!"); static const u8 sText_ShellTrapDidntWork[] = _("{B_ATK_NAME_WITH_PREFIX}'s shell trap didn't work!"); diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index d5469db81..c6e29884c 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -5517,18 +5517,38 @@ static void Cmd_moveend(void) gBattleScripting.moveendState++; break; case MOVEEND_RECOIL: - if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) - && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) - && IsBattlerAlive(gBattlerAttacker) - && gBattleScripting.savedDmg != 0) // Some checks may be redundant alongside this one + if (gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) { - if (gMovesInfo[gCurrentMove].recoil > 0) - { - gBattleMoveDamage = max(1, gBattleScripting.savedDmg * max(1, gMovesInfo[gCurrentMove].recoil) / 100); - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_MoveEffectRecoil; - effect = TRUE; - } + gBattleScripting.moveendState++; + break; + } + else if (gMovesInfo[gCurrentMove].recoil > 0 + && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) + && IsBattlerAlive(gBattlerAttacker) + && gBattleScripting.savedDmg != 0) // Some checks may be redundant alongside this one + { + gBattleMoveDamage = max(1, gBattleScripting.savedDmg * max(1, gMovesInfo[gCurrentMove].recoil) / 100); + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_MoveEffectRecoil; + effect = TRUE; + } + else if (gMovesInfo[gCurrentMove].effect == EFFECT_EXPLOSION && !IsAbilityOnField(ABILITY_DAMP)) + { + gBattleMoveDamage = 0; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_FaintAttackerForExplosion; + effect = TRUE; + } + else if ((gMovesInfo[gCurrentMove].effect == EFFECT_MAX_HP_50_RECOIL + || gMovesInfo[gCurrentMove].effect == EFFECT_MIND_BLOWN) + && IsBattlerAlive(gBattlerAttacker) + && !(gMoveResultFlags & MOVE_RESULT_FAILED) + && GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) + { + gBattleMoveDamage = (GetNonDynamaxMaxHP(gBattlerAttacker) + 1) / 2; // Half of Max HP Rounded UP + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_MaxHp50Recoil; + effect = TRUE; } gBattleScripting.moveendState++; break; @@ -5609,7 +5629,10 @@ static void Cmd_moveend(void) switch (gBattleStruct->moveEffect2) { case MOVE_EFFECT_KNOCK_OFF: - effect = TryKnockOffBattleScript(gBattlerTarget); + if (!DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove)) + { + effect = TryKnockOffBattleScript(gBattlerTarget); + } break; case MOVE_EFFECT_STOCKPILE_WORE_OFF: if (gDisableStructs[gBattlerAttacker].stockpileCounter != 0) @@ -5621,7 +5644,9 @@ static void Cmd_moveend(void) } break; case MOVE_EFFECT_SMACK_DOWN: - if (!IsBattlerGrounded(gBattlerTarget) && IsBattlerAlive(gBattlerTarget)) + if (!IsBattlerGrounded(gBattlerTarget) + && IsBattlerAlive(gBattlerTarget) + && !DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove)) { gStatuses3[gBattlerTarget] |= STATUS3_SMACKED_DOWN; gStatuses3[gBattlerTarget] &= ~(STATUS3_MAGNET_RISE | STATUS3_TELEKINESIS | STATUS3_ON_AIR); @@ -5631,10 +5656,12 @@ static void Cmd_moveend(void) } break; case MOVE_EFFECT_REMOVE_STATUS: // Smelling salts, Wake-Up Slap, Sparkling Aria - if ((gBattleMons[gBattlerTarget].status1 & gMovesInfo[gCurrentMove].argument) && IsBattlerAlive(gBattlerTarget)) + if ((gBattleMons[gBattlerTarget].status1 & gMovesInfo[gCurrentMove].argument) + && IsBattlerAlive(gBattlerTarget) + && !DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove)) { gBattleMons[gBattlerTarget].status1 &= ~(gMovesInfo[gCurrentMove].argument); - + BtlController_EmitSetMonData(gBattlerTarget, 0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gBattlerTarget].status1); MarkBattlerForControllerExec(gBattlerTarget); effect = TRUE; @@ -5650,6 +5677,17 @@ static void Cmd_moveend(void) case STATUS1_BURN: gBattlescriptCurrInstr = BattleScript_TargetBurnHeal; break; + case STATUS1_FREEZE: + gBattlescriptCurrInstr = BattleScript_FrostbiteHealedViaFireMove; + break; + case STATUS1_FROSTBITE: + gBattlescriptCurrInstr = BattleScript_DefrostedViaFireMove; + break; + case STATUS1_POISON: + case STATUS1_TOXIC_POISON: + case STATUS1_PSN_ANY: + gBattlescriptCurrInstr = BattleScript_TargetPoisonHealed; + break; } } break; // MOVE_EFFECT_REMOVE_STATUS @@ -5873,7 +5911,11 @@ static void Cmd_moveend(void) gBattleScripting.moveendState = 0; MoveValuesCleanUp(); gBattleScripting.moveEffect = gBattleScripting.savedMoveEffect; - BattleScriptPush(GET_MOVE_BATTLESCRIPT(gCurrentMove)); + + if (gMovesInfo[gCurrentMove].effect == EFFECT_EXPLOSION) + BattleScriptPush(gBattleMoveEffects[EFFECT_HIT].battleScript); // Edge case for Explosion not changing targets + else + BattleScriptPush(GET_MOVE_BATTLESCRIPT(gCurrentMove)); gBattlescriptCurrInstr = BattleScript_FlushMessageBox; return; } @@ -6007,8 +6049,6 @@ static void Cmd_moveend(void) for (i = 0; i < gBattlersCount; i++) { u32 holdEffect; - if (i == gBattlerAttacker) - continue; holdEffect = GetBattlerHoldEffect(i, TRUE); if (holdEffect == HOLD_EFFECT_EJECT_BUTTON) ejectButtonBattlers |= gBitTable[i]; @@ -6024,7 +6064,7 @@ static void Cmd_moveend(void) { u32 battler = battlers[i]; - if (ejectButtonBattlers & gBitTable[battler]) + if (battler != gBattlerAttacker && ejectButtonBattlers & gBitTable[battler]) { if (TestIfSheerForceAffected(gBattlerAttacker, gCurrentMove)) // Apparently Sheer Force blocks Eject Button, but not Eject Pack continue; @@ -6178,8 +6218,19 @@ static void Cmd_moveend(void) case MOVEEND_DANCER: // Special case because it's so annoying if (gMovesInfo[gCurrentMove].danceMove) { - u8 battler, nextDancer = 0; + u32 battler, nextDancer = 0; + bool32 turnOnHitmarker = FALSE; + for (battler = 0; battler < MAX_BATTLERS_COUNT; battler++) + { + if (gSpecialStatuses[battler].dancerUsedMove) + { + // in case a battler fails to act on a Dancer-called move + turnOnHitmarker = TRUE; + break; + } + } + if (!(gBattleStruct->lastMoveFailed & gBitTable[gBattlerAttacker] || (!gSpecialStatuses[gBattlerAttacker].dancerUsedMove && gBattleStruct->bouncedMoveIsUsed))) @@ -6195,6 +6246,8 @@ static void Cmd_moveend(void) { if (GetBattlerAbility(battler) == ABILITY_DANCER && !gSpecialStatuses[battler].dancerUsedMove) { + if (turnOnHitmarker) + gHitMarker |= HITMARKER_ATTACKSTRING_PRINTED; if (!nextDancer || (gBattleMons[battler].speed < gBattleMons[nextDancer & 0x3].speed)) nextDancer = battler | 0x4; } @@ -6259,14 +6312,11 @@ static void Cmd_moveend(void) gBattleScripting.moveendState++; break; case MOVEEND_SET_EVOLUTION_TRACKER: - { // If the Pokémon needs to keep track of move usage for its evolutions, do it if (originallyUsedMove != MOVE_NONE) TryUpdateEvolutionTracker(EVO_LEVEL_MOVE_TWENTY_TIMES, 1, originallyUsedMove); gBattleScripting.moveendState++; break; - - } case MOVEEND_CLEAR_BITS: // Clear/Set bits for things like using a move for all targets and all hits. if (gSpecialStatuses[gBattlerAttacker].instructedChosenTarget) *(gBattleStruct->moveTarget + gBattlerAttacker) = gSpecialStatuses[gBattlerAttacker].instructedChosenTarget & 0x3; @@ -10897,19 +10947,9 @@ static void Cmd_tryexplosion(void) { CMD_ARGS(); - u32 dampBattler; if (gBattleControllerExecFlags) return; - if ((dampBattler = IsAbilityOnField(ABILITY_DAMP))) - { - // Failed, a battler has Damp - gLastUsedAbility = ABILITY_DAMP; - gBattlerTarget = --dampBattler; - gBattlescriptCurrInstr = BattleScript_DampStopsExplosion; - return; - } - gBattleMoveDamage = gBattleMons[gBattlerAttacker].hp; BtlController_EmitHealthBarUpdate(gBattlerAttacker, BUFFER_A, INSTANT_HP_BAR_DROP); MarkBattlerForControllerExec(gBattlerAttacker); @@ -16832,6 +16872,40 @@ void BS_TryGulpMissile(void) gBattlescriptCurrInstr = cmd->nextInstr; } +void BS_TryActivateGulpMissile(void) +{ + NATIVE_ARGS(); + + if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) + && !gProtectStructs[gBattlerAttacker].confusionSelfDmg + && TARGET_TURN_DAMAGED + && gBattleMons[gBattlerTarget].species != SPECIES_CRAMORANT + && GetBattlerAbility(gBattlerTarget) == ABILITY_GULP_MISSILE) + { + if (GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) + { + gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerAttacker) / 4; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + } + + switch(gBattleMons[gBattlerTarget].species) + { + case SPECIES_CRAMORANT_GORGING: + BattleScriptPushCursor(); + TryBattleFormChange(gBattlerTarget, FORM_CHANGE_HIT_BY_MOVE); + gBattlescriptCurrInstr = BattleScript_GulpMissileGorging; + return; + case SPECIES_CRAMORANT_GULPING: + BattleScriptPushCursor(); + TryBattleFormChange(gBattlerTarget, FORM_CHANGE_HIT_BY_MOVE); + gBattlescriptCurrInstr = BattleScript_GulpMissileGulping; + return; + } + } + gBattlescriptCurrInstr = cmd->nextInstr; +} + void BS_TryQuash(void) { diff --git a/src/battle_util.c b/src/battle_util.c index 7e2574f50..a5ef67942 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -364,7 +364,7 @@ void HandleAction_UseItem(void) gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT; } -bool8 TryRunFromBattle(u8 battler) +bool32 TryRunFromBattle(u32 battler) { bool32 effect = FALSE; u8 holdEffect; @@ -4200,6 +4200,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && CountBattlerStatIncreases(BATTLE_PARTNER(battler), FALSE)) { gSpecialStatuses[battler].switchInAbilityDone = TRUE; + gBattlerAttacker = battler; for (i = 0; i < NUM_BATTLE_STATS; i++) gBattleMons[battler].statStages[i] = gBattleMons[BATTLE_PARTNER(battler)].statStages[i]; gBattlerTarget = BATTLE_PARTNER(battler); @@ -4216,6 +4217,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && !(gBattleStruct->transformZeroToHero[side] & gBitTable[gBattlerPartyIndexes[battler]])) { gSpecialStatuses[battler].switchInAbilityDone = TRUE; + gBattlerAttacker = battler; gBattleStruct->transformZeroToHero[side] |= gBitTable[gBattlerPartyIndexes[battler]]; BattleScriptPushCursorAndCallback(BattleScript_ZeroToHeroActivates); effect++; @@ -4243,16 +4245,16 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_EMBODY_ASPECT_CORNERSTONE_MASK: if (!gSpecialStatuses[battler].switchInAbilityDone) { - u32 stat = STAT_SPATK; + u32 stat; - if (gLastUsedAbility == ABILITY_EMBODY_ASPECT_TEAL_MASK) - stat = STAT_SPATK; - else if (gLastUsedAbility == ABILITY_EMBODY_ASPECT_HEARTHFLAME_MASK) + if (gLastUsedAbility == ABILITY_EMBODY_ASPECT_HEARTHFLAME_MASK) stat = STAT_ATK; else if (gLastUsedAbility == ABILITY_EMBODY_ASPECT_WELLSPRING_MASK) stat = STAT_SPDEF; else if (gLastUsedAbility == ABILITY_EMBODY_ASPECT_CORNERSTONE_MASK) stat = STAT_DEF; + else //ABILITY_EMBODY_ASPECT_TEAL_MASK + stat = STAT_SPEED; if (CompareStat(battler, stat, MAX_STAT_STAGE, CMP_EQUAL)) break; @@ -4387,10 +4389,10 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 BattleScriptPushCursorAndCallback(BattleScript_BadDreamsActivates); effect++; break; - SOLAR_POWER_HP_DROP: case ABILITY_SOLAR_POWER: if (IsBattlerWeatherAffected(battler, B_WEATHER_SUN)) { + SOLAR_POWER_HP_DROP: BattleScriptPushCursorAndCallback(BattleScript_SolarPowerActivates); gBattleMoveDamage = GetNonDynamaxMaxHP(battler) / 8; if (gBattleMoveDamage == 0) @@ -4424,7 +4426,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 break; case ABILITY_BALL_FETCH: if (gBattleMons[battler].item == ITEM_NONE - && gBattleResults.catchAttempts[gLastUsedBall - FIRST_BALL] >= 1 + && gBattleResults.catchAttempts[gLastUsedBall - ITEM_ULTRA_BALL] >= 1 && !gHasFetchedBall) { gBattleScripting.battler = battler; @@ -4461,30 +4463,69 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITYEFFECT_MOVES_BLOCK: // 2 { u16 moveTarget = GetBattlerMoveTargetType(battler, move); - u16 battlerAbility = GetBattlerAbility(battler); - u16 targetAbility = GetBattlerAbility(gBattlerTarget); - if ((gLastUsedAbility == ABILITY_SOUNDPROOF && gMovesInfo[move].soundMove && !(moveTarget & MOVE_TARGET_USER)) - || (gLastUsedAbility == ABILITY_BULLETPROOF && gMovesInfo[move].ballisticMove)) + switch (gLastUsedAbility) + { + case ABILITY_SOUNDPROOF: + if (gMovesInfo[move].soundMove && !(moveTarget & MOVE_TARGET_USER)) + effect = 1; + break; + case ABILITY_BULLETPROOF: + if (gMovesInfo[move].ballisticMove) + effect = 1; + break; + case ABILITY_DAZZLING: + case ABILITY_QUEENLY_MAJESTY: + case ABILITY_ARMOR_TAIL: + if (GetChosenMovePriority(gBattlerAttacker) > 0 && GetBattlerSide(gBattlerAttacker) != GetBattlerSide(battler)) + effect = 2; + break; + case ABILITY_GOOD_AS_GOLD: + if (IS_MOVE_STATUS(gCurrentMove) + && !(moveTarget & MOVE_TARGET_USER) + && !(moveTarget & MOVE_TARGET_OPPONENTS_FIELD) + && !(moveTarget & MOVE_TARGET_ALL_BATTLERS)) + effect = 3; + break; + } + + if (!effect) + { + switch (GetBattlerAbility(BATTLE_PARTNER(battler))) + { + case ABILITY_DAZZLING: + case ABILITY_QUEENLY_MAJESTY: + case ABILITY_ARMOR_TAIL: + if (GetChosenMovePriority(gBattlerAttacker) > 0 && GetBattlerSide(gBattlerAttacker) != GetBattlerSide(battler)) + effect = 4; + break; + } + } + + if (effect == 1) { if (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS) gHitMarker |= HITMARKER_NO_PPDEDUCT; gBattlescriptCurrInstr = BattleScript_SoundproofProtected; - effect = 1; } - else if ((gLastUsedAbility == ABILITY_DAZZLING || gLastUsedAbility == ABILITY_QUEENLY_MAJESTY || gLastUsedAbility == ABILITY_ARMOR_TAIL || IsBattlerAlive(battler ^= BIT_FLANK)) - && (battlerAbility == ABILITY_DAZZLING || battlerAbility == ABILITY_QUEENLY_MAJESTY || battlerAbility == ABILITY_ARMOR_TAIL) - && GetChosenMovePriority(gBattlerAttacker) > 0 - && GetBattlerSide(gBattlerAttacker) != GetBattlerSide(battler)) + else if (effect == 2 || effect == 4) { + if (effect == 4) + gBattleScripting.battler = BATTLE_PARTNER(battler); + else + gBattleScripting.battler = battler; + if (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS) gHitMarker |= HITMARKER_NO_PPDEDUCT; gBattlescriptCurrInstr = BattleScript_DazzlingProtected; - effect = 1; + } + else if (effect == 3) + { + gBattlescriptCurrInstr = BattleScript_GoodAsGoldActivates; } else if (GetChosenMovePriority(gBattlerAttacker) > 0 - && BlocksPrankster(move, gBattlerAttacker, gBattlerTarget, TRUE) - && !(IS_MOVE_STATUS(move) && (targetAbility == ABILITY_MAGIC_BOUNCE || gProtectStructs[gBattlerTarget].bounceMove))) + && BlocksPrankster(move, gBattlerAttacker, gBattlerTarget, TRUE) + && !(IS_MOVE_STATUS(move) && (gLastUsedAbility == ABILITY_MAGIC_BOUNCE || gProtectStructs[gBattlerTarget].bounceMove))) { if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE) || !(moveTarget & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))) CancelMultiTurnMoves(gBattlerAttacker); // Don't cancel moves that can hit two targets bc one target might not be protected @@ -4492,15 +4533,6 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 gBattlescriptCurrInstr = BattleScript_DarkTypePreventsPrankster; effect = 1; } - else if (GetBattlerAbility(gBattlerTarget) == ABILITY_GOOD_AS_GOLD - && IS_MOVE_STATUS(gCurrentMove) - && !(moveTarget & MOVE_TARGET_USER) - && !(moveTarget & MOVE_TARGET_OPPONENTS_FIELD) - && !(moveTarget & MOVE_TARGET_ALL_BATTLERS)) - { - gBattlescriptCurrInstr = BattleScript_GoodAsGoldActivates; - effect = 1; - } break; } case ABILITYEFFECT_ABSORBING: // 3 @@ -4960,6 +4992,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && RandomWeighted(RNG_STATIC, 2, 1)) { gBattleScripting.moveEffect = MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_PARALYSIS; + PREPARE_ABILITY_BUFFER(gBattleTextBuff1, gLastUsedAbility); BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_AbilityStatusEffect; gHitMarker |= HITMARKER_STATUS_ABILITY_EFFECT; @@ -4977,6 +5010,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && RandomWeighted(RNG_FLAME_BODY, 2, 1)) { gBattleScripting.moveEffect = MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_BURN; + PREPARE_ABILITY_BUFFER(gBattleTextBuff1, gLastUsedAbility); BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_AbilityStatusEffect; gHitMarker |= HITMARKER_STATUS_ABILITY_EFFECT; @@ -5083,34 +5117,30 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && TARGET_TURN_DAMAGED - && IsBattlerAlive(battler)) + && IsBattlerAlive(battler) + && gBattleMons[gBattlerTarget].species != SPECIES_CRAMORANT) { - // TODO: Convert this to a proper FORM_CHANGE type. - if (gBattleMons[gBattlerTarget].species == SPECIES_CRAMORANT_GORGING) + if (GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) { - gBattleMons[gBattlerTarget].species = SPECIES_CRAMORANT; - if (GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) - { - gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerAttacker) / 4; - if (gBattleMoveDamage == 0) - gBattleMoveDamage = 1; - } - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_GulpMissileGorging; - effect++; + gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerAttacker) / 4; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; } - else if (gBattleMons[gBattlerTarget].species == SPECIES_CRAMORANT_GULPING) + + switch(gBattleMons[gBattlerTarget].species) { - gBattleMons[gBattlerTarget].species = SPECIES_CRAMORANT; - if (GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) - { - gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerAttacker) / 4; - if (gBattleMoveDamage == 0) - gBattleMoveDamage = 1; - } - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_GulpMissileGulping; - effect++; + case SPECIES_CRAMORANT_GORGING: + TryBattleFormChange(battler, FORM_CHANGE_HIT_BY_MOVE); + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_GulpMissileGorging; + effect++; + break; + case SPECIES_CRAMORANT_GULPING: + TryBattleFormChange(battler, FORM_CHANGE_HIT_BY_MOVE); + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_GulpMissileGulping; + effect++; + break; } } break; @@ -5241,6 +5271,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (IsBattlerAlive(battler) && (gMovesInfo[gCurrentMove].danceMove) && !gSpecialStatuses[battler].dancerUsedMove + && (gHitMarker & HITMARKER_ATTACKSTRING_PRINTED) && gBattlerAttacker != battler) { // Set bit and save Dancer mon's original target @@ -10478,6 +10509,7 @@ u16 GetBattleFormChangeTargetSpecies(u32 battler, u16 method) } break; case FORM_CHANGE_BATTLE_TURN_END: + case FORM_CHANGE_HIT_BY_MOVE: if (formChanges[i].param1 == GetBattlerAbility(battler)) targetSpecies = formChanges[i].targetSpecies; break; diff --git a/src/data/battle_move_effects.h b/src/data/battle_move_effects.h index 71052f935..e8765ec58 100644 --- a/src/data/battle_move_effects.h +++ b/src/data/battle_move_effects.h @@ -1495,7 +1495,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_MIND_BLOWN] = { - .battleScript = BattleScript_EffectMindBlown, + .battleScript = BattleScript_EffectHit, }, [EFFECT_PURIFY] = diff --git a/src/data/pokemon/form_change_tables.h b/src/data/pokemon/form_change_tables.h index 5edd6f42b..8eb96e04b 100644 --- a/src/data/pokemon/form_change_tables.h +++ b/src/data/pokemon/form_change_tables.h @@ -1098,6 +1098,7 @@ static const struct FormChange sSandacondaFormChangeTable[] = 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_HIT_BY_MOVE, SPECIES_CRAMORANT, ABILITY_GULP_MISSILE}, {FORM_CHANGE_BATTLE_SWITCH, SPECIES_CRAMORANT}, {FORM_CHANGE_FAINT, SPECIES_CRAMORANT}, {FORM_CHANGE_END_BATTLE, SPECIES_CRAMORANT},