diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index cdec01dbd8..69f382046f 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1477,6 +1477,15 @@ various \battler, VARIOUS_HANDLE_MEGA_EVO .endm + .macro jumpifcantuselastresort battler ptr + various \battler, VARIOUS_TRY_LAST_RESORT + .4byte \ptr + .endm + + .macro argumentstatuseffect + various BS_ATTACKER, VARIOUS_ARGUMENT_STATUS_EFFECT + .endm + @ helpful macros .macro setstatchanger stat, stages, down setbyte sSTATCHANGER \stat | \stages << 4 | \down << 7 diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index d57063bd95..2c0abf1dcc 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -300,6 +300,17 @@ gBattleScriptsForMoveEffects:: @ 82D86A8 .4byte BattleScript_EffectSoak .4byte BattleScript_EffectGrowth .4byte BattleScript_EffectCloseCombat + .4byte BattleScript_EffectLastResort + .4byte BattleScript_EffectRecoil33WithStatus + .4byte BattleScript_EffectFlinchWithStatus + +BattleScript_EffectLastResort: + attackcanceler + attackstring + ppreduce + jumpifcantuselastresort BS_ATTACKER, BattleScript_ButItFailed + accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE + goto BattleScript_HitFromCritCalc BattleScript_EffectGrowth: attackcanceler @@ -1468,7 +1479,32 @@ BattleScript_EffectConversion:: BattleScript_EffectFlinchHit:: setmoveeffect MOVE_EFFECT_FLINCH goto BattleScript_EffectHit - + +BattleScript_EffectFlinchWithStatus: + setmoveeffect MOVE_EFFECT_FLINCH + attackcanceler + accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE + attackstring + ppreduce + critcalc + damagecalc + adjustdamage + attackanimation + waitanimation + effectivenesssound + hitanimation BS_TARGET + waitstate + healthbarupdate BS_TARGET + datahpupdate BS_TARGET + critmessage + waitmessage 0x40 + resultmessage + waitmessage 0x40 + seteffectwithchance + argumentstatuseffect + tryfaintmon BS_TARGET, FALSE, NULL + goto BattleScript_MoveEnd + BattleScript_EffectRestoreHp:: attackcanceler attackstring @@ -3348,6 +3384,10 @@ BattleScript_EffectSecretPower:: BattleScript_EffectDoubleEdge:: setmoveeffect MOVE_EFFECT_RECOIL_33 | MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN goto BattleScript_EffectHit + +BattleScript_EffectRecoil33WithStatus: + setmoveeffect MOVE_EFFECT_RECOIL_33_STATUS | MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN + goto BattleScript_EffectHit BattleScript_EffectTeeterDance:: attackcanceler @@ -4563,14 +4603,14 @@ BattleScript_AtkDefDown:: jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0x2, BattleScript_AtkDefDownTryDef printfromtable gStatDownStringIds waitmessage 0x40 -BattleScript_AtkDefDownTryDef:: +BattleScript_AtkDefDownTryDef: playstatchangeanimation BS_ATTACKER, BIT_DEF, ATK48_DONT_CHECK_LOWER | ATK48_STAT_NEGATIVE setstatchanger STAT_DEF, 1, TRUE statbuffchange MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN | 0x1, BattleScript_AtkDefDownRet jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0x2, BattleScript_AtkDefDownRet printfromtable gStatDownStringIds waitmessage 0x40 -BattleScript_AtkDefDownRet:: +BattleScript_AtkDefDownRet: return BattleScript_DefSpDefDown:: @@ -4945,6 +4985,9 @@ BattleScript_MoveEffectConfusion:: waitmessage 0x40 return +BattleScript_MoveEffectRecoilWithStatus:: + argumentstatuseffect + copyword gBattleMoveDamage, sSAVED_DMG BattleScript_MoveEffectRecoil:: jumpifmove MOVE_STRUGGLE, BattleScript_DoRecoil jumpifability BS_ATTACKER, ABILITY_ROCK_HEAD, BattleScript_RecoilEnd @@ -4957,6 +5000,10 @@ BattleScript_DoRecoil:: tryfaintmon BS_ATTACKER, FALSE, NULL BattleScript_RecoilEnd:: return + +BattleScript_EffectWithChance:: + seteffectwithchance + return BattleScript_ItemSteal:: playanimation BS_TARGET, B_ANIM_ITEM_STEAL, NULL diff --git a/include/battle.h b/include/battle.h index b605e352b3..85bf5937fa 100644 --- a/include/battle.h +++ b/include/battle.h @@ -179,6 +179,7 @@ struct DisableStruct u8 telekinesisTimer; u8 healBlockTimer; u8 laserFocusTimer; + u8 usedMoves:4; }; struct ProtectStruct @@ -673,6 +674,7 @@ struct BattleScripting u8 windowsType; // 0 - normal, 1 - battle arena u8 multiplayerId; bool8 monCaught; + s32 savedDmg; }; // rom_80A5C6C diff --git a/include/battle_scripts.h b/include/battle_scripts.h index f1c80da4bd..70733b41a3 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -273,5 +273,7 @@ extern const u8 BattleScript_ToxicSpikesFree[]; extern const u8 BattleScript_StickyWebFree[]; extern const u8 BattleScript_StealthRockFree[]; extern const u8 BattleScript_MegaEvolution[]; +extern const u8 BattleScript_MoveEffectRecoilWithStatus[]; +extern const u8 BattleScript_EffectWithChance[]; #endif // GUARD_BATTLE_SCRIPTS_H diff --git a/include/constants/battle.h b/include/constants/battle.h index 6eb81e0ef4..2fedc4aa36 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -310,7 +310,7 @@ #define MOVE_EFFECT_THRASH 0x35 #define MOVE_EFFECT_KNOCK_OFF 0x36 #define MOVE_EFFECT_DEF_SPDEF_DOWN 0x37 -#define MOVE_EFFECT_NOTHING_38 0x38 +#define MOVE_EFFECT_RECOIL_33_STATUS 0x38 #define MOVE_EFFECT_NOTHING_39 0x39 #define MOVE_EFFECT_NOTHING_3A 0x3A #define MOVE_EFFECT_SP_ATK_TWO_DOWN 0x3B diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index 3ebf8f6a3b..f9c550318f 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -289,5 +289,8 @@ #define EFFECT_SOAK 283 #define EFFECT_GROWTH 284 #define EFFECT_CLOSE_COMBAT 285 +#define EFFECT_LAST_RESORT 286 +#define EFFECT_RECOIL_33_STATUS 287 +#define EFFECT_FLINCH_STATUS 288 #endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index cdb3bae3f8..830c2a7d57 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -29,6 +29,7 @@ #define sFIELD_24 gBattleScripting + 0x24 #define sMULTIPLAYER_ID gBattleScripting + 0x25 #define sMON_CAUGHT gBattleScripting + 0x26 +#define sSAVED_DMG gBattleScripting + 0x28 #define cEFFECT_CHOOSER gBattleCommunication + 3 #define cMULTISTRING_CHOOSER gBattleCommunication + 5 @@ -100,6 +101,8 @@ #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 // atk80, dmg manipulation #define ATK80_DMG_CHANGE_SIGN 0 diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 5fa738f08e..f457fdb86d 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -2297,7 +2297,7 @@ void SetMoveEffect(bool8 primary, u8 certain) } break; case MOVE_EFFECT_FLINCH: - if (gBattleMons[gEffectBattler].ability == ABILITY_INNER_FOCUS) + if (GetBattlerAbility(gEffectBattler) == ABILITY_INNER_FOCUS) { if (primary == TRUE || certain == MOVE_EFFECT_CERTAIN) { @@ -2606,6 +2606,14 @@ void SetMoveEffect(bool8 primary, u8 certain) BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = sMoveEffectBS_Ptrs[gBattleCommunication[MOVE_EFFECT_BYTE]]; break; + case MOVE_EFFECT_RECOIL_33_STATUS: // Flare Blitz - can burn, Volt Tackle - can paralyze + gBattleScripting.savedDmg = gHpDealt / 3; + if (gBattleScripting.savedDmg == 0) + gBattleScripting.savedDmg = 1; + + BattleScriptPush(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = BattleScript_MoveEffectRecoilWithStatus; + break; case MOVE_EFFECT_THRASH: if (gBattleMons[gEffectBattler].status2 & STATUS2_LOCK_CONFUSE) { @@ -2667,7 +2675,7 @@ static void atk15_seteffectwithchance(void) { u32 percentChance; - if (gBattleMons[gBattlerAttacker].ability == ABILITY_SERENE_GRACE) + if (GetBattlerAbility(gBattlerAttacker) == ABILITY_SERENE_GRACE) percentChance = gBattleMoves[gCurrentMove].secondaryEffectChance * 2; else percentChance = gBattleMoves[gCurrentMove].secondaryEffectChance; @@ -4193,6 +4201,7 @@ static void atk49_moveend(void) gBattleScripting.atk49_state++; break; case ATK49_UPDATE_LAST_MOVES: + gDisableStructs[gBattlerAttacker].usedMoves |= gBitTable[gCurrMovePos]; if (gHitMarker & HITMARKER_SWAP_ATTACKER_TARGET) { gActiveBattler = gBattlerAttacker; @@ -6121,6 +6130,25 @@ static void HandleTerrainMove(u32 moveEffect) } } +bool32 CanUseLastResort(u8 battlerId) +{ + u32 i; + u32 knownMovesCount = 0, usedMovesCount = 0; + + for (i = 0; i < 4; i++) + { + if (gBattleMons[battlerId].moves[i] != MOVE_NONE) + knownMovesCount++; + if (gDisableStructs[battlerId].usedMoves & gBitTable[i]) + usedMovesCount++; + } + + if (knownMovesCount >= 2 && usedMovesCount >= knownMovesCount - 1) + return TRUE; + else + return FALSE; +} + static void atk76_various(void) { struct Pokemon *mon; @@ -6630,6 +6658,41 @@ static void atk76_various(void) BtlController_EmitSetMonData(0, REQUEST_ALL_BATTLE, gBitTable[gBattlerPartyIndexes[gActiveBattler]], sizeof(struct BattlePokemon), &gBattleMons[gActiveBattler]); MarkBattlerForControllerExec(gActiveBattler); break; + case VARIOUS_TRY_LAST_RESORT: + if (CanUseLastResort(gActiveBattler)) + gBattlescriptCurrInstr += 7; + else + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); + return; + case VARIOUS_ARGUMENT_STATUS_EFFECT: + switch (gBattleMoves[gCurrentMove].argument) + { + case STATUS1_BURN: + gBattleCommunication[MOVE_EFFECT_BYTE] = MOVE_EFFECT_BURN; + break; + case STATUS1_FREEZE: + gBattleCommunication[MOVE_EFFECT_BYTE] = MOVE_EFFECT_FREEZE; + break; + case STATUS1_PARALYSIS: + gBattleCommunication[MOVE_EFFECT_BYTE] = MOVE_EFFECT_PARALYSIS; + break; + case STATUS1_POISON: + gBattleCommunication[MOVE_EFFECT_BYTE] = MOVE_EFFECT_POISON; + break; + case STATUS1_TOXIC_POISON: + gBattleCommunication[MOVE_EFFECT_BYTE] = MOVE_EFFECT_TOXIC; + break; + default: + gBattleCommunication[MOVE_EFFECT_BYTE] = 0; + break; + } + if (gBattleCommunication[MOVE_EFFECT_BYTE] != 0) + { + BattleScriptPush(gBattlescriptCurrInstr + 3); + gBattlescriptCurrInstr = BattleScript_EffectWithChance; + return; + } + break; } gBattlescriptCurrInstr += 3; @@ -7901,6 +7964,7 @@ static void atk9B_transformdataexecution(void) gDisableStructs[gBattlerAttacker].disableTimer1 = 0; gDisableStructs[gBattlerAttacker].transformedMonPersonality = gBattleMons[gBattlerTarget].personality; gDisableStructs[gBattlerAttacker].unk18_b = 0; + gDisableStructs[gBattlerAttacker].usedMoves = 0; PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[gBattlerTarget].species) diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 569539f5c2..6c9498ad02 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -4132,16 +4132,17 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_GEN6] = .split = SPLIT_PHYSICAL, }, { // MOVE_VOLT_TACKLE - .effect = EFFECT_DOUBLE_EDGE, + .effect = EFFECT_RECOIL_33_STATUS, .power = 120, .type = TYPE_ELECTRIC, .accuracy = 100, .pp = 15, - .secondaryEffectChance = 0, + .secondaryEffectChance = 10, .target = MOVE_TARGET_SELECTED, .priority = 0, .flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGSROCK_AFFECTED | FLAG_RECKLESS_BOOST, .split = SPLIT_PHYSICAL, + .argument = STATUS1_PARALYSIS, }, { // MOVE_MAGICAL_LEAF .effect = EFFECT_HIT, @@ -4648,7 +4649,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_GEN6] = .split = SPLIT_PHYSICAL, }, { // MOVE_LAST_RESORT - .effect = EFFECT_PLACEHOLDER, // Needs a custom move effect + .effect = EFFECT_LAST_RESORT, .power = 140, .type = TYPE_NORMAL, .accuracy = 100, @@ -4732,7 +4733,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_GEN6] = .split = SPLIT_STATUS, }, { // MOVE_FLARE_BLITZ - .effect = EFFECT_PLACEHOLDER, // Needs a custom move effect + .effect = EFFECT_RECOIL_33_STATUS, .power = 120, .type = TYPE_FIRE, .accuracy = 100, @@ -4742,6 +4743,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_GEN6] = .priority = 0, .flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGSROCK_AFFECTED | FLAG_SHEER_FORCE_BOOST | FLAG_RECKLESS_BOOST, .split = SPLIT_PHYSICAL, + .argument = STATUS1_BURN, }, { // MOVE_FORCE_PALM .effect = EFFECT_PARALYZE_HIT, @@ -5068,7 +5070,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_GEN6] = .split = SPLIT_PHYSICAL, }, { // MOVE_THUNDER_FANG - .effect = EFFECT_PLACEHOLDER, // Needs a custom move effect (10% paralyze AND 10% flinch) + .effect = EFFECT_FLINCH_STATUS, .power = 65, .type = TYPE_ELECTRIC, .accuracy = 95, @@ -5078,9 +5080,10 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_GEN6] = .priority = 0, .flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGSROCK_AFFECTED | FLAG_SHEER_FORCE_BOOST | FLAG_STRONG_JAW_BOOST, .split = SPLIT_PHYSICAL, + .argument = STATUS1_PARALYSIS, }, { // MOVE_ICE_FANG - .effect = EFFECT_PLACEHOLDER, // Needs a custom move effect (10% paralyze AND 10% flinch) + .effect = EFFECT_FLINCH_STATUS, .power = 65, .type = TYPE_ICE, .accuracy = 95, @@ -5090,9 +5093,10 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_GEN6] = .priority = 0, .flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGSROCK_AFFECTED | FLAG_SHEER_FORCE_BOOST | FLAG_STRONG_JAW_BOOST, .split = SPLIT_PHYSICAL, + .argument = STATUS1_FREEZE, }, { // MOVE_FIRE_FANG - .effect = EFFECT_PLACEHOLDER, // Needs a custom move effect (10% paralyze AND 10% flinch) + .effect = EFFECT_FLINCH_STATUS, .power = 65, .type = TYPE_FIRE, .accuracy = 95, @@ -5102,6 +5106,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_GEN6] = .priority = 0, .flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGSROCK_AFFECTED | FLAG_SHEER_FORCE_BOOST | FLAG_STRONG_JAW_BOOST, .split = SPLIT_PHYSICAL, + .argument = STATUS1_BURN, }, { // MOVE_SHADOW_SNEAK .effect = EFFECT_HIT,