Implemented Disguise

Somehow it works.
This commit is contained in:
NxKarim 2024-04-17 02:59:25 -06:00
parent b116828b07
commit 7a6307d200
5 changed files with 160 additions and 76 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 333 B

View File

@ -4923,6 +4923,48 @@
"h": 22 "h": 22
} }
}, },
{
"filename": "778-busted",
"rotated": false,
"trimmed": true,
"sourceSize": {
"w": 40,
"h": 30
},
"spriteSourceSize": {
"x": 13,
"y": 5,
"w": 17,
"h": 22
},
"frame": {
"x": 156,
"y": 443,
"w": 17,
"h": 22
}
},
{
"filename": "778s-busted",
"rotated": false,
"trimmed": true,
"sourceSize": {
"w": 40,
"h": 30
},
"spriteSourceSize": {
"x": 13,
"y": 5,
"w": 17,
"h": 22
},
"frame": {
"x": 217,
"y": 367,
"w": 17,
"h": 22
}
},
{ {
"filename": "741s-pompom", "filename": "741s-pompom",
"rotated": false, "rotated": false,

View File

@ -52,10 +52,10 @@ export class Ability {
const attr = new AttrType(...args); const attr = new AttrType(...args);
attr.addCondition(condition); attr.addCondition(condition);
this.attrs.push(attr); this.attrs.push(attr);
return this; return this;
} }
hasAttr(attrType: { new(...args: any[]): AbAttr }): boolean { hasAttr(attrType: { new(...args: any[]): AbAttr }): boolean {
return !!this.getAttrs(attrType).length; return !!this.getAttrs(attrType).length;
} }
@ -91,7 +91,7 @@ export abstract class AbAttr {
constructor(showAbility: boolean = true) { constructor(showAbility: boolean = true) {
this.showAbility = showAbility; this.showAbility = showAbility;
} }
apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise<boolean> { apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise<boolean> {
return false; return false;
} }
@ -166,8 +166,8 @@ export class PostBattleInitStatChangeAbAttr extends PostBattleInitAbAttr {
constructor(stats: BattleStat | BattleStat[], levels: integer, selfTarget?: boolean) { constructor(stats: BattleStat | BattleStat[], levels: integer, selfTarget?: boolean) {
super(); super();
this.stats = typeof(stats) === 'number' this.stats = typeof (stats) === 'number'
? [ stats as BattleStat ] ? [stats as BattleStat]
: stats as BattleStat[]; : stats as BattleStat[];
this.levels = levels; this.levels = levels;
this.selfTarget = !!selfTarget; this.selfTarget = !!selfTarget;
@ -189,7 +189,7 @@ export class PostBattleInitStatChangeAbAttr extends PostBattleInitAbAttr {
else else
pokemon.scene.unshiftPhase(statChangePhase); pokemon.scene.unshiftPhase(statChangePhase);
} }
return true; return true;
} }
} }
@ -214,7 +214,7 @@ export class PreDefendFullHpEndureAbAttr extends PreDefendAbAttr {
export class BlockItemTheftAbAttr extends AbAttr { export class BlockItemTheftAbAttr extends AbAttr {
apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean {
cancelled.value = true; cancelled.value = true;
return true; return true;
} }
@ -229,13 +229,13 @@ export class StabBoostAbAttr extends AbAttr {
(args[0] as Utils.NumberHolder).value += 0.5; (args[0] as Utils.NumberHolder).value += 0.5;
return true; return true;
} }
return false; return false;
} }
} }
export class ReceivedMoveDamageMultiplierAbAttr extends PreDefendAbAttr { export class ReceivedMoveDamageMultiplierAbAttr extends PreDefendAbAttr {
private condition: PokemonDefendCondition; protected condition: PokemonDefendCondition;
private powerMultiplier: number; private powerMultiplier: number;
constructor(condition: PokemonDefendCondition, powerMultiplier: number) { constructor(condition: PokemonDefendCondition, powerMultiplier: number) {
@ -261,6 +261,21 @@ export class ReceivedTypeDamageMultiplierAbAttr extends ReceivedMoveDamageMultip
} }
} }
export class SetMovePowerToOneAbAttr extends ReceivedMoveDamageMultiplierAbAttr {
constructor(condition: PokemonDefendCondition) {
super(condition, 1);
}
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean {
if (this.condition(pokemon, attacker, move.getMove())) {
(args[0] as Utils.NumberHolder).value = 0.001;
return true;
}
return false;
}
}
export class TypeImmunityAbAttr extends PreDefendAbAttr { export class TypeImmunityAbAttr extends PreDefendAbAttr {
private immuneType: Type; private immuneType: Type;
private condition: AbAttrCondition; private condition: AbAttrCondition;
@ -305,7 +320,7 @@ export class TypeImmunityHealAbAttr extends TypeImmunityAbAttr {
} }
return true; return true;
} }
return false; return false;
} }
} }
@ -328,9 +343,9 @@ class TypeImmunityStatChangeAbAttr extends TypeImmunityAbAttr {
cancelled.value = true; cancelled.value = true;
const simulated = args.length > 1 && args[1]; const simulated = args.length > 1 && args[1];
if (!simulated) if (!simulated)
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ this.stat ], this.levels)); pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [this.stat], this.levels));
} }
return ret; return ret;
} }
} }
@ -355,7 +370,7 @@ class TypeImmunityAddBattlerTagAbAttr extends TypeImmunityAbAttr {
if (!simulated) if (!simulated)
pokemon.addTag(this.tagType, this.turnCount, undefined, pokemon.id); pokemon.addTag(this.tagType, this.turnCount, undefined, pokemon.id);
} }
return ret; return ret;
} }
} }
@ -386,16 +401,36 @@ export class PostDefendAbAttr extends AbAttr {
} }
} }
export class PostDefendDisguiseAbAttr extends PostDefendAbAttr {
constructor(damageRatio?: number) {
super(true);
}
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
if (pokemon.formIndex == 0 && pokemon.battleData.hitCount != 0 && (move.getMove().category == MoveCategory.SPECIAL || move.getMove().category == MoveCategory.PHYSICAL)) {
const recoilDamage = Math.ceil((pokemon.getMaxHp() / 8) - attacker.turnData.damageDealt);
if (!recoilDamage)
return false;
pokemon.damageAndUpdate(recoilDamage, HitResult.OTHER);
pokemon.scene.queueMessage(getPokemonMessage(pokemon, '\'s disguise was busted!'));
return true;
}
return false;
}
}
export class FieldPriorityMoveImmunityAbAttr extends PreDefendAbAttr { export class FieldPriorityMoveImmunityAbAttr extends PreDefendAbAttr {
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean { applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, cancelled: Utils.BooleanHolder, args: any[]): boolean {
const attackPriority = new Utils.IntegerHolder(move.getMove().priority); const attackPriority = new Utils.IntegerHolder(move.getMove().priority);
applyAbAttrs(IncrementMovePriorityAbAttr, attacker, null, move.getMove(), attackPriority); applyAbAttrs(IncrementMovePriorityAbAttr, attacker, null, move.getMove(), attackPriority);
if(attackPriority.value > 0 && !move.getMove().isMultiTarget()) { if (attackPriority.value > 0 && !move.getMove().isMultiTarget()) {
cancelled.value = true; cancelled.value = true;
return true; return true;
} }
return false; return false;
} }
} }
@ -446,7 +481,7 @@ export class PostDefendStatChangeAbAttr extends PostDefendAbAttr {
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
if (this.condition(pokemon, attacker, move.getMove())) { if (this.condition(pokemon, attacker, move.getMove())) {
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, (this.selfTarget ? pokemon : attacker).getBattlerIndex(), true, [ this.stat ], this.levels)); pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, (this.selfTarget ? pokemon : attacker).getBattlerIndex(), true, [this.stat], this.levels));
return true; return true;
} }
@ -460,7 +495,7 @@ export class PostDefendTypeChangeAbAttr extends PostDefendAbAttr {
const type = move.getMove().type; const type = move.getMove().type;
const pokemonTypes = pokemon.getTypes(true); const pokemonTypes = pokemon.getTypes(true);
if (pokemonTypes.length !== 1 || pokemonTypes[0] !== type) { if (pokemonTypes.length !== 1 || pokemonTypes[0] !== type) {
pokemon.summonData.types = [ type ]; pokemon.summonData.types = [type];
return true; return true;
} }
} }
@ -544,8 +579,8 @@ export class PostDefendCritStatChangeAbAttr extends PostDefendAbAttr {
} }
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ this.stat ], this.levels)); pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [this.stat], this.levels));
return true; return true;
} }
@ -562,13 +597,13 @@ export class PostDefendContactDamageAbAttr extends PostDefendAbAttr {
this.damageRatio = damageRatio; this.damageRatio = damageRatio;
} }
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) { if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) {
attacker.damageAndUpdate(Math.ceil(attacker.getMaxHp() * (1 / this.damageRatio)), HitResult.OTHER); attacker.damageAndUpdate(Math.ceil(attacker.getMaxHp() * (1 / this.damageRatio)), HitResult.OTHER);
return true; return true;
} }
return false; return false;
} }
@ -598,7 +633,7 @@ export class PostDefendAbilitySwapAbAttr extends PostDefendAbAttr {
constructor() { constructor() {
super(); super();
} }
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.getAbility().hasAttr(UnswappableAbilityAbAttr)) { if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.getAbility().hasAttr(UnswappableAbilityAbAttr)) {
const tempAbilityId = attacker.getAbility().id; const tempAbilityId = attacker.getAbility().id;
@ -606,7 +641,7 @@ export class PostDefendAbilitySwapAbAttr extends PostDefendAbAttr {
pokemon.summonData.ability = tempAbilityId; pokemon.summonData.ability = tempAbilityId;
return true; return true;
} }
return false; return false;
} }
@ -619,14 +654,14 @@ export class PostDefendAbilityGiveAbAttr extends PostDefendAbAttr {
constructor() { constructor() {
super(); super();
} }
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean { applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.getAbility().hasAttr(UnsuppressableAbilityAbAttr) && !attacker.getAbility().hasAttr(PostDefendAbilityGiveAbAttr)) { if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.getAbility().hasAttr(UnsuppressableAbilityAbAttr) && !attacker.getAbility().hasAttr(PostDefendAbilityGiveAbAttr)) {
attacker.summonData.ability = pokemon.getAbility().id; attacker.summonData.ability = pokemon.getAbility().id;
return true; return true;
} }
return false; return false;
} }
@ -674,7 +709,7 @@ export class VariableMovePowerAbAttr extends PreAttackAbAttr {
export class VariableMoveTypeAbAttr extends AbAttr { export class VariableMoveTypeAbAttr extends AbAttr {
apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean {
//const power = args[0] as Utils.IntegerHolder; //const power = args[0] as Utils.IntegerHolder;
return false; return false;
} }
} }
@ -683,7 +718,7 @@ export class MoveTypeChangePowerMultiplierAbAttr extends VariableMoveTypeAbAttr
private newType: Type; private newType: Type;
private powerMultiplier: number; private powerMultiplier: number;
constructor(matchType: Type, newType: Type, powerMultiplier: number){ constructor(matchType: Type, newType: Type, powerMultiplier: number) {
super(true); super(true);
this.matchType = matchType; this.matchType = matchType;
this.newType = newType; this.newType = newType;
@ -697,7 +732,7 @@ export class MoveTypeChangePowerMultiplierAbAttr extends VariableMoveTypeAbAttr
(args[1] as Utils.NumberHolder).value *= this.powerMultiplier; (args[1] as Utils.NumberHolder).value *= this.powerMultiplier;
return true; return true;
} }
return false; return false;
} }
} }
@ -707,7 +742,7 @@ export class MoveTypeChangeAttr extends PreAttackAbAttr {
private powerMultiplier: number; private powerMultiplier: number;
private condition: PokemonAttackCondition; private condition: PokemonAttackCondition;
constructor(newType: Type, powerMultiplier: number, condition: PokemonAttackCondition){ constructor(newType: Type, powerMultiplier: number, condition: PokemonAttackCondition) {
super(true); super(true);
this.newType = newType; this.newType = newType;
this.powerMultiplier = powerMultiplier; this.powerMultiplier = powerMultiplier;
@ -766,7 +801,7 @@ export class LowHpMoveTypePowerBoostAbAttr extends MoveTypePowerBoostAbAttr {
export class FieldVariableMovePowerAbAttr extends AbAttr { export class FieldVariableMovePowerAbAttr extends AbAttr {
applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, args: any[]): boolean { applyPreAttack(pokemon: Pokemon, passive: boolean, defender: Pokemon, move: PokemonMove, args: any[]): boolean {
//const power = args[0] as Utils.NumberHolder; //const power = args[0] as Utils.NumberHolder;
return false; return false;
} }
} }
@ -940,8 +975,8 @@ class PostVictoryStatChangeAbAttr extends PostVictoryAbAttr {
const stat = typeof this.stat === 'function' const stat = typeof this.stat === 'function'
? this.stat(pokemon) ? this.stat(pokemon)
: this.stat; : this.stat;
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ stat ], this.levels)); pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [stat], this.levels));
return true; return true;
} }
} }
@ -967,8 +1002,8 @@ export class PostKnockOutStatChangeAbAttr extends PostKnockOutAbAttr {
const stat = typeof this.stat === 'function' const stat = typeof this.stat === 'function'
? this.stat(pokemon) ? this.stat(pokemon)
: this.stat; : this.stat;
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ stat ], this.levels)); pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [stat], this.levels));
return true; return true;
} }
} }
@ -984,7 +1019,7 @@ export class CopyFaintedAllyAbilityAbAttr extends PostKnockOutAbAttr {
pokemon.scene.queueMessage(getPokemonMessage(knockedOut, `'s ${allAbilities[knockedOut.getAbility().id].name} was taken over!`)); pokemon.scene.queueMessage(getPokemonMessage(knockedOut, `'s ${allAbilities[knockedOut.getAbility().id].name} was taken over!`));
return true; return true;
} }
return false; return false;
} }
} }
@ -1047,8 +1082,8 @@ export class PostSummonStatChangeAbAttr extends PostSummonAbAttr {
constructor(stats: BattleStat | BattleStat[], levels: integer, selfTarget?: boolean) { constructor(stats: BattleStat | BattleStat[], levels: integer, selfTarget?: boolean) {
super(); super();
this.stats = typeof(stats) === 'number' this.stats = typeof (stats) === 'number'
? [ stats as BattleStat ] ? [stats as BattleStat]
: stats as BattleStat[]; : stats as BattleStat[];
this.levels = levels; this.levels = levels;
this.selfTarget = !!selfTarget; this.selfTarget = !!selfTarget;
@ -1070,7 +1105,7 @@ export class PostSummonStatChangeAbAttr extends PostSummonAbAttr {
else else
pokemon.scene.unshiftPhase(statChangePhase); pokemon.scene.unshiftPhase(statChangePhase);
} }
return true; return true;
} }
} }
@ -1083,12 +1118,12 @@ export class DownloadAbAttr extends PostSummonAbAttr {
applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean { applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean {
this.enemyDef = 0; this.enemyDef = 0;
this.enemySpDef = 0; this.enemySpDef = 0;
for (let opponent of pokemon.getOpponents()) { for (let opponent of pokemon.getOpponents()) {
this.enemyDef += opponent.stats[BattleStat.DEF]; this.enemyDef += opponent.stats[BattleStat.DEF];
this.enemySpDef += opponent.stats[BattleStat.SPDEF]; this.enemySpDef += opponent.stats[BattleStat.SPDEF];
} }
if (this.enemyDef < this.enemySpDef) if (this.enemyDef < this.enemySpDef)
this.stats = [BattleStat.ATK]; this.stats = [BattleStat.ATK];
else else
@ -1098,7 +1133,7 @@ export class DownloadAbAttr extends PostSummonAbAttr {
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), false, this.stats, 1)); pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), false, this.stats, 1));
return true; return true;
} }
return false; return false;
} }
} }
@ -1193,11 +1228,11 @@ export class PostSummonTransformAbAttr extends PostSummonAbAttr {
pokemon.summonData.ability = target.getAbility().id; pokemon.summonData.ability = target.getAbility().id;
pokemon.summonData.gender = target.getGender(); pokemon.summonData.gender = target.getGender();
pokemon.summonData.fusionGender = target.getFusionGender(); pokemon.summonData.fusionGender = target.getFusionGender();
pokemon.summonData.stats = [ pokemon.stats[Stat.HP] ].concat(target.stats.slice(1)); pokemon.summonData.stats = [pokemon.stats[Stat.HP]].concat(target.stats.slice(1));
pokemon.summonData.battleStats = target.summonData.battleStats.slice(0); pokemon.summonData.battleStats = target.summonData.battleStats.slice(0);
pokemon.summonData.moveset = target.getMoveset().map(m => new PokemonMove(m.moveId, m.ppUsed, m.ppUp)); pokemon.summonData.moveset = target.getMoveset().map(m => new PokemonMove(m.moveId, m.ppUsed, m.ppUp));
pokemon.summonData.types = target.getTypes(); pokemon.summonData.types = target.getTypes();
pokemon.scene.playSound('PRSFX- Transform'); pokemon.scene.playSound('PRSFX- Transform');
pokemon.loadAssets(false).then(() => pokemon.playAnim()); pokemon.loadAssets(false).then(() => pokemon.playAnim());
@ -1232,7 +1267,7 @@ export class PreSwitchOutResetStatusAbAttr extends PreSwitchOutAbAttr {
export class PreSwitchOutHealAbAttr extends PreSwitchOutAbAttr { export class PreSwitchOutHealAbAttr extends PreSwitchOutAbAttr {
applyPreSwitchOut(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise<boolean> { applyPreSwitchOut(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise<boolean> {
if (pokemon.getHpRatio() < 1 ) { if (pokemon.getHpRatio() < 1) {
const healAmount = Math.floor(pokemon.getMaxHp() * 0.33); const healAmount = Math.floor(pokemon.getMaxHp() * 0.33);
pokemon.heal(healAmount); pokemon.heal(healAmount);
pokemon.updateInfo(); pokemon.updateInfo();
@ -1263,7 +1298,7 @@ export class ProtectStatAbAttr extends PreStatChangeAbAttr {
cancelled.value = true; cancelled.value = true;
return true; return true;
} }
return false; return false;
} }
@ -1372,7 +1407,7 @@ export class IncrementMovePriorityAbAttr extends AbAttr {
apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean { apply(pokemon: Pokemon, passive: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean {
if (!this.moveIncrementFunc(pokemon, args[0] as Move)) if (!this.moveIncrementFunc(pokemon, args[0] as Move))
return false; return false;
(args[1] as Utils.IntegerHolder).value += this.increaseAmount; (args[1] as Utils.IntegerHolder).value += this.increaseAmount;
return true; return true;
} }
@ -1484,7 +1519,7 @@ export class PostWeatherLapseHealAbAttr extends PostWeatherLapseAbAttr {
constructor(healFactor: integer, ...weatherTypes: WeatherType[]) { constructor(healFactor: integer, ...weatherTypes: WeatherType[]) {
super(...weatherTypes); super(...weatherTypes);
this.healFactor = healFactor; this.healFactor = healFactor;
} }
@ -1506,7 +1541,7 @@ export class PostWeatherLapseDamageAbAttr extends PostWeatherLapseAbAttr {
constructor(damageFactor: integer, ...weatherTypes: WeatherType[]) { constructor(damageFactor: integer, ...weatherTypes: WeatherType[]) {
super(...weatherTypes); super(...weatherTypes);
this.damageFactor = damageFactor; this.damageFactor = damageFactor;
} }
@ -1566,13 +1601,13 @@ export class PostTurnAbAttr extends AbAttr {
export class PostTurnResetStatusAbAttr extends PostTurnAbAttr { export class PostTurnResetStatusAbAttr extends PostTurnAbAttr {
applyPostTurn(pokemon: Pokemon, passive: boolean, args: any[]): boolean { applyPostTurn(pokemon: Pokemon, passive: boolean, args: any[]): boolean {
if (pokemon.status) { if (pokemon.status) {
pokemon.scene.queueMessage(getPokemonMessage(pokemon, getStatusEffectHealText(pokemon.status?.effect))); pokemon.scene.queueMessage(getPokemonMessage(pokemon, getStatusEffectHealText(pokemon.status?.effect)));
pokemon.resetStatus(); pokemon.resetStatus();
pokemon.updateInfo(); pokemon.updateInfo();
return true; return true;
} }
return false; return false;
} }
} }
@ -1586,7 +1621,7 @@ export class PostTurnStatChangeAbAttr extends PostTurnAbAttr {
this.stats = Array.isArray(stats) this.stats = Array.isArray(stats)
? stats ? stats
: [ stats ]; : [stats];
this.levels = levels; this.levels = levels;
} }
@ -1719,7 +1754,7 @@ export class CheckTrappedAbAttr extends AbAttr {
constructor() { constructor() {
super(false); super(false);
} }
applyCheckTrapped(pokemon: Pokemon, passive: boolean, trapped: Utils.BooleanHolder, args: any[]): boolean | Promise<boolean> { applyCheckTrapped(pokemon: Pokemon, passive: boolean, trapped: Utils.BooleanHolder, args: any[]): boolean | Promise<boolean> {
return false; return false;
} }
@ -1778,7 +1813,7 @@ export class PostFaintAbAttr extends AbAttr {
export class PostFaintContactDamageAbAttr extends PostFaintAbAttr { export class PostFaintContactDamageAbAttr extends PostFaintAbAttr {
private damageRatio: integer; private damageRatio: integer;
constructor(damageRatio: integer) { constructor(damageRatio: integer) {
super(); super();
@ -1812,10 +1847,10 @@ export class RedirectMoveAbAttr extends AbAttr {
return false; return false;
} }
canRedirect(moveId: Moves): boolean { canRedirect(moveId: Moves): boolean {
const move = allMoves[moveId]; const move = allMoves[moveId];
return !![ MoveTarget.NEAR_OTHER, MoveTarget.OTHER ].find(t => move.moveTarget === t); return !![MoveTarget.NEAR_OTHER, MoveTarget.OTHER].find(t => move.moveTarget === t);
} }
} }
@ -1866,7 +1901,7 @@ export class FlinchStatChangeAbAttr extends FlinchEffectAbAttr {
this.stats = Array.isArray(stats) this.stats = Array.isArray(stats)
? stats ? stats
: [ stats ]; : [stats];
this.levels = levels; this.levels = levels;
} }
@ -2060,7 +2095,7 @@ export function applyPostAttackAbAttrs(attrType: { new(...args: any[]): PostAtta
export function applyPostKnockOutAbAttrs(attrType: { new(...args: any[]): PostKnockOutAbAttr }, export function applyPostKnockOutAbAttrs(attrType: { new(...args: any[]): PostKnockOutAbAttr },
pokemon: Pokemon, knockedOut: Pokemon, ...args: any[]): Promise<void> { pokemon: Pokemon, knockedOut: Pokemon, ...args: any[]): Promise<void> {
return applyAbAttrsInternal<PostKnockOutAbAttr>(attrType, pokemon, (attr, passive) => attr.applyPostKnockOut(pokemon, passive, knockedOut, args), args); return applyAbAttrsInternal<PostKnockOutAbAttr>(attrType, pokemon, (attr, passive) => attr.applyPostKnockOut(pokemon, passive, knockedOut, args), args);
} }
export function applyPostVictoryAbAttrs(attrType: { new(...args: any[]): PostVictoryAbAttr }, export function applyPostVictoryAbAttrs(attrType: { new(...args: any[]): PostVictoryAbAttr },
pokemon: Pokemon, ...args: any[]): Promise<void> { pokemon: Pokemon, ...args: any[]): Promise<void> {
@ -2148,7 +2183,7 @@ function queueShowAbility(pokemon: Pokemon, passive: boolean): void {
pokemon.scene.clearPhaseQueueSplice(); pokemon.scene.clearPhaseQueueSplice();
} }
export const allAbilities = [ new Ability(Abilities.NONE, "-", "", 3) ]; export const allAbilities = [new Ability(Abilities.NONE, "-", "", 3)];
export function initAbilities() { export function initAbilities() {
allAbilities.push( allAbilities.push(
@ -2161,7 +2196,7 @@ export function initAbilities() {
new Ability(Abilities.BATTLE_ARMOR, "Battle Armor", "Hard armor protects the Pokémon from critical hits.", 3) new Ability(Abilities.BATTLE_ARMOR, "Battle Armor", "Hard armor protects the Pokémon from critical hits.", 3)
.attr(BlockCritAbAttr) .attr(BlockCritAbAttr)
.ignorable(), .ignorable(),
new Ability(Abilities.STURDY, "Sturdy", "It cannot be knocked out with one hit. One-hit KO moves cannot knock it out, either.", 3) new Ability(Abilities.STURDY, "Sturdy", "It cannot be knocked out with one hit. One-hit KO moves cannot knock it out, either.", 3)
.attr(PreDefendFullHpEndureAbAttr) .attr(PreDefendFullHpEndureAbAttr)
.attr(BlockOneHitKOAbAttr) .attr(BlockOneHitKOAbAttr)
.ignorable(), .ignorable(),
@ -2401,8 +2436,8 @@ export function initAbilities() {
.conditionalAttr(pokemon => pokemon.status.effect === StatusEffect.PARALYSIS, BattleStatMultiplierAbAttr, BattleStat.SPD, 2) .conditionalAttr(pokemon => pokemon.status.effect === StatusEffect.PARALYSIS, BattleStatMultiplierAbAttr, BattleStat.SPD, 2)
.conditionalAttr(pokemon => !!pokemon.status, BattleStatMultiplierAbAttr, BattleStat.SPD, 1.5), .conditionalAttr(pokemon => !!pokemon.status, BattleStatMultiplierAbAttr, BattleStat.SPD, 1.5),
new Ability(Abilities.NORMALIZE, "Normalize", "All the Pokémon's moves become Normal type. The power of those moves is boosted a little.", 4) new Ability(Abilities.NORMALIZE, "Normalize", "All the Pokémon's moves become Normal type. The power of those moves is boosted a little.", 4)
.attr(MoveTypeChangeAttr, Type.NORMAL, 1.2, (user, target, move) => move.id !== Moves.HIDDEN_POWER && move.id !== Moves.WEATHER_BALL && .attr(MoveTypeChangeAttr, Type.NORMAL, 1.2, (user, target, move) => move.id !== Moves.HIDDEN_POWER && move.id !== Moves.WEATHER_BALL &&
move.id !== Moves.NATURAL_GIFT && move.id !== Moves.JUDGMENT && move.id !== Moves.TECHNO_BLAST), move.id !== Moves.NATURAL_GIFT && move.id !== Moves.JUDGMENT && move.id !== Moves.TECHNO_BLAST),
new Ability(Abilities.SNIPER, "Sniper (N)", "Powers up moves if they become critical hits when attacking.", 4), new Ability(Abilities.SNIPER, "Sniper (N)", "Powers up moves if they become critical hits when attacking.", 4),
new Ability(Abilities.MAGIC_GUARD, "Magic Guard", "The Pokémon only takes damage from attacks.", 4) new Ability(Abilities.MAGIC_GUARD, "Magic Guard", "The Pokémon only takes damage from attacks.", 4)
.attr(BlockNonDirectDamageAbAttr), .attr(BlockNonDirectDamageAbAttr),
@ -2421,7 +2456,7 @@ export function initAbilities() {
new Ability(Abilities.SUPER_LUCK, "Super Luck (P)", "The Pokémon is so lucky that the critical-hit ratios of its moves are boosted.", 4) new Ability(Abilities.SUPER_LUCK, "Super Luck (P)", "The Pokémon is so lucky that the critical-hit ratios of its moves are boosted.", 4)
.attr(BonusCritAbAttr), .attr(BonusCritAbAttr),
new Ability(Abilities.AFTERMATH, "Aftermath", "Damages the attacker if it contacts the Pokémon with a finishing hit.", 4) new Ability(Abilities.AFTERMATH, "Aftermath", "Damages the attacker if it contacts the Pokémon with a finishing hit.", 4)
.attr(PostFaintContactDamageAbAttr,4) .attr(PostFaintContactDamageAbAttr, 4)
.bypassFaint(), .bypassFaint(),
new Ability(Abilities.ANTICIPATION, "Anticipation (N)", "The Pokémon can sense an opposing Pokémon's dangerous moves.", 4), new Ability(Abilities.ANTICIPATION, "Anticipation (N)", "The Pokémon can sense an opposing Pokémon's dangerous moves.", 4),
new Ability(Abilities.FOREWARN, "Forewarn (N)", "When it enters a battle, the Pokémon can tell one of the moves an opposing Pokémon has.", 4), new Ability(Abilities.FOREWARN, "Forewarn (N)", "When it enters a battle, the Pokémon can tell one of the moves an opposing Pokémon has.", 4),
@ -2431,7 +2466,7 @@ export function initAbilities() {
new Ability(Abilities.TINTED_LENS, "Tinted Lens", "The Pokémon can use \"not very effective\" moves to deal regular damage.", 4) new Ability(Abilities.TINTED_LENS, "Tinted Lens", "The Pokémon can use \"not very effective\" moves to deal regular damage.", 4)
.attr(MovePowerBoostAbAttr, (user, target, move) => target.getAttackTypeEffectiveness(move.type) <= 0.5, 2), .attr(MovePowerBoostAbAttr, (user, target, move) => target.getAttackTypeEffectiveness(move.type) <= 0.5, 2),
new Ability(Abilities.FILTER, "Filter", "Reduces the power of supereffective attacks taken.", 4) new Ability(Abilities.FILTER, "Filter", "Reduces the power of supereffective attacks taken.", 4)
.attr(ReceivedMoveDamageMultiplierAbAttr,(target, user, move) => target.getAttackTypeEffectiveness(move.type) >= 2, 0.75) .attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => target.getAttackTypeEffectiveness(move.type) >= 2, 0.75)
.ignorable(), .ignorable(),
new Ability(Abilities.SLOW_START, "Slow Start", "For five turns, the Pokémon's Attack and Speed stats are halved.", 4) new Ability(Abilities.SLOW_START, "Slow Start", "For five turns, the Pokémon's Attack and Speed stats are halved.", 4)
.attr(PostSummonAddBattlerTagAbAttr, BattlerTagType.SLOW_START, 5), .attr(PostSummonAddBattlerTagAbAttr, BattlerTagType.SLOW_START, 5),
@ -2444,7 +2479,7 @@ export function initAbilities() {
.attr(BlockWeatherDamageAttr, WeatherType.HAIL) .attr(BlockWeatherDamageAttr, WeatherType.HAIL)
.attr(PostWeatherLapseHealAbAttr, 1, WeatherType.HAIL, WeatherType.SNOW), .attr(PostWeatherLapseHealAbAttr, 1, WeatherType.HAIL, WeatherType.SNOW),
new Ability(Abilities.SOLID_ROCK, "Solid Rock", "Reduces the power of supereffective attacks taken.", 4) new Ability(Abilities.SOLID_ROCK, "Solid Rock", "Reduces the power of supereffective attacks taken.", 4)
.attr(ReceivedMoveDamageMultiplierAbAttr,(target, user, move) => target.getAttackTypeEffectiveness(move.type) >= 2, 0.75) .attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => target.getAttackTypeEffectiveness(move.type) >= 2, 0.75)
.ignorable(), .ignorable(),
new Ability(Abilities.SNOW_WARNING, "Snow Warning", "The Pokémon makes it snow when it enters a battle.", 4) new Ability(Abilities.SNOW_WARNING, "Snow Warning", "The Pokémon makes it snow when it enters a battle.", 4)
.attr(PostSummonWeatherChangeAbAttr, WeatherType.SNOW) .attr(PostSummonWeatherChangeAbAttr, WeatherType.SNOW)
@ -2491,7 +2526,7 @@ export function initAbilities() {
.attr(WeightMultiplierAbAttr, 0.5) .attr(WeightMultiplierAbAttr, 0.5)
.ignorable(), .ignorable(),
new Ability(Abilities.MULTISCALE, "Multiscale", "Reduces the amount of damage the Pokémon takes while its HP is full.", 5) new Ability(Abilities.MULTISCALE, "Multiscale", "Reduces the amount of damage the Pokémon takes while its HP is full.", 5)
.attr(ReceivedMoveDamageMultiplierAbAttr,(target, user, move) => target.getHpRatio() === 1, 0.5) .attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => target.getHpRatio() === 1, 0.5)
.ignorable(), .ignorable(),
new Ability(Abilities.TOXIC_BOOST, "Toxic Boost", "Powers up physical attacks when the Pokémon is poisoned.", 5) new Ability(Abilities.TOXIC_BOOST, "Toxic Boost", "Powers up physical attacks when the Pokémon is poisoned.", 5)
.attr(MovePowerBoostAbAttr, (user, target, move) => move.category === MoveCategory.PHYSICAL && (user.status?.effect === StatusEffect.POISON || user.status?.effect === StatusEffect.TOXIC), 1.5), .attr(MovePowerBoostAbAttr, (user, target, move) => move.category === MoveCategory.PHYSICAL && (user.status?.effect === StatusEffect.POISON || user.status?.effect === StatusEffect.TOXIC), 1.5),
@ -2510,7 +2545,7 @@ export function initAbilities() {
new Ability(Abilities.POISON_TOUCH, "Poison Touch", "May poison a target when the Pokémon makes contact.", 5) new Ability(Abilities.POISON_TOUCH, "Poison Touch", "May poison a target when the Pokémon makes contact.", 5)
.attr(PostAttackContactApplyStatusEffectAbAttr, 30, StatusEffect.POISON), .attr(PostAttackContactApplyStatusEffectAbAttr, 30, StatusEffect.POISON),
new Ability(Abilities.REGENERATOR, "Regenerator", "Restores a little HP when withdrawn from battle.", 5) new Ability(Abilities.REGENERATOR, "Regenerator", "Restores a little HP when withdrawn from battle.", 5)
.attr(PreSwitchOutHealAbAttr), .attr(PreSwitchOutHealAbAttr),
new Ability(Abilities.BIG_PECKS, "Big Pecks", "Protects the Pokémon from Defense-lowering effects.", 5) new Ability(Abilities.BIG_PECKS, "Big Pecks", "Protects the Pokémon from Defense-lowering effects.", 5)
.attr(ProtectStatAbAttr, BattleStat.DEF) .attr(ProtectStatAbAttr, BattleStat.DEF)
.ignorable(), .ignorable(),
@ -2669,7 +2704,10 @@ export function initAbilities() {
.attr(UncopiableAbilityAbAttr) .attr(UncopiableAbilityAbAttr)
.attr(UnswappableAbilityAbAttr) .attr(UnswappableAbilityAbAttr)
.attr(UnsuppressableAbilityAbAttr), .attr(UnsuppressableAbilityAbAttr),
new Ability(Abilities.DISGUISE, "Disguise (N)", "Once per battle, the shroud that covers the Pokémon can protect it from an attack.", 7) new Ability(Abilities.DISGUISE, "Disguise (T)", "Once per battle, the shroud that covers the Pokémon can protect it from an attack.", 7)
.attr(SetMovePowerToOneAbAttr, (target, user, move) => target.formIndex == 0)
.attr(PostTurnFormChangeAbAttr, pokemon => pokemon.battleData.hitCount === 0 ? 0 : 1)
.attr(PostDefendDisguiseAbAttr)
.attr(UncopiableAbilityAbAttr) .attr(UncopiableAbilityAbAttr)
.attr(UnswappableAbilityAbAttr) .attr(UnswappableAbilityAbAttr)
.attr(UnsuppressableAbilityAbAttr) .attr(UnsuppressableAbilityAbAttr)
@ -2744,9 +2782,9 @@ export function initAbilities() {
new Ability(Abilities.FULL_METAL_BODY, "Full Metal Body", "Prevents other Pokémon's moves or Abilities from lowering the Pokémon's stats.", 7) new Ability(Abilities.FULL_METAL_BODY, "Full Metal Body", "Prevents other Pokémon's moves or Abilities from lowering the Pokémon's stats.", 7)
.attr(ProtectStatAbAttr), .attr(ProtectStatAbAttr),
new Ability(Abilities.SHADOW_SHIELD, "Shadow Shield", "Reduces the amount of damage the Pokémon takes while its HP is full.", 7) new Ability(Abilities.SHADOW_SHIELD, "Shadow Shield", "Reduces the amount of damage the Pokémon takes while its HP is full.", 7)
.attr(ReceivedMoveDamageMultiplierAbAttr,(target, user, move) => target.getHpRatio() === 1, 0.5), .attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => target.getHpRatio() === 1, 0.5),
new Ability(Abilities.PRISM_ARMOR, "Prism Armor", "Reduces the power of supereffective attacks taken.", 7) new Ability(Abilities.PRISM_ARMOR, "Prism Armor", "Reduces the power of supereffective attacks taken.", 7)
.attr(ReceivedMoveDamageMultiplierAbAttr,(target, user, move) => target.getAttackTypeEffectiveness(move.type) >= 2, 0.75), .attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => target.getAttackTypeEffectiveness(move.type) >= 2, 0.75),
new Ability(Abilities.NEUROFORCE, "Neuroforce", "Powers up moves that are super effective.", 7) new Ability(Abilities.NEUROFORCE, "Neuroforce", "Powers up moves that are super effective.", 7)
.attr(MovePowerBoostAbAttr, (user, target, move) => target.getAttackTypeEffectiveness(move.type) >= 2, 1.25), .attr(MovePowerBoostAbAttr, (user, target, move) => target.getAttackTypeEffectiveness(move.type) >= 2, 1.25),
new Ability(Abilities.INTREPID_SWORD, "Intrepid Sword", "Boosts the Pokémon's Attack stat when the Pokémon enters a battle.", 8) new Ability(Abilities.INTREPID_SWORD, "Intrepid Sword", "Boosts the Pokémon's Attack stat when the Pokémon enters a battle.", 8)
@ -2899,7 +2937,7 @@ export function initAbilities() {
new Ability(Abilities.COSTAR, "Costar (N)", "When the Pokémon enters a battle, it copies an ally's stat changes.", 9), new Ability(Abilities.COSTAR, "Costar (N)", "When the Pokémon enters a battle, it copies an ally's stat changes.", 9),
new Ability(Abilities.TOXIC_DEBRIS, "Toxic Debris (N)", "Scatters poison spikes at the feet of the opposing team when the Pokémon takes damage from physical moves.", 9), new Ability(Abilities.TOXIC_DEBRIS, "Toxic Debris (N)", "Scatters poison spikes at the feet of the opposing team when the Pokémon takes damage from physical moves.", 9),
new Ability(Abilities.ARMOR_TAIL, "Armor Tail", "The mysterious tail covering the Pokémon's head makes opponents unable to use priority moves against the Pokémon or its allies.", 9) new Ability(Abilities.ARMOR_TAIL, "Armor Tail", "The mysterious tail covering the Pokémon's head makes opponents unable to use priority moves against the Pokémon or its allies.", 9)
.attr(FieldPriorityMoveImmunityAbAttr) .attr(FieldPriorityMoveImmunityAbAttr)
.ignorable(), .ignorable(),
new Ability(Abilities.EARTH_EATER, "Earth Eater", "If hit by a Ground-type move, the Pokémon has its HP restored instead of taking damage.", 9) new Ability(Abilities.EARTH_EATER, "Earth Eater", "If hit by a Ground-type move, the Pokémon has its HP restored instead of taking damage.", 9)
.attr(TypeImmunityHealAbAttr, Type.GROUND) .attr(TypeImmunityHealAbAttr, Type.GROUND)

View File

@ -565,6 +565,10 @@ export const pokemonFormChanges: PokemonFormChanges = {
new SpeciesFormChange(Species.MINIOR, 'violet-meteor', 'violet', new SpeciesFormChangeManualTrigger(), true), new SpeciesFormChange(Species.MINIOR, 'violet-meteor', 'violet', new SpeciesFormChangeManualTrigger(), true),
new SpeciesFormChange(Species.MINIOR, 'violet', 'violet-meteor', new SpeciesFormChangeManualTrigger(), true) new SpeciesFormChange(Species.MINIOR, 'violet', 'violet-meteor', new SpeciesFormChangeManualTrigger(), true)
], ],
[Species.MIMIKYU]: [
new SpeciesFormChange(Species.MIMIKYU, 'disguised', 'busted', new SpeciesFormChangeManualTrigger(), true),
new SpeciesFormChange(Species.MIMIKYU, 'busted', 'disquised', new SpeciesFormChangeManualTrigger(), true)
],
[Species.NECROZMA]: [ [Species.NECROZMA]: [
new SpeciesFormChange(Species.NECROZMA, '', 'dawn-wings', new SpeciesFormChangeItemTrigger(FormChangeItem.N_LUNARIZER)), new SpeciesFormChange(Species.NECROZMA, '', 'dawn-wings', new SpeciesFormChangeItemTrigger(FormChangeItem.N_LUNARIZER)),
new SpeciesFormChange(Species.NECROZMA, '', 'dusk-mane', new SpeciesFormChangeItemTrigger(FormChangeItem.N_SOLARIZER)) new SpeciesFormChange(Species.NECROZMA, '', 'dusk-mane', new SpeciesFormChangeItemTrigger(FormChangeItem.N_SOLARIZER))