From 4e6cf2a6aced2e5d23c4fbe74e03574db7f91431 Mon Sep 17 00:00:00 2001 From: Matt Ross <13306707+mattrossdev@users.noreply.github.com> Date: Mon, 13 May 2024 11:06:15 -0700 Subject: [PATCH] Facade should ignore burn damage reduction (#530) * Facade should ignore burn damage reduction * update order of burn conditions * remove unnecessary space * undo facade check in apply * Rework facade bypassing burn as move attribute * Only check ability attribute if move attribute was false * Add missing semicolon * Add tsdoc comment * Add comment to burn damage reduction class * Added changes from Discord thread --------- Co-authored-by: Benjamin Odom --- src/data/move.ts | 22 +++++++++++++++++++++- src/field/pokemon.ts | 12 +++++++----- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/data/move.ts b/src/data/move.ts index 2a841a401..652e832fd 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -1353,6 +1353,25 @@ export class BypassSleepAttr extends MoveAttr { } } +/** + * Attribute used for moves that bypass the burn damage reduction of physical moves, currently only facade + * Called during damage calculation + * @param user N/A + * @param target N/A + * @param move Move with this attribute + * @param args Utils.BooleanHolder for burnDamageReductionCancelled + * @returns true if the function succeeds + */ +export class BypassBurnDamageReductionAttr extends MoveAttr { + + /** Prevents the move's damage from being reduced by burn */ + apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + (args[0] as Utils.BooleanHolder).value = true; + + return true; + } +} + export class WeatherChangeAttr extends MoveEffectAttr { private weatherType: WeatherType; @@ -4904,7 +4923,8 @@ export function initMoves() { .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.SPATK ], -2), new AttackMove(Moves.FACADE, Type.NORMAL, MoveCategory.PHYSICAL, 70, 100, 20, -1, 0, 3) .attr(MovePowerMultiplierAttr, (user, target, move) => user.status - && (user.status.effect === StatusEffect.BURN || user.status.effect === StatusEffect.POISON || user.status.effect === StatusEffect.TOXIC || user.status.effect === StatusEffect.PARALYSIS) ? 2 : 1), + && (user.status.effect === StatusEffect.BURN || user.status.effect === StatusEffect.POISON || user.status.effect === StatusEffect.TOXIC || user.status.effect === StatusEffect.PARALYSIS) ? 2 : 1) + .attr(BypassBurnDamageReductionAttr), new AttackMove(Moves.FOCUS_PUNCH, Type.FIGHTING, MoveCategory.PHYSICAL, 150, 100, 20, -1, -3, 3) .punchingMove() .ignoresVirtual() diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 307f98f2f..245820484 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -4,7 +4,7 @@ import { Variant, VariantSet, variantColorCache } from '#app/data/variant'; import { variantData } from '#app/data/variant'; import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from '../ui/battle-info'; import { Moves } from "../data/enums/moves"; -import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, VariablePowerAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, MultiHitAttr, StatusMoveTypeImmunityAttr, MoveTarget, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatChangesAttr, SacrificialAttr, VariableMoveTypeAttr, VariableMoveCategoryAttr, CounterDamageAttr, StatChangeAttr, RechargeAttr, ChargeAttr, IgnoreWeatherTypeDebuffAttr } from "../data/move"; +import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, VariablePowerAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, MultiHitAttr, StatusMoveTypeImmunityAttr, MoveTarget, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatChangesAttr, SacrificialAttr, VariableMoveTypeAttr, VariableMoveCategoryAttr, CounterDamageAttr, StatChangeAttr, RechargeAttr, ChargeAttr, IgnoreWeatherTypeDebuffAttr, BypassBurnDamageReductionAttr } from "../data/move"; import { default as PokemonSpecies, PokemonSpeciesForm, SpeciesFormKey, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm, getStarterValueFriendshipCap, speciesStarters, starterPassiveAbilities } from '../data/pokemon-species'; import * as Utils from '../utils'; import { Type, TypeDamageMultiplier, getTypeDamageMultiplier, getTypeRgb } from '../data/type'; @@ -1540,10 +1540,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (!isTypeImmune) { damage.value = Math.ceil(((((2 * source.level / 5 + 2) * power.value * sourceAtk.value / targetDef.value) / 50) + 2) * stabMultiplier.value * typeMultiplier.value * arenaAttackTypeMultiplier.value * screenMultiplier.value * ((this.scene.randBattleSeedInt(15) + 85) / 100) * criticalMultiplier.value); if (isPhysical && source.status && source.status.effect === StatusEffect.BURN) { - const burnDamageReductionCancelled = new Utils.BooleanHolder(false); - applyAbAttrs(BypassBurnDamageReductionAbAttr, source, burnDamageReductionCancelled); - if (!burnDamageReductionCancelled.value) - damage.value = Math.floor(damage.value / 2); + if(!move.getAttrs(BypassBurnDamageReductionAttr).length) { + const burnDamageReductionCancelled = new Utils.BooleanHolder(false); + applyAbAttrs(BypassBurnDamageReductionAbAttr, source, burnDamageReductionCancelled); + if (!burnDamageReductionCancelled.value) + damage.value = Math.floor(damage.value / 2); + } } applyPreAttackAbAttrs(DamageBoostAbAttr, source, this, battlerMove, damage);