diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 208ef616c..371c1e27f 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1780,6 +1780,10 @@ .4byte \ptr .endm + .macro removeterrain + various BS_ATTACKER, VARIOUS_REMOVE_TERRAIN + .endm + @ helpful macros .macro setstatchanger stat:req, stages:req, down:req setbyte sSTATCHANGER \stat | \stages << 3 | \down << 7 diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index 3b3d59c82..9e9f4f441 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -13492,7 +13492,7 @@ Move_BODY_PRESS:: end Move_DECORATE:: - end @to do: + goto Move_FLOWER_SHIELD Move_DRUM_BEATING:: loadspritegfx ANIM_TAG_MUSIC_NOTES @@ -13968,7 +13968,7 @@ Move_EXPANDING_FORCE:: end @to do: Move_STEEL_ROLLER:: - end @to do: + goto Move_GYRO_BALL Move_SCALE_SHOT:: end @to do: diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 39a000cbd..63f99c7a4 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -369,6 +369,62 @@ gBattleScriptsForMoveEffects:: @ 82D86A8 .4byte BattleScript_EffectJungleHealing .4byte BattleScript_EffectCoaching .4byte BattleScript_EffectLashOut + .4byte BattleScript_EffectGrassyGlide + .4byte BattleScript_EffectRemoveTerrain + .4byte BattleScript_EffectBehemoth + .4byte BattleScript_EffectDecorate + +BattleScript_EffectDecorate: + attackcanceler + attackstring + ppreduce + jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_ATK, 12, BattleScript_DecorateBoost + jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_SPATK, 12, BattleScript_DecorateBoost + goto BattleScript_ButItFailed +BattleScript_DecorateBoost: + attackanimation + waitanimation + setbyte sSTAT_ANIM_PLAYED, FALSE + playstatchangeanimation BS_TARGET, BIT_ATK | BIT_SPATK, 0x0 + setstatchanger STAT_ATK, 2, FALSE + statbuffchange STAT_BUFF_ALLOW_PTR | STAT_BUFF_NOT_PROTECT_AFFECTED, BattleScript_DecorateBoostSpAtk + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0x2, BattleScript_DecorateBoostSpAtk + printfromtable gStatUpStringIds + waitmessage 0x40 +BattleScript_DecorateBoostSpAtk: + setstatchanger STAT_SPATK, 2, FALSE + statbuffchange STAT_BUFF_ALLOW_PTR | STAT_BUFF_NOT_PROTECT_AFFECTED, BattleScript_MoveEnd + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0x2, BattleScript_MoveEnd + printfromtable gStatUpStringIds + waitmessage 0x40 + goto BattleScript_MoveEnd + +BattleScript_EffectRemoveTerrain: + attackcanceler + attackstring + ppreduce + jumpifword CMP_NO_COMMON_BITS, gFieldStatuses, STATUS_FIELD_TERRAIN_ANY, BattleScript_ButItFailed + critcalc + damagecalc + adjustdamage + attackanimation + waitanimation + effectivenesssound + hitanimation BS_TARGET + waitstate + healthbarupdate BS_TARGET + datahpupdate BS_TARGET + critmessage + waitmessage 0x40 + resultmessage + waitmessage 0x40 + removeterrain + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 4, BattleScript_MoveEnd + printfromtable gTerrainEndingStringIds + waitmessage 0x40 + playanimation BS_ATTACKER, B_ANIM_RESTORE_BG, NULL + tryfaintmon BS_TARGET, FALSE, NULL + goto BattleScript_MoveEnd BattleScript_EffectCoaching: attackcanceler @@ -383,6 +439,8 @@ EffectCoaching_CheckAllyStats: jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_DEF, 12, BattleScript_CoachingWorks goto BattleScript_ButItFailed @ ally at max atk, def BattleScript_CoachingWorks: + attackanimation + waitanimation setbyte sSTAT_ANIM_PLAYED, FALSE playstatchangeanimation BS_TARGET, BIT_ATK | BIT_DEF, 0x0 setstatchanger STAT_ATK, 1, FALSE @@ -2113,6 +2171,8 @@ BattleScript_EffectFusionCombo: BattleScript_EffectRevelationDance: BattleScript_EffectBelch: BattleScript_EffectLashOut: +BattleScript_EffectGrassyGlide: +BattleScript_EffectBehemoth: BattleScript_HitFromAtkCanceler:: attackcanceler diff --git a/include/battle.h b/include/battle.h index 632d7e7fa..95f03d8e1 100644 --- a/include/battle.h +++ b/include/battle.h @@ -117,6 +117,7 @@ struct ProtectStruct u32 spikyShielded:1; u32 kingsShielded:1; u32 banefulBunkered:1; + u32 obstruct:1; u32 endured:1; u32 noValidMoves:1; u32 helpingHand:1; @@ -140,12 +141,12 @@ struct ProtectStruct u32 usedGravityPreventedMove:1; u32 powderSelfDmg:1; u32 usedThroatChopPreventedMove:1; + u32 statFell:1; + u32 statRaised:1; u32 physicalDmg; u32 specialDmg; u8 physicalBattlerId; u8 specialBattlerId; - u8 statFell:1; // placed here since cleared at end of round - u8 statRaised:1; }; struct SpecialStatus diff --git a/include/constants/battle.h b/include/constants/battle.h index a0c29d3cd..f9e34d88b 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -234,7 +234,7 @@ #define STATUS_FIELD_ION_DELUGE 0x400 #define STATUS_FIELD_FAIRY_LOCK 0x800 -#define STATUS_TERRAIN_ANY (STATUS_FIELD_GRASSY_TERRAIN | STATUS_FIELD_MISTY_TERRAIN | STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_PSYCHIC_TERRAIN) +#define STATUS_FIELD_TERRAIN_ANY (STATUS_FIELD_GRASSY_TERRAIN | STATUS_FIELD_MISTY_TERRAIN | STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_PSYCHIC_TERRAIN) // Flags describing move's result #define MOVE_RESULT_MISSED (1 << 0) diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index a15cb0c6b..8e1f1a0cf 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -355,5 +355,10 @@ #define EFFECT_JUNGLE_HEALING 349 #define EFFECT_COACHING 350 #define EFFECT_LASH_OUT 351 +#define EFFECT_GRASSY_GLIDE 352 +#define EFFECT_REMOVE_TERRAIN 353 +#define EFFECT_BEHEMOTH 354 +#define EFFECT_DECORATE 355 +#define EFFECT_SNIPE_SHOT 356 #endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index f2e6fbf88..04d824830 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -171,6 +171,7 @@ #define VARIOUS_EERIE_SPELL_PP_REDUCE 104 #define VARIOUS_JUMP_IF_TEAM_HEALTHY 105 #define VARIOUS_TRY_HEAL_QUARTER_HP 106 +#define VARIOUS_REMOVE_TERRAIN 107 // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 diff --git a/src/battle_anim.c b/src/battle_anim.c index cb7ea5bea..168b7a980 100644 --- a/src/battle_anim.c +++ b/src/battle_anim.c @@ -3205,7 +3205,7 @@ static void LoadDefaultBg(void) if (IsContest()) LoadContestBgAfterMoveAnim(); #if B_TERRAIN_BG_CHANGE == TRUE - else if (gFieldStatuses & STATUS_TERRAIN_ANY) + else if (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) DrawTerrainTypeBattleBackground(); #endif else diff --git a/src/battle_bg.c b/src/battle_bg.c index ca1893d65..521d0eae5 100644 --- a/src/battle_bg.c +++ b/src/battle_bg.c @@ -1422,7 +1422,7 @@ bool8 LoadChosenBattleElement(u8 caseId) void DrawTerrainTypeBattleBackground(void) { - switch (gFieldStatuses & STATUS_TERRAIN_ANY) + switch (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) { case STATUS_FIELD_GRASSY_TERRAIN: LoadMoveBg(BG_GRASSY_TERRAIN); diff --git a/src/battle_main.c b/src/battle_main.c index f48129acb..0ae2ca952 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3081,6 +3081,7 @@ void FaintClearSetData(void) gProtectStructs[gActiveBattler].spikyShielded = 0; gProtectStructs[gActiveBattler].kingsShielded = 0; gProtectStructs[gActiveBattler].banefulBunkered = 0; + gProtectStructs[gActiveBattler].obstruct = 0; gProtectStructs[gActiveBattler].endured = 0; gProtectStructs[gActiveBattler].noValidMoves = 0; gProtectStructs[gActiveBattler].helpingHand = 0; @@ -3102,6 +3103,8 @@ void FaintClearSetData(void) gProtectStructs[gActiveBattler].usesBouncedMove = 0; gProtectStructs[gActiveBattler].usedGravityPreventedMove = 0; gProtectStructs[gActiveBattler].usedThroatChopPreventedMove = 0; + gProtectStructs[gActiveBattler].statFell = 0; + gProtectStructs[gActiveBattler].statRaised = 0; gDisableStructs[gActiveBattler].isFirstTurn = 2; @@ -4315,6 +4318,10 @@ s8 GetMovePriority(u32 battlerId, u16 move) { priority++; } + else if (gBattleMoves[move].effect == EFFECT_GRASSY_GLIDE && gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN && IsBattlerGrounded(battlerId)) + { + priority++; + } else if (GetBattlerAbility(battlerId) == ABILITY_TRIAGE) { switch (gBattleMoves[move].effect) diff --git a/src/battle_message.c b/src/battle_message.c index 90e8c8967..cddfb3745 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -1252,6 +1252,11 @@ const u16 gTerrainStringIds[] = STRINGID_TERRAINBECOMESMISTY, STRINGID_TERRAINBECOMESGRASSY, STRINGID_TERRAINBECOMESELECTRIC, STRINGID_TERRAINBECOMESPSYCHIC }; +const u16 gTerrainEndingStringIds[] = +{ + STRINGID_MISTYTERRAINENDS, STRINGID_GRASSYTERRAINENDS, STRINGID_ELECTRICTERRAINENDS, STRINGID_PSYCHICTERRAINENDS +}; + const u16 gTerrainPreventsStringIds[] = { STRINGID_MISTYTERRAINPREVENTS, STRINGID_ELECTRICTERRAINPREVENTS, STRINGID_PSYCHICTERRAINPREVENTS @@ -1330,7 +1335,7 @@ const u16 gRainContinuesStringIds[] = const u16 gProtectLikeUsedStringIds[] = { - STRINGID_PKMNPROTECTEDITSELF2, STRINGID_PKMNBRACEDITSELF, STRINGID_BUTITFAILED, STRINGID_PROTECTEDTEAM, + STRINGID_PKMNPROTECTEDITSELF2, STRINGID_PKMNBRACEDITSELF, STRINGID_BUTITFAILED, STRINGID_PROTECTEDTEAM }; const u16 gReflectLightScreenSafeguardStringIds[] = diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 7ce9692d2..d2bcf86b6 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1171,13 +1171,15 @@ bool32 IsBattlerProtected(u8 battlerId, u16 move) return FALSE; else if (gBattleMoves[move].effect == MOVE_EFFECT_FEINT) return FALSE; - else if (gProtectStructs[battlerId].protected) + else if (gProtectStructs[battlerId].protected && move != MOVE_DECORATE) return TRUE; else if (gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_WIDE_GUARD && gBattleMoves[move].target & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)) return TRUE; else if (gProtectStructs[battlerId].banefulBunkered) return TRUE; + else if (gProtectStructs[battlerId].obstruct && !IS_MOVE_STATUS(move)) + return TRUE; else if (gProtectStructs[battlerId].spikyShielded) return TRUE; else if (gProtectStructs[battlerId].kingsShielded && gBattleMoves[move].power != 0) @@ -3126,7 +3128,8 @@ void SetMoveEffect(bool32 primary, u32 certain) || gSideStatuses[GetBattlerSide(gBattlerTarget)] & SIDE_STATUS_MAT_BLOCK || gProtectStructs[gBattlerTarget].spikyShielded || gProtectStructs[gBattlerTarget].kingsShielded - || gProtectStructs[gBattlerTarget].banefulBunkered) + || gProtectStructs[gBattlerTarget].banefulBunkered + || gProtectStructs[gBattlerTarget].obstruct) { gProtectStructs[gBattlerTarget].protected = 0; gSideStatuses[GetBattlerSide(gBattlerTarget)] &= ~(SIDE_STATUS_WIDE_GUARD); @@ -3136,6 +3139,7 @@ void SetMoveEffect(bool32 primary, u32 certain) gProtectStructs[gBattlerTarget].spikyShielded = 0; gProtectStructs[gBattlerTarget].kingsShielded = 0; gProtectStructs[gBattlerTarget].banefulBunkered = 0; + gProtectStructs[gBattlerTarget].obstruct = 0; if (gCurrentMove == MOVE_FEINT) { BattleScriptPush(gBattlescriptCurrInstr + 1); @@ -4722,6 +4726,16 @@ static void Cmd_moveend(void) gBattlescriptCurrInstr = BattleScript_BanefulBunkerEffect; effect = 1; } + else if (gProtectStructs[gBattlerTarget].obstruct && gCurrentMove != MOVE_SUCKER_PUNCH) + { + i = gBattlerAttacker; + gBattlerAttacker = gBattlerTarget; + gBattlerTarget = i; // gBattlerTarget and gBattlerAttacker are swapped in order to activate Defiant, if applicable + gBattleScripting.moveEffect = MOVE_EFFECT_DEF_MINUS_2; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_KingsShieldEffect; + effect = 1; + } } gBattleScripting.moveendState++; break; @@ -6951,7 +6965,7 @@ static void HandleTerrainMove(u32 moveEffect) } else { - gFieldStatuses &= ~STATUS_TERRAIN_ANY; + gFieldStatuses &= ~STATUS_FIELD_TERRAIN_ANY; gFieldStatuses |= statusFlag; if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_TERRAIN_EXTENDER) *timer = 8; @@ -8410,6 +8424,27 @@ static void Cmd_various(void) else gBattlescriptCurrInstr += 7; // can heal return; + case VARIOUS_REMOVE_TERRAIN: + switch (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) + { + case STATUS_FIELD_MISTY_TERRAIN: + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + break; + case STATUS_FIELD_GRASSY_TERRAIN: + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + break; + case STATUS_FIELD_ELECTRIC_TERRAIN: + gBattleCommunication[MULTISTRING_CHOOSER] = 2; + break; + case STATUS_FIELD_PSYCHIC_TERRAIN: + gBattleCommunication[MULTISTRING_CHOOSER] = 3; + break; + default: + gBattleCommunication[MULTISTRING_CHOOSER] = 4; // failsafe + break; + } + gFieldStatuses &= ~STATUS_FIELD_TERRAIN_ANY; // remove the terrain + break; } gBattlescriptCurrInstr += 3; @@ -8455,6 +8490,11 @@ static void Cmd_setprotectlike(void) gProtectStructs[gBattlerAttacker].banefulBunkered = 1; gBattleCommunication[MULTISTRING_CHOOSER] = 0; } + else if (gCurrentMove == MOVE_OBSTRUCT) + { + gProtectStructs[gBattlerAttacker].obstruct = 1; + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + } gDisableStructs[gBattlerAttacker].protectUses++; fail = FALSE; diff --git a/src/battle_util.c b/src/battle_util.c index 69c7706b1..326aa412c 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -141,6 +141,7 @@ void HandleAction_UseMove(void) && gBattleMoves[gCurrentMove].target == MOVE_TARGET_SELECTED && GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gSideTimers[side].followmeTarget) && gBattleMons[gSideTimers[side].followmeTarget].hp != 0 + && gBattleMoves[gCurrentMove].effect != EFFECT_SNIPE_SHOT && (GetBattlerAbility(gBattlerAttacker) != ABILITY_PROPELLER_TAIL || GetBattlerAbility(gBattlerAttacker) != ABILITY_STALWART)) { @@ -162,6 +163,7 @@ void HandleAction_UseMove(void) && ((GetBattlerAbility(gActiveBattler) == ABILITY_LIGHTNING_ROD && moveType == TYPE_ELECTRIC) || (GetBattlerAbility(gActiveBattler) == ABILITY_STORM_DRAIN && moveType == TYPE_WATER)) && GetBattlerTurnOrderNum(gActiveBattler) < var + && gBattleMoves[gCurrentMove].effect != EFFECT_SNIPE_SHOT && (GetBattlerAbility(gBattlerAttacker) != ABILITY_PROPELLER_TAIL || GetBattlerAbility(gBattlerAttacker) != ABILITY_STALWART)) { @@ -6690,6 +6692,16 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef) if (gProtectStructs[battlerAtk].statFell == 1) basePower *= 2; break; + case EFFECT_EXPLOSION: + if (move == MOVE_MISTY_EXPLOSION && gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN && IsBattlerGrounded(battlerAtk)) + basePower = 150; + break; + case EFFECT_BEHEMOTH: + #ifdef B_DYNAMAX + if (IsDynamaxed(battlerDef))/ + basePower *= 2; + #endif + break; } if (basePower == 0) diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 9ba9c20bc..5a45f8dda 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -10605,7 +10605,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_SNIPE_SHOT] = { - .effect = EFFECT_PLACEHOLDER, //TODO + .effect = EFFECT_SNIPE_SHOT, .power = 80, .type = TYPE_WATER, .accuracy = 100, @@ -10613,7 +10613,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .secondaryEffectChance = 0, .target = MOVE_TARGET_SELECTED, .priority = 0, - .flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED, + .flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED | FLAG_HIGH_CRIT, .split = SPLIT_SPECIAL, }, @@ -10802,7 +10802,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_DECORATE] = { - .effect = EFFECT_PLACEHOLDER, // TODO .. EFFECT_DECORATE + .effect = EFFECT_DECORATE, .power = 0, .type = TYPE_FAIRY, .accuracy = 0, @@ -10858,7 +10858,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_BEHEMOTH_BLADE] = { - .effect = EFFECT_HIT, //TODO: 2x damage if dynamaxed? meh... + .effect = EFFECT_BEHEMOTH, .power = 100, .type = TYPE_STEEL, .accuracy = 100, @@ -10872,7 +10872,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_BEHEMOTH_BASH] = { - .effect = EFFECT_HIT, //TODO: 2x damage if dynamaxed? meh... + .effect = EFFECT_BEHEMOTH, .power = 100, .type = TYPE_STEEL, .accuracy = 100, @@ -11012,7 +11012,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_OBSTRUCT] = { - .effect = EFFECT_PLACEHOLDER, //TODO. EFFECT_PROTECT? + .effect = EFFECT_PROTECT, .power = 0, .type = TYPE_DARK, .accuracy = 100, @@ -11096,7 +11096,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_STEEL_ROLLER] = { - .effect = EFFECT_PLACEHOLDER, //TODO + .effect = EFFECT_REMOVE_TERRAIN, .power = 130, .type = TYPE_STEEL, .accuracy = 100, @@ -11152,7 +11152,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_MISTY_EXPLOSION] = { - .effect = EFFECT_PLACEHOLDER, //TODO + .effect = EFFECT_EXPLOSION, .power = 100, .type = TYPE_FAIRY, .accuracy = 100, @@ -11166,7 +11166,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_GRASSY_GLIDE] = { - .effect = EFFECT_PLACEHOLDER, //TODO + .effect = EFFECT_GRASSY_GLIDE, .power = 70, .type = TYPE_GRASS, .accuracy = 100,