diff --git a/src/data/ability.ts b/src/data/ability.ts index 92b26ea15..88cf2d10b 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 802a3f047..9eb5ae5ba 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(),