From bb6bb1e6c1b275e27ba8016beb9589000dd3f39c Mon Sep 17 00:00:00 2001 From: Benjamin Odom Date: Tue, 7 May 2024 23:28:35 -0500 Subject: [PATCH] Fixed Crash Moves and Reckless (#609) * Fixed Crash Moves and Reckless Added a new MoveFlags flag 'RECKLESS_MOVE' to make crash and recoil moves in line with other move flag boosting attacks. Modified how flags were defined so they are easier to maintain. Added the appropriate flag to all mvoes listed as being affected by Reckless. Steel Beam and Mind Blown do not count according to source: https://bulbapedia.bulbagarden.net/wiki/Reckless_(Ability) * Update move.ts * Update abilities.ts --- src/data/ability.ts | 2 +- src/data/move.ts | 97 ++++++++++++++++++++++++++++++--------------- 2 files changed, 66 insertions(+), 33 deletions(-) diff --git a/src/data/ability.ts b/src/data/ability.ts index 92b26ea1551..88cf2d10b97 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -3035,7 +3035,7 @@ export function initAbilities() { new Ability(Abilities.FRISK, 4) .attr(FriskAbAttr), new Ability(Abilities.RECKLESS, 4) - .attr(MovePowerBoostAbAttr, (user, target, move) => move.getAttrs(RecoilAttr).length && move.id !== Moves.STRUGGLE, 1.2), + .attr(MovePowerBoostAbAttr, (user, target, move) => move.hasFlag(MoveFlags.RECKLESS_MOVE), 1.2), new Ability(Abilities.MULTITYPE, 4) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) diff --git a/src/data/move.ts b/src/data/move.ts index 802a3f047b8..9eb5ae5baa4 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -54,22 +54,28 @@ export enum MoveTarget { } export enum MoveFlags { - MAKES_CONTACT = 1, - IGNORE_PROTECT = 2, - IGNORE_VIRTUAL = 4, - SOUND_BASED = 8, - HIDE_USER = 16, - HIDE_TARGET = 32, - BITING_MOVE = 64, - PULSE_MOVE = 128, - PUNCHING_MOVE = 256, - SLICING_MOVE = 512, - BALLBOMB_MOVE = 1024, - POWDER_MOVE = 2048, - DANCE_MOVE = 4096, - WIND_MOVE = 8192, - TRIAGE_MOVE = 16384, - IGNORE_ABILITIES = 32768 + NONE = 0, + MAKES_CONTACT = 1 << 0, + IGNORE_PROTECT = 1 << 1, + IGNORE_VIRTUAL = 1 << 2, + SOUND_BASED = 1 << 3, + HIDE_USER = 1 << 4, + HIDE_TARGET = 1 << 5, + BITING_MOVE = 1 << 6, + PULSE_MOVE = 1 << 7, + PUNCHING_MOVE = 1 << 8, + SLICING_MOVE = 1 << 9, + /** + * Indicates a move should be affected by {@link Abilities.RECKLESS} + * @see {@link Move.recklessMove()} + */ + RECKLESS_MOVE = 1 << 10, + BALLBOMB_MOVE = 1 << 11, + POWDER_MOVE = 1 << 12, + DANCE_MOVE = 1 << 13, + WIND_MOVE = 1 << 14, + TRIAGE_MOVE = 1 << 15, + IGNORE_ABILITIES = 1 << 16, } type MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => boolean; @@ -269,6 +275,17 @@ export default class Move implements Localizable { return this; } + /** + * Sets the {@link MoveFlags.RECKLESS_MOVE} flag for the calling Move + * @see {@link Abilities.RECKLESS} + * @param {boolean} recklessMove The value to set the flag to + * @returns {Move} The {@link Move} that called this function + */ + recklessMove(recklessMove?: boolean): this { + this.setFlag(MoveFlags.RECKLESS_MOVE, recklessMove); + return this; + } + ballBombMove(ballBombMove?: boolean): this { this.setFlag(MoveFlags.BALLBOMB_MOVE, ballBombMove); return this; @@ -4073,7 +4090,8 @@ export function initMoves() { new AttackMove(Moves.JUMP_KICK, Type.FIGHTING, MoveCategory.PHYSICAL, 100, 95, 10, -1, 0, 1) .attr(MissEffectAttr, crashDamageFunc) .attr(NoEffectAttr, crashDamageFunc) - .condition(failOnGravityCondition), + .condition(failOnGravityCondition) + .recklessMove(), new AttackMove(Moves.ROLLING_KICK, Type.FIGHTING, MoveCategory.PHYSICAL, 60, 85, 15, 30, 0, 1) .attr(FlinchAttr), new StatusMove(Moves.SAND_ATTACK, Type.GROUND, 100, 15, -1, 0, 1) @@ -4092,13 +4110,15 @@ export function initMoves() { new AttackMove(Moves.WRAP, Type.NORMAL, MoveCategory.PHYSICAL, 15, 90, 20, 100, 0, 1) .attr(TrapAttr, BattlerTagType.WRAP), new AttackMove(Moves.TAKE_DOWN, Type.NORMAL, MoveCategory.PHYSICAL, 90, 85, 20, -1, 0, 1) - .attr(RecoilAttr), + .attr(RecoilAttr) + .recklessMove(), new AttackMove(Moves.THRASH, Type.NORMAL, MoveCategory.PHYSICAL, 120, 100, 10, -1, 0, 1) .attr(FrenzyAttr) .attr(MissEffectAttr, frenzyMissFunc) .target(MoveTarget.RANDOM_NEAR_ENEMY), new AttackMove(Moves.DOUBLE_EDGE, Type.NORMAL, MoveCategory.PHYSICAL, 120, 100, 15, -1, 0, 1) - .attr(RecoilAttr, false, 0.33), + .attr(RecoilAttr, false, 0.33) + .recklessMove(), new StatusMove(Moves.TAIL_WHIP, Type.NORMAL, 100, 30, -1, 0, 1) .attr(StatChangeAttr, BattleStat.DEF, -1) .target(MoveTarget.ALL_NEAR_ENEMIES), @@ -4170,7 +4190,8 @@ export function initMoves() { new AttackMove(Moves.PECK, Type.FLYING, MoveCategory.PHYSICAL, 35, 100, 35, -1, 0, 1), new AttackMove(Moves.DRILL_PECK, Type.FLYING, MoveCategory.PHYSICAL, 80, 100, 20, -1, 0, 1), new AttackMove(Moves.SUBMISSION, Type.FIGHTING, MoveCategory.PHYSICAL, 80, 80, 20, -1, 0, 1) - .attr(RecoilAttr), + .attr(RecoilAttr) + .recklessMove(), new AttackMove(Moves.LOW_KICK, Type.FIGHTING, MoveCategory.PHYSICAL, -1, 100, 20, -1, 0, 1) .attr(WeightPowerAttr) .condition(failOnMaxCondition), @@ -4358,7 +4379,8 @@ export function initMoves() { new AttackMove(Moves.HIGH_JUMP_KICK, Type.FIGHTING, MoveCategory.PHYSICAL, 130, 90, 10, -1, 0, 1) .attr(MissEffectAttr, crashDamageFunc) .attr(NoEffectAttr, crashDamageFunc) - .condition(failOnGravityCondition), + .condition(failOnGravityCondition) + .recklessMove(), new StatusMove(Moves.GLARE, Type.NORMAL, 100, 30, -1, 0, 1) .attr(StatusEffectAttr, StatusEffect.PARALYSIS), new AttackMove(Moves.DREAM_EATER, Type.PSYCHIC, MoveCategory.SPECIAL, 100, 100, 15, -1, 0, 1) @@ -4943,7 +4965,8 @@ export function initMoves() { .attr(StealHeldItemChanceAttr, 0.3), new AttackMove(Moves.VOLT_TACKLE, Type.ELECTRIC, MoveCategory.PHYSICAL, 120, 100, 15, 10, 0, 3) .attr(RecoilAttr, false, 0.33) - .attr(StatusEffectAttr, StatusEffect.PARALYSIS), + .attr(StatusEffectAttr, StatusEffect.PARALYSIS) + .recklessMove(), new AttackMove(Moves.MAGICAL_LEAF, Type.GRASS, MoveCategory.SPECIAL, 60, -1, 20, -1, 0, 3), new StatusMove(Moves.WATER_SPORT, Type.WATER, -1, 15, -1, 0, 3) .attr(AddArenaTagAttr, ArenaTagType.WATER_SPORT, 5) @@ -5086,7 +5109,8 @@ export function initMoves() { .attr(RecoilAttr, false, 0.33) .attr(HealStatusEffectAttr, true, StatusEffect.FREEZE) .attr(StatusEffectAttr, StatusEffect.BURN) - .condition(failOnGravityCondition), + .condition(failOnGravityCondition) + .recklessMove(), new AttackMove(Moves.FORCE_PALM, Type.FIGHTING, MoveCategory.PHYSICAL, 60, 100, 10, 30, 0, 4) .attr(StatusEffectAttr, StatusEffect.PARALYSIS), new AttackMove(Moves.AURA_SPHERE, Type.FIGHTING, MoveCategory.SPECIAL, 80, -1, 20, -1, 0, 4) @@ -5131,7 +5155,8 @@ export function initMoves() { .attr(StatChangeAttr, BattleStat.SPDEF, -1) .ballBombMove(), new AttackMove(Moves.BRAVE_BIRD, Type.FLYING, MoveCategory.PHYSICAL, 120, 100, 15, -1, 0, 4) - .attr(RecoilAttr, false, 0.33), + .attr(RecoilAttr, false, 0.33) + .recklessMove(), new AttackMove(Moves.EARTH_POWER, Type.GROUND, MoveCategory.SPECIAL, 90, 100, 10, 10, 0, 4) .attr(StatChangeAttr, BattleStat.SPDEF, -1), new StatusMove(Moves.SWITCHEROO, Type.DARK, 100, 10, -1, 0, 4) @@ -5237,7 +5262,8 @@ export function initMoves() { new AttackMove(Moves.CHARGE_BEAM, Type.ELECTRIC, MoveCategory.SPECIAL, 50, 90, 10, 70, 0, 4) .attr(StatChangeAttr, BattleStat.SPATK, 1, true), new AttackMove(Moves.WOOD_HAMMER, Type.GRASS, MoveCategory.PHYSICAL, 120, 100, 15, -1, 0, 4) - .attr(RecoilAttr, false, 0.33), + .attr(RecoilAttr, false, 0.33) + .recklessMove(), new AttackMove(Moves.AQUA_JET, Type.WATER, MoveCategory.PHYSICAL, 40, 100, 20, -1, 1, 4), new AttackMove(Moves.ATTACK_ORDER, Type.BUG, MoveCategory.PHYSICAL, 90, 100, 15, -1, 0, 4) .attr(HighCritAttr) @@ -5248,7 +5274,8 @@ export function initMoves() { .attr(HealAttr, 0.5) .triageMove(), new AttackMove(Moves.HEAD_SMASH, Type.ROCK, MoveCategory.PHYSICAL, 150, 80, 5, -1, 0, 4) - .attr(RecoilAttr, false, 0.5), + .attr(RecoilAttr, false, 0.5) + .recklessMove(), new AttackMove(Moves.DOUBLE_HIT, Type.NORMAL, MoveCategory.PHYSICAL, 35, 90, 10, -1, 0, 4) .attr(MultiHitAttr, MultiHitType._2), new AttackMove(Moves.ROAR_OF_TIME, Type.DRAGON, MoveCategory.SPECIAL, 150, 90, 5, -1, 0, 4) @@ -5436,7 +5463,8 @@ export function initMoves() { .attr(StatChangeAttr, BattleStat.SPD, -1) .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.WILD_CHARGE, Type.ELECTRIC, MoveCategory.PHYSICAL, 90, 100, 15, -1, 0, 5) - .attr(RecoilAttr), + .attr(RecoilAttr) + .recklessMove(), new AttackMove(Moves.DRILL_RUN, Type.GROUND, MoveCategory.PHYSICAL, 80, 95, 10, -1, 0, 5) .attr(HighCritAttr), new AttackMove(Moves.DUAL_CHOP, Type.DRAGON, MoveCategory.PHYSICAL, 40, 90, 15, -1, 0, 5) @@ -5473,7 +5501,8 @@ export function initMoves() { .attr(HitsTagAttr, BattlerTagType.FLYING, false) .windMove(), new AttackMove(Moves.HEAD_CHARGE, Type.NORMAL, MoveCategory.PHYSICAL, 120, 100, 15, -1, 0, 5) - .attr(RecoilAttr), + .attr(RecoilAttr) + .recklessMove(), new AttackMove(Moves.GEAR_GRIND, Type.STEEL, MoveCategory.PHYSICAL, 50, 85, 15, -1, 0, 5) .attr(MultiHitAttr, MultiHitType._2), new AttackMove(Moves.SEARING_SHOT, Type.FIRE, MoveCategory.SPECIAL, 100, 100, 5, 30, 0, 5) @@ -5687,7 +5716,8 @@ export function initMoves() { .makesContact(false) .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.LIGHT_OF_RUIN, Type.FAIRY, MoveCategory.SPECIAL, 140, 90, 5, -1, 0, 6) - .attr(RecoilAttr, false, 0.5), + .attr(RecoilAttr, false, 0.5) + .recklessMove(), new AttackMove(Moves.ORIGIN_PULSE, Type.WATER, MoveCategory.SPECIAL, 110, 85, 10, -1, 0, 6) .pulseMove() .target(MoveTarget.ALL_NEAR_ENEMIES), @@ -6268,7 +6298,8 @@ export function initMoves() { .attr(MissEffectAttr, frenzyMissFunc) .target(MoveTarget.RANDOM_NEAR_ENEMY), new AttackMove(Moves.WAVE_CRASH, Type.WATER, MoveCategory.PHYSICAL, 120, 100, 10, -1, 0, 8) - .attr(RecoilAttr, false, 0.33), + .attr(RecoilAttr, false, 0.33) + .recklessMove(), new AttackMove(Moves.CHLOROBLAST, Type.GRASS, MoveCategory.SPECIAL, 150, 95, 5, -1, 0, 8) .attr(RecoilAttr, true, 0.5), new AttackMove(Moves.MOUNTAIN_GALE, Type.ICE, MoveCategory.PHYSICAL, 100, 85, 10, 30, 0, 8) @@ -6432,7 +6463,8 @@ export function initMoves() { new AttackMove(Moves.AXE_KICK, Type.FIGHTING, MoveCategory.PHYSICAL, 120, 90, 10, 30, 0, 9) .attr(MissEffectAttr, crashDamageFunc) .attr(NoEffectAttr, crashDamageFunc) - .attr(ConfuseAttr), + .attr(ConfuseAttr) + .recklessMove(), new AttackMove(Moves.LAST_RESPECTS, Type.GHOST, MoveCategory.PHYSICAL, 50, 100, 10, -1, 0, 9) .attr(MovePowerMultiplierAttr, (user, target, move) => { return user.scene.getParty().reduce((acc, pokemonInParty) => acc + (pokemonInParty.status?.effect == StatusEffect.FAINT ? 1 : 0), @@ -6636,7 +6668,8 @@ export function initMoves() { .attr(MovePowerMultiplierAttr, (user, target, move) => user.getLastXMoves(2)[1]?.result == MoveResult.MISS || user.getLastXMoves(2)[1]?.result == MoveResult.FAIL ? 2 : 1), new AttackMove(Moves.SUPERCELL_SLAM, Type.ELECTRIC, MoveCategory.PHYSICAL, 100, 95, 15, -1, 0, 9) .attr(MissEffectAttr, crashDamageFunc) - .attr(NoEffectAttr, crashDamageFunc), + .attr(NoEffectAttr, crashDamageFunc) + .recklessMove(), new AttackMove(Moves.PSYCHIC_NOISE, Type.PSYCHIC, MoveCategory.SPECIAL, 75, 100, 10, -1, 0, 9) .soundBased() .partial(),