Implement Revival Blessing

pull/343/head
arColm 2024-04-29 11:45:01 -04:00
parent 28c75e4377
commit 7e2095bae0
4 changed files with 99 additions and 5 deletions

View File

@ -1,6 +1,6 @@
import { Moves } from "./enums/moves"; import { Moves } from "./enums/moves";
import { ChargeAnim, MoveChargeAnim, initMoveAnim, loadMoveAnimAssets } from "./battle-anims"; import { ChargeAnim, MoveChargeAnim, initMoveAnim, loadMoveAnimAssets } from "./battle-anims";
import { BattleEndPhase, MovePhase, NewBattlePhase, PartyStatusCurePhase, PokemonHealPhase, StatChangePhase, SwitchSummonPhase } from "../phases"; import { BattleEndPhase, MovePhase, NewBattlePhase, PartyStatusCurePhase, PokemonHealPhase, StatChangePhase, SwitchSummonPhase, ToggleDoublePositionPhase } from "../phases";
import { BattleStat, getBattleStatName } from "./battle-stat"; import { BattleStat, getBattleStatName } from "./battle-stat";
import { EncoreTag } from "./battler-tags"; import { EncoreTag } from "./battler-tags";
import { BattlerTagType } from "./enums/battler-tag-type"; import { BattlerTagType } from "./enums/battler-tag-type";
@ -3132,6 +3132,52 @@ export class RemoveScreensAttr extends MoveEffectAttr {
} }
} }
export class RevivalBlessingAttr extends MoveEffectAttr {
constructor(user?: boolean) {
super(true);
}
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): Promise<boolean> {
return new Promise(resolve => {
if(user instanceof PlayerPokemon
&& user.scene.getParty().findIndex(p => p.isFainted())>-1) {
(user as PlayerPokemon).revivalBlessing().then(() => {
resolve(true)
});
} else if(user instanceof EnemyPokemon
&& user.hasTrainer()
&& user.scene.getEnemyParty().findIndex(p => p.isFainted() && !p.isBoss()) > -1) {
const faintedPokemon = user.scene.getEnemyParty().filter(p => p.isFainted() && !p.isBoss());
const pokemon = faintedPokemon[user.randSeedInt(faintedPokemon.length)];
const slotIndex = user.scene.getEnemyParty().findIndex(p => pokemon.id === p.id);
pokemon.resetStatus();
pokemon.heal(Math.min(Math.max(Math.ceil(Math.floor(0.5 * pokemon.getMaxHp())), 1), pokemon.getMaxHp()));
user.scene.queueMessage(`${pokemon.name} was revived!`,0,true);
if(user.scene.currentBattle.double && user.scene.getEnemyParty().length > 1) {
const allyPokemon = user.getAlly();
if(slotIndex<=1) {
user.scene.unshiftPhase(new SwitchSummonPhase(user.scene, pokemon.getFieldIndex(), slotIndex, false, false, false));
} else if(allyPokemon.isFainted()){
user.scene.unshiftPhase(new SwitchSummonPhase(user.scene, allyPokemon.getFieldIndex(), slotIndex, false, false,false));
}
}
resolve(true);
} else {
user.scene.queueMessage(`But it failed!`);
resolve(false);
}
})
}
getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer {
if(user.hasTrainer() && user.scene.getEnemyParty().findIndex(p => p.isFainted() && !p.isBoss()) > -1)
return 20;
return -20;
}
}
export class ForceSwitchOutAttr extends MoveEffectAttr { export class ForceSwitchOutAttr extends MoveEffectAttr {
private user: boolean; private user: boolean;
private batonPass: boolean; private batonPass: boolean;
@ -6650,7 +6696,8 @@ export function initMoves() {
.partial(), .partial(),
new StatusMove(Moves.REVIVAL_BLESSING, Type.NORMAL, -1, 1, -1, 0, 9) new StatusMove(Moves.REVIVAL_BLESSING, Type.NORMAL, -1, 1, -1, 0, 9)
.triageMove() .triageMove()
.unimplemented(), .attr(RevivalBlessingAttr)
.target(MoveTarget.USER),
new AttackMove(Moves.SALT_CURE, Type.ROCK, MoveCategory.PHYSICAL, 40, 100, 15, -1, 0, 9) new AttackMove(Moves.SALT_CURE, Type.ROCK, MoveCategory.PHYSICAL, 40, 100, 15, -1, 0, 9)
.attr(AddBattlerTagAttr, BattlerTagType.SALT_CURED) .attr(AddBattlerTagAttr, BattlerTagType.SALT_CURED)
.makesContact(false), .makesContact(false),

View File

@ -17,7 +17,7 @@ import { initMoveAnim, loadMoveAnimAssets } from '../data/battle-anims';
import { Status, StatusEffect, getRandomStatus } from '../data/status-effect'; import { Status, StatusEffect, getRandomStatus } from '../data/status-effect';
import { pokemonEvolutions, pokemonPrevolutions, SpeciesFormEvolution, SpeciesEvolutionCondition, FusionSpeciesFormEvolution } from '../data/pokemon-evolutions'; import { pokemonEvolutions, pokemonPrevolutions, SpeciesFormEvolution, SpeciesEvolutionCondition, FusionSpeciesFormEvolution } from '../data/pokemon-evolutions';
import { reverseCompatibleTms, tmSpecies, tmPoolTiers } from '../data/tms'; import { reverseCompatibleTms, tmSpecies, tmPoolTiers } from '../data/tms';
import { DamagePhase, FaintPhase, LearnMovePhase, ObtainStatusEffectPhase, StatChangePhase, SwitchSummonPhase } from '../phases'; import { DamagePhase, FaintPhase, LearnMovePhase, ObtainStatusEffectPhase, StatChangePhase, SwitchPhase, SwitchSummonPhase, ToggleDoublePositionPhase } from '../phases';
import { BattleStat } from '../data/battle-stat'; import { BattleStat } from '../data/battle-stat';
import { BattlerTag, BattlerTagLapseType, EncoreTag, HelpingHandTag, HighestStatBoostTag, TypeBoostTag, getBattlerTag } from '../data/battler-tags'; import { BattlerTag, BattlerTagLapseType, EncoreTag, HelpingHandTag, HighestStatBoostTag, TypeBoostTag, getBattlerTag } from '../data/battler-tags';
import { BattlerTagType } from "../data/enums/battler-tag-type"; import { BattlerTagType } from "../data/enums/battler-tag-type";
@ -2566,6 +2566,38 @@ export class PlayerPokemon extends Pokemon {
sd.friendship = Math.max((sd.friendship || 0) + starterAmount.value, 0); sd.friendship = Math.max((sd.friendship || 0) + starterAmount.value, 0);
} }
} }
revivalBlessing(): Promise<void> {
return new Promise(resolve => {
this.scene.ui.setMode(Mode.PARTY, PartyUiMode.REVIVAL_BLESSING, this.getFieldIndex(), (slotIndex:integer, option: PartyOption) => {
if(slotIndex >= 0 && slotIndex<6) {
const pokemon = this.scene.getParty()[slotIndex];
if(!pokemon || !pokemon.isFainted())
resolve();
pokemon.resetTurnData();
pokemon.resetStatus();
pokemon.heal(Math.min(Math.max(Math.ceil(Math.floor(0.5 * pokemon.getMaxHp())), 1), pokemon.getMaxHp()));
this.scene.queueMessage(`${pokemon.name} was revived!`,0,true);
if(this.scene.currentBattle.double && this.scene.getParty().length > 1) {
const allyPokemon = this.getAlly();
if(slotIndex<=1) {
// Revived ally pokemon
this.scene.unshiftPhase(new SwitchSummonPhase(this.scene, pokemon.getFieldIndex(), slotIndex, false, false, true));
this.scene.unshiftPhase(new ToggleDoublePositionPhase(this.scene, true));
} else if(allyPokemon.isFainted()) {
// Revived party pokemon, and ally pokemon is fainted
this.scene.unshiftPhase(new SwitchSummonPhase(this.scene, allyPokemon.getFieldIndex(), slotIndex, false, false, true));
this.scene.unshiftPhase(new ToggleDoublePositionPhase(this.scene, true));
}
}
}
this.scene.ui.setMode(Mode.MESSAGE).then(() => resolve());
}, PartyUiHandler.FilterFainted)
})
}
getPossibleEvolution(evolution: SpeciesFormEvolution): Promise<Pokemon> { getPossibleEvolution(evolution: SpeciesFormEvolution): Promise<Pokemon> {
return new Promise(resolve => { return new Promise(resolve => {

View File

@ -3701,6 +3701,10 @@ export class SwitchPhase extends BattlePhase {
if (this.isModal && !this.scene.getParty().filter(p => !p.isFainted() && !p.isActive(true)).length) if (this.isModal && !this.scene.getParty().filter(p => !p.isFainted() && !p.isActive(true)).length)
return super.end(); return super.end();
// Check if there is any space still in field
if (this.isModal && this.scene.getPlayerField().filter(p => !p.isFainted() && p.isActive(true)).length >= this.scene.currentBattle.getBattlerCount())
return super.end();
// Override field index to 0 in case of double battle where 2/3 remaining party members fainted at once // Override field index to 0 in case of double battle where 2/3 remaining party members fainted at once
const fieldIndex = this.scene.currentBattle.getBattlerCount() === 1 || this.scene.getParty().filter(p => !p.isFainted()).length > 1 ? this.fieldIndex : 0; const fieldIndex = this.scene.currentBattle.getBattlerCount() === 1 || this.scene.getParty().filter(p => !p.isFainted()).length > 1 ? this.fieldIndex : 0;

View File

@ -24,6 +24,7 @@ export enum PartyUiMode {
SWITCH, SWITCH,
FAINT_SWITCH, FAINT_SWITCH,
POST_BATTLE_SWITCH, POST_BATTLE_SWITCH,
REVIVAL_BLESSING,
MODIFIER, MODIFIER,
MOVE_MODIFIER, MOVE_MODIFIER,
TM_MODIFIER, TM_MODIFIER,
@ -37,6 +38,7 @@ export enum PartyOption {
CANCEL = -1, CANCEL = -1,
SEND_OUT, SEND_OUT,
PASS_BATON, PASS_BATON,
REVIVE,
APPLY, APPLY,
TEACH, TEACH,
TRANSFER, TRANSFER,
@ -103,6 +105,12 @@ export default class PartyUiHandler extends MessageUiHandler {
return null; return null;
}; };
public static FilterFainted = (pokemon: PlayerPokemon) => {
if(!pokemon.isFainted())
return `${pokemon.name} still has energy\nto battle!`;
return null;
}
private static FilterAllMoves = (_pokemonMove: PokemonMove) => null; private static FilterAllMoves = (_pokemonMove: PokemonMove) => null;
public static FilterItemMaxStacks = (pokemon: PlayerPokemon, modifier: PokemonHeldItemModifier) => { public static FilterItemMaxStacks = (pokemon: PlayerPokemon, modifier: PokemonHeldItemModifier) => {
@ -361,7 +369,7 @@ export default class PartyUiHandler extends MessageUiHandler {
if (this.cursor < 6) { if (this.cursor < 6) {
this.showOptions(); this.showOptions();
ui.playSelect(); ui.playSelect();
} else if (this.partyUiMode === PartyUiMode.FAINT_SWITCH) } else if (this.partyUiMode === PartyUiMode.FAINT_SWITCH || this.partyUiMode === PartyUiMode.REVIVAL_BLESSING)
ui.playError(); ui.playError();
else else
return this.processInput(Button.CANCEL); return this.processInput(Button.CANCEL);
@ -370,7 +378,7 @@ export default class PartyUiHandler extends MessageUiHandler {
if ((this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER || this.partyUiMode === PartyUiMode.SPLICE) && this.transferMode) { if ((this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER || this.partyUiMode === PartyUiMode.SPLICE) && this.transferMode) {
this.clearTransfer(); this.clearTransfer();
ui.playSelect(); ui.playSelect();
} else if (this.partyUiMode !== PartyUiMode.FAINT_SWITCH) { } else if (this.partyUiMode !== PartyUiMode.FAINT_SWITCH && this.partyUiMode !== PartyUiMode.REVIVAL_BLESSING) {
if (this.selectCallback) { if (this.selectCallback) {
const selectCallback = this.selectCallback; const selectCallback = this.selectCallback;
this.selectCallback = null; this.selectCallback = null;
@ -580,6 +588,9 @@ export default class PartyUiHandler extends MessageUiHandler {
this.options.push(PartyOption.FORM_CHANGE_ITEM + i); this.options.push(PartyOption.FORM_CHANGE_ITEM + i);
} }
break; break;
case PartyUiMode.REVIVAL_BLESSING:
this.options.push(PartyOption.REVIVE);
break;
case PartyUiMode.MODIFIER: case PartyUiMode.MODIFIER:
this.options.push(PartyOption.APPLY); this.options.push(PartyOption.APPLY);
break; break;