Implement Aftermath (#71)

* Implement Aftermath

* Clean up unused imports & Consistency

* Minor changes

---------

Co-authored-by: Flashfyre <flashfireex@gmail.com>
pull/73/head
kd8lvt 2024-04-09 18:05:15 -04:00 committed by GitHub
parent 8ec7333b1e
commit 3e5a0d5c9c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 49 additions and 4 deletions

View File

@ -1558,6 +1558,35 @@ export class PostBattleLootAbAttr extends PostBattleAbAttr {
} }
} }
export class PostFaintAbAttr extends AbAttr {
applyPostFaint(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
return false;
}
}
export class PostFaintContactDamageAbAttr extends PostFaintAbAttr {
private damageRatio: integer;
constructor(damageRatio: integer) {
super();
this.damageRatio = damageRatio;
}
applyPostFaint(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
if (move.getMove().checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) {
attacker.damageAndUpdate(Math.ceil(attacker.getMaxHp() * (1 / this.damageRatio)), HitResult.OTHER);
return true;
}
return false;
}
getTriggerMessage(pokemon: Pokemon, ...args: any[]): string {
return getPokemonMessage(pokemon, `'s ${pokemon.getAbility().name} hurt\nits attacker!`);
}
}
export class RedirectMoveAbAttr extends AbAttr { export class RedirectMoveAbAttr extends AbAttr {
apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean { apply(pokemon: Pokemon, cancelled: Utils.BooleanHolder, args: any[]): boolean {
if (this.canRedirect(args[0] as Moves)) { if (this.canRedirect(args[0] as Moves)) {
@ -1860,6 +1889,11 @@ export function applyPostBattleAbAttrs(attrType: { new(...args: any[]): PostBatt
return applyAbAttrsInternal<PostBattleAbAttr>(attrType, pokemon, attr => attr.applyPostBattle(pokemon, args), args); return applyAbAttrsInternal<PostBattleAbAttr>(attrType, pokemon, attr => attr.applyPostBattle(pokemon, args), args);
} }
export function applyPostFaintAbAttrs(attrType: { new(...args: any[]): PostFaintAbAttr },
pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, ...args: any[]): Promise<void> {
return applyAbAttrsInternal<PostFaintAbAttr>(attrType, pokemon, attr => attr.applyPostFaint(pokemon, attacker, move, hitResult, args), args);
}
function canApplyAttr(pokemon: Pokemon, attr: AbAttr): boolean { function canApplyAttr(pokemon: Pokemon, attr: AbAttr): boolean {
const condition = attr.getCondition(); const condition = attr.getCondition();
return !condition || condition(pokemon); return !condition || condition(pokemon);
@ -2250,7 +2284,8 @@ export function initAbilities() {
.attr(ArenaTrapAbAttr), .attr(ArenaTrapAbAttr),
new Ability(Abilities.ROUGH_SKIN, "Rough Skin", "This Pokémon inflicts damage with its rough skin to the attacker on contact.", 3) new Ability(Abilities.ROUGH_SKIN, "Rough Skin", "This Pokémon inflicts damage with its rough skin to the attacker on contact.", 3)
.attr(PostDefendContactDamageAbAttr, 8) .attr(PostDefendContactDamageAbAttr, 8)
.ignorable(), .ignorable()
.passive(),
new Ability(Abilities.WONDER_GUARD, "Wonder Guard", "Its mysterious power only lets supereffective moves hit the Pokémon.", 3) new Ability(Abilities.WONDER_GUARD, "Wonder Guard", "Its mysterious power only lets supereffective moves hit the Pokémon.", 3)
.attr(NonSuperEffectiveImmunityAbAttr) .attr(NonSuperEffectiveImmunityAbAttr)
.attr(ProtectAbilityAbAttr) .attr(ProtectAbilityAbAttr)
@ -2439,7 +2474,9 @@ export function initAbilities() {
.attr(PostSummonMessageAbAttr, (pokemon: Pokemon) => getPokemonMessage(pokemon, ' breaks the mold!')) .attr(PostSummonMessageAbAttr, (pokemon: Pokemon) => getPokemonMessage(pokemon, ' breaks the mold!'))
.attr(MoveAbilityBypassAbAttr), .attr(MoveAbilityBypassAbAttr),
new Ability(Abilities.SUPER_LUCK, "Super Luck (N)", "The Pokémon is so lucky that the critical-hit ratios of its moves are boosted.", 4), new Ability(Abilities.SUPER_LUCK, "Super Luck (N)", "The Pokémon is so lucky that the critical-hit ratios of its moves are boosted.", 4),
new Ability(Abilities.AFTERMATH, "Aftermath (N)", "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)
.passive(),
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),
new Ability(Abilities.UNAWARE, "Unaware", "When attacking, the Pokémon ignores the target Pokémon's stat changes.", 4) new Ability(Abilities.UNAWARE, "Unaware", "When attacking, the Pokémon ignores the target Pokémon's stat changes.", 4)
@ -2558,7 +2595,8 @@ export function initAbilities() {
.attr(BlockWeatherDamageAttr, WeatherType.SANDSTORM) .attr(BlockWeatherDamageAttr, WeatherType.SANDSTORM)
.condition(getWeatherCondition(WeatherType.SANDSTORM)), .condition(getWeatherCondition(WeatherType.SANDSTORM)),
new Ability(Abilities.IRON_BARBS, "Iron Barbs", "Inflicts damage on the attacker upon contact with iron barbs.", 5) new Ability(Abilities.IRON_BARBS, "Iron Barbs", "Inflicts damage on the attacker upon contact with iron barbs.", 5)
.attr(PostDefendContactDamageAbAttr, 8), .attr(PostDefendContactDamageAbAttr, 8)
.passive(),
new Ability(Abilities.ZEN_MODE, "Zen Mode", "Changes the Pokémon's shape when HP is half or less.", 5) new Ability(Abilities.ZEN_MODE, "Zen Mode", "Changes the Pokémon's shape when HP is half or less.", 5)
.attr(PostBattleInitFormChangeAbAttr, p => p.getHpRatio() >= 0.5 ? 0 : 1) .attr(PostBattleInitFormChangeAbAttr, p => p.getHpRatio() >= 0.5 ? 0 : 1)
.attr(PostSummonFormChangeAbAttr, p => p.getHpRatio() >= 0.5 ? 0 : 1) .attr(PostSummonFormChangeAbAttr, p => p.getHpRatio() >= 0.5 ? 0 : 1)

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 { Abilities, CheckTrappedAbAttr, MoveAbilityBypassAbAttr, IgnoreOpponentStatChangesAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, 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 } from "./data/ability"; import { Abilities, CheckTrappedAbAttr, MoveAbilityBypassAbAttr, IgnoreOpponentStatChangesAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, 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 } 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";
@ -2876,6 +2876,13 @@ export class FaintPhase extends PokemonPhase {
this.scene.queueMessage(getPokemonMessage(pokemon, ' fainted!'), null, true); this.scene.queueMessage(getPokemonMessage(pokemon, ' fainted!'), null, true);
if (pokemon.getAbility().hasAttr(PostFaintAbAttr)) {
if (pokemon.turnData?.attacksReceived?.length) {
const lastAttack = pokemon.turnData.attacksReceived[0];
applyPostFaintAbAttrs(PostFaintAbAttr,pokemon, this.scene.getPokemonById(lastAttack.sourceId), new PokemonMove(lastAttack.move), lastAttack.result);
}
}
const alivePlayField = this.scene.getField(true); const alivePlayField = this.scene.getField(true);
alivePlayField.forEach(p => applyPostKnockOutAbAttrs(PostKnockOutAbAttr, p)); alivePlayField.forEach(p => applyPostKnockOutAbAttrs(PostKnockOutAbAttr, p));
if (pokemon.turnData?.attacksReceived?.length) { if (pokemon.turnData?.attacksReceived?.length) {