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.
pull/840/head
Jesse Lerner 2024-05-14 23:54:11 -04:00
parent 6bed21770d
commit 6641b17abd
3 changed files with 39 additions and 4 deletions

View File

@ -2126,6 +2126,32 @@ export class PostTerrainChangeAddBattlerTagAttr extends PostTerrainChangeAbAttr
} }
} }
export class PostTerrainChangeTypeAttr extends PostTerrainChangeAbAttr {
private oldType: Type[];
private terrainToTypeMap: Record<TerrainType, Type>;
constructor(terrainToTypeMap: Record<TerrainType, Type>) {
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 { function getTerrainCondition(...terrainTypes: TerrainType[]): AbAttrCondition {
return (pokemon: Pokemon) => { return (pokemon: Pokemon) => {
const terrainType = pokemon.scene.arena.terrain?.terrainType; const terrainType = pokemon.scene.arena.terrain?.terrainType;
@ -3637,7 +3663,11 @@ export function initAbilities() {
new Ability(Abilities.POWER_SPOT, 8) new Ability(Abilities.POWER_SPOT, 8)
.unimplemented(), .unimplemented(),
new Ability(Abilities.MIMICRY, 8) 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) new Ability(Abilities.SCREEN_CLEANER, 8)
.unimplemented(), .unimplemented(),
new Ability(Abilities.STEELY_SPIRIT, 8) new Ability(Abilities.STEELY_SPIRIT, 8)
@ -3740,14 +3770,12 @@ export function initAbilities() {
new Ability(Abilities.ELECTROMORPHOSIS, 9) new Ability(Abilities.ELECTROMORPHOSIS, 9)
.attr(PostDefendApplyBattlerTagAbAttr, (target, user, move) => move.category !== MoveCategory.STATUS, BattlerTagType.CHARGED), .attr(PostDefendApplyBattlerTagAbAttr, (target, user, move) => move.category !== MoveCategory.STATUS, BattlerTagType.CHARGED),
new Ability(Abilities.PROTOSYNTHESIS, 9) 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(PostWeatherChangeAddBattlerTagAttr, BattlerTagType.PROTOSYNTHESIS, 0, WeatherType.SUNNY, WeatherType.HARSH_SUN)
.attr(UncopiableAbilityAbAttr) .attr(UncopiableAbilityAbAttr)
.attr(UnswappableAbilityAbAttr) .attr(UnswappableAbilityAbAttr)
.attr(NoTransformAbilityAbAttr) .attr(NoTransformAbilityAbAttr)
.partial(), // While setting the tag, the getbattlestat should ignore all modifiers to stats except stat stages .partial(), // While setting the tag, the getbattlestat should ignore all modifiers to stats except stat stages
new Ability(Abilities.QUARK_DRIVE, 9) 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(PostTerrainChangeAddBattlerTagAttr, BattlerTagType.QUARK_DRIVE, 0, TerrainType.ELECTRIC)
.attr(UncopiableAbilityAbAttr) .attr(UncopiableAbilityAbAttr)
.attr(UnswappableAbilityAbAttr) .attr(UnswappableAbilityAbAttr)

View File

@ -343,6 +343,10 @@ export class Arena {
return this.terrain?.terrainType || TerrainType.NONE; return this.terrain?.terrainType || TerrainType.NONE;
} }
getWeatherType(): WeatherType {
return this.weather?.weatherType || WeatherType.NONE;
}
getAttackTypeMultiplier(attackType: Type, grounded: boolean): number { getAttackTypeMultiplier(attackType: Type, grounded: boolean): number {
let weatherMultiplier = 1; let weatherMultiplier = 1;
if (this.weather && !this.weather.isEffectSuppressed(this.scene)) if (this.weather && !this.weather.isEffectSuppressed(this.scene))

View File

@ -30,7 +30,7 @@ import { Weather, WeatherType, getRandomWeatherType, getTerrainBlockMessage, get
import { TempBattleStat } from "./data/temp-battle-stat"; import { TempBattleStat } from "./data/temp-battle-stat";
import { ArenaTagSide, ArenaTrapTag, MistTag, TrickRoomTag } from "./data/arena-tag"; import { ArenaTagSide, ArenaTrapTag, MistTag, TrickRoomTag } from "./data/arena-tag";
import { ArenaTagType } from "./data/enums/arena-tag-type"; 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 { Unlockables, getUnlockableName } from "./system/unlockables";
import { getBiomeKey } from "./field/arena"; import { getBiomeKey } from "./field/arena";
import { BattleType, BattlerIndex, TurnCommand } from "./battle"; import { BattleType, BattlerIndex, TurnCommand } from "./battle";
@ -1043,6 +1043,9 @@ export class PostSummonPhase extends PokemonPhase {
const pokemon = this.getPokemon(); const pokemon = this.getPokemon();
this.scene.arena.applyTags(ArenaTrapTag, pokemon); 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()); applyPostSummonAbAttrs(PostSummonAbAttr, pokemon).then(() => this.end());
} }
} }