Implement encore move
parent
23c2b4fc63
commit
85866169ac
|
@ -18,7 +18,7 @@ import { BattleStat, getBattleStatLevelChangeDescription, getBattleStatName } fr
|
||||||
import { Biome, biomeLinks } from "./data/biome";
|
import { Biome, biomeLinks } from "./data/biome";
|
||||||
import { FusePokemonModifierType, ModifierPoolType, ModifierTier, ModifierType, ModifierTypeFunc, ModifierTypeOption, PokemonModifierType, PokemonMoveModifierType, RememberMoveModifierType, TmModifierType, getEnemyBuffModifierForWave, getModifierType, getPlayerModifierTypeOptionsForWave, modifierTypes, regenerateModifierPoolThresholds } from "./modifier/modifier-type";
|
import { FusePokemonModifierType, ModifierPoolType, ModifierTier, ModifierType, ModifierTypeFunc, ModifierTypeOption, PokemonModifierType, PokemonMoveModifierType, RememberMoveModifierType, TmModifierType, getEnemyBuffModifierForWave, getModifierType, getPlayerModifierTypeOptionsForWave, modifierTypes, regenerateModifierPoolThresholds } from "./modifier/modifier-type";
|
||||||
import SoundFade from "phaser3-rex-plugins/plugins/soundfade";
|
import SoundFade from "phaser3-rex-plugins/plugins/soundfade";
|
||||||
import { BattlerTagLapseType, BattlerTagType, HideSpriteTag as HiddenTag, TrappedTag } from "./data/battler-tag";
|
import { BattlerTagLapseType, BattlerTagType, EncoreTag, HideSpriteTag as HiddenTag, TrappedTag } from "./data/battler-tag";
|
||||||
import { getPokemonMessage } from "./messages";
|
import { getPokemonMessage } from "./messages";
|
||||||
import { Starter } from "./ui/starter-select-ui-handler";
|
import { Starter } from "./ui/starter-select-ui-handler";
|
||||||
import { Gender } from "./data/gender";
|
import { Gender } from "./data/gender";
|
||||||
|
@ -1002,8 +1002,7 @@ export class CommandPhase extends FieldPhase {
|
||||||
let useStruggle = false;
|
let useStruggle = false;
|
||||||
if (cursor === -1 || playerPokemon.trySelectMove(cursor, args[0] as boolean) || (useStruggle = cursor > -1 && !playerPokemon.getMoveset().filter(m => m.isUsable(playerPokemon)).length)) {
|
if (cursor === -1 || playerPokemon.trySelectMove(cursor, args[0] as boolean) || (useStruggle = cursor > -1 && !playerPokemon.getMoveset().filter(m => m.isUsable(playerPokemon)).length)) {
|
||||||
const moveId = !useStruggle ? playerPokemon.getMoveset()[cursor].moveId : Moves.STRUGGLE;
|
const moveId = !useStruggle ? playerPokemon.getMoveset()[cursor].moveId : Moves.STRUGGLE;
|
||||||
const turnCommand: TurnCommand = { command: Command.FIGHT, cursor: cursor,
|
const turnCommand: TurnCommand = { command: Command.FIGHT, cursor: cursor, move: cursor > -1 ? { move: moveId, targets: [] } : null, args: args };
|
||||||
move: cursor > -1 ? { move: moveId, targets: [] } : null, args: args };
|
|
||||||
const moveTargets: MoveTargetSet = args.length < 3 ? getMoveTargets(playerPokemon, cursor > -1 ? moveId : Moves.NONE) : args[2];
|
const moveTargets: MoveTargetSet = args.length < 3 ? getMoveTargets(playerPokemon, cursor > -1 ? moveId : Moves.NONE) : args[2];
|
||||||
console.log(moveTargets, playerPokemon.name);
|
console.log(moveTargets, playerPokemon.name);
|
||||||
if (moveTargets.targets.length <= 1 || moveTargets.multiple)
|
if (moveTargets.targets.length <= 1 || moveTargets.multiple)
|
||||||
|
@ -1116,6 +1115,24 @@ export class CommandPhase extends FieldPhase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkFightOverride(): boolean {
|
||||||
|
const pokemon = this.getPokemon();
|
||||||
|
|
||||||
|
const encoreTag = pokemon.getTag(EncoreTag) as EncoreTag;
|
||||||
|
|
||||||
|
if (!encoreTag)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const moveIndex = pokemon.getMoveset().findIndex(m => m.moveId === encoreTag.moveId);
|
||||||
|
|
||||||
|
if (moveIndex === -1 || !pokemon.getMoveset()[moveIndex].isUsable(pokemon))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
this.handleCommand(Command.FIGHT, moveIndex, false);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
getFieldIndex(): integer {
|
getFieldIndex(): integer {
|
||||||
return this.fieldIndex;
|
return this.fieldIndex;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import Pokemon, { MoveResult } from "../pokemon";
|
||||||
import { Stat } from "./pokemon-stat";
|
import { Stat } from "./pokemon-stat";
|
||||||
import { StatusEffect } from "./status-effect";
|
import { StatusEffect } from "./status-effect";
|
||||||
import * as Utils from "../utils";
|
import * as Utils from "../utils";
|
||||||
import { Moves, allMoves } from "./move";
|
import { ChargeAttr, Moves, allMoves } from "./move";
|
||||||
import { Type } from "./type";
|
import { Type } from "./type";
|
||||||
import { Abilities } from "./ability";
|
import { Abilities } from "./ability";
|
||||||
|
|
||||||
|
@ -289,7 +289,7 @@ export class SeedTag extends BattlerTag {
|
||||||
const damage = Math.max(Math.floor(pokemon.getMaxHp() / 8), 1);
|
const damage = Math.max(Math.floor(pokemon.getMaxHp() / 8), 1);
|
||||||
pokemon.scene.unshiftPhase(new DamagePhase(pokemon.scene, pokemon.getBattlerIndex()));
|
pokemon.scene.unshiftPhase(new DamagePhase(pokemon.scene, pokemon.getBattlerIndex()));
|
||||||
pokemon.damage(damage);
|
pokemon.damage(damage);
|
||||||
pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, source.getBattlerIndex(), damage, getPokemonMessage(pokemon, '\'s health is\nsapped by LEECH SEED!'), false, true));
|
pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, source.getBattlerIndex(), damage, getPokemonMessage(pokemon, '\'s health is\nsapped by Leech Seed!'), false, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -308,20 +308,20 @@ export class NightmareTag extends BattlerTag {
|
||||||
onAdd(pokemon: Pokemon): void {
|
onAdd(pokemon: Pokemon): void {
|
||||||
super.onAdd(pokemon);
|
super.onAdd(pokemon);
|
||||||
|
|
||||||
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' began\nhaving a NIGHTMARE!'));
|
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' began\nhaving a Nightmare!'));
|
||||||
}
|
}
|
||||||
|
|
||||||
onOverlap(pokemon: Pokemon): void {
|
onOverlap(pokemon: Pokemon): void {
|
||||||
super.onOverlap(pokemon);
|
super.onOverlap(pokemon);
|
||||||
|
|
||||||
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' is\nalready locked in a NIGHTMARE!'));
|
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' is\nalready locked in a Nightmare!'));
|
||||||
}
|
}
|
||||||
|
|
||||||
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
|
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
|
||||||
const ret = lapseType !== BattlerTagLapseType.CUSTOM || super.lapse(pokemon, lapseType);
|
const ret = lapseType !== BattlerTagLapseType.CUSTOM || super.lapse(pokemon, lapseType);
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' is locked\nin a NIGHTMARE!'));
|
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' is locked\nin a Nightmare!'));
|
||||||
pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, pokemon.getBattlerIndex(), undefined, CommonAnim.CURSE)); // TODO: Update animation type
|
pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, pokemon.getBattlerIndex(), undefined, CommonAnim.CURSE)); // TODO: Update animation type
|
||||||
|
|
||||||
const damage = Math.ceil(pokemon.getMaxHp() / 4);
|
const damage = Math.ceil(pokemon.getMaxHp() / 4);
|
||||||
|
@ -349,6 +349,59 @@ export class FrenzyTag extends BattlerTag {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class EncoreTag extends BattlerTag {
|
||||||
|
public moveId: Moves;
|
||||||
|
|
||||||
|
constructor(sourceMove: Moves, sourceId: integer) {
|
||||||
|
super(BattlerTagType.ENCORE, BattlerTagLapseType.AFTER_MOVE, 3, sourceMove, sourceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
canAdd(pokemon: Pokemon): boolean {
|
||||||
|
const lastMoves = pokemon.getLastXMoves(1);
|
||||||
|
if (!lastMoves.length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const repeatableMove = lastMoves[0];
|
||||||
|
|
||||||
|
if (!repeatableMove.move || repeatableMove.virtual)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch (repeatableMove.move) {
|
||||||
|
case Moves.MIMIC:
|
||||||
|
case Moves.MIRROR_MOVE:
|
||||||
|
case Moves.TRANSFORM:
|
||||||
|
case Moves.STRUGGLE:
|
||||||
|
case Moves.SKETCH:
|
||||||
|
case Moves.SLEEP_TALK:
|
||||||
|
case Moves.ENCORE:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allMoves[repeatableMove.move].getAttrs(ChargeAttr).length && repeatableMove.result === MoveResult.OTHER)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
this.moveId = repeatableMove.move;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
onAdd(pokemon: Pokemon): void {
|
||||||
|
super.onRemove(pokemon);
|
||||||
|
|
||||||
|
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' got\nan Encore!'));
|
||||||
|
|
||||||
|
const turnCommand = pokemon.scene.currentBattle.turnCommands[pokemon.getFieldIndex()];
|
||||||
|
if (turnCommand)
|
||||||
|
turnCommand.move = { move: this.moveId, targets: pokemon.getLastXMoves(1)[0].targets };
|
||||||
|
}
|
||||||
|
|
||||||
|
onRemove(pokemon: Pokemon): void {
|
||||||
|
super.onRemove(pokemon);
|
||||||
|
|
||||||
|
pokemon.scene.queueMessage(getPokemonMessage(pokemon, '\'s Encore\nended!'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class IngrainTag extends TrappedTag {
|
export class IngrainTag extends TrappedTag {
|
||||||
constructor(sourceId: integer) {
|
constructor(sourceId: integer) {
|
||||||
super(BattlerTagType.INGRAIN, BattlerTagLapseType.TURN_END, 1, Moves.INGRAIN, sourceId);
|
super(BattlerTagType.INGRAIN, BattlerTagLapseType.TURN_END, 1, Moves.INGRAIN, sourceId);
|
||||||
|
@ -465,7 +518,7 @@ export class WrapTag extends DamagingTrapTag {
|
||||||
}
|
}
|
||||||
|
|
||||||
getTrapMessage(pokemon: Pokemon): string {
|
getTrapMessage(pokemon: Pokemon): string {
|
||||||
return getPokemonMessage(pokemon, ` was WRAPPED\nby ${pokemon.scene.getPokemonById(this.sourceId).name}!`);
|
return getPokemonMessage(pokemon, ` was Wrapped\nby ${pokemon.scene.getPokemonById(this.sourceId).name}!`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -497,7 +550,7 @@ export class ClampTag extends DamagingTrapTag {
|
||||||
}
|
}
|
||||||
|
|
||||||
getTrapMessage(pokemon: Pokemon): string {
|
getTrapMessage(pokemon: Pokemon): string {
|
||||||
return getPokemonMessage(pokemon.scene.getPokemonById(this.sourceId), ` CLAMPED\n${pokemon.name}!`);
|
return getPokemonMessage(pokemon.scene.getPokemonById(this.sourceId), ` Clamped\n${pokemon.name}!`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -642,6 +695,8 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourc
|
||||||
return new NightmareTag();
|
return new NightmareTag();
|
||||||
case BattlerTagType.FRENZY:
|
case BattlerTagType.FRENZY:
|
||||||
return new FrenzyTag(sourceMove, sourceId);
|
return new FrenzyTag(sourceMove, sourceId);
|
||||||
|
case BattlerTagType.ENCORE:
|
||||||
|
return new EncoreTag(sourceMove, sourceId);
|
||||||
case BattlerTagType.INGRAIN:
|
case BattlerTagType.INGRAIN:
|
||||||
return new IngrainTag(sourceId);
|
return new IngrainTag(sourceId);
|
||||||
case BattlerTagType.AQUA_RING:
|
case BattlerTagType.AQUA_RING:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { ChargeAnim, MoveChargeAnim, initMoveAnim, loadMoveAnimAssets } from "./battle-anims";
|
import { ChargeAnim, MoveChargeAnim, initMoveAnim, loadMoveAnimAssets } from "./battle-anims";
|
||||||
import { BattleEndPhase, DamagePhase, MovePhase, NewBattlePhase, ObtainStatusEffectPhase, PokemonHealPhase, StatChangePhase, SwitchSummonPhase } from "../battle-phases";
|
import { BattleEndPhase, DamagePhase, MovePhase, NewBattlePhase, ObtainStatusEffectPhase, PokemonHealPhase, StatChangePhase, SwitchSummonPhase } from "../battle-phases";
|
||||||
import { BattleStat } from "./battle-stat";
|
import { BattleStat } from "./battle-stat";
|
||||||
import { BattlerTagType } from "./battler-tag";
|
import { BattlerTagType, EncoreTag } from "./battler-tag";
|
||||||
import { getPokemonMessage } from "../messages";
|
import { getPokemonMessage } from "../messages";
|
||||||
import Pokemon, { AttackMoveResult, HitResult, MoveResult, PlayerPokemon, PokemonMove, TurnMove } from "../pokemon";
|
import Pokemon, { AttackMoveResult, HitResult, MoveResult, PlayerPokemon, PokemonMove, TurnMove } from "../pokemon";
|
||||||
import { StatusEffect, getStatusEffectDescriptor } from "./status-effect";
|
import { StatusEffect, getStatusEffectDescriptor } from "./status-effect";
|
||||||
|
@ -2177,16 +2177,16 @@ export class CopyMoveAttr extends OverrideMoveEffectAttr {
|
||||||
// TODO: Review this
|
// TODO: Review this
|
||||||
const targetMoveCopiableCondition = (user: Pokemon, target: Pokemon, move: Move) => {
|
const targetMoveCopiableCondition = (user: Pokemon, target: Pokemon, move: Move) => {
|
||||||
const targetMoves = target.getMoveHistory().filter(m => !m.virtual);
|
const targetMoves = target.getMoveHistory().filter(m => !m.virtual);
|
||||||
if (!targetMoves.length)
|
if (!targetMoves.length)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const copiableMove = targetMoves[0];
|
const copiableMove = targetMoves[0];
|
||||||
|
|
||||||
if (!copiableMove.move)
|
if (!copiableMove.move)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (allMoves[copiableMove.move].getAttrs(ChargeAttr).length && copiableMove.result === MoveResult.OTHER)
|
if (allMoves[copiableMove.move].getAttrs(ChargeAttr).length && copiableMove.result === MoveResult.OTHER)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// TODO: Add last turn of Bide
|
// TODO: Add last turn of Bide
|
||||||
|
|
||||||
|
@ -2252,15 +2252,15 @@ export class SketchAttr extends MoveEffectAttr {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const targetMoves = target.getMoveHistory().filter(m => !m.virtual);
|
const targetMoves = target.getMoveHistory().filter(m => !m.virtual);
|
||||||
if (!targetMoves.length)
|
if (!targetMoves.length)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const sketchableMove = targetMoves[0];
|
const sketchableMove = targetMoves[0];
|
||||||
|
|
||||||
if (user.getMoveset().find(m => m.moveId === sketchableMove.move))
|
if (user.getMoveset().find(m => m.moveId === sketchableMove.move))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2907,8 +2907,9 @@ export function initMoves() {
|
||||||
new SelfStatusMove(Moves.BATON_PASS, "Baton Pass", Type.NORMAL, -1, 40, 132, "User switches out and gives stat changes to the incoming Pokémon.", -1, 0, 2)
|
new SelfStatusMove(Moves.BATON_PASS, "Baton Pass", Type.NORMAL, -1, 40, 132, "User switches out and gives stat changes to the incoming Pokémon.", -1, 0, 2)
|
||||||
.attr(ForceSwitchOutAttr, true, true)
|
.attr(ForceSwitchOutAttr, true, true)
|
||||||
.hidesUser(),
|
.hidesUser(),
|
||||||
new StatusMove(Moves.ENCORE, "Encore (N)", Type.NORMAL, 100, 5, 122, "Forces opponent to keep using its last move for 3 turns.", -1, 0, 2)
|
new StatusMove(Moves.ENCORE, "Encore", Type.NORMAL, 100, 5, 122, "Forces opponent to keep using its last move for 3 turns.", -1, 0, 2)
|
||||||
.attr(AddBattlerTagAttr, BattlerTagType.ENCORE, false, undefined, true),
|
.attr(AddBattlerTagAttr, BattlerTagType.ENCORE, false, undefined, true)
|
||||||
|
.condition((user: Pokemon, target: Pokemon, move: Move) => new EncoreTag(move.id, user.id).canAdd(target)),
|
||||||
new AttackMove(Moves.PURSUIT, "Pursuit (N)", Type.DARK, MoveCategory.PHYSICAL, 40, 100, 20, -1, "Double power if the opponent is switching out.", -1, 0, 2),
|
new AttackMove(Moves.PURSUIT, "Pursuit (N)", Type.DARK, MoveCategory.PHYSICAL, 40, 100, 20, -1, "Double power if the opponent is switching out.", -1, 0, 2),
|
||||||
new AttackMove(Moves.RAPID_SPIN, "Rapid Spin", Type.NORMAL, MoveCategory.PHYSICAL, 50, 100, 40, -1, "Raises user's Speed and removes entry hazards and trap move effects.", 100, 0, 2)
|
new AttackMove(Moves.RAPID_SPIN, "Rapid Spin", Type.NORMAL, MoveCategory.PHYSICAL, 50, 100, 40, -1, "Raises user's Speed and removes entry hazards and trap move effects.", 100, 0, 2)
|
||||||
.attr(StatChangeAttr, BattleStat.SPD, 1, true)
|
.attr(StatChangeAttr, BattleStat.SPD, 1, true)
|
||||||
|
|
|
@ -16,7 +16,7 @@ import { tmSpecies } from './data/tms';
|
||||||
import { pokemonEvolutions, pokemonPrevolutions, SpeciesEvolution, SpeciesEvolutionCondition } from './data/pokemon-evolutions';
|
import { pokemonEvolutions, pokemonPrevolutions, SpeciesEvolution, SpeciesEvolutionCondition } from './data/pokemon-evolutions';
|
||||||
import { DamagePhase, FaintPhase, SwitchSummonPhase } from './battle-phases';
|
import { DamagePhase, FaintPhase, SwitchSummonPhase } from './battle-phases';
|
||||||
import { BattleStat } from './data/battle-stat';
|
import { BattleStat } from './data/battle-stat';
|
||||||
import { BattlerTag, BattlerTagLapseType, BattlerTagType, TypeBoostTag, getBattlerTag } from './data/battler-tag';
|
import { BattlerTag, BattlerTagLapseType, BattlerTagType, EncoreTag, TypeBoostTag, getBattlerTag } from './data/battler-tag';
|
||||||
import { Species } from './data/species';
|
import { Species } from './data/species';
|
||||||
import { WeatherType } from './data/weather';
|
import { WeatherType } from './data/weather';
|
||||||
import { TempBattleStat } from './data/temp-battle-stat';
|
import { TempBattleStat } from './data/temp-battle-stat';
|
||||||
|
@ -1569,6 +1569,12 @@ export class EnemyPokemon extends Pokemon {
|
||||||
if (movePool.length) {
|
if (movePool.length) {
|
||||||
if (movePool.length === 1)
|
if (movePool.length === 1)
|
||||||
return { move: movePool[0].moveId, targets: this.getNextTargets(movePool[0].moveId) };
|
return { move: movePool[0].moveId, targets: this.getNextTargets(movePool[0].moveId) };
|
||||||
|
const encoreTag = this.getTag(EncoreTag) as EncoreTag;
|
||||||
|
if (encoreTag) {
|
||||||
|
const encoreMove = movePool.find(m => m.moveId === encoreTag.moveId);
|
||||||
|
if (encoreMove)
|
||||||
|
return { move: encoreMove.moveId, targets: this.getNextTargets(encoreMove.moveId) };
|
||||||
|
}
|
||||||
switch (this.aiType) {
|
switch (this.aiType) {
|
||||||
case AiType.RANDOM:
|
case AiType.RANDOM:
|
||||||
const moveId = movePool[Utils.randInt(movePool.length)].moveId;
|
const moveId = movePool[Utils.randInt(movePool.length)].moveId;
|
||||||
|
|
|
@ -63,6 +63,8 @@ export default class CommandUiHandler extends UiHandler {
|
||||||
if (button === Button.ACTION) {
|
if (button === Button.ACTION) {
|
||||||
switch (cursor) {
|
switch (cursor) {
|
||||||
case 0:
|
case 0:
|
||||||
|
if ((this.scene.getCurrentPhase() as CommandPhase).checkFightOverride())
|
||||||
|
return true;
|
||||||
ui.setMode(Mode.FIGHT, (this.scene.getCurrentPhase() as CommandPhase).getFieldIndex());
|
ui.setMode(Mode.FIGHT, (this.scene.getCurrentPhase() as CommandPhase).getFieldIndex());
|
||||||
success = true;
|
success = true;
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue