From b3b0154a2dedcaf7531217b1ac792c14c280a358 Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Fri, 19 Apr 2024 17:19:24 -0400 Subject: [PATCH] Disguise changes --- src/data/ability.ts | 75 +++++++++++++++++++++++++++++++--------- src/data/battler-tags.ts | 13 +++++-- src/field/pokemon.ts | 9 +++-- 3 files changed, 76 insertions(+), 21 deletions(-) diff --git a/src/data/ability.ts b/src/data/ability.ts index 0ff17d021d5..b2399844a85 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -280,19 +280,28 @@ export class ReceivedTypeDamageMultiplierAbAttr extends ReceivedMoveDamageMultip } } -export class PreDefendMovePowerToOneAbAttr extends ReceivedMoveDamageMultiplierAbAttr { +export class PreDefendReceivedMoveNullifierAbAttr extends PreDefendAbAttr { + protected condition: PokemonDefendCondition; + constructor(condition: PokemonDefendCondition) { - super(condition, 1); + super(); + + this.condition = condition; } applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (this.condition(pokemon, attacker, move.getMove())) { + if (this.condition(pokemon, attacker, move.getMove()) && (args[1] as Utils.NumberHolder).value != HitResult.NO_EFFECT && (args[1] as Utils.NumberHolder).value != HitResult.FAIL) { (args[0] as Utils.NumberHolder).value = 1; + (args[1] as Utils.NumberHolder).value = HitResult.EFFECTIVE; return true; } return false; } + + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { + return `Its disguise served it as a decoy!`; + } } export class TypeImmunityAbAttr extends PreDefendAbAttr { @@ -421,20 +430,32 @@ export class PostDefendAbAttr extends AbAttr { } export class PostDefendDisguiseAbAttr extends PostDefendAbAttr { + protected condition: PokemonDefendCondition; + + constructor(condition: PokemonDefendCondition) { + super(true); + this.condition = condition; + } applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { - if (pokemon.formIndex == 0 && pokemon.battleData.hitCount != 0 && (move.getMove().category == MoveCategory.SPECIAL || move.getMove().category == MoveCategory.PHYSICAL)) { - - const recoilDamage = Math.ceil((pokemon.getMaxHp() / 8) - attacker.turnData.damageDealt); - if (!recoilDamage) - return false; + + if (this.condition(pokemon, attacker, move.getMove()) && (hitResult == HitResult.EFFECTIVE)) { + + const damageDealt = attacker.turnData.damageDealt; + let recoilDamage = Math.round(pokemon.getMaxHp() / 8 - damageDealt); + if (!recoilDamage) return false; + pokemon.damageAndUpdate(recoilDamage, HitResult.OTHER); - pokemon.scene.queueMessage(getPokemonMessage(pokemon, '\'s disguise was busted!')); + pokemon.battleData.abilityTriggered = true; + return true; } - return false; } + + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { + return `${pokemon.name}\'s disguise was busted!`; + } } export class PostDefendFormChangeAbAttr extends PostDefendAbAttr { @@ -1487,6 +1508,27 @@ export class BlockNonDirectDamageAbAttr extends AbAttr { } } +export class DisguiseConfusionDamageInteractionAbAttr extends AbAttr { + apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { + + if(pokemon.battleData.abilityTriggered == false){ + + cancelled.value = true; + pokemon.damageAndUpdate(Math.round(pokemon.getMaxHp() / 8), HitResult.OTHER); + pokemon.battleData.abilityTriggered = true; + pokemon.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false); + pokemon.scene.queueMessage(`Its disguise served it as a decoy!`); + return true; + } + + return false; + } + + getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { + return `${pokemon.name}\'s disguise was busted!`; + } +} + export class BlockOneHitKOAbAttr extends AbAttr { apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { cancelled.value = true; @@ -2848,12 +2890,13 @@ export function initAbilities() { .attr(UnsuppressableAbilityAbAttr) .attr(NoFusionAbilityAbAttr), new Ability(Abilities.DISGUISE, "Disguise (P)", "Once per battle, the shroud that covers the Pokémon can protect it from an attack.", 7) - .attr(PreDefendMovePowerToOneAbAttr, (target, user, move) => target.formIndex == 0 && target.getAttackTypeEffectiveness(move.type) > 0) - .attr(PostSummonFormChangeAbAttr, p => p.battleData.hitCount === 0 ? 0 : 1) - .attr(PostBattleInitFormChangeAbAttr, p => p.battleData.hitCount === 0 ? 0 : 1) - .attr(PostDefendFormChangeAbAttr, p => p.battleData.hitCount === 0 ? 0 : 1) - .attr(PreDefendFormChangeAbAttr, p => p.battleData.hitCount === 0 ? 0 : 1) - .attr(PostDefendDisguiseAbAttr) + .attr(DisguiseConfusionDamageInteractionAbAttr) + .attr(PreDefendReceivedMoveNullifierAbAttr, (target, user, move) => target.battleData.abilityTriggered == false) + .attr(PostDefendDisguiseAbAttr, (target, user, move) => target.battleData.abilityTriggered == false) + .attr(PreDefendFormChangeAbAttr, p => p.battleData.abilityTriggered == false ? 0 : 1) + .attr(PostSummonFormChangeAbAttr, p => p.battleData.abilityTriggered == false ? 0 : 1) + .attr(PostBattleInitFormChangeAbAttr, p => p.battleData.abilityTriggered == false ? 0 : 1) + .attr(PostDefendFormChangeAbAttr, p => p.battleData.abilityTriggered == false ? 0 : 1) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) .attr(UnsuppressableAbilityAbAttr) diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index 5d4c1c94d89..ce90b038fd5 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -8,7 +8,7 @@ import * as Utils from "../utils"; import { Moves } from "./enums/moves"; import { ChargeAttr, MoveFlags, allMoves } from "./move"; import { Type } from "./type"; -import { BlockNonDirectDamageAbAttr, FlinchEffectAbAttr, applyAbAttrs } from "./ability"; +import { BlockNonDirectDamageAbAttr, FlinchEffectAbAttr, applyAbAttrs, DisguiseConfusionDamageInteractionAbAttr } from "./ability"; import { Abilities } from "./enums/abilities"; import { BattlerTagType } from "./enums/battler-tag-type"; import { TerrainType } from "./terrain"; @@ -199,8 +199,15 @@ export class ConfusedTag extends BattlerTag { const def = pokemon.getBattleStat(Stat.DEF); const damage = Math.ceil(((((2 * pokemon.level / 5 + 2) * 40 * atk / def) / 50) + 2) * (pokemon.randSeedInt(15, 85) / 100)); pokemon.scene.queueMessage('It hurt itself in its\nconfusion!'); - pokemon.damageAndUpdate(damage); - pokemon.battleData.hitCount++; + + const cancelled = new Utils.BooleanHolder(false); + applyAbAttrs(DisguiseConfusionDamageInteractionAbAttr, pokemon, cancelled); + + if (!cancelled.value) { + pokemon.damageAndUpdate(damage); + pokemon.battleData.hitCount++; + } + (pokemon.scene.getCurrentPhase() as MovePhase).cancel(); } } diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index a7c383d9818..21a665fc3b1 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -27,7 +27,7 @@ import { TempBattleStat } from '../data/temp-battle-stat'; import { ArenaTagSide, WeakenMoveScreenTag, WeakenMoveTypeTag } from '../data/arena-tag'; import { ArenaTagType } from "../data/enums/arena-tag-type"; import { Biome } from "../data/enums/biome"; -import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, MoveTypeChangeAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, VariableMoveTypeAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr } from '../data/ability'; +import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, MoveTypeChangeAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, PreDefendReceivedMoveNullifierAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, VariableMoveTypeAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr } from '../data/ability'; import { Abilities } from "#app/data/enums/abilities"; import PokemonData from '../system/pokemon-data'; import Battle, { BattlerIndex } from '../battle'; @@ -1381,7 +1381,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (power.value === 0) { damage.value = 0; } - + + let preResult = new Utils.NumberHolder(result); + applyPreDefendAbAttrs(PreDefendReceivedMoveNullifierAbAttr, this, source, battlerMove, cancelled, damage , preResult); + result = (preResult as Utils.NumberHolder).value; + console.log('damage', damage.value, move.name, power.value, sourceAtk, targetDef); if (damage.value) { @@ -2959,6 +2963,7 @@ export class PokemonSummonData { export class PokemonBattleData { public hitCount: integer = 0; public endured: boolean = false; + public abilityTriggered: boolean = false; } export class PokemonBattleSummonData {