pull/754/merge
Brandon Rodgers 2024-05-15 09:09:09 -04:00 committed by GitHub
commit 631949cad4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 65 additions and 26 deletions

View File

@ -1709,15 +1709,22 @@ export class PreStatChangeAbAttr extends AbAttr {
export class ProtectStatAbAttr extends PreStatChangeAbAttr { export class ProtectStatAbAttr extends PreStatChangeAbAttr {
private protectedStat: BattleStat; private protectedStat: BattleStat;
private applyToAlly: boolean;
constructor(protectedStat?: BattleStat) { constructor(protectedStat?: BattleStat, applyToAlly: boolean = false) {
super(); super();
this.protectedStat = protectedStat; this.protectedStat = protectedStat;
this.applyToAlly = applyToAlly;
} }
applyPreStatChange(pokemon: Pokemon, passive: boolean, stat: BattleStat, cancelled: Utils.BooleanHolder, args: any[]): boolean { applyPreStatChange(pokemon: Pokemon, passive: boolean, stat: BattleStat, cancelled: Utils.BooleanHolder, args: any[]): boolean {
if (this.protectedStat === undefined || stat === this.protectedStat) { const allyCheck = args[0];
if ((this.protectedStat === undefined || stat === this.protectedStat) && !allyCheck) {
cancelled.value = true;
return true;
} else if ((this.protectedStat === undefined || stat === this.protectedStat)
&& allyCheck && this.applyToAlly) {
cancelled.value = true; cancelled.value = true;
return true; return true;
} }
@ -1737,16 +1744,24 @@ export class PreSetStatusAbAttr extends AbAttr {
} }
export class StatusEffectImmunityAbAttr extends PreSetStatusAbAttr { export class StatusEffectImmunityAbAttr extends PreSetStatusAbAttr {
private applyToAlly: boolean;
private immuneEffects: StatusEffect[]; private immuneEffects: StatusEffect[];
constructor(...immuneEffects: StatusEffect[]) { constructor(immuneEffects: StatusEffect[] = [], applyToAlly: boolean = false) {
super(); super();
this.immuneEffects = immuneEffects; this.immuneEffects = immuneEffects;
this.applyToAlly = applyToAlly;
} }
applyPreSetStatus(pokemon: Pokemon, passive: boolean, effect: StatusEffect, cancelled: Utils.BooleanHolder, args: any[]): boolean { applyPreSetStatus(pokemon: Pokemon, passive: boolean, effect: StatusEffect, cancelled: Utils.BooleanHolder, args: any[]): boolean {
if (!this.immuneEffects.length || this.immuneEffects.indexOf(effect) > -1) { const allyCheck = args[1];
if ((!this.immuneEffects.length || this.immuneEffects.indexOf(effect) > -1) && !allyCheck) {
cancelled.value = true;
return true;
}
else if((!this.immuneEffects.length || this.immuneEffects.indexOf(effect) > -1)
&& allyCheck && this.applyToAlly) {
cancelled.value = true; cancelled.value = true;
return true; return true;
} }
@ -1767,15 +1782,22 @@ export class PreApplyBattlerTagAbAttr extends AbAttr {
export class BattlerTagImmunityAbAttr extends PreApplyBattlerTagAbAttr { export class BattlerTagImmunityAbAttr extends PreApplyBattlerTagAbAttr {
private immuneTagType: BattlerTagType; private immuneTagType: BattlerTagType;
private applyToAlly: boolean;
constructor(immuneTagType: BattlerTagType) { constructor(immuneTagType: BattlerTagType, applyToAlly: boolean = false) {
super(); super();
this.immuneTagType = immuneTagType; this.immuneTagType = immuneTagType;
this.applyToAlly = applyToAlly;
} }
applyPreApplyBattlerTag(pokemon: Pokemon, passive: boolean, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): boolean { applyPreApplyBattlerTag(pokemon: Pokemon, passive: boolean, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): boolean {
if (tag.tagType === this.immuneTagType) { const allyCheck = args[0];
if ((tag.tagType === this.immuneTagType) && !allyCheck) {
cancelled.value = true;
return true;
} else if ((tag.tagType === this.immuneTagType)
&& allyCheck && this.applyToAlly) {
cancelled.value = true; cancelled.value = true;
return true; return true;
} }
@ -2824,7 +2846,7 @@ export function applyPostStatChangeAbAttrs(attrType: { new(...args: any[]): Post
export function applyPreSetStatusAbAttrs(attrType: { new(...args: any[]): PreSetStatusAbAttr }, export function applyPreSetStatusAbAttrs(attrType: { new(...args: any[]): PreSetStatusAbAttr },
pokemon: Pokemon, effect: StatusEffect, cancelled: Utils.BooleanHolder, ...args: any[]): Promise<void> { pokemon: Pokemon, effect: StatusEffect, cancelled: Utils.BooleanHolder, ...args: any[]): Promise<void> {
const simulated = args.length > 1 && args[1]; const simulated = args.length > 2 && args[2];
return applyAbAttrsInternal<PreSetStatusAbAttr>(attrType, pokemon, (attr, passive) => attr.applyPreSetStatus(pokemon, passive, effect, cancelled, args), args, false, false, simulated); return applyAbAttrsInternal<PreSetStatusAbAttr>(attrType, pokemon, (attr, passive) => attr.applyPreSetStatus(pokemon, passive, effect, cancelled, args), args, false, false, simulated);
} }
@ -2905,7 +2927,7 @@ export function initAbilities() {
.attr(FieldPreventExplosiveMovesAbAttr) .attr(FieldPreventExplosiveMovesAbAttr)
.ignorable(), .ignorable(),
new Ability(Abilities.LIMBER, 3) new Ability(Abilities.LIMBER, 3)
.attr(StatusEffectImmunityAbAttr, StatusEffect.PARALYSIS) .attr(StatusEffectImmunityAbAttr, [StatusEffect.PARALYSIS])
.ignorable(), .ignorable(),
new Ability(Abilities.SAND_VEIL, 3) new Ability(Abilities.SAND_VEIL, 3)
.attr(BattleStatMultiplierAbAttr, BattleStat.EVA, 1.2) .attr(BattleStatMultiplierAbAttr, BattleStat.EVA, 1.2)
@ -2930,13 +2952,13 @@ export function initAbilities() {
new Ability(Abilities.COMPOUND_EYES, 3) new Ability(Abilities.COMPOUND_EYES, 3)
.attr(BattleStatMultiplierAbAttr, BattleStat.ACC, 1.3), .attr(BattleStatMultiplierAbAttr, BattleStat.ACC, 1.3),
new Ability(Abilities.INSOMNIA, 3) new Ability(Abilities.INSOMNIA, 3)
.attr(StatusEffectImmunityAbAttr, StatusEffect.SLEEP) .attr(StatusEffectImmunityAbAttr, [StatusEffect.SLEEP])
.attr(BattlerTagImmunityAbAttr, BattlerTagType.DROWSY) .attr(BattlerTagImmunityAbAttr, BattlerTagType.DROWSY)
.ignorable(), .ignorable(),
new Ability(Abilities.COLOR_CHANGE, 3) new Ability(Abilities.COLOR_CHANGE, 3)
.attr(PostDefendTypeChangeAbAttr), .attr(PostDefendTypeChangeAbAttr),
new Ability(Abilities.IMMUNITY, 3) new Ability(Abilities.IMMUNITY, 3)
.attr(StatusEffectImmunityAbAttr, StatusEffect.POISON, StatusEffect.TOXIC) .attr(StatusEffectImmunityAbAttr, [StatusEffect.POISON, StatusEffect.TOXIC])
.ignorable(), .ignorable(),
new Ability(Abilities.FLASH_FIRE, 3) new Ability(Abilities.FLASH_FIRE, 3)
.attr(TypeImmunityAddBattlerTagAbAttr, Type.FIRE, BattlerTagType.FIRE_BOOST, 1, (pokemon: Pokemon) => !pokemon.status || pokemon.status.effect !== StatusEffect.FREEZE) .attr(TypeImmunityAddBattlerTagAbAttr, Type.FIRE, BattlerTagType.FIRE_BOOST, 1, (pokemon: Pokemon) => !pokemon.status || pokemon.status.effect !== StatusEffect.FREEZE)
@ -3005,10 +3027,10 @@ export function initAbilities() {
.attr(IntimidateImmunityAbAttr) .attr(IntimidateImmunityAbAttr)
.ignorable(), .ignorable(),
new Ability(Abilities.MAGMA_ARMOR, 3) new Ability(Abilities.MAGMA_ARMOR, 3)
.attr(StatusEffectImmunityAbAttr, StatusEffect.FREEZE) .attr(StatusEffectImmunityAbAttr, [StatusEffect.FREEZE])
.ignorable(), .ignorable(),
new Ability(Abilities.WATER_VEIL, 3) new Ability(Abilities.WATER_VEIL, 3)
.attr(StatusEffectImmunityAbAttr, StatusEffect.BURN) .attr(StatusEffectImmunityAbAttr, [StatusEffect.BURN])
.ignorable(), .ignorable(),
new Ability(Abilities.MAGNET_PULL, 3) new Ability(Abilities.MAGNET_PULL, 3)
/*.attr(ArenaTrapAbAttr) /*.attr(ArenaTrapAbAttr)
@ -3090,7 +3112,7 @@ export function initAbilities() {
.attr(ArenaTrapAbAttr) .attr(ArenaTrapAbAttr)
.attr(DoubleBattleChanceAbAttr), .attr(DoubleBattleChanceAbAttr),
new Ability(Abilities.VITAL_SPIRIT, 3) new Ability(Abilities.VITAL_SPIRIT, 3)
.attr(StatusEffectImmunityAbAttr, StatusEffect.SLEEP) .attr(StatusEffectImmunityAbAttr, [StatusEffect.SLEEP])
.attr(BattlerTagImmunityAbAttr, BattlerTagType.DROWSY) .attr(BattlerTagImmunityAbAttr, BattlerTagType.DROWSY)
.ignorable(), .ignorable(),
new Ability(Abilities.WHITE_SMOKE, 3) new Ability(Abilities.WHITE_SMOKE, 3)
@ -3365,9 +3387,13 @@ export function initAbilities() {
new Ability(Abilities.AROMA_VEIL, 6) new Ability(Abilities.AROMA_VEIL, 6)
.ignorable() .ignorable()
.unimplemented(), .unimplemented(),
new Ability(Abilities.FLOWER_VEIL, 6) new Ability(Abilities.FLOWER_VEIL, 6) // TODO: Check against Spectral Thief once implemented, check against Toxic orb and flame orb once implemented.
// Also needs to not prevent the user from using Rest.
.conditionalAttr(p => (p.isOfType(Type.GRASS)), ProtectStatAbAttr, undefined, true)
.conditionalAttr(p => (p.isOfType(Type.GRASS)), StatusEffectImmunityAbAttr, [], true)
.conditionalAttr(p => (p.isOfType(Type.GRASS)), BattlerTagImmunityAbAttr, BattlerTagType.DROWSY, true)
.ignorable() .ignorable()
.unimplemented(), .partial(),
new Ability(Abilities.CHEEK_POUCH, 6) new Ability(Abilities.CHEEK_POUCH, 6)
.unimplemented(), .unimplemented(),
new Ability(Abilities.PROTEAN, 6) new Ability(Abilities.PROTEAN, 6)
@ -3387,10 +3413,9 @@ export function initAbilities() {
new Ability(Abilities.REFRIGERATE, 6) new Ability(Abilities.REFRIGERATE, 6)
.attr(MoveTypeChangePowerMultiplierAbAttr, Type.NORMAL, Type.ICE, 1.2), .attr(MoveTypeChangePowerMultiplierAbAttr, Type.NORMAL, Type.ICE, 1.2),
new Ability(Abilities.SWEET_VEIL, 6) new Ability(Abilities.SWEET_VEIL, 6)
.attr(StatusEffectImmunityAbAttr, StatusEffect.SLEEP) .attr(StatusEffectImmunityAbAttr, [StatusEffect.SLEEP], true)
.attr(BattlerTagImmunityAbAttr, BattlerTagType.DROWSY) .attr(BattlerTagImmunityAbAttr, BattlerTagType.DROWSY, true)
.ignorable() .ignorable(),
.partial(),
new Ability(Abilities.STANCE_CHANGE, 6) new Ability(Abilities.STANCE_CHANGE, 6)
.attr(UncopiableAbilityAbAttr) .attr(UncopiableAbilityAbAttr)
.attr(UnswappableAbilityAbAttr) .attr(UnswappableAbilityAbAttr)
@ -3457,7 +3482,7 @@ export function initAbilities() {
new Ability(Abilities.WATER_BUBBLE, 7) new Ability(Abilities.WATER_BUBBLE, 7)
.attr(ReceivedTypeDamageMultiplierAbAttr, Type.FIRE, 0.5) .attr(ReceivedTypeDamageMultiplierAbAttr, Type.FIRE, 0.5)
.attr(MoveTypePowerBoostAbAttr, Type.WATER, 1) .attr(MoveTypePowerBoostAbAttr, Type.WATER, 1)
.attr(StatusEffectImmunityAbAttr, StatusEffect.BURN) .attr(StatusEffectImmunityAbAttr, [StatusEffect.BURN])
.ignorable(), .ignorable(),
new Ability(Abilities.STEELWORKER, 7) new Ability(Abilities.STEELWORKER, 7)
.attr(MoveTypePowerBoostAbAttr, Type.STEEL), .attr(MoveTypePowerBoostAbAttr, Type.STEEL),
@ -3658,7 +3683,7 @@ export function initAbilities() {
.attr(PostSummonMessageAbAttr, (pokemon: Pokemon) => getPokemonMessage(pokemon, '\'s Neutralizing Gas filled the area!')) .attr(PostSummonMessageAbAttr, (pokemon: Pokemon) => getPokemonMessage(pokemon, '\'s Neutralizing Gas filled the area!'))
.partial(), .partial(),
new Ability(Abilities.PASTEL_VEIL, 8) new Ability(Abilities.PASTEL_VEIL, 8)
.attr(StatusEffectImmunityAbAttr, StatusEffect.POISON, StatusEffect.TOXIC) .attr(StatusEffectImmunityAbAttr, [StatusEffect.POISON, StatusEffect.TOXIC], true)
.ignorable(), .ignorable(),
new Ability(Abilities.HUNGER_SWITCH, 8) new Ability(Abilities.HUNGER_SWITCH, 8)
.attr(PostTurnFormChangeAbAttr, p => p.getFormKey ? 0 : 1) .attr(PostTurnFormChangeAbAttr, p => p.getFormKey ? 0 : 1)
@ -3701,7 +3726,7 @@ export function initAbilities() {
.attr(PostDefendTerrainChangeAbAttr, TerrainType.GRASSY), .attr(PostDefendTerrainChangeAbAttr, TerrainType.GRASSY),
new Ability(Abilities.THERMAL_EXCHANGE, 9) new Ability(Abilities.THERMAL_EXCHANGE, 9)
.attr(PostDefendStatChangeAbAttr, (target, user, move) => move.type === Type.FIRE && move.category !== MoveCategory.STATUS, BattleStat.ATK, 1) .attr(PostDefendStatChangeAbAttr, (target, user, move) => move.type === Type.FIRE && move.category !== MoveCategory.STATUS, BattleStat.ATK, 1)
.attr(StatusEffectImmunityAbAttr, StatusEffect.BURN) .attr(StatusEffectImmunityAbAttr, [StatusEffect.BURN])
.ignorable(), .ignorable(),
new Ability(Abilities.ANGER_SHELL, 9) new Ability(Abilities.ANGER_SHELL, 9)
.attr(PostDefendHpGatedStatChangeAbAttr, (target, user, move) => move.category !== MoveCategory.STATUS, 0.5, [ BattleStat.ATK, BattleStat.SPATK, BattleStat.SPD ], 1) .attr(PostDefendHpGatedStatChangeAbAttr, (target, user, move) => move.category !== MoveCategory.STATUS, 0.5, [ BattleStat.ATK, BattleStat.SPATK, BattleStat.SPD ], 1)

View File

@ -435,7 +435,11 @@ class StickyWebTag extends ArenaTrapTag {
activateTrap(pokemon: Pokemon): boolean { activateTrap(pokemon: Pokemon): boolean {
if (pokemon.isGrounded()) { if (pokemon.isGrounded()) {
const cancelled = new Utils.BooleanHolder(false); const cancelled = new Utils.BooleanHolder(false);
applyAbAttrs(ProtectStatAbAttr, pokemon, cancelled); const allyCheck = true;
applyAbAttrs(ProtectStatAbAttr, pokemon, cancelled, !allyCheck);
if (!cancelled.value) // If Pokemon fails to protect themselves, check if ally has an ability to protect them
applyAbAttrs(ProtectStatAbAttr, pokemon.getAlly(), cancelled, allyCheck);
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);

View File

@ -1746,7 +1746,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const newTag = getBattlerTag(tagType, turnCount, sourceMove, sourceId); const newTag = getBattlerTag(tagType, turnCount, sourceMove, sourceId);
const cancelled = new Utils.BooleanHolder(false); const cancelled = new Utils.BooleanHolder(false);
applyPreApplyBattlerTagAbAttrs(PreApplyBattlerTagAbAttr, this, newTag, cancelled); const allyCheck = true;
applyPreApplyBattlerTagAbAttrs(PreApplyBattlerTagAbAttr, this, newTag, cancelled, !allyCheck);
if (!cancelled.value) // If the tag was not cancelled, check if Ally has an ability that provides immunity to allies
applyPreApplyBattlerTagAbAttrs(PreApplyBattlerTagAbAttr, this.getAlly(), newTag, cancelled, allyCheck);
if (!cancelled.value && newTag.canAdd(this)) { if (!cancelled.value && newTag.canAdd(this)) {
this.summonData.tags.push(newTag); this.summonData.tags.push(newTag);
@ -2106,7 +2109,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
const cancelled = new Utils.BooleanHolder(false); const cancelled = new Utils.BooleanHolder(false);
applyPreSetStatusAbAttrs(StatusEffectImmunityAbAttr, this, effect, cancelled, quiet); const allyCheck = true;
applyPreSetStatusAbAttrs(StatusEffectImmunityAbAttr, this, effect, cancelled, quiet, !allyCheck);
if (!cancelled.value) {// If Pokemon fails to protect themselves, check if ally has an ability to protect them
applyPreSetStatusAbAttrs(StatusEffectImmunityAbAttr, this.getAlly(), effect, cancelled, quiet, allyCheck);
}
if (cancelled.value) if (cancelled.value)
return false; return false;

View File

@ -2761,8 +2761,11 @@ export class StatChangePhase extends PokemonPhase {
if (!this.selfTarget && this.levels < 0) if (!this.selfTarget && this.levels < 0)
this.scene.arena.applyTagsForSide(MistTag, pokemon.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY, cancelled); this.scene.arena.applyTagsForSide(MistTag, pokemon.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY, cancelled);
const allyCheck = true;
if (!cancelled.value && !this.selfTarget && this.levels < 0) if (!cancelled.value && !this.selfTarget && this.levels < 0)
applyPreStatChangeAbAttrs(ProtectStatAbAttr, this.getPokemon(), stat, cancelled); applyPreStatChangeAbAttrs(ProtectStatAbAttr, this.getPokemon(), stat, cancelled, !allyCheck);
if (!cancelled.value && !this.selfTarget) // If Pokemon fails to protect themselves, check if ally has an ability to protect them
applyPreStatChangeAbAttrs(ProtectStatAbAttr, this.getPokemon().getAlly(), stat, cancelled, allyCheck);
return !cancelled.value; return !cancelled.value;
}); });