From cc7db08fe8e1d86503ae93f6590d6a13e61ad362 Mon Sep 17 00:00:00 2001 From: NxKarim <43686802+NxKarim@users.noreply.github.com> Date: Mon, 17 Jun 2024 22:23:34 -0600 Subject: [PATCH] [Bug] Sheer Force Fix (Stone Axe and self status moves) (#2366) Implements AddArenaTrapTagHitAttr for moves like Stone Axe and Ceaseless Edge. Fixes chance for selfstatus moves. Added Comments For AddArenaTrapTagHitAttr --- src/data/move.ts | 59 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 18 deletions(-) diff --git a/src/data/move.ts b/src/data/move.ts index 87cbd5e4a30..3f9d9685fd8 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -4237,20 +4237,43 @@ export class RemoveArenaTagsAttr extends MoveEffectAttr { export class AddArenaTrapTagAttr extends AddArenaTagAttr { getCondition(): MoveConditionFunc { return (user, target, move) => { - const moveChance = this.getMoveChance(user,target,move,this.selfTarget); const side = (this.selfSideTarget ? user : target).isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; - if (moveChance < 0 || moveChance === 100 || user.randSeedInt(100) < moveChance) { - if (move.category !== MoveCategory.STATUS || !user.scene.arena.getTagOnSide(this.tagType, side)) { - return true; - } - } - const tag = user.scene.arena.getTagOnSide(this.tagType, side) as ArenaTrapTag; - return tag && tag.layers < tag.maxLayers; + if (!tag) { + return true; + } + return tag.layers < tag.maxLayers; }; } } +/** + * Attribute used for Stone Axe and Ceaseless Edge. + * Applies the given ArenaTrapTag when move is used. + * @extends AddArenaTagAttr + * @see {@linkcode apply} + */ +export class AddArenaTrapTagHitAttr extends AddArenaTagAttr { + /** + * @param user {@linkcode Pokemon} using this move + * @param target {@linkcode Pokemon} target of this move + * @param move {@linkcode Move} being used + */ + apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + const moveChance = this.getMoveChance(user,target,move,this.selfTarget); + const side = (this.selfSideTarget ? user : target).isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; + const tag = user.scene.arena.getTagOnSide(this.tagType, side) as ArenaTrapTag; + if ((moveChance < 0 || moveChance === 100 || user.randSeedInt(100) < moveChance)) { + user.scene.arena.addTag(this.tagType, 0, move.id, user.id, side); + if (!tag) { + return true; + } + return tag.layers < tag.maxLayers; + } + return false; + } +} + export class RemoveArenaTrapAttr extends MoveEffectAttr { private targetBothSides: boolean; @@ -7552,7 +7575,7 @@ export function initMoves() { new AttackMove(Moves.PULVERIZING_PANCAKE, Type.NORMAL, MoveCategory.PHYSICAL, 210, -1, 1, -1, 0, 7) .partial() .ignoresVirtual(), - new SelfStatusMove(Moves.EXTREME_EVOBOOST, Type.NORMAL, -1, 1, 100, 0, 7) + new SelfStatusMove(Moves.EXTREME_EVOBOOST, Type.NORMAL, -1, 1, -1, 0, 7) .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.DEF, BattleStat.SPATK, BattleStat.SPDEF, BattleStat.SPD ], 2, true) .ignoresVirtual(), new AttackMove(Moves.GENESIS_SUPERNOVA, Type.PSYCHIC, MoveCategory.SPECIAL, 185, -1, 1, 100, 0, 7) @@ -7684,7 +7707,7 @@ export function initMoves() { .attr(AddBattlerTagAttr, BattlerTagType.TRAPPED, false, false, 1) .attr(AddBattlerTagAttr, BattlerTagType.TRAPPED, true, false, 1) .bitingMove(), - new SelfStatusMove(Moves.STUFF_CHEEKS, Type.NORMAL, -1, 10, 100, 0, 8) // TODO: Stuff Cheeks should not be selectable when the user does not have a berry, see wiki + new SelfStatusMove(Moves.STUFF_CHEEKS, Type.NORMAL, -1, 10, -1, 0, 8) // TODO: Stuff Cheeks should not be selectable when the user does not have a berry, see wiki .attr(EatBerryAttr) .attr(StatChangeAttr, BattleStat.DEF, 2, true) .condition((user) => { @@ -7692,7 +7715,7 @@ export function initMoves() { return userBerries.length > 0; }) .partial(), - new SelfStatusMove(Moves.NO_RETREAT, Type.FIGHTING, -1, 5, 100, 0, 8) + new SelfStatusMove(Moves.NO_RETREAT, Type.FIGHTING, -1, 5, -1, 0, 8) .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.DEF, BattleStat.SPATK, BattleStat.SPDEF, BattleStat.SPD ], 1, true) .attr(AddBattlerTagAttr, BattlerTagType.TRAPPED, true, true, 1), new StatusMove(Moves.TAR_SHOT, Type.ROCK, 100, 15, -1, 0, 8) @@ -7791,7 +7814,7 @@ export function initMoves() { .unimplemented() .ignoresVirtual(), /* End Unused */ - new SelfStatusMove(Moves.CLANGOROUS_SOUL, Type.DRAGON, 100, 5, 100, 0, 8) + new SelfStatusMove(Moves.CLANGOROUS_SOUL, Type.DRAGON, 100, 5, -1, 0, 8) .attr(CutHpStatBoostAttr, [ BattleStat.ATK, BattleStat.DEF, BattleStat.SPATK, BattleStat.SPDEF, BattleStat.SPD ], 1, 3) .soundBased() .danceMove(), @@ -7945,10 +7968,10 @@ export function initMoves() { .attr(MultiStatusEffectAttr, [StatusEffect.POISON, StatusEffect.PARALYSIS, StatusEffect.SLEEP]), new AttackMove(Moves.PSYSHIELD_BASH, Type.PSYCHIC, MoveCategory.PHYSICAL, 70, 90, 10, 100, 0, 8) .attr(StatChangeAttr, BattleStat.DEF, 1, true), - new SelfStatusMove(Moves.POWER_SHIFT, Type.NORMAL, -1, 10, 100, 0, 8) + new SelfStatusMove(Moves.POWER_SHIFT, Type.NORMAL, -1, 10, -1, 0, 8) .unimplemented(), new AttackMove(Moves.STONE_AXE, Type.ROCK, MoveCategory.PHYSICAL, 65, 90, 15, 100, 0, 8) - .attr(AddArenaTrapTagAttr, ArenaTagType.STEALTH_ROCK) + .attr(AddArenaTrapTagHitAttr, ArenaTagType.STEALTH_ROCK) .slicingMove(), new AttackMove(Moves.SPRINGTIDE_STORM, Type.FAIRY, MoveCategory.SPECIAL, 100, 80, 5, 30, 0, 8) .attr(StatChangeAttr, BattleStat.ATK, -1) @@ -7967,7 +7990,7 @@ export function initMoves() { .attr(RecoilAttr, true, 0.5), new AttackMove(Moves.MOUNTAIN_GALE, Type.ICE, MoveCategory.PHYSICAL, 100, 85, 10, 30, 0, 8) .attr(FlinchAttr), - new SelfStatusMove(Moves.VICTORY_DANCE, Type.FIGHTING, -1, 10, 100, 0, 8) + new SelfStatusMove(Moves.VICTORY_DANCE, Type.FIGHTING, -1, 10, -1, 0, 8) .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.DEF, BattleStat.SPD ], 1, true) .danceMove(), new AttackMove(Moves.HEADLONG_RUSH, Type.GROUND, MoveCategory.PHYSICAL, 120, 100, 5, -1, 0, 8) @@ -7992,7 +8015,7 @@ export function initMoves() { .attr(StatusEffectAttr, StatusEffect.BURN) .attr(MovePowerMultiplierAttr, (user, target, move) => target.status ? 2 : 1), new AttackMove(Moves.CEASELESS_EDGE, Type.DARK, MoveCategory.PHYSICAL, 65, 90, 15, 100, 0, 8) - .attr(AddArenaTrapTagAttr, ArenaTagType.SPIKES) + .attr(AddArenaTrapTagHitAttr, ArenaTagType.SPIKES) .slicingMove(), new AttackMove(Moves.BLEAKWIND_STORM, Type.FLYING, MoveCategory.SPECIAL, 100, 80, 10, 30, 0, 8) .attr(ThunderAccuracyAttr) @@ -8218,7 +8241,7 @@ export function initMoves() { .attr(WeatherChangeAttr, WeatherType.SNOW) .attr(ForceSwitchOutAttr, true, false) .target(MoveTarget.BOTH_SIDES), - new SelfStatusMove(Moves.TIDY_UP, Type.NORMAL, -1, 10, 100, 0, 9) + new SelfStatusMove(Moves.TIDY_UP, Type.NORMAL, -1, 10, -1, 0, 9) .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.SPD ], 1, true, null, true, true) .attr(RemoveArenaTrapAttr) .target(MoveTarget.BOTH_SIDES), @@ -8310,7 +8333,7 @@ export function initMoves() { new AttackMove(Moves.FICKLE_BEAM, Type.DRAGON, MoveCategory.SPECIAL, 80, 100, 5, 30, 0, 9) .attr(PreMoveMessageAttr, doublePowerChanceMessageFunc) .attr(DoublePowerChanceAttr), - new SelfStatusMove(Moves.BURNING_BULWARK, Type.FIRE, -1, 10, 100, 4, 9) + new SelfStatusMove(Moves.BURNING_BULWARK, Type.FIRE, -1, 10, -1, 4, 9) .attr(ProtectAttr, BattlerTagType.BURNING_BULWARK), new AttackMove(Moves.THUNDERCLAP, Type.ELECTRIC, MoveCategory.SPECIAL, 70, 100, 5, -1, 1, 9) .condition((user, target, move) => user.scene.currentBattle.turnCommands[target.getBattlerIndex()].command === Command.FIGHT && !target.turnData.acted && allMoves[user.scene.currentBattle.turnCommands[target.getBattlerIndex()].move.move].category !== MoveCategory.STATUS),