diff --git a/include/pokemon.h b/include/pokemon.h index 30abf8a037..c303e32dff 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -393,8 +393,49 @@ struct BattleMove u32 instructBanned:1; u32 encoreBanned:1; u32 parentalBondBanned:1; + u32 numAdditionalEffects:2; // limited to 3 - don't want to get too crazy + + // primary/secondary effects + const struct AdditionalEffect *additionalEffects; }; +#define ADDITIONAL_EFFECTS(...)\ + .numAdditionalEffects = NARG_8(__VA_ARGS__) - 1,\ + .additionalEffects = (const struct AdditionalEffect[]){\ + VARARG_8(ADDITIONAL_EFFECTS_, __VA_ARGS__)\ + } +#define ADDITIONAL_EFFECTS_0() +#define ADDITIONAL_EFFECTS_1(a) a, +#define ADDITIONAL_EFFECTS_2(a, b) a, b, +#define ADDITIONAL_EFFECTS_3(a, b, c) a, b, c, + +#define PRIMARY_EFFECT(_moveEffect, ...) {.moveEffect = _moveEffect} +#define PRIMARY_EFFECT_SELF(_moveEffect, ...) {.self = TRUE, .moveEffect = _moveEffect} +#define SECONDARY_EFFECT(_moveEffect, _chance, ...) {.chance = _chance, .moveEffect = _moveEffect} +#define SECONDARY_EFFECT_SELF(_moveEffect, _chance, ...) {.self = TRUE, .chance = _chance, .moveEffect = _moveEffect} + +struct AdditionalEffect +{ + bool8 self; + u8 chance; // 0% = effect certain, primary effect + u16 moveEffect; + // union { + // u32 data; // status effect etc. (not sure what to call this) + // // struct StatChange *statChange; // will include when stat changer overhaul is merged + // }; +}; + +// struct StatChange +// { +// s8 atk; +// s8 def; +// s8 spa; +// s8 spd; +// s8 spe; +// s8 acc; +// s8 eva; +// }; + #define SPINDA_SPOT_WIDTH 16 #define SPINDA_SPOT_HEIGHT 16 diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index b1cdcd583b..272e9ca592 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -843,15 +843,26 @@ static bool32 AI_IsMoveEffectInPlus(u32 battlerAtk, u32 battlerDef, u32 move, s3 u32 abilityDef = AI_DATA->abilities[battlerDef]; u32 abilityAtk = AI_DATA->abilities[battlerAtk]; + // check ADDITIONAL_EFFECTS + if (gBattleMoves[move].numAdditionalEffects > 0) + { + for (i = gBattleMoves[move].numAdditionalEffects; i > 0; i--) + { + switch (gBattleMoves[move].additionalEffects[i - 1].moveEffect) + { + case MOVE_EFFECT_PARALYSIS: + if (AI_CanParalyze(battlerAtk, battlerDef, abilityDef, move, MOVE_NONE)) + return TRUE; + break; + } + } + } + switch (gBattleMoves[move].effect) { case EFFECT_HIT: default: return FALSE; - case EFFECT_PARALYZE_HIT: - if (AI_CanParalyze(battlerAtk, battlerDef, abilityDef, move, MOVE_NONE)) - return TRUE; - break; case EFFECT_BURN_HIT: if (AI_CanBurn(battlerAtk, battlerDef, abilityDef, BATTLE_PARTNER(battlerAtk), move, MOVE_NONE)) return TRUE; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 83795e3582..ef00c476f5 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -3663,6 +3663,22 @@ static void Cmd_seteffectwithchance(void) gBattleScripting.moveEffect = 0; gBattleScripting.multihitMoveEffect = 0; + + // Set any move effects in this move's ADDITIONAL_EFFECTS + if (gBattleMoves[gCurrentMove].numAdditionalEffects > 0) + { + u8 i, percentChance; + for (i = gBattleMoves[gCurrentMove].numAdditionalEffects; i > 0; i--) + { + percentChance = gBattleMoves[gCurrentMove].additionalEffects[i - 1].chance; + if (percentChance == 0 || RandomPercentage(RNG_SECONDARY_EFFECT, percentChance)) + { + gBattleScripting.moveEffect = gBattleMoves[gCurrentMove].additionalEffects[i - 1].moveEffect; + SetMoveEffect(percentChance == 0, 0); + } + + } + } } static void Cmd_seteffectprimary(void) diff --git a/src/battle_tv.c b/src/battle_tv.c index af485df70d..0d2ddc75ad 100644 --- a/src/battle_tv.c +++ b/src/battle_tv.c @@ -92,7 +92,7 @@ static const u16 sPoints_MoveEffect[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_ABSORB] = 4, [EFFECT_BURN_HIT] = 1, [EFFECT_FREEZE_HIT] = 1, - [EFFECT_PARALYZE_HIT] = 1, + // [EFFECT_PARALYZE_HIT] = 1, // same as EFFECT_HIT so who cares [EFFECT_EXPLOSION] = 0, [EFFECT_DREAM_EATER] = 5, [EFFECT_MIRROR_MOVE] = 1, diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 6cfa42e2b7..2e90484dc3 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -148,12 +148,11 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = [MOVE_THUNDER_PUNCH] = { - .effect = EFFECT_PARALYZE_HIT, + .effect = EFFECT_HIT, .power = 75, .type = TYPE_ELECTRIC, .accuracy = 100, .pp = 15, - .secondaryEffectChance = 10, .target = MOVE_TARGET_SELECTED, .priority = 0, .split = SPLIT_PHYSICAL, @@ -161,6 +160,9 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .makesContact = TRUE, .punchingMove = TRUE, .sheerForceBoost = TRUE, + ADDITIONAL_EFFECTS( + SECONDARY_EFFECT(MOVE_EFFECT_PARALYSIS, 10) + ) }, [MOVE_SCRATCH] = @@ -591,12 +593,11 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = [MOVE_BODY_SLAM] = { - .effect = EFFECT_PARALYZE_HIT, + .effect = EFFECT_HIT, .power = 85, .type = TYPE_NORMAL, .accuracy = 100, .pp = 15, - .secondaryEffectChance = 30, .target = MOVE_TARGET_SELECTED, .priority = 0, .split = SPLIT_PHYSICAL, @@ -604,6 +605,9 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .makesContact = TRUE, .sheerForceBoost = TRUE, .minimizeDoubleDamage = B_UPDATED_MOVE_FLAGS >= GEN_6, + ADDITIONAL_EFFECTS( + SECONDARY_EFFECT(MOVE_EFFECT_PARALYSIS, 30) + ) }, [MOVE_WRAP] = @@ -1475,17 +1479,19 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = [MOVE_THUNDER_SHOCK] = { - .effect = EFFECT_PARALYZE_HIT, + .effect = EFFECT_HIT, .power = 40, .type = TYPE_ELECTRIC, .accuracy = 100, .pp = 30, - .secondaryEffectChance = 10, .target = MOVE_TARGET_SELECTED, .priority = 0, .split = SPLIT_SPECIAL, .zMoveEffect = Z_EFFECT_NONE, .sheerForceBoost = TRUE, + ADDITIONAL_EFFECTS( + SECONDARY_EFFECT(MOVE_EFFECT_PARALYSIS, 10) + ) }, [MOVE_THUNDERBOLT] = @@ -1495,16 +1501,18 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = #else .power = 95, #endif - .effect = EFFECT_PARALYZE_HIT, + .effect = EFFECT_HIT, .type = TYPE_ELECTRIC, .accuracy = 100, .pp = 15, - .secondaryEffectChance = 10, .target = MOVE_TARGET_SELECTED, .priority = 0, .split = SPLIT_SPECIAL, .zMoveEffect = Z_EFFECT_NONE, .sheerForceBoost = TRUE, + ADDITIONAL_EFFECTS( + SECONDARY_EFFECT(MOVE_EFFECT_PARALYSIS, 10) + ) }, [MOVE_THUNDER_WAVE] = @@ -2147,17 +2155,19 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = #else .power = 20, #endif - .effect = EFFECT_PARALYZE_HIT, + .effect = EFFECT_HIT, .type = TYPE_GHOST, .accuracy = 100, .pp = 30, - .secondaryEffectChance = 30, .target = MOVE_TARGET_SELECTED, .priority = 0, .split = SPLIT_PHYSICAL, .zMoveEffect = Z_EFFECT_NONE, .makesContact = TRUE, .sheerForceBoost = TRUE, + ADDITIONAL_EFFECTS( + SECONDARY_EFFECT(MOVE_EFFECT_PARALYSIS, 30) + ) }, [MOVE_SMOG] = @@ -3425,17 +3435,19 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = #else .power = 100, #endif - .effect = EFFECT_PARALYZE_HIT, + .effect = EFFECT_HIT, .type = TYPE_ELECTRIC, .accuracy = 50, .pp = 5, - .secondaryEffectChance = 100, .target = MOVE_TARGET_SELECTED, .priority = 0, .split = SPLIT_SPECIAL, .zMoveEffect = Z_EFFECT_NONE, .sheerForceBoost = TRUE, .ballisticMove = TRUE, + ADDITIONAL_EFFECTS( + SECONDARY_EFFECT(MOVE_EFFECT_PARALYSIS, 100) + ) }, [MOVE_FORESIGHT] = @@ -3755,18 +3767,20 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = [MOVE_SPARK] = { - .effect = EFFECT_PARALYZE_HIT, + .effect = EFFECT_HIT, .power = 65, .type = TYPE_ELECTRIC, .accuracy = 100, .pp = 20, - .secondaryEffectChance = 30, .target = MOVE_TARGET_SELECTED, .priority = 0, .split = SPLIT_PHYSICAL, .zMoveEffect = Z_EFFECT_NONE, .makesContact = TRUE, .sheerForceBoost = TRUE, + ADDITIONAL_EFFECTS( + SECONDARY_EFFECT(MOVE_EFFECT_PARALYSIS, 30) + ) }, [MOVE_FURY_CUTTER] = @@ -4022,18 +4036,20 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = [MOVE_DRAGON_BREATH] = { - .effect = EFFECT_PARALYZE_HIT, + .effect = EFFECT_HIT, .power = 60, .type = TYPE_DRAGON, .accuracy = 100, .pp = 20, - .secondaryEffectChance = 30, .target = MOVE_TARGET_SELECTED, .priority = 0, .split = SPLIT_SPECIAL, .zMoveEffect = Z_EFFECT_NONE, .sheerForceBoost = TRUE, .ignoresKingsRock = B_UPDATED_MOVE_FLAGS < GEN_3, + ADDITIONAL_EFFECTS( + SECONDARY_EFFECT(MOVE_EFFECT_PARALYSIS, 30) + ) }, [MOVE_BATON_PASS] = @@ -7006,18 +7022,20 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = [MOVE_FORCE_PALM] = { - .effect = EFFECT_PARALYZE_HIT, + .effect = EFFECT_HIT, .power = 60, .type = TYPE_FIGHTING, .accuracy = 100, .pp = 10, - .secondaryEffectChance = 30, .target = MOVE_TARGET_SELECTED, .priority = 0, .split = SPLIT_PHYSICAL, .zMoveEffect = Z_EFFECT_NONE, .makesContact = TRUE, .sheerForceBoost = TRUE, + ADDITIONAL_EFFECTS( + SECONDARY_EFFECT(MOVE_EFFECT_PARALYSIS, 30) + ) }, [MOVE_AURA_SPHERE] = @@ -7673,17 +7691,19 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = [MOVE_DISCHARGE] = { - .effect = EFFECT_PARALYZE_HIT, + .effect = EFFECT_HIT, .power = 80, .type = TYPE_ELECTRIC, .accuracy = 100, .pp = 15, - .secondaryEffectChance = 30, .target = MOVE_TARGET_FOES_AND_ALLY, .priority = 0, .split = SPLIT_SPECIAL, .zMoveEffect = Z_EFFECT_NONE, .sheerForceBoost = TRUE, + ADDITIONAL_EFFECTS( + SECONDARY_EFFECT(MOVE_EFFECT_PARALYSIS, 30) + ) }, [MOVE_LAVA_PLUME] = @@ -9596,18 +9616,20 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = [MOVE_BOLT_STRIKE] = { - .effect = EFFECT_PARALYZE_HIT, + .effect = EFFECT_HIT, .power = 130, .type = TYPE_ELECTRIC, .accuracy = 85, .pp = 5, - .secondaryEffectChance = 20, .target = MOVE_TARGET_SELECTED, .priority = 0, .split = SPLIT_PHYSICAL, .zMoveEffect = Z_EFFECT_NONE, .makesContact = TRUE, .sheerForceBoost = TRUE, + ADDITIONAL_EFFECTS( + SECONDARY_EFFECT(MOVE_EFFECT_PARALYSIS, 20) + ) }, [MOVE_BLUE_FLARE] = @@ -10612,18 +10634,20 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = [MOVE_NUZZLE] = { - .effect = EFFECT_PARALYZE_HIT, + .effect = EFFECT_HIT, .power = 20, .type = TYPE_ELECTRIC, .accuracy = 100, .pp = 20, - .secondaryEffectChance = 100, .target = MOVE_TARGET_SELECTED, .priority = 0, .split = SPLIT_PHYSICAL, .zMoveEffect = Z_EFFECT_NONE, .makesContact = TRUE, .sheerForceBoost = TRUE, + ADDITIONAL_EFFECTS( + SECONDARY_EFFECT(MOVE_EFFECT_PARALYSIS, 100) + ) }, [MOVE_HOLD_BACK] = @@ -11722,12 +11746,11 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = [MOVE_SPLISHY_SPLASH] = { - .effect = EFFECT_PARALYZE_HIT, + .effect = EFFECT_HIT, .power = 90, .type = TYPE_WATER, .accuracy = 100, .pp = 15, - .secondaryEffectChance = 30, .target = MOVE_TARGET_BOTH, .priority = 0, .split = SPLIT_SPECIAL, @@ -11735,6 +11758,9 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .sheerForceBoost = TRUE, .mirrorMoveBanned = B_UPDATED_MOVE_FLAGS < GEN_8, .metronomeBanned = TRUE, + ADDITIONAL_EFFECTS( + SECONDARY_EFFECT(MOVE_EFFECT_PARALYSIS, 30) + ) }, [MOVE_FLOATY_FALL] = @@ -11804,16 +11830,18 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .power = 90, .pp = 15, #endif - .effect = EFFECT_PARALYZE_HIT, + .effect = EFFECT_HIT, .type = TYPE_ELECTRIC, .accuracy = 100, - .secondaryEffectChance = 100, .target = MOVE_TARGET_SELECTED, .priority = 0, .split = SPLIT_SPECIAL, .zMoveEffect = Z_EFFECT_NONE, .mirrorMoveBanned = B_UPDATED_MOVE_FLAGS < GEN_8, .metronomeBanned = TRUE, + ADDITIONAL_EFFECTS( + SECONDARY_EFFECT(MOVE_EFFECT_PARALYSIS, 100) + ) }, [MOVE_SIZZLY_SLIDE] = @@ -13432,16 +13460,18 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .power = 95, .pp = 5, #endif - .effect = EFFECT_PARALYZE_HIT, + .effect = EFFECT_HIT, .type = TYPE_ELECTRIC, .accuracy = 80, - .secondaryEffectChance = 20, .target = MOVE_TARGET_SELECTED, .priority = 0, .split = SPLIT_SPECIAL, .zMoveEffect = Z_EFFECT_NONE, .sheerForceBoost = TRUE, .windMove = TRUE, + ADDITIONAL_EFFECTS( + SECONDARY_EFFECT(MOVE_EFFECT_PARALYSIS, 20) + ) }, [MOVE_SANDSEAR_STORM] = @@ -14273,12 +14303,11 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = [MOVE_COMBAT_TORQUE] = { - .effect = EFFECT_PARALYZE_HIT, + .effect = EFFECT_HIT, .power = 100, .type = TYPE_FIGHTING, .accuracy = 100, .pp = 10, - .secondaryEffectChance = 30, .target = MOVE_TARGET_SELECTED, .priority = 0, .split = SPLIT_PHYSICAL, @@ -14293,6 +14322,9 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .instructBanned = TRUE, .encoreBanned = TRUE, .assistBanned = TRUE, + ADDITIONAL_EFFECTS( + SECONDARY_EFFECT(MOVE_EFFECT_PARALYSIS, 30) + ) }, [MOVE_MAGICAL_TORQUE] = @@ -14678,16 +14710,18 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = }, [MOVE_STOKED_SPARKSURFER] = { - .effect = EFFECT_PARALYZE_HIT, + .effect = EFFECT_HIT, .power = 175, .type = TYPE_ELECTRIC, .accuracy = 0, .pp = 1, - .secondaryEffectChance = 100, .target = MOVE_TARGET_SELECTED, .priority = 0, .split = SPLIT_SPECIAL, .zMoveEffect = 0, + ADDITIONAL_EFFECTS( + SECONDARY_EFFECT(MOVE_EFFECT_PARALYSIS, 100) + ) }, [MOVE_EXTREME_EVOBOOST] = { diff --git a/test/battle/ai_check_viability.c b/test/battle/ai_check_viability.c index fa46e2a9f0..4b5fb5c9b2 100644 --- a/test/battle/ai_check_viability.c +++ b/test/battle/ai_check_viability.c @@ -4,7 +4,7 @@ ASSUMPTIONS { - ASSUME(gBattleMoves[MOVE_BODY_SLAM].effect == EFFECT_PARALYZE_HIT); + ASSUME(gBattleMoves[MOVE_BODY_SLAM].additionalEffects[0].moveEffect == MOVE_EFFECT_PARALYSIS); } AI_SINGLE_BATTLE_TEST("AI sees increased base power of Facade") diff --git a/test/battle/move.c b/test/battle/move.c index 03ed84f53c..4766414e41 100644 --- a/test/battle/move.c +++ b/test/battle/move.c @@ -21,15 +21,15 @@ SINGLE_BATTLE_TEST("Accuracy controls the proportion of misses") } } -SINGLE_BATTLE_TEST("Secondary Effect Chance controls the proportion of secondary effects") +SINGLE_BATTLE_TEST("AdditionalEffect.effect controls the proportion of secondary effects") { u32 move; PARAMETRIZE { move = MOVE_THUNDER_SHOCK; } PARAMETRIZE { move = MOVE_DISCHARGE; } PARAMETRIZE { move = MOVE_NUZZLE; } - ASSUME(gBattleMoves[move].effect == EFFECT_PARALYZE_HIT); - ASSUME(0 < gBattleMoves[move].secondaryEffectChance && gBattleMoves[move].secondaryEffectChance <= 100); - PASSES_RANDOMLY(gBattleMoves[move].secondaryEffectChance, 100, RNG_SECONDARY_EFFECT); + ASSUME(gBattleMoves[move].additionalEffects[0].moveEffect == MOVE_EFFECT_PARALYSIS); + ASSUME(0 < gBattleMoves[move].additionalEffects[0].chance && gBattleMoves[move].additionalEffects[0].chance <= 100); + PASSES_RANDOMLY(gBattleMoves[move].additionalEffects[0].chance, 100, RNG_SECONDARY_EFFECT); GIVEN { PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); diff --git a/test/battle/move_effect/paralyze_hit.c b/test/battle/move_effect/paralyze_hit.c index c2fa440be1..893e443ea1 100644 --- a/test/battle/move_effect/paralyze_hit.c +++ b/test/battle/move_effect/paralyze_hit.c @@ -3,7 +3,7 @@ ASSUMPTIONS { - ASSUME(gBattleMoves[MOVE_THUNDER_SHOCK].effect == EFFECT_PARALYZE_HIT); + ASSUME(gBattleMoves[MOVE_THUNDER_SHOCK].additionalEffects[0].moveEffect == MOVE_EFFECT_PARALYSIS); } SINGLE_BATTLE_TEST("Thunder Shock inflicts paralysis")