From bb8e397e5b2e0ac57f31c5a81a8e93be0e359c49 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Tue, 7 May 2019 15:26:58 +0200 Subject: [PATCH] Gems and dmg reducing berries --- data/battle_scripts_1.s | 21 +++++++++++ include/battle.h | 3 ++ include/battle_scripts.h | 3 ++ include/constants/battle_string_ids.h | 3 ++ include/constants/hold_effects.h | 30 +++++++++++---- src/battle_main.c | 16 +++++++- src/battle_message.c | 6 +++ src/battle_script_commands.c | 53 ++++++++++++++++++++------- src/battle_util.c | 28 ++++++++++---- 9 files changed, 134 insertions(+), 29 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 3fff8417a0..e57eda0304 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -6722,6 +6722,27 @@ BattleScript_BerryCureSlpRet:: updatestatusicon BS_SCRIPTING removeitem BS_SCRIPTING return + +BattleScript_GemActivates:: + playanimation BS_ATTACKER, B_ANIM_ITEM_EFFECT, NULL + waitanimation + printstring STRINGID_GEMACTIVATES + waitmessage 0x40 + removeitem BS_ATTACKER + return + +BattleScript_BerryReduceDmg:: + playanimation BS_TARGET, B_ANIM_ITEM_EFFECT, NULL + waitanimation + printstring STRINGID_TARGETATEITEM + waitmessage 0x40 + removeitem BS_TARGET + return + +BattleScript_PrintBerryReduceString:: + waitmessage 0x40 + printstring STRINGID_BERRYDMGREDUCES + return BattleScript_BerryCureConfusionEnd2:: call BattleScript_BerryCureConfusionRet diff --git a/include/battle.h b/include/battle.h index 594adb8884..701297c597 100644 --- a/include/battle.h +++ b/include/battle.h @@ -166,6 +166,9 @@ struct SpecialStatus u8 stormDrainRedirected:1; u8 switchInAbilityDone:1; u8 instructedChosenTarget:3; + u8 berryReduced:1; + u8 gemBoost:1; + u8 gemParam; s32 dmg; s32 physicalDmg; s32 specialDmg; diff --git a/include/battle_scripts.h b/include/battle_scripts.h index cf8504f6c0..f80671a1a1 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -309,5 +309,8 @@ extern const u8 BattleScript_SelectingNotAllowedMoveThroatChop[]; extern const u8 BattleScript_MoveUsedIsThroatChopPrevented[]; extern const u8 BattleScript_SelectingNotAllowedMoveThroatChopInPalace[]; extern const u8 BattleScript_ThroatChopEndTurn[]; +extern const u8 BattleScript_GemActivates[]; +extern const u8 BattleScript_BerryReduceDmg[]; +extern const u8 BattleScript_PrintBerryReduceString[]; #endif // GUARD_BATTLE_SCRIPTS_H diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index ad740bc6d2..0d419b9611 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -532,6 +532,9 @@ #define STRINGID_THROATCHOPENDS 528 #define STRINGID_PKMNCANTUSEMOVETHROATCHOP 529 #define STRINGID_LASERFOCUS 530 +#define STRINGID_GEMACTIVATES 531 +#define STRINGID_BERRYDMGREDUCES 532 +#define STRINGID_TARGETATEITEM 533 #define BATTLESTRINGS_COUNT 530 diff --git a/include/constants/hold_effects.h b/include/constants/hold_effects.h index 84368ae913..9d4089101c 100644 --- a/include/constants/hold_effects.h +++ b/include/constants/hold_effects.h @@ -100,25 +100,39 @@ #define HOLD_EFFECT_ADAMANT_ORB 94 #define HOLD_EFFECT_LUSTROUS_ORB 95 #define HOLD_EFFECT_GRISEOUS_ORB 96 +#define HOLD_EFFECT_GRACIDEA 97 +#define HOLD_EFFECT_RESIST_BERRY 98 +#define HOLD_EFFECT_EV_BOOST 99 // Gen5 hold effects #define HOLD_EFFECT_FLOAT_STONE 115 #define HOLD_EFFECT_EVIOLITE 116 #define HOLD_EFFECT_ASSAULT_VEST 117 -#define HOLD_EFFECT_BINDING_BAND 118 -#define HOLD_EFFECT_DRIVE 119 -#define HOLD_EFFECT_GEMS 120 +#define HOLD_EFFECT_DRIVE 118 +#define HOLD_EFFECT_GEMS 119 +#define HOLD_EFFECT_ROCKY_HELMET 120 +#define HOLD_EFFECT_AIR_BALLOON 121 +#define HOLD_EFFECT_RED_CARD 122 +#define HOLD_EFFECT_RING_TARGET 123 +#define HOLD_EFFECT_BINDING_BAND 124 +#define HOLD_EFFECT_EJECT_BUTTON 125 +#define HOLD_EFFECT_ABSORB_BULB 126 +#define HOLD_EFFECT_CELL_BATTERY 127 // Gen6 hold effects -#define HOLD_EFFECT_FAIRY_POWER 129 -#define HOLD_EFFECT_MEGA_STONE 130 -#define HOLD_EFFECT_SAFETY_GOOGLES 131 +#define HOLD_EFFECT_FAIRY_POWER 129 +#define HOLD_EFFECT_MEGA_STONE 130 +#define HOLD_EFFECT_SAFETY_GOOGLES 131 +#define HOLD_EFFECT_LUMINOUS_MOSS 132 +#define HOLD_EFFECT_SNOWBALL 133 +#define HOLD_EFFECT_WEAKNESS_POLICY 134 // Gen7 hold effects #define HOLD_EFFECT_PROTECTIVE_PADS 149 #define HOLD_EFFECT_TERRAIN_EXTENDER 150 -#define HOLD_EFFECT_SEEDS 151 -#define HOLD_EFFECT_ADRENALINE_ORB 152 +#define HOLD_EFFECT_SEEDS 151 +#define HOLD_EFFECT_ADRENALINE_ORB 152 +#define HOLD_EFFECT_MEMORY 153 #define HOLD_EFFECT_CHOICE(holdEffect)((holdEffect == HOLD_EFFECT_CHOICE_BAND || holdEffect == HOLD_EFFECT_CHOICE_SCARF || holdEffect == HOLD_EFFECT_CHOICE_SPECS)) diff --git a/src/battle_main.c b/src/battle_main.c index 6b97aff4b2..b1f6cf81ce 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -4303,7 +4303,7 @@ u32 GetBattlerTotalSpeedStat(u8 battlerId) } // item effects - if (holdEffect == HOLD_EFFECT_MACHO_BRACE) + if (GetBattlerHoldEffect(battlerId, FALSE) == HOLD_EFFECT_MACHO_BRACE || GetBattlerHoldEffect(battlerId, FALSE) == HOLD_EFFECT_EV_BOOST) speed /= 2; else if (holdEffect == HOLD_EFFECT_IRON_BALL) speed /= 2; @@ -5033,6 +5033,11 @@ void SetTypeBeforeUsingMove(u16 move, u8 battlerAtk) if (GetBattlerHoldEffect(battlerAtk, TRUE) == HOLD_EFFECT_DRIVE) gBattleStruct->dynamicMoveType = ItemId_GetSecondaryId(gBattleMons[battlerAtk].item) | 0x80; } + else if (move == MOVE_MULTI_ATTACK) + { + if (GetBattlerHoldEffect(battlerAtk, TRUE) == HOLD_EFFECT_MEMORY) + gBattleStruct->dynamicMoveType = ItemId_GetSecondaryId(gBattleMons[battlerAtk].item) | 0x80; + } else if (gBattleMoves[move].effect == EFFECT_JUDGMENT) { // TODO: @@ -5076,6 +5081,15 @@ void SetTypeBeforeUsingMove(u16 move, u8 battlerAtk) gBattleStruct->dynamicMoveType = 0x80 | TYPE_NORMAL; gBattleStruct->ateBoost[battlerAtk] = 1; } + + // Check if a gem should activate. + GET_MOVE_TYPE(move, moveType); + if (GetBattlerHoldEffect(battlerAtk, TRUE) == HOLD_EFFECT_GEMS + && moveType == ItemId_GetSecondaryId(gBattleMons[battlerAtk].item)) + { + gSpecialStatuses[battlerAtk].gemParam = GetBattlerHoldEffectParam(battlerAtk); + gSpecialStatuses[battlerAtk].gemBoost = 1; + } } static void HandleAction_UseMove(void) diff --git a/src/battle_message.c b/src/battle_message.c index e633b73317..8244709d7c 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -657,9 +657,15 @@ static const u8 sText_AromaVeilProtected[] = _("{B_DEF_NAME_WITH_PREFIX} is prot static const u8 sText_CelebrateMessage[] = _("Congratulations, {B_PLAYER_NAME}!"); static const u8 sText_UsedInstructedMove[] = _("{B_ATK_NAME_WITH_PREFIX} used the move\ninstructed by {B_BUFF1}!"); static const u8 sText_LaserFocusMessage[] = _("{B_ATK_NAME_WITH_PREFIX}\nconcentrated intensely!"); +static const u8 sText_GemActivates[] = _("{B_LAST_ITEM} strengthened\n{B_ATK_NAME_WITH_PREFIX}'s power!"); +static const u8 sText_BerryDmgReducing[] = _("{B_LAST_ITEM} weakened the damage\nto {B_DEF_NAME_WITH_PREFIX}!"); +static const u8 sText_TargetAteItem[] = _("{B_DEF_NAME_WITH_PREFIX} ate its {B_LAST_ITEM}!"); const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { + [STRINGID_TARGETATEITEM - 12] = sText_TargetAteItem, + [STRINGID_BERRYDMGREDUCES - 12] = sText_BerryDmgReducing, + [STRINGID_GEMACTIVATES - 12] = sText_GemActivates, [STRINGID_LASERFOCUS - 12] = sText_LaserFocusMessage, [STRINGID_THROATCHOPENDS - 12] = sText_ThroatChopEnds, [STRINGID_PKMNCANTUSEMOVETHROATCHOP - 12] = sText_PkmnCantUseMoveThroatChop, diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 9dce6b0617..a8fd91003d 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1371,6 +1371,15 @@ static void atk03_ppreduce(void) gBattlescriptCurrInstr++; } +// The chance is 1/N for each stage. +#if B_CRIT_CHANCE == GEN_7 + static const u8 sCriticalHitChance[] = {24, 8, 2, 1, 1}; +#elif B_CRIT_CHANCE == GEN_6 + static const u8 sCriticalHitChance[] = {16, 8, 2, 1, 1}; +#else + static const u8 sCriticalHitChance[] = {16, 8, 4, 3, 2}; // Gens 2,3,4,5 +#endif // B_CRIT_CHANCE + s32 CalcCritChanceStage(u8 battlerAtk, u8 battlerDef, u32 move, bool32 recordAbility) { s32 critChance = 0; @@ -1404,23 +1413,14 @@ s32 CalcCritChanceStage(u8 battlerAtk, u8 battlerDef, u32 move, bool32 recordAbi + 2 * (holdEffectAtk == HOLD_EFFECT_LUCKY_PUNCH && gBattleMons[gBattlerAttacker].species == SPECIES_CHANSEY) + 2 * (holdEffectAtk == HOLD_EFFECT_STICK && gBattleMons[gBattlerAttacker].species == SPECIES_FARFETCHD) + (abilityAtk == ABILITY_SUPER_LUCK); - } - if (critChance >= ARRAY_COUNT(sCriticalHitChance)) - critChance = ARRAY_COUNT(sCriticalHitChance) - 1; + if (critChance >= ARRAY_COUNT(sCriticalHitChance)) + critChance = ARRAY_COUNT(sCriticalHitChance) - 1; + } return critChance; } -// The chance is 1/N for each stage. -#if B_CRIT_CHANCE == GEN_7 - static const u8 sCriticalHitChance[] = {24, 8, 2, 1, 1}; -#elif B_CRIT_CHANCE == GEN_6 - static const u8 sCriticalHitChance[] = {16, 8, 2, 1, 1}; -#else - static const u8 sCriticalHitChance[] = {16, 8, 4, 3, 2}; // Gens 2,3,4,5 -#endif // B_CRIT_CHANCE - static void atk04_critcalc(void) { s32 critChance = CalcCritChanceStage(gBattlerAttacker, gBattlerTarget, gCurrentMove, TRUE); @@ -1516,6 +1516,22 @@ static void atk07_adjustdamage(void) END: gBattlescriptCurrInstr++; + + // Check gems and damage reducing berries. + if (gSpecialStatuses[gBattlerTarget].berryReduced + && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) + && gBattleMons[gBattlerTarget].item) + { + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_BerryReduceDmg; + } + if (gSpecialStatuses[gBattlerAttacker].gemBoost + && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) + && gBattleMons[gBattlerAttacker].item) + { + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_GemActivates; + } } static void atk08_multihitresultmessage(void) @@ -1927,6 +1943,15 @@ static void atk0F_resultmessage(void) PrepareStringBattle(stringId, gBattlerAttacker); gBattlescriptCurrInstr++; + + // Print berry reducing message after result message. + if (gSpecialStatuses[gBattlerTarget].berryReduced + && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)) + { + gSpecialStatuses[gBattlerTarget].berryReduced = 0; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_PrintBerryReduceString; + } } static void atk10_printstring(void) @@ -4547,12 +4572,14 @@ static void atk49_moveend(void) } gBattleScripting.atk49_state++; break; - case ATK49_CLEAR_BITS: // Clear bits active just while using a move. + case ATK49_CLEAR_BITS: // Clear bits active while using a move for all targets and all hits. if (gSpecialStatuses[gBattlerAttacker].instructedChosenTarget) *(gBattleStruct->moveTarget + gBattlerAttacker) = gSpecialStatuses[gBattlerAttacker].instructedChosenTarget & 0x3; gProtectStructs[gBattlerAttacker].usesBouncedMove = 0; gBattleStruct->ateBoost[gBattlerAttacker] = 0; gStatuses3[gBattlerAttacker] &= ~(STATUS3_ME_FIRST); + gSpecialStatuses[gBattlerAttacker].gemBoost = 0; + gSpecialStatuses[gBattlerTarget].berryReduced = 0; gBattleScripting.atk49_state++; break; case ATK49_COUNT: diff --git a/src/battle_util.c b/src/battle_util.c index 3e4b1b4f09..aa6f9d1cec 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -2365,7 +2365,7 @@ u8 AtkCanceller_UnableToUseMove(void) } gBattleStruct->atkCancellerTracker++; break; - case CANCELLER_THROAT_CHOP: + case CANCELLER_THROAT_CHOP: if (gDisableStructs[gBattlerAttacker].throatChopTimer && gBattleMoves[gCurrentMove].flags & FLAG_SOUND) { gProtectStructs[gBattlerAttacker].usedThroatChopPreventedMove = 1; @@ -2395,6 +2395,7 @@ u8 AtkCanceller_UnableToUseMove(void) u8 AtkCanceller_UnableToUseMove2(void) { u8 effect = 0; + do { switch (gBattleStruct->atkCancellerTracker) @@ -4969,7 +4970,7 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef) return basePower; } -static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType) +static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, bool32 updateFlags) { u32 i; u32 holdEffectAtk, holdEffectParamAtk; @@ -5141,6 +5142,10 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe if ((gBattleMons[battlerAtk].species == SPECIES_LATIAS || gBattleMons[battlerAtk].species == SPECIES_LATIOS) && !(gBattleTypeFlags & BATTLE_TYPE_FRONTIER)) MulModifier(&modifier, holdEffectModifier); break; + case HOLD_EFFECT_GEMS: + if (gSpecialStatuses[battlerAtk].gemBoost && gBattleMons[battlerAtk].item) + MulModifier(&modifier, UQ_4_12(1.0) + sPercentToModifier[gSpecialStatuses[battlerAtk].gemParam]); + break; case HOLD_EFFECT_BUG_POWER: case HOLD_EFFECT_STEEL_POWER: case HOLD_EFFECT_GROUND_POWER: @@ -5485,7 +5490,7 @@ static u32 CalcDefenseStat(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, return ApplyModifier(modifier, defStat); } -static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, u16 typeEffectivenessModifier, bool32 isCrit) +static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, u16 typeEffectivenessModifier, bool32 isCrit, bool32 updateFlags) { u32 abilityAtk = GetBattlerAbility(battlerAtk); u32 abilityDef = GetBattlerAbility(battlerDef); @@ -5600,7 +5605,16 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move // target's hold effect switch (GetBattlerHoldEffect(battlerDef, TRUE)) { - // berries reducing dmg + // berries reducing dmg + case HOLD_EFFECT_RESIST_BERRY: + if (moveType == GetBattlerHoldEffectParam(battlerDef) + && (moveType == TYPE_NORMAL || typeEffectivenessModifier >= UQ_4_12(2.0))) + { + MulModifier(&finalModifier, UQ_4_12(0.5)); + if (updateFlags) + gSpecialStatuses[battlerDef].berryReduced = 1; + } + break; } if (gBattleMoves[move].flags & FLAG_DMG_MINIMIZE && gStatuses3[battlerDef] & STATUS3_MINIMIZED) @@ -5631,7 +5645,7 @@ s32 CalculateMoveDamage(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, s32 if (fixedBasePower) gBattleMovePower = fixedBasePower; else - gBattleMovePower = CalcMoveBasePowerAfterModifiers(move, battlerAtk, battlerDef, moveType); + gBattleMovePower = CalcMoveBasePowerAfterModifiers(move, battlerAtk, battlerDef, moveType, updateFlags); // long dmg basic formula dmg = ((gBattleMons[battlerAtk].level * 2) / 5) + 2; @@ -5641,7 +5655,7 @@ s32 CalculateMoveDamage(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, s32 dmg = (dmg / 50) + 2; // Calculate final modifiers. - dmg = CalcFinalDmg(dmg, move, battlerAtk, battlerDef, moveType, typeEffectivenessModifier, isCrit); + dmg = CalcFinalDmg(dmg, move, battlerAtk, battlerDef, moveType, typeEffectivenessModifier, isCrit, updateFlags); // Add a random factor. if (randomFactor) @@ -5670,7 +5684,7 @@ static inline void MulByTypeEffectiveness(u16 *modifier, u16 move, u8 moveType, mod = UQ_4_12(2.0); if (moveType == TYPE_GROUND && defType == TYPE_FLYING && IsBattlerGrounded(battlerDef)) mod = UQ_4_12(1.0); - + if (gProtectStructs[battlerDef].kingsShielded && gBattleMoves[move].effect != EFFECT_FEINT) mod = UQ_4_12(1.0);