diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 769fa895b3..eaf32d53fd 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -2236,6 +2236,7 @@ BattleScript_EffectAbsorb:: resultmessage waitmessage B_WAIT_TIME_LONG setdrainedhp + manipulatedamage DMG_BIG_ROOT orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE jumpifability BS_TARGET, ABILITY_LIQUID_OOZE, BattleScript_AbsorbLiquidOoze setbyte cMULTISTRING_CHOOSER, B_MSG_ABSORB @@ -2363,6 +2364,7 @@ BattleScript_DreamEaterWorked: resultmessage waitmessage B_WAIT_TIME_LONG setdrainedhp + manipulatedamage DMG_BIG_ROOT orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER diff --git a/include/constants/pokemon.h b/include/constants/pokemon.h index 5579102f5b..94a2adfcd8 100644 --- a/include/constants/pokemon.h +++ b/include/constants/pokemon.h @@ -374,4 +374,6 @@ #define MON_PIC_SIZE (64 * 64 / 2) +#define NUM_ABILITY_SLOTS 2 + #endif // GUARD_CONSTANTS_POKEMON_H diff --git a/include/pokemon.h b/include/pokemon.h index 67672fb113..696040fd62 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -201,10 +201,7 @@ struct BaseStats /* 0x13 */ u8 growthRate; /* 0x14 */ u8 eggGroup1; /* 0x15 */ u8 eggGroup2; - /* 0x16 */ u16 abilities[2]; -#ifdef POKEMON_EXPANSION - u16 abilityHidden; -#endif + /* 0x16 */ u16 abilities[NUM_ABILITY_SLOTS]; u8 safariZoneFleeRate; u8 bodyColor : 7; u8 noFlip : 1; diff --git a/src/battle_interface.c b/src/battle_interface.c index b3e7b97dfd..3494da329b 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -1483,8 +1483,11 @@ bool32 IsMegaTriggerSpriteActive(void) void HideMegaTriggerSprite(void) { - ChangeMegaTriggerSprite(gBattleStruct->mega.triggerSpriteId, 0); - gSprites[gBattleStruct->mega.triggerSpriteId].tHide = TRUE; + if (gBattleStruct->mega.triggerSpriteId != 0xFF) + { + ChangeMegaTriggerSprite(gBattleStruct->mega.triggerSpriteId, 0); + gSprites[gBattleStruct->mega.triggerSpriteId].tHide = TRUE; + } } void DestroyMegaTriggerSprite(void) diff --git a/src/battle_message.c b/src/battle_message.c index 68cf7d791d..c7464b70c9 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -544,7 +544,7 @@ static const u8 sText_VanishedInstantly[] =_("{B_ATK_NAME_WITH_PREFIX} vanished\ static const u8 sText_ProtectedTeam[] =_("{B_CURRENT_MOVE} protected\n{B_ATK_TEAM2} team!"); static const u8 sText_SharedItsGuard[] =_("{B_ATK_NAME_WITH_PREFIX} shared its\nguard with the target!"); static const u8 sText_SharedItsPower[] =_("{B_ATK_NAME_WITH_PREFIX} shared its\npower with the target!"); -static const u8 sText_SwapsDefAndSpDefOfAllPkmn[] =_("It created a bizarre area in which\nthe Defense and Sp.Def stats are swapped!"); +static const u8 sText_SwapsDefAndSpDefOfAllPkmn[] =_("It created a bizarre area in which the\nDefense and Sp.Def stats are swapped!"); static const u8 sText_BecameNimble[] =_("{B_ATK_NAME_WITH_PREFIX} became nimble!"); static const u8 sText_HurledIntoTheAir[] =_("{B_DEF_NAME_WITH_PREFIX} was hurled\ninto the air!"); static const u8 sText_HeldItemsLoseEffects[] =_("It created a bizarre area in which\nPokémon's held items lose their effects!"); @@ -568,8 +568,8 @@ static const u8 sText_TelekinesisEnds[] = _("{B_ATK_NAME_WITH_PREFIX} was freed\ static const u8 sText_TailwindEnds[] = _("{B_ATK_TEAM1} team's tailwind\n petered out!"); static const u8 sText_LuckyChantEnds[] = _("{B_ATK_TEAM1} team's Lucky Chant\n wore off!"); static const u8 sText_TrickRoomEnds[] = _("The twisted dimensions returned to\nnormal!"); -static const u8 sText_WonderRoomEnds[] = _("Wonder Room wore off, and\nDefense and Sp. Def stats returned to normal!"); -static const u8 sText_MagicRoomEnds[] = _("Magic Room wore off, and\nheld items' effects returned to normal!"); +static const u8 sText_WonderRoomEnds[] = _("Wonder Room wore off, and Defense\nand Sp. Def stats returned to normal!"); +static const u8 sText_MagicRoomEnds[] = _("Magic Room wore off, and held items'\neffects returned to normal!"); static const u8 sText_MudSportEnds[] = _("The effects of Mud Sport have faded."); static const u8 sText_WaterSportEnds[] = _("The effects of Water Sport have faded."); static const u8 sText_GravityEnds[] = _("Gravity returned to normal!"); diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 81153b347d..fc0eedcbc4 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1509,7 +1509,7 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move) accStage = gBattleMons[battlerAtk].statStages[STAT_ACC]; evasionStage = gBattleMons[battlerDef].statStages[STAT_EVASION]; - if (atkAbility == ABILITY_UNAWARE) + if (atkAbility == ABILITY_UNAWARE || atkAbility == ABILITY_KEEN_EYE) evasionStage = 6; if (gBattleMoves[move].flags & FLAG_STAT_STAGES_IGNORED) evasionStage = 6; @@ -1572,6 +1572,9 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move) calc = (calc * 120) / 100; // 20% acc boost } + if (gFieldStatuses & STATUS_FIELD_GRAVITY) + calc = (calc * 5) / 3; // 1.66 Gravity acc boost + return calc; } @@ -8878,15 +8881,16 @@ static void Cmd_stockpiletohpheal(void) } } +// Sign change for drained HP handled in GetDrainedBigRootHp static void Cmd_setdrainedhp(void) { if (gBattleMoves[gCurrentMove].argument != 0) - gBattleMoveDamage = -(gHpDealt * gBattleMoves[gCurrentMove].argument / 100); + gBattleMoveDamage = (gHpDealt * gBattleMoves[gCurrentMove].argument / 100); else - gBattleMoveDamage = -(gHpDealt / 2); + gBattleMoveDamage = (gHpDealt / 2); if (gBattleMoveDamage == 0) - gBattleMoveDamage = -1; + gBattleMoveDamage = 1; gBattlescriptCurrInstr++; } diff --git a/src/battle_util.c b/src/battle_util.c index 0f9d3f47dc..0fe791c959 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -120,7 +120,7 @@ void HandleAction_UseMove(void) } // encore forces you to use the same move else if (gDisableStructs[gBattlerAttacker].encoredMove != MOVE_NONE - && gDisableStructs[gBattlerAttacker].encoredMove == gBattleMons[gBattlerAttacker].moves[gDisableStructs[gBattlerAttacker].encoredMovePos]) + && gDisableStructs[gBattlerAttacker].encoredMove == gBattleMons[gBattlerAttacker].moves[gDisableStructs[gBattlerAttacker].encoredMovePos]) { gCurrentMove = gChosenMove = gDisableStructs[gBattlerAttacker].encoredMove; gCurrMovePos = gChosenMovePos = gDisableStructs[gBattlerAttacker].encoredMovePos; @@ -128,7 +128,7 @@ void HandleAction_UseMove(void) } // check if the encored move wasn't overwritten else if (gDisableStructs[gBattlerAttacker].encoredMove != MOVE_NONE - && gDisableStructs[gBattlerAttacker].encoredMove != gBattleMons[gBattlerAttacker].moves[gDisableStructs[gBattlerAttacker].encoredMovePos]) + && gDisableStructs[gBattlerAttacker].encoredMove != gBattleMons[gBattlerAttacker].moves[gDisableStructs[gBattlerAttacker].encoredMovePos]) { gCurrMovePos = gChosenMovePos = gDisableStructs[gBattlerAttacker].encoredMovePos; gCurrentMove = gChosenMove = gBattleMons[gBattlerAttacker].moves[gCurrMovePos]; @@ -166,17 +166,15 @@ void HandleAction_UseMove(void) && GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gSideTimers[side].followmeTarget) && gBattleMons[gSideTimers[side].followmeTarget].hp != 0 && (GetBattlerAbility(gBattlerAttacker) != ABILITY_PROPELLER_TAIL - || GetBattlerAbility(gBattlerAttacker) != ABILITY_STALWART)) + || GetBattlerAbility(gBattlerAttacker) != ABILITY_STALWART)) { gBattlerTarget = gSideTimers[side].followmeTarget; } else if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) - && gSideTimers[side].followmeTimer == 0 - && (gBattleMoves[gCurrentMove].power != 0 || gBattleMoves[gCurrentMove].target != MOVE_TARGET_USER) - && ((gBattleMons[*(gBattleStruct->moveTarget + gBattlerAttacker)].ability != ABILITY_LIGHTNING_ROD && moveType == TYPE_ELECTRIC) - || (gBattleMons[*(gBattleStruct->moveTarget + gBattlerAttacker)].ability != ABILITY_STORM_DRAIN && moveType == TYPE_WATER) - ) - ) + && gSideTimers[side].followmeTimer == 0 + && (gBattleMoves[gCurrentMove].power != 0 || gBattleMoves[gCurrentMove].target != MOVE_TARGET_USER) + && ((gBattleMons[*(gBattleStruct->moveTarget + gBattlerAttacker)].ability != ABILITY_LIGHTNING_ROD && moveType == TYPE_ELECTRIC) + || (gBattleMons[*(gBattleStruct->moveTarget + gBattlerAttacker)].ability != ABILITY_STORM_DRAIN && moveType == TYPE_WATER))) { side = GetBattlerSide(gBattlerAttacker); for (gActiveBattler = 0; gActiveBattler < gBattlersCount; gActiveBattler++) @@ -184,10 +182,10 @@ void HandleAction_UseMove(void) if (side != GetBattlerSide(gActiveBattler) && *(gBattleStruct->moveTarget + gBattlerAttacker) != gActiveBattler && ((GetBattlerAbility(gActiveBattler) == ABILITY_LIGHTNING_ROD && moveType == TYPE_ELECTRIC) - || (GetBattlerAbility(gActiveBattler) == ABILITY_STORM_DRAIN && moveType == TYPE_WATER)) + || (GetBattlerAbility(gActiveBattler) == ABILITY_STORM_DRAIN && moveType == TYPE_WATER)) && GetBattlerTurnOrderNum(gActiveBattler) < var && (GetBattlerAbility(gBattlerAttacker) != ABILITY_PROPELLER_TAIL - || GetBattlerAbility(gBattlerAttacker) != ABILITY_STALWART)) + || GetBattlerAbility(gBattlerAttacker) != ABILITY_STALWART)) { var = GetBattlerTurnOrderNum(gActiveBattler); } @@ -252,7 +250,7 @@ void HandleAction_UseMove(void) } } else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE - && gBattleMoves[gChosenMove].target & MOVE_TARGET_RANDOM) + && gBattleMoves[gChosenMove].target & MOVE_TARGET_RANDOM) { if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER) { @@ -283,7 +281,7 @@ void HandleAction_UseMove(void) gBattlerTarget = gBattlerAttacker; } else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE - && gBattleMoves[gChosenMove].target == MOVE_TARGET_FOES_AND_ALLY) + && gBattleMoves[gChosenMove].target == MOVE_TARGET_FOES_AND_ALLY) { for (gBattlerTarget = 0; gBattlerTarget < gBattlersCount; gBattlerTarget++) { @@ -738,6 +736,43 @@ void HandleAction_ActionFinished(void) // rom const data +static const u8 sMovesNotAffectedByStench[] = +{ + [MOVE_AIR_SLASH] = 1, + [MOVE_ASTONISH] = 1, + [MOVE_BITE] = 1, + [MOVE_BONE_CLUB] = 1, + [MOVE_DARK_PULSE] = 1, + [MOVE_DOUBLE_IRON_BASH] = 1, + [MOVE_DRAGON_RUSH] = 1, + [MOVE_EXTRASENSORY] = 1, + [MOVE_FAKE_OUT] = 1, + [MOVE_FIERY_WRATH] = 1, + [MOVE_FIRE_FANG] = 1, + [MOVE_FLING] = 1, + [MOVE_FLOATY_FALL] = 1, + [MOVE_HEADBUTT] = 1, + [MOVE_HEART_STAMP] = 1, + [MOVE_HYPER_FANG] = 1, + [MOVE_ICE_FANG] = 1, + [MOVE_ICICLE_CRASH] = 1, + [MOVE_IRON_HEAD] = 1, + [MOVE_NEEDLE_ARM] = 1, + [MOVE_NONE] = 1, + [MOVE_ROCK_SLIDE] = 1, + [MOVE_ROLLING_KICK] = 1, + [MOVE_SECRET_POWER] = 1, + [MOVE_SKY_ATTACK] = 1, + [MOVE_SNORE] = 1, + [MOVE_STEAMROLLER] = 1, + [MOVE_STOMP] = 1, + [MOVE_THUNDER_FANG] = 1, + [MOVE_TWISTER] = 1, + [MOVE_WATERFALL] = 1, + [MOVE_ZEN_HEADBUTT] = 1, + [MOVE_ZING_ZAP] = 1, +}; + static const u8 sAbilitiesAffectedByMoldBreaker[] = { [ABILITY_BATTLE_ARMOR] = 1, @@ -2171,7 +2206,7 @@ s32 GetDrainedBigRootHp(u32 battler, s32 hp) return hp * -1; } -#define MAGIC_GAURD_CHECK \ +#define MAGIC_GUARD_CHECK \ if (ability == ABILITY_MAGIC_GUARD) \ {\ RecordAbilityBattle(gActiveBattler, ability);\ @@ -2246,7 +2281,7 @@ u8 DoBattlerEndTurnEffects(void) && gBattleMons[gStatuses3[gActiveBattler] & STATUS3_LEECHSEED_BATTLER].hp != 0 && gBattleMons[gActiveBattler].hp != 0) { - MAGIC_GAURD_CHECK; + MAGIC_GUARD_CHECK; gBattlerTarget = gStatuses3[gActiveBattler] & STATUS3_LEECHSEED_BATTLER; // Notice gBattlerTarget is actually the HP receiver. gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 8; @@ -2263,7 +2298,7 @@ u8 DoBattlerEndTurnEffects(void) if ((gBattleMons[gActiveBattler].status1 & STATUS1_POISON) && gBattleMons[gActiveBattler].hp != 0) { - MAGIC_GAURD_CHECK; + MAGIC_GUARD_CHECK; if (ability == ABILITY_POISON_HEAL) { @@ -2292,7 +2327,7 @@ u8 DoBattlerEndTurnEffects(void) if ((gBattleMons[gActiveBattler].status1 & STATUS1_TOXIC_POISON) && gBattleMons[gActiveBattler].hp != 0) { - MAGIC_GAURD_CHECK; + MAGIC_GUARD_CHECK; if (ability == ABILITY_POISON_HEAL) { @@ -2324,7 +2359,7 @@ u8 DoBattlerEndTurnEffects(void) if ((gBattleMons[gActiveBattler].status1 & STATUS1_BURN) && gBattleMons[gActiveBattler].hp != 0) { - MAGIC_GAURD_CHECK; + MAGIC_GUARD_CHECK; gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / (B_BURN_DAMAGE >= GEN_7 ? 16 : 8); if (ability == ABILITY_HEATPROOF) @@ -2344,7 +2379,7 @@ u8 DoBattlerEndTurnEffects(void) if ((gBattleMons[gActiveBattler].status2 & STATUS2_NIGHTMARE) && gBattleMons[gActiveBattler].hp != 0) { - MAGIC_GAURD_CHECK; + MAGIC_GUARD_CHECK; // R/S does not perform this sleep check, which causes the nightmare effect to // persist even after the affected Pokemon has been awakened by Shed Skin. if (gBattleMons[gActiveBattler].status1 & STATUS1_SLEEP) @@ -2366,7 +2401,7 @@ u8 DoBattlerEndTurnEffects(void) if ((gBattleMons[gActiveBattler].status2 & STATUS2_CURSED) && gBattleMons[gActiveBattler].hp != 0) { - MAGIC_GAURD_CHECK; + MAGIC_GUARD_CHECK; gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 4; if (gBattleMoveDamage == 0) gBattleMoveDamage = 1; @@ -2380,7 +2415,7 @@ u8 DoBattlerEndTurnEffects(void) { if (--gDisableStructs[gActiveBattler].wrapTurns != 0) // damaged by wrap { - MAGIC_GAURD_CHECK; + MAGIC_GUARD_CHECK; gBattleScripting.animArg1 = gBattleStruct->wrappedMove[gActiveBattler]; gBattleScripting.animArg2 = gBattleStruct->wrappedMove[gActiveBattler] >> 8; @@ -4839,6 +4874,21 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move effect++; } break; + case ABILITY_STENCH: + if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) + && gBattleMons[gBattlerTarget].hp != 0 + && !gProtectStructs[gBattlerAttacker].confusionSelfDmg + && (Random() % 10) == 0 + && !IS_MOVE_STATUS(move) + && !sMovesNotAffectedByStench[gCurrentMove]) + { + gBattleScripting.moveEffect = MOVE_EFFECT_FLINCH; + BattleScriptPushCursor(); + SetMoveEffect(FALSE, 0); + BattleScriptPop(); + effect++; + } + break; } break; case ABILITYEFFECT_MOVE_END_OTHER: // Abilities that activate on *another* battler's moveend: Dancer, Soul-Heart, Receiver, Symbiosis @@ -6303,7 +6353,9 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) case HOLD_EFFECT_TOXIC_ORB: if (!gBattleMons[battlerId].status1 && CanPoisonType(battlerId, battlerId) - && GetBattlerAbility(battlerId) != ABILITY_IMMUNITY) + && GetBattlerAbility(battlerId) != ABILITY_IMMUNITY + && GetBattlerAbility(battlerId) != ABILITY_COMATOSE + && IsBattlerAlive) { effect = ITEM_STATUS_CHANGE; gBattleMons[battlerId].status1 = STATUS1_TOXIC_POISON; @@ -6314,7 +6366,10 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) case HOLD_EFFECT_FLAME_ORB: if (!gBattleMons[battlerId].status1 && !IS_BATTLER_OF_TYPE(battlerId, TYPE_FIRE) - && GetBattlerAbility(battlerId) != ABILITY_WATER_VEIL) + && GetBattlerAbility(battlerId) != ABILITY_WATER_VEIL + && GetBattlerAbility(battlerId) != ABILITY_WATER_BUBBLE + && GetBattlerAbility(battlerId) != ABILITY_COMATOSE + && IsBattlerAlive) { effect = ITEM_STATUS_CHANGE; gBattleMons[battlerId].status1 = STATUS1_BURN; @@ -7595,7 +7650,7 @@ static u32 CalcDefenseStat(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, break; case ABILITY_PUNK_ROCK: if (gBattleMoves[move].flags & FLAG_SOUND) - MulModifier(&modifier, UQ_4_12(1.3)); + MulModifier(&modifier, UQ_4_12(2.0)); break; } diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 661af2eab5..c8203aa0e4 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -4939,8 +4939,8 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = .power = 130, .flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED, #elif B_UPDATED_MOVE_DATA >= GEN_4 - .power = 130, - .flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED, + .power = 140, + .flags = FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED, #else .power = 140, .flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED, diff --git a/src/data/pokemon/level_up_learnsets.h b/src/data/pokemon/level_up_learnsets.h index a5091c5e1c..77382a1512 100644 --- a/src/data/pokemon/level_up_learnsets.h +++ b/src/data/pokemon/level_up_learnsets.h @@ -1,5 +1,4 @@ #define LEVEL_UP_MOVE(lvl, moveLearned) {.move = moveLearned, .level = lvl} -#define LEVEL_UP_END (0xffff) static const struct LevelUpMove sBulbasaurLevelUpLearnset[] = { LEVEL_UP_MOVE( 1, MOVE_TACKLE), diff --git a/src/data/text/abilities.h b/src/data/text/abilities.h index fdecea8a8a..a9f8ba7aba 100644 --- a/src/data/text/abilities.h +++ b/src/data/text/abilities.h @@ -1,5 +1,5 @@ static const u8 sNoneDescription[] = _("No special ability."); -static const u8 sStenchDescription[] = _("Helps repel wild POKéMON."); +static const u8 sStenchDescription[] = _("May cause a foe to flinch."); static const u8 sDrizzleDescription[] = _("Summons rain in battle."); static const u8 sSpeedBoostDescription[] = _("Gradually boosts Speed."); static const u8 sBattleArmorDescription[] = _("Blocks critical hits.");