From 6641b17abd0cd2a35d4f6e11ecad546f7a5402fa Mon Sep 17 00:00:00 2001 From: Jesse Lerner Date: Tue, 14 May 2024 23:54:11 -0400 Subject: [PATCH] Partially implemented mimicry. Edge cases where other effects also change type may exhibit some unintended behavior (soak, forest's curse). Streamlined on summon weather/terrain effects. --- src/data/ability.ts | 34 +++++++++++++++++++++++++++++++--- src/field/arena.ts | 4 ++++ src/phases.ts | 5 ++++- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/data/ability.ts b/src/data/ability.ts index 0ff03ed67..bd4c54128 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -2126,6 +2126,32 @@ export class PostTerrainChangeAddBattlerTagAttr extends PostTerrainChangeAbAttr } } +export class PostTerrainChangeTypeAttr extends PostTerrainChangeAbAttr { + private oldType: Type[]; + private terrainToTypeMap: Record; + + constructor(terrainToTypeMap: Record) { + super(); + this.terrainToTypeMap = terrainToTypeMap; + } + + applyPostTerrainChange(pokemon: Pokemon, passive: boolean, terrain: TerrainType, args: any[]): boolean { + + if (this.terrainToTypeMap[terrain] == Type.UNKNOWN) { + if (pokemon.summonData.types == null) return false; + pokemon.summonData.types = null; + pokemon.updateInfo(); + pokemon.scene.queueMessage(getPokemonMessage(pokemon, ` transformed\nback into its original type!`)); + return true; + } + + pokemon.summonData.types = [this.terrainToTypeMap[terrain]] + pokemon.updateInfo(); + pokemon.scene.queueMessage(getPokemonMessage(pokemon, ` transformed\ninto the ${Utils.toReadableString(Type[pokemon.getTypes()[0]])} type!`)); + return true; + } +} + function getTerrainCondition(...terrainTypes: TerrainType[]): AbAttrCondition { return (pokemon: Pokemon) => { const terrainType = pokemon.scene.arena.terrain?.terrainType; @@ -3637,7 +3663,11 @@ export function initAbilities() { new Ability(Abilities.POWER_SPOT, 8) .unimplemented(), new Ability(Abilities.MIMICRY, 8) - .unimplemented(), + .attr(PostTerrainChangeTypeAttr, { + [TerrainType.NONE]: Type.UNKNOWN, [TerrainType.MISTY]: Type.FAIRY, [TerrainType.ELECTRIC]: Type.ELECTRIC, + [TerrainType.GRASSY]: Type.GRASS, [TerrainType.PSYCHIC]: Type.PSYCHIC + }) + .partial(), new Ability(Abilities.SCREEN_CLEANER, 8) .unimplemented(), new Ability(Abilities.STEELY_SPIRIT, 8) @@ -3740,14 +3770,12 @@ export function initAbilities() { new Ability(Abilities.ELECTROMORPHOSIS, 9) .attr(PostDefendApplyBattlerTagAbAttr, (target, user, move) => move.category !== MoveCategory.STATUS, BattlerTagType.CHARGED), new Ability(Abilities.PROTOSYNTHESIS, 9) - .conditionalAttr(getWeatherCondition(WeatherType.SUNNY, WeatherType.HARSH_SUN), PostSummonAddBattlerTagAbAttr, BattlerTagType.PROTOSYNTHESIS, 0, true) .attr(PostWeatherChangeAddBattlerTagAttr, BattlerTagType.PROTOSYNTHESIS, 0, WeatherType.SUNNY, WeatherType.HARSH_SUN) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) .attr(NoTransformAbilityAbAttr) .partial(), // While setting the tag, the getbattlestat should ignore all modifiers to stats except stat stages new Ability(Abilities.QUARK_DRIVE, 9) - .conditionalAttr(getTerrainCondition(TerrainType.ELECTRIC), PostSummonAddBattlerTagAbAttr, BattlerTagType.QUARK_DRIVE, 0, true) .attr(PostTerrainChangeAddBattlerTagAttr, BattlerTagType.QUARK_DRIVE, 0, TerrainType.ELECTRIC) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) diff --git a/src/field/arena.ts b/src/field/arena.ts index a2bde9422..4b0ffbced 100644 --- a/src/field/arena.ts +++ b/src/field/arena.ts @@ -343,6 +343,10 @@ export class Arena { return this.terrain?.terrainType || TerrainType.NONE; } + getWeatherType(): WeatherType { + return this.weather?.weatherType || WeatherType.NONE; + } + getAttackTypeMultiplier(attackType: Type, grounded: boolean): number { let weatherMultiplier = 1; if (this.weather && !this.weather.isEffectSuppressed(this.scene)) diff --git a/src/phases.ts b/src/phases.ts index 123169021..e871e195c 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -30,7 +30,7 @@ import { Weather, WeatherType, getRandomWeatherType, getTerrainBlockMessage, get import { TempBattleStat } from "./data/temp-battle-stat"; import { ArenaTagSide, ArenaTrapTag, MistTag, TrickRoomTag } from "./data/arena-tag"; import { ArenaTagType } from "./data/enums/arena-tag-type"; -import { CheckTrappedAbAttr, IgnoreOpponentStatChangesAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, BlockRedirectAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, BattleStatMultiplierAbAttr, applyBattleStatMultiplierAbAttrs, IncrementMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, applyPostBattleInitAbAttrs, PostBattleInitAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr, IncreasePpAbAttr, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr, PreventBerryUseAbAttr, StatChangeCopyAbAttr } from "./data/ability"; +import { CheckTrappedAbAttr, IgnoreOpponentStatChangesAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, BlockRedirectAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, BattleStatMultiplierAbAttr, applyBattleStatMultiplierAbAttrs, IncrementMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, applyPostBattleInitAbAttrs, PostBattleInitAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr, IncreasePpAbAttr, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr, PreventBerryUseAbAttr, StatChangeCopyAbAttr, PostTerrainChangeAbAttr, applyPostTerrainChangeAbAttrs, applyPostWeatherChangeAbAttrs, PostWeatherChangeAbAttr } from "./data/ability"; import { Unlockables, getUnlockableName } from "./system/unlockables"; import { getBiomeKey } from "./field/arena"; import { BattleType, BattlerIndex, TurnCommand } from "./battle"; @@ -1043,6 +1043,9 @@ export class PostSummonPhase extends PokemonPhase { const pokemon = this.getPokemon(); this.scene.arena.applyTags(ArenaTrapTag, pokemon); + + applyPostWeatherChangeAbAttrs(PostWeatherChangeAbAttr, pokemon, this.scene.arena.getWeatherType()); + applyPostTerrainChangeAbAttrs(PostTerrainChangeAbAttr, pokemon, this.scene.arena.getTerrainType()); applyPostSummonAbAttrs(PostSummonAbAttr, pokemon).then(() => this.end()); } }