got the basics working for moves like growl etc, need to check all sources of stat changes

pull/920/head
shayebeadlingkl 2024-05-15 13:17:14 -04:00
parent 7769c06393
commit 37244bc62f
4 changed files with 46 additions and 12 deletions

View File

@ -1702,7 +1702,7 @@ export class PreSwitchOutHealAbAttr extends PreSwitchOutAbAttr {
} }
export class PreStatChangeAbAttr extends AbAttr { export class PreStatChangeAbAttr extends AbAttr {
applyPreStatChange(pokemon: Pokemon, passive: boolean, stat: BattleStat, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise<boolean> { applyPreStatChange(pokemon: Pokemon, user: Pokemon, passive: boolean, stat: BattleStat, levels: integer, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise<boolean> {
return false; return false;
} }
} }
@ -1716,7 +1716,7 @@ export class ProtectStatAbAttr extends PreStatChangeAbAttr {
this.protectedStat = protectedStat; this.protectedStat = protectedStat;
} }
applyPreStatChange(pokemon: Pokemon, passive: boolean, stat: BattleStat, cancelled: Utils.BooleanHolder, args: any[]): boolean { applyPreStatChange(pokemon: Pokemon, user: Pokemon, passive: boolean, stat: BattleStat, levels: integer, cancelled: Utils.BooleanHolder, args: any[]): boolean {
if (this.protectedStat === undefined || stat === this.protectedStat) { if (this.protectedStat === undefined || stat === this.protectedStat) {
cancelled.value = true; cancelled.value = true;
return true; return true;
@ -1730,6 +1730,28 @@ export class ProtectStatAbAttr extends PreStatChangeAbAttr {
} }
} }
export class ReflectStatAbAttr extends PreStatChangeAbAttr {
private reflectedStat: BattleStat;
constructor(reflectedStat?: BattleStat) {
super();
this.reflectedStat = reflectedStat;
}
applyPreStatChange(pokemon: Pokemon, sourcePokemon: Pokemon, passive: boolean, stat: BattleStat, levels: integer, cancelled: Utils.BooleanHolder, args: any[]): boolean {
if ((this.reflectedStat === undefined || stat === this.reflectedStat) && pokemon !== sourcePokemon) {
cancelled.value = true;
const statChangePhase = new StatChangePhase(pokemon.scene, sourcePokemon.getBattlerIndex(), false, [stat], levels);
pokemon.scene.unshiftPhase(statChangePhase);
return true;
}
return false;
}
}
export class PreSetStatusAbAttr extends AbAttr { export class PreSetStatusAbAttr extends AbAttr {
applyPreSetStatus(pokemon: Pokemon, passive: boolean, effect: StatusEffect, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise<boolean> { applyPreSetStatus(pokemon: Pokemon, passive: boolean, effect: StatusEffect, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise<boolean> {
return false; return false;
@ -2813,8 +2835,8 @@ export function applyPreSwitchOutAbAttrs(attrType: { new(...args: any[]): PreSwi
} }
export function applyPreStatChangeAbAttrs(attrType: { new(...args: any[]): PreStatChangeAbAttr }, export function applyPreStatChangeAbAttrs(attrType: { new(...args: any[]): PreStatChangeAbAttr },
pokemon: Pokemon, stat: BattleStat, cancelled: Utils.BooleanHolder, ...args: any[]): Promise<void> { pokemon: Pokemon, sourcePokemon: Pokemon, stat: BattleStat, levels: integer, cancelled: Utils.BooleanHolder, ...args: any[]): Promise<void> {
return applyAbAttrsInternal<PreStatChangeAbAttr>(attrType, pokemon, (attr, passive) => attr.applyPreStatChange(pokemon, passive, stat, cancelled, args), args); return applyAbAttrsInternal<PreStatChangeAbAttr>(attrType, pokemon, (attr, passive) => attr.applyPreStatChange(pokemon, sourcePokemon, passive, stat, levels, cancelled, args), args);
} }
export function applyPostStatChangeAbAttrs(attrType: { new(...args: any[]): PostStatChangeAbAttr }, export function applyPostStatChangeAbAttrs(attrType: { new(...args: any[]): PostStatChangeAbAttr },
@ -3604,8 +3626,8 @@ export function initAbilities() {
new Ability(Abilities.PROPELLER_TAIL, 8) new Ability(Abilities.PROPELLER_TAIL, 8)
.attr(BlockRedirectAbAttr), .attr(BlockRedirectAbAttr),
new Ability(Abilities.MIRROR_ARMOR, 8) new Ability(Abilities.MIRROR_ARMOR, 8)
.ignorable() .attr(ReflectStatAbAttr)
.unimplemented(), .ignorable(),
new Ability(Abilities.GULP_MISSILE, 8) new Ability(Abilities.GULP_MISSILE, 8)
.attr(UnsuppressableAbilityAbAttr) .attr(UnsuppressableAbilityAbAttr)
.attr(NoTransformAbilityAbAttr) .attr(NoTransformAbilityAbAttr)

View File

@ -439,7 +439,7 @@ class StickyWebTag extends ArenaTrapTag {
if (!cancelled.value) { if (!cancelled.value) {
pokemon.scene.queueMessage(`The opposing ${pokemon.name} was caught in a sticky web!`); pokemon.scene.queueMessage(`The opposing ${pokemon.name} was caught in a sticky web!`);
const statLevels = new Utils.NumberHolder(-1); const statLevels = new Utils.NumberHolder(-1);
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), false, [BattleStat.SPD], statLevels.value)); pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), false, [BattleStat.SPD], statLevels.value, true, false, true, pokemon.scene.getPokemonById(this.sourceId)));
} }
} }

View File

@ -1733,7 +1733,7 @@ export class StatChangeAttr extends MoveEffectAttr {
if (move.chance < 0 || move.chance === 100 || user.randSeedInt(100) < move.chance) { if (move.chance < 0 || move.chance === 100 || user.randSeedInt(100) < move.chance) {
const levels = this.getLevels(user); const levels = this.getLevels(user);
user.scene.unshiftPhase(new StatChangePhase(user.scene, (this.selfTarget ? user : target).getBattlerIndex(), this.selfTarget, this.stats, levels, this.showMessage)); user.scene.unshiftPhase(new StatChangePhase(user.scene, (this.selfTarget ? user : target).getBattlerIndex(), this.selfTarget, this.stats, levels, this.showMessage, false, true, user));
return true; return true;
} }
@ -1813,7 +1813,7 @@ export class AcupressureStatChangeAttr extends MoveEffectAttr {
randStats = randStats.filter(s => target.summonData.battleStats[s] < 6); randStats = randStats.filter(s => target.summonData.battleStats[s] < 6);
if (randStats.length > 0) { if (randStats.length > 0) {
let boostStat = [randStats[Utils.randInt(randStats.length)]]; let boostStat = [randStats[Utils.randInt(randStats.length)]];
user.scene.unshiftPhase(new StatChangePhase(user.scene, target.getBattlerIndex(), this.selfTarget, boostStat, 2)); user.scene.unshiftPhase(new StatChangePhase(user.scene, target.getBattlerIndex(), this.selfTarget, boostStat, 2, true, false, true, user));
return true; return true;
} }
return false; return false;

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, PreStatChangeAbAttr } 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";
@ -2739,8 +2739,19 @@ export class StatChangePhase extends PokemonPhase {
private showMessage: boolean; private showMessage: boolean;
private ignoreAbilities: boolean; private ignoreAbilities: boolean;
private canBeCopied: boolean; private canBeCopied: boolean;
private sourcePokemon: Pokemon;
constructor(scene: BattleScene, battlerIndex: BattlerIndex, selfTarget: boolean, stats: BattleStat[], levels: integer, showMessage: boolean = true, ignoreAbilities: boolean = false, canBeCopied: boolean = true) { constructor(
scene: BattleScene,
battlerIndex: BattlerIndex,
selfTarget: boolean,
stats: BattleStat[],
levels: integer,
showMessage: boolean = true,
ignoreAbilities: boolean = false,
canBeCopied: boolean = true,
sourcePokemon?: Pokemon,
) {
super(scene, battlerIndex); super(scene, battlerIndex);
this.selfTarget = selfTarget; this.selfTarget = selfTarget;
@ -2749,6 +2760,7 @@ export class StatChangePhase extends PokemonPhase {
this.showMessage = showMessage; this.showMessage = showMessage;
this.ignoreAbilities = ignoreAbilities; this.ignoreAbilities = ignoreAbilities;
this.canBeCopied = canBeCopied; this.canBeCopied = canBeCopied;
this.sourcePokemon = sourcePokemon;
} }
start() { start() {
@ -2773,7 +2785,7 @@ export class StatChangePhase extends PokemonPhase {
this.scene.arena.applyTagsForSide(MistTag, pokemon.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY, cancelled); this.scene.arena.applyTagsForSide(MistTag, pokemon.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY, cancelled);
if (!cancelled.value && !this.selfTarget && this.levels < 0) if (!cancelled.value && !this.selfTarget && this.levels < 0)
applyPreStatChangeAbAttrs(ProtectStatAbAttr, this.getPokemon(), stat, cancelled); applyPreStatChangeAbAttrs(PreStatChangeAbAttr, this.getPokemon(), this.sourcePokemon, stat, this.levels, cancelled);
return !cancelled.value; return !cancelled.value;
}); });