diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index a15dd459f5..c49c43d9c7 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1921,6 +1921,25 @@ various BS_ATTACKER, VARIOUS_SHELL_SIDE_ARM_CHECK .endm + .macro jumpifflingfails battler:req, ptr:req + various \battler, VARIOUS_JUMP_IF_FLING_FAILS + .4byte \ptr + .endm + + .macro jumpifholdeffect battler:req, holdEffet:req, ptr:req + various \battler, VARIOUS_JUMP_IF_HOLD_EFFECT + .byte \holdEffet + .4byte \ptr + .endm + + .macro curecertainstatuses battler:req + various \battler, VARIOUS_CURE_CERTAIN_STATUSES + .endm + + .macro tryresetnegativestatstages battler:req + various \battler, VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES + .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 ee859f0e03..dd90c9bf41 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -235,7 +235,7 @@ gBattleScriptsForMoveEffects:: .4byte BattleScript_EffectDragonDance @ EFFECT_DRAGON_DANCE .4byte BattleScript_EffectCamouflage @ EFFECT_CAMOUFLAGE .4byte BattleScript_EffectHit @ EFFECT_PLEDGE - .4byte BattleScript_EffectHit @ EFFECT_FLING + .4byte BattleScript_EffectFling @ EFFECT_FLING .4byte BattleScript_EffectNaturalGift @ EFFECT_NATURAL_GIFT .4byte BattleScript_EffectWakeUpSlap @ EFFECT_WAKE_UP_SLAP .4byte BattleScript_EffectHit @ EFFECT_WRING_OUT @@ -404,6 +404,78 @@ gBattleScriptsForMoveEffects:: .4byte BattleScript_EffectClangorousSoul @ EFFECT_CLANGOROUS_SOUL .4byte BattleScript_EffectHit @ EFFECT_BOLT_BEAK +BattleScript_EffectFling: + jumpifword CMP_COMMON_BITS, gFieldStatuses, STATUS_FIELD_MAGIC_ROOM, BattleScript_ButItFailed + jumpifability BS_ATTACKER, ABILITY_KLUTZ, BattleScript_ButItFailedAtkStringPpReduce + jumpifability BS_ATTACKER, ABILITY_UNNERVE, BattleScript_ButItFailedAtkStringPpReduce + jumpifflingfails BS_ATTACKER, BattleScript_ButItFailedAtkStringPpReduce + attackcanceler + accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE + attackstring + pause B_WAIT_TIME_SHORT + setlastuseditem BS_ATTACKER + printstring STRINGID_PKMNFLUNG + waitmessage B_WAIT_TIME_SHORT + ppreduce + critcalc + damagecalc + adjustdamage + attackanimation + waitanimation + effectivenesssound + hitanimation BS_TARGET + waitstate + healthbarupdate BS_TARGET + datahpupdate BS_TARGET + critmessage + waitmessage B_WAIT_TIME_MED + resultmessage + waitmessage B_WAIT_TIME_MED +.if B_FLING_EMBARGO_ITEM <= GEN_4 + jumpifstatus3 BS_TARGET, STATUS3_EMBARGO, BattleScript_FlingEnd +.endif + jumpifholdeffect BS_ATTACKER, HOLD_EFFECT_FLAME_ORB, BattleScript_FlingFlameOrb + jumpifholdeffect BS_ATTACKER, HOLD_EFFECT_FLINCH, BattleScript_FlingFlinch + jumpifholdeffect BS_ATTACKER, HOLD_EFFECT_LIGHT_BALL, BattleScript_FlingLightBall + jumpifholdeffect BS_ATTACKER, HOLD_EFFECT_MENTAL_HERB, BattleScript_FlingMentalHerb + jumpifholdeffect BS_ATTACKER, HOLD_EFFECT_POISON_POWER, BattleScript_FlingPoisonBarb + jumpifholdeffect BS_ATTACKER, HOLD_EFFECT_TOXIC_ORB, BattleScript_FlingToxicOrb + jumpifholdeffect BS_ATTACKER, HOLD_EFFECT_RESTORE_STATS, BattleScript_FlingWhiteHerb +BattleScript_FlingFlameOrb: + setmoveeffect MOVE_EFFECT_BURN + seteffectprimary + goto BattleScript_FlingEnd +BattleScript_FlingFlinch: + setmoveeffect MOVE_EFFECT_FLINCH + seteffectprimary + goto BattleScript_FlingEnd +BattleScript_FlingLightBall: + setmoveeffect MOVE_EFFECT_PARALYSIS + seteffectprimary + goto BattleScript_FlingEnd +BattleScript_FlingMentalHerb: + curecertainstatuses BS_TARGET + goto BattleScript_FlingEnd +BattleScript_FlingPoisonBarb: + setmoveeffect MOVE_EFFECT_POISON + seteffectprimary + goto BattleScript_FlingEnd +BattleScript_FlingToxicOrb: + setmoveeffect MOVE_EFFECT_TOXIC + seteffectprimary + goto BattleScript_FlingEnd +BattleScript_FlingWhiteHerb: + tryresetnegativestatstages BS_TARGET + swapattackerwithtarget + printstring STRINGID_PKMNSTATUSNORMAL + waitmessage B_WAIT_TIME_MED + swapattackerwithtarget + goto BattleScript_FlingEnd +BattleScript_FlingEnd: + tryfaintmon BS_TARGET, FALSE, NULL + removeitem BS_ATTACKER + goto BattleScript_MoveEnd + BattleScript_EffectShellSideArm: shellsidearmcheck setmoveeffect MOVE_EFFECT_POISON diff --git a/include/constants/battle_config.h b/include/constants/battle_config.h index 8e72b2c99d..793bfacf70 100644 --- a/include/constants/battle_config.h +++ b/include/constants/battle_config.h @@ -137,6 +137,7 @@ #define B_KINGS_SHIELD_LOWER_ATK GEN_7 // In Gen7+, it lowers Atk by 1 stage instead of 2 of oponents that hit it. #define B_SPEED_BUFFING_RAPID_SPIN GEN_8 // In Gen8, Rapid Spin raises the user's Speed by 1 stage. #define B_RECOIL_IF_MISS_DMG GEN_7 // In Gen5+, Jump Kick and High Jump Kick will always do half of the user's max HP when missing. +#define B_FLING_EMBARGO_ITEM GEN_7 // In Gen4, if a target is under the effects of Embargo, the user's item's hold effect doesn't activate. // Move accuracy settings #define B_TOXIC_NEVER_MISS GEN_7 // In Gen6+, if Toxic is used by a Poison-type Pokémon, it will never miss. diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 7ceb1d64bf..6ace7458ea 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -207,6 +207,10 @@ #define VARIOUS_CHECK_POLTERGEIST 134 #define VARIOUS_SET_OCTOLOCK 135 #define VARIOUS_CUT_1_3_HP_RAISE_STATS 136 +#define VARIOUS_JUMP_IF_FLING_FAILS 137 +#define VARIOUS_JUMP_IF_HOLD_EFFECT 138 +#define VARIOUS_CURE_CERTAIN_STATUSES 139 +#define VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES 140 // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index d439e3e7f1..89d3be8b86 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -607,8 +607,9 @@ #define STRINGID_PKMNBECAMEWEAKERTOFIRE 604 #define STRINGID_ABOUTTOUSEPOLTERGEIST 605 #define STRINGID_CANTESCAPEBECAUSEOFCURRENTMOVE 606 +#define STRINGID_TARGETGOTOVERINFATUATION 607 -#define BATTLESTRINGS_COUNT 607 +#define BATTLESTRINGS_COUNT 608 // The below IDs are all indexes into battle message tables, // used to determine which of a set of messages to print. diff --git a/src/battle_message.c b/src/battle_message.c index 30af20a784..728870d690 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -733,9 +733,11 @@ static const u8 sText_CantEscapeDueToUsedMove[] = _("{B_ATK_NAME_WITH_PREFIX} ca static const u8 sText_PkmnBecameWeakerToFire[] = _("{B_DEF_NAME_WITH_PREFIX} became\nweaker to fire!"); static const u8 sText_PkmnAboutToBeAttackedByItsItem[] = _("{B_DEF_NAME_WITH_PREFIX} is about\nto be attacked by its {B_BUFF1}!"); static const u8 sText_CantEscapeBecauseOfCurrentMove[] = _("{B_DEF_NAME_WITH_PREFIX} can no longer escape\nbecause of {B_CURRENT_MOVE}!"); +static const u8 sText_TargetGotOverInfatuation[] =_("{B_DEF_NAME_WITH_PREFIX} got over\nits infatuation!"); const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { + [STRINGID_TARGETGOTOVERINFATUATION - 12] = sText_TargetGotOverInfatuation, [STRINGID_BATTLERTYPECHANGEDTO - 12] = sText_BattlerTypeChangedTo, [STRINGID_PASTELVEILENTERS - 12] = sText_PastelVeilEnters, [STRINGID_PASTELVEILPROTECTED -12] = sText_PastelVeilProtected, diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 3f9ba388f7..88c3af2f05 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -9287,6 +9287,106 @@ static void Cmd_various(void) gBattlescriptCurrInstr += 7; return; } + case VARIOUS_JUMP_IF_FLING_FAILS: + #ifdef ITEM_EXPANSION + if (!ItemId_GetFlingPower(gBattleMons[gActiveBattler].item)) + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); + else if (!CanBattlerGetOrLoseItem(gActiveBattler, gBattleMons[gActiveBattler].item)) + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); + #else + if (!CanBattlerGetOrLoseItem(gActiveBattler, gBattleMons[gActiveBattler].item)) + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); + #endif + else + gBattlescriptCurrInstr += 7; + return; + case VARIOUS_JUMP_IF_HOLD_EFFECT: + if (GetBattlerHoldEffect(gActiveBattler, TRUE) == gBattlescriptCurrInstr[3]) + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 4); + else + gBattlescriptCurrInstr += 8; + return; + case VARIOUS_CURE_CERTAIN_STATUSES: + if (gBattleMons[gActiveBattler].status2 & STATUS2_INFATUATION) + { + gBattleMons[gActiveBattler].status2 &= ~(STATUS2_INFATUATION); + gBattleMons[gActiveBattler].status2 = 0; + BtlController_EmitSetMonData(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBattler].status2); + MarkBattlerForControllerExec(gActiveBattler); + PrepareStringBattle(STRINGID_TARGETGOTOVERINFATUATION, gActiveBattler); + gBattleCommunication[MSG_DISPLAY] = 1; + } + else if (gBattleMons[gActiveBattler].status2 & STATUS2_TORMENT) + { + gBattleMons[gActiveBattler].status2 &= ~(STATUS2_TORMENT); + gBattleMons[gActiveBattler].status2 = 0; + BtlController_EmitSetMonData(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBattler].status2); + MarkBattlerForControllerExec(gActiveBattler); + // Swap gBattlerTarget and gBattlerAttacker so STRINGID_BUFFERENDS works correctly + gActiveBattler = gBattlerAttacker; + gBattlerAttacker = gBattlerTarget; + gBattlerTarget = gActiveBattler; + gHitMarker |= HITMARKER_SWAP_ATTACKER_TARGET; + PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_TORMENT); + PrepareStringBattle(STRINGID_BUFFERENDS, gActiveBattler); + gBattleCommunication[MSG_DISPLAY] = 1; + // Swap gBattlerTarget and gBattlerAttacker back + if (gHitMarker & HITMARKER_SWAP_ATTACKER_TARGET) + gHitMarker &= ~(HITMARKER_SWAP_ATTACKER_TARGET); + } + else if (gDisableStructs[gActiveBattler].tauntTimer != 0) + { + gDisableStructs[gActiveBattler].tauntTimer = 0; + // Swap gBattlerTarget and gBattlerAttacker so STRINGID_BUFFERENDS works correctly + gActiveBattler = gBattlerAttacker; + gBattlerAttacker = gBattlerTarget; + gBattlerTarget = gActiveBattler; + gHitMarker |= HITMARKER_SWAP_ATTACKER_TARGET; + PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_TAUNT); + PrepareStringBattle(STRINGID_BUFFERENDS, gActiveBattler); + gBattleCommunication[MSG_DISPLAY] = 1; + // Swap gBattlerTarget and gBattlerAttacker back + if (gHitMarker & HITMARKER_SWAP_ATTACKER_TARGET) + gHitMarker &= ~(HITMARKER_SWAP_ATTACKER_TARGET); + } + else if (gDisableStructs[gActiveBattler].encoreTimer) + { + gDisableStructs[gActiveBattler].encoredMove = 0; + gDisableStructs[gActiveBattler].encoreTimer = 0; + // Swap gBattlerTarget and gBattlerAttacker so STRINGID_BUFFERENDS works correctly + gActiveBattler = gBattlerAttacker; + gBattlerAttacker = gBattlerTarget; + gBattlerTarget = gActiveBattler; + gHitMarker |= HITMARKER_SWAP_ATTACKER_TARGET; + PrepareStringBattle(STRINGID_PKMNENCOREENDED, gActiveBattler); + gBattleCommunication[MSG_DISPLAY] = 1; + // Swap gBattlerTarget and gBattlerAttacker back + if (gHitMarker & HITMARKER_SWAP_ATTACKER_TARGET) + gHitMarker &= ~(HITMARKER_SWAP_ATTACKER_TARGET); + } + else if (gDisableStructs[gActiveBattler].disableTimer) + { + gDisableStructs[gActiveBattler].disabledMove = 0; + // Swap gBattlerTarget and gBattlerAttacker so STRINGID_BUFFERENDS works correctly + gActiveBattler = gBattlerAttacker; + gBattlerAttacker = gBattlerTarget; + gBattlerTarget = gActiveBattler; + gHitMarker |= HITMARKER_SWAP_ATTACKER_TARGET; + PrepareStringBattle(STRINGID_PKMNMOVEDISABLEDNOMORE, gBattlerTarget); + gBattleCommunication[MSG_DISPLAY] = 1; + // Swap gBattlerTarget and gBattlerAttacker back + if (gHitMarker & HITMARKER_SWAP_ATTACKER_TARGET) + gHitMarker &= ~(HITMARKER_SWAP_ATTACKER_TARGET); + } + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 7); + return; + case VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES: + gActiveBattler = gBattlerTarget; + for (i = 0; i < NUM_BATTLE_STATS; i++) + if (gBattleMons[gActiveBattler].statStages[i] < DEFAULT_STAT_STAGE) + gBattleMons[gActiveBattler].statStages[i] = DEFAULT_STAT_STAGE; + gBattlescriptCurrInstr += 3; + return; } // End of switch (gBattlescriptCurrInstr[2]) gBattlescriptCurrInstr += 3; diff --git a/src/battle_util.c b/src/battle_util.c index 18847b8cce..0c8ff91b92 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -7693,7 +7693,9 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef) // todo break; case EFFECT_FLING: - // todo: program Fling + Unburden interaction + #ifdef ITEM_EXPANSION + basePower = ItemId_GetFlingPower(gBattleMons[battlerAtk].item); + #endif break; case EFFECT_ERUPTION: basePower = gBattleMons[battlerAtk].hp * basePower / gBattleMons[battlerAtk].maxHP;