From 548a43f8d965767d00c1a107a314a546615a067c Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Thu, 25 Jun 2020 16:15:11 +0200 Subject: [PATCH] Rocky Helmet before Knock Off --- asm/macros/battle_script.inc | 5 ++ data/battle_scripts_1.s | 3 + include/battle.h | 1 + include/constants/battle_script_commands.h | 22 ++--- src/battle_script_commands.c | 93 +++++++++++++--------- 5 files changed, 76 insertions(+), 48 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 315c8c327d..a6a611b4b6 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1751,6 +1751,11 @@ various \battler, VARIOUS_SET_LAST_USED_ITEM .endm + .macro jumpifabsent battler:req, ptr:req + various \battler, VARIOUS_JUMP_IF_ABSENT + .4byte \ptr + .endm + @ helpful macros .macro setstatchanger stat:req, stages:req, down:req setbyte sSTATCHANGER \stat | \stages << 3 | \down << 7 diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 86162ba850..94eaecc2d3 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -7100,8 +7100,11 @@ BattleScript_RoughSkinActivates:: return BattleScript_RockyHelmetActivates:: + @ don't play the animation for a fainted mon + jumpifabsent BS_TARGET, BattleScript_RockyHelmetActivatesDmg playanimation BS_TARGET, B_ANIM_HELD_ITEM_EFFECT, NULL waitanimation +BattleScript_RockyHelmetActivatesDmg: call BattleScript_HurtAttacker return diff --git a/include/battle.h b/include/battle.h index 8e49f2644f..a9c9516c89 100644 --- a/include/battle.h +++ b/include/battle.h @@ -547,6 +547,7 @@ struct BattleStruct u8 friskedBattler; // Frisk needs to identify 2 battlers in double battles. bool8 friskedAbility; // If identifies two mons, show the ability pop-up only once. u8 sameMoveTurns[MAX_BATTLERS_COUNT]; // For Metronome, number of times the same moves has been SUCCESFULLY used. + u16 moveEffect2; // For Knock Off }; #define GET_MOVE_TYPE(move, typeArg) \ diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 4e6e56650f..764d0d422d 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -161,6 +161,7 @@ #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 // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 @@ -200,16 +201,17 @@ #define MOVEEND_ATTACKER_VISIBLE 11 #define MOVEEND_TARGET_VISIBLE 12 #define MOVEEND_ITEM_EFFECTS_TARGET 13 -#define MOVEEND_ITEM_EFFECTS_ALL 14 -#define MOVEEND_KINGSROCK_SHELLBELL 15 -#define MOVEEND_SUBSTITUTE 16 -#define MOVEEND_UPDATE_LAST_MOVES 17 -#define MOVEEND_MIRROR_MOVE 18 -#define MOVEEND_NEXT_TARGET 19 -#define MOVEEND_LIFE_ORB 20 -#define MOVEEND_DANCER 21 -#define MOVEEND_CLEAR_BITS 22 -#define MOVEEND_COUNT 23 +#define MOVEEND_MOVE_EFFECTS2 14 +#define MOVEEND_ITEM_EFFECTS_ALL 15 +#define MOVEEND_KINGSROCK_SHELLBELL 16 +#define MOVEEND_SUBSTITUTE 17 +#define MOVEEND_UPDATE_LAST_MOVES 18 +#define MOVEEND_MIRROR_MOVE 19 +#define MOVEEND_NEXT_TARGET 20 +#define MOVEEND_LIFE_ORB 21 +#define MOVEEND_DANCER 22 +#define MOVEEND_CLEAR_BITS 23 +#define MOVEEND_COUNT 24 // stat flags for Cmd_playstatchangeanimation #define BIT_HP 0x1 diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 06fcbd4293..a4ee9be4da 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -2179,6 +2179,14 @@ void SetMoveEffect(bool32 primary, u32 certain) bool32 statusChanged = FALSE; bool32 noSunCanFreeze = TRUE; + switch (gBattleScripting.moveEffect) // Set move effects which happen later on + { + case MOVE_EFFECT_KNOCK_OFF: + gBattleStruct->moveEffect2 = gBattleScripting.moveEffect; + gBattlescriptCurrInstr++; + return; + } + if (gBattleScripting.moveEffect & MOVE_EFFECT_AFFECTS_USER) { gEffectBattler = gBattlerAttacker; // battlerId that effects get applied on @@ -2861,43 +2869,6 @@ void SetMoveEffect(bool32 primary, u32 certain) gBattleMons[gEffectBattler].status2 |= (((Random() & 1) + 2) << 0xA); } break; - case MOVE_EFFECT_KNOCK_OFF: - if (!CanBattlerGetOrLoseItem(gEffectBattler, gBattleMons[gEffectBattler].item)) - { - gBattlescriptCurrInstr++; - } - else if (GetBattlerAbility(gEffectBattler) == ABILITY_STICKY_HOLD) - { - if (gBattleMons[gEffectBattler].item == 0) - { - gBattlescriptCurrInstr++; - } - else - { - gLastUsedAbility = ABILITY_STICKY_HOLD; - gBattlescriptCurrInstr = BattleScript_StickyHoldActivates; - RecordAbilityBattle(gEffectBattler, ABILITY_STICKY_HOLD); - } - } - else if (gBattleMons[gEffectBattler].item) - { - side = GetBattlerSide(gEffectBattler); - - gLastUsedItem = gBattleMons[gEffectBattler].item; - gBattleMons[gEffectBattler].item = 0; - gWishFutureKnock.knockedOffMons[side] |= gBitTable[gBattlerPartyIndexes[gEffectBattler]]; - CheckSetUnburden(gEffectBattler); - - BattleScriptPush(gBattlescriptCurrInstr + 1); - gBattlescriptCurrInstr = BattleScript_KnockedOff; - - gBattleStruct->choicedMove[gEffectBattler] = 0; - } - else - { - gBattlescriptCurrInstr++; - } - break; case MOVE_EFFECT_SP_ATK_TWO_DOWN: // Overheat BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_SAtkDown2; @@ -4437,6 +4408,36 @@ static void Cmd_playstatchangeanimation(void) } } +static bool32 TryKnockOffBattleScript(u32 battlerDef) +{ + if (gBattleMons[battlerDef].item != 0 + && CanBattlerGetOrLoseItem(battlerDef, gBattleMons[battlerDef].item) + && !NoAliveMonsForEitherParty()) + { + if (GetBattlerAbility(battlerDef) == ABILITY_STICKY_HOLD && IsBattlerAlive(battlerDef)) + { + gBattlerAbility = battlerDef; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_StickyHoldActivates; + } + else + { + u32 side = GetBattlerSide(battlerDef); + + gLastUsedItem = gBattleMons[battlerDef].item; + gBattleMons[battlerDef].item = 0; + gBattleStruct->choicedMove[battlerDef] = 0; + gWishFutureKnock.knockedOffMons[side] |= gBitTable[gBattlerPartyIndexes[battlerDef]]; + CheckSetUnburden(battlerDef); + + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_KnockedOff; + } + return TRUE; + } + return FALSE; +} + static void Cmd_moveend(void) { s32 i; @@ -4594,6 +4595,16 @@ static void Cmd_moveend(void) effect = TRUE; gBattleScripting.moveendState++; break; + case MOVEEND_MOVE_EFFECTS2: // For effects which should happen after target items, for example Knock Off after damage from Rocky Helmet. + switch (gBattleStruct->moveEffect2) + { + case MOVE_EFFECT_KNOCK_OFF: + effect = TryKnockOffBattleScript(gBattlerTarget); + break; + } + gBattleStruct->moveEffect2 = 0; + gBattleScripting.moveendState++; + break; case MOVEEND_ITEM_EFFECTS_ALL: // item effects for all battlers if (ItemBattleEffects(ITEMEFFECT_MOVE_END, 0, FALSE)) effect = TRUE; @@ -6841,6 +6852,12 @@ static void Cmd_various(void) else gBattlescriptCurrInstr += 7; return; + case VARIOUS_JUMP_IF_ABSENT: + if (!IsBattlerAlive(gActiveBattler)) + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); + else + gBattlescriptCurrInstr += 7; + return; case VARIOUS_JUMP_IF_SHIELDS_DOWN_PROTECTED: if (IsShieldsDownProtected(gActiveBattler)) gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); @@ -9595,7 +9612,7 @@ static void Cmd_disablelastusedattack(void) gDisableStructs[gBattlerTarget].disableTimer = (Random() & 3) + 2; else if (B_DISABLE_TURNS == GEN_4) gDisableStructs[gBattlerTarget].disableTimer = (Random() & 3) + 4; - else + else gDisableStructs[gBattlerTarget].disableTimer = 4; gDisableStructs[gBattlerTarget].disableTimerStartValue = gDisableStructs[gBattlerTarget].disableTimer; // used to save the random amount of turns? gBattlescriptCurrInstr += 5;