diff --git a/src/data/ability.ts b/src/data/ability.ts index 22867ee13..01d81a213 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -715,7 +715,7 @@ export class PostDefendContactApplyStatusEffectAbAttr extends PostDefendAbAttr { applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.status && (this.chance === -1 || pokemon.randSeedInt(100) < this.chance)) { const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)]; - return attacker.trySetStatus(effect, true); + return attacker.trySetStatus(effect, true, pokemon); } return false; @@ -1759,6 +1759,24 @@ export class StatusEffectImmunityAbAttr extends PreSetStatusAbAttr { } } +export class PostSetStatusAbAttr extends AbAttr { + applyPostSetStatus(pokemon: Pokemon, source: Pokemon = null, passive: boolean, effect: StatusEffect, args: any[]): boolean | Promise { + return false; + } +} + +/** + * If another Pokemon burns, paralyzes, poisons, or badly poisons this Pokemon, that Pokemon receives the same non-volatile status condition. + */ +export class StatusSyncAbAttr extends PostSetStatusAbAttr { + applyPostSetStatus(pokemon: Pokemon, source: Pokemon = null, passive: boolean, effect: StatusEffect, args: any[]): boolean | Promise { + if (source && [StatusEffect.BURN, StatusEffect.PARALYSIS, StatusEffect.POISON, StatusEffect.TOXIC].includes(effect)) { + return source.trySetStatus(effect, true); + } + return false; + } +} + export class PreApplyBattlerTagAbAttr extends AbAttr { applyPreApplyBattlerTag(pokemon: Pokemon, passive: boolean, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise { return false; @@ -2804,6 +2822,11 @@ export function applyPreSetStatusAbAttrs(attrType: { new(...args: any[]): PreSet return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreSetStatus(pokemon, passive, effect, cancelled, args), args, false, false, !simulated); } +export function applyPostSetStatusAbAttrs(attrType: { new(...args: any[]): PostSetStatusAbAttr }, + pokemon: Pokemon, effect: StatusEffect, source?: Pokemon, ...args: any[]): Promise { + return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostSetStatus(pokemon, source, passive, effect, args), args); +} + export function applyPreApplyBattlerTagAbAttrs(attrType: { new(...args: any[]): PreApplyBattlerTagAbAttr }, pokemon: Pokemon, tag: BattlerTag, cancelled: Utils.BooleanHolder, ...args: any[]): Promise { return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreApplyBattlerTag(pokemon, passive, tag, cancelled, args), args); @@ -2945,8 +2968,8 @@ export function initAbilities() { new Ability(Abilities.EFFECT_SPORE, 3) .attr(EffectSporeAbAttr), new Ability(Abilities.SYNCHRONIZE, 3) - .attr(SyncEncounterNatureAbAttr) - .unimplemented(), + .attr(StatusSyncAbAttr) + .attr(SyncEncounterNatureAbAttr), new Ability(Abilities.CLEAR_BODY, 3) .attr(ProtectStatAbAttr) .ignorable(), diff --git a/src/data/move.ts b/src/data/move.ts index 6a6bee468..7a3371448 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -1156,7 +1156,7 @@ export class StatusEffectAttr extends MoveEffectAttr { return false; } if (!pokemon.status || (pokemon.status.effect === this.effect && move.chance < 0)) - return pokemon.trySetStatus(this.effect, true, this.cureTurn); + return pokemon.trySetStatus(this.effect, true, user, this.cureTurn); } return false; } @@ -1197,7 +1197,7 @@ export class PsychoShiftEffectAttr extends MoveEffectAttr { return false; } if (!target.status || (target.status.effect === statusToApply && move.chance < 0)) { - var statusAfflictResult = target.trySetStatus(statusToApply, true); + var statusAfflictResult = target.trySetStatus(statusToApply, true, user); if (statusAfflictResult) { user.scene.queueMessage(getPokemonMessage(user, getStatusEffectHealText(user.status.effect))); user.resetStatus(); diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index fd1613df1..3e8e5c2df 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, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr } from '../data/ability'; +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, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr, applyPostSetStatusAbAttrs, PostSetStatusAbAttr } from '../data/ability'; import { Abilities } from "#app/data/enums/abilities"; import PokemonData from '../system/pokemon-data'; import Battle, { BattlerIndex } from '../battle'; @@ -2065,12 +2065,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return true; } - trySetStatus(effect: StatusEffect, asPhase: boolean = false, cureTurn: integer = 0, sourceText: string = null): boolean { + trySetStatus(effect: StatusEffect, asPhase: boolean = false, source?: Pokemon, cureTurn: integer = 0, sourceText: string = null): boolean { if (!this.canSetStatus(effect, asPhase)) return false; if (asPhase) { - this.scene.unshiftPhase(new ObtainStatusEffectPhase(this.scene, this.getBattlerIndex(), effect, cureTurn, sourceText)); + this.scene.unshiftPhase(new ObtainStatusEffectPhase(this.scene, this.getBattlerIndex(), effect, cureTurn, sourceText, source)); return true; } @@ -2102,6 +2102,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (effect !== StatusEffect.FAINT) this.scene.triggerPokemonFormChange(this, SpeciesFormChangeStatusEffectTrigger, true); + applyPostSetStatusAbAttrs(PostSetStatusAbAttr, this, effect, source); return true; } diff --git a/src/phases.ts b/src/phases.ts index 271e5350c..b522bcdf5 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -2931,19 +2931,21 @@ export class ObtainStatusEffectPhase extends PokemonPhase { private statusEffect: StatusEffect; private cureTurn: integer; private sourceText: string; + private source: Pokemon; - constructor(scene: BattleScene, battlerIndex: BattlerIndex, statusEffect: StatusEffect, cureTurn?: integer, sourceText?: string) { + constructor(scene: BattleScene, battlerIndex: BattlerIndex, statusEffect: StatusEffect, cureTurn?: integer, sourceText?: string, source?: Pokemon) { super(scene, battlerIndex); this.statusEffect = statusEffect; this.cureTurn = cureTurn; this.sourceText = sourceText; + this.source = source; } start() { const pokemon = this.getPokemon(); if (!pokemon.status) { - if (pokemon.trySetStatus(this.statusEffect)) { + if (pokemon.trySetStatus(this.statusEffect, false, this.source)) { if (this.cureTurn) pokemon.status.cureTurn = this.cureTurn; pokemon.updateInfo(true);