Add color change ability, some moves, and fix mimic
This commit is contained in:
parent
45f73cc6ed
commit
15cfd3bad4
|
@ -413,12 +413,16 @@ export class SummonPhase extends BattlePhase {
|
|||
}
|
||||
|
||||
end() {
|
||||
if (this.scene.getPlayerPokemon().shiny)
|
||||
const pokemon = this.scene.getPlayerPokemon();
|
||||
|
||||
if (pokemon.shiny)
|
||||
this.scene.unshiftPhase(new ShinySparklePhase(this.scene, true));
|
||||
|
||||
this.scene.arena.applyTags(ArenaTrapTag, this.scene.getPlayerPokemon());
|
||||
pokemon.resetTurnData();
|
||||
|
||||
applyPostSummonAbAttrs(PostSummonAbAttr, this.scene.getPlayerPokemon());
|
||||
this.scene.arena.applyTags(ArenaTrapTag, pokemon);
|
||||
|
||||
applyPostSummonAbAttrs(PostSummonAbAttr, pokemon);
|
||||
|
||||
super.end();
|
||||
}
|
||||
|
@ -594,8 +598,8 @@ export class CommandPhase extends FieldPhase {
|
|||
const moveQueue = playerPokemon.getMoveQueue();
|
||||
|
||||
while (moveQueue.length && moveQueue[0]
|
||||
&& moveQueue[0].move && (!playerPokemon.moveset.find(m => m.moveId === moveQueue[0].move)
|
||||
|| !playerPokemon.moveset[playerPokemon.moveset.findIndex(m => m.moveId === moveQueue[0].move)].isUsable(moveQueue[0].ignorePP)))
|
||||
&& moveQueue[0].move && (!playerPokemon.getMoveset().find(m => m.moveId === moveQueue[0].move)
|
||||
|| !playerPokemon.getMoveset()[playerPokemon.getMoveset().findIndex(m => m.moveId === moveQueue[0].move)].isUsable(moveQueue[0].ignorePP)))
|
||||
moveQueue.shift();
|
||||
|
||||
if (moveQueue.length) {
|
||||
|
@ -603,8 +607,8 @@ export class CommandPhase extends FieldPhase {
|
|||
if (!queuedMove.move)
|
||||
this.handleCommand(Command.FIGHT, -1, false);
|
||||
else {
|
||||
const moveIndex = playerPokemon.moveset.findIndex(m => m.moveId === queuedMove.move);
|
||||
if (moveIndex > -1 && playerPokemon.moveset[moveIndex].isUsable(queuedMove.ignorePP))
|
||||
const moveIndex = playerPokemon.getMoveset().findIndex(m => m.moveId === queuedMove.move);
|
||||
if (moveIndex > -1 && playerPokemon.getMoveset()[moveIndex].isUsable(queuedMove.ignorePP))
|
||||
this.handleCommand(Command.FIGHT, moveIndex, queuedMove.ignorePP);
|
||||
}
|
||||
} else
|
||||
|
@ -647,12 +651,12 @@ export class CommandPhase extends FieldPhase {
|
|||
}
|
||||
|
||||
if (playerPokemon.trySelectMove(cursor, args[0] as boolean)) {
|
||||
playerMove = playerPokemon.moveset[cursor];
|
||||
playerMove = playerPokemon.getMoveset()[cursor];
|
||||
const playerPhase = new PlayerMovePhase(this.scene, playerPokemon, playerMove, false, args[0] as boolean);
|
||||
this.scene.pushPhase(playerPhase);
|
||||
success = true;
|
||||
} else if (cursor < playerPokemon.moveset.length) {
|
||||
const move = playerPokemon.moveset[cursor];
|
||||
} else if (cursor < playerPokemon.getMoveset().length) {
|
||||
const move = playerPokemon.getMoveset()[cursor];
|
||||
if (move.isDisabled()) {
|
||||
this.scene.ui.setMode(Mode.MESSAGE);
|
||||
this.scene.ui.showText(`${move.getName()} is disabled!`, null, () => {
|
||||
|
@ -703,7 +707,7 @@ export class CommandPhase extends FieldPhase {
|
|||
const enemyNextMove = enemyPokemon.getNextMove();
|
||||
let enemyMove: PokemonMove;
|
||||
if (enemyNextMove.move) {
|
||||
enemyMove = enemyPokemon.moveset.find(m => m.moveId === enemyNextMove.move) || new PokemonMove(enemyNextMove.move, 0, 0);
|
||||
enemyMove = enemyPokemon.getMoveset().find(m => m.moveId === enemyNextMove.move) || new PokemonMove(enemyNextMove.move, 0, 0);
|
||||
const enemyPhase = new EnemyMovePhase(this.scene, enemyPokemon, enemyMove, false, enemyNextMove.ignorePP);
|
||||
if (isDelayed(command, playerMove, enemyMove))
|
||||
this.scene.unshiftPhase(enemyPhase);
|
||||
|
@ -753,7 +757,7 @@ export class TurnEndPhase extends FieldPhase {
|
|||
|
||||
pokemon.lapseTags(BattlerTagLapseType.TURN_END);
|
||||
|
||||
const disabledMoves = pokemon.moveset.filter(m => m.isDisabled());
|
||||
const disabledMoves = pokemon.getMoveset().filter(m => m.isDisabled());
|
||||
for (let dm of disabledMoves) {
|
||||
if (!--dm.disableTurns)
|
||||
this.scene.pushPhase(new MessagePhase(this.scene, `${dm.getName()} is disabled\nno more!`));
|
||||
|
@ -1048,7 +1052,7 @@ abstract class MoveEffectPhase extends PokemonPhase {
|
|||
if (!isProtected && !this.move.getMove().getAttrs(ChargeAttr).filter(ca => (ca as ChargeAttr).chargeEffect).length) {
|
||||
applyFilteredMoveAttrs((attr: MoveAttr) => attr instanceof MoveHitEffectAttr && (!!target.hp || (attr as MoveHitEffectAttr).selfTarget), user, target, this.move.getMove());
|
||||
if (target.hp)
|
||||
applyPostDefendAbAttrs(PostDefendAbAttr, user, target, this.move, result);
|
||||
applyPostDefendAbAttrs(PostDefendAbAttr, target, user, this.move, result);
|
||||
if (this.move.getMove().hasFlag(MoveFlags.MAKES_CONTACT))
|
||||
this.scene.applyModifiers(ContactHeldItemTransferChanceModifier, this.player, user);
|
||||
}
|
||||
|
@ -1763,23 +1767,23 @@ export class LearnMovePhase extends PartyMemberPokemonPhase {
|
|||
const pokemon = this.getPokemon();
|
||||
const move = allMoves[this.moveId];
|
||||
|
||||
const existingMoveIndex = pokemon.moveset.findIndex(m => m?.moveId === move.id);
|
||||
const existingMoveIndex = pokemon.getMoveset().findIndex(m => m?.moveId === move.id);
|
||||
|
||||
if (existingMoveIndex > -1) {
|
||||
this.end();
|
||||
return;
|
||||
}
|
||||
|
||||
const emptyMoveIndex = pokemon.moveset.length < 4
|
||||
? pokemon.moveset.length
|
||||
: pokemon.moveset.findIndex(m => m === null);
|
||||
const emptyMoveIndex = pokemon.getMoveset().length < 4
|
||||
? pokemon.getMoveset().length
|
||||
: pokemon.getMoveset().findIndex(m => m === null);
|
||||
|
||||
const messageMode = this.scene.ui.getHandler() instanceof EvolutionSceneHandler
|
||||
? Mode.EVOLUTION_SCENE
|
||||
: Mode.MESSAGE;
|
||||
|
||||
if (emptyMoveIndex > -1) {
|
||||
pokemon.moveset[emptyMoveIndex] = new PokemonMove(this.moveId, 0, 0);
|
||||
pokemon.setMove(emptyMoveIndex, this.moveId);
|
||||
initMoveAnim(this.moveId).then(() => {
|
||||
loadMoveAnimAssets(this.scene, [ this.moveId ], true)
|
||||
.then(() => {
|
||||
|
@ -1820,7 +1824,7 @@ export class LearnMovePhase extends PartyMemberPokemonPhase {
|
|||
this.scene.ui.showText('@d{32}1, @d{15}2, and@d{15}… @d{15}… @d{15}… @d{15}@s{pb_bounce_1}Poof!', null, () => {
|
||||
this.scene.ui.showText(`${pokemon.name} forgot how to\nuse ${pokemon.moveset[moveIndex].getName()}.`, null, () => {
|
||||
this.scene.ui.showText('And…', null, () => {
|
||||
pokemon.moveset[moveIndex] = null;
|
||||
pokemon.setMove(moveIndex, Moves.NONE);
|
||||
this.scene.unshiftPhase(new LearnMovePhase(this.scene, this.partyMemberIndex, this.moveId));
|
||||
this.end();
|
||||
}, null, true);
|
||||
|
|
|
@ -7,7 +7,7 @@ import { getPokemonMessage } from "../messages";
|
|||
import { Weather, WeatherType } from "./weather";
|
||||
import { BattlerTag, BattlerTagType, TrappedTag } from "./battler-tag";
|
||||
import { StatusEffect, getStatusEffectDescriptor } from "./status-effect";
|
||||
import { MoveFlags, Moves, RecoilAttr } from "./move";
|
||||
import { MoveFlags, Moves, RecoilAttr, allMoves } from "./move";
|
||||
|
||||
export class Ability {
|
||||
public id: Abilities;
|
||||
|
@ -230,6 +230,25 @@ export class PostDefendAbAttr extends AbAttr {
|
|||
}
|
||||
}
|
||||
|
||||
export class PostDefendTypeChangeAbAttr extends PostDefendAbAttr {
|
||||
applyPostDefend(pokemon: Pokemon, attacker: Pokemon, move: PokemonMove, moveResult: MoveResult, args: any[]): boolean {
|
||||
if (moveResult < MoveResult.NO_EFFECT) {
|
||||
const type = move.getMove().type;
|
||||
const type2 = pokemon.species.type2;
|
||||
if (type !== pokemon.getTypes()[0] && type !== type2) {
|
||||
pokemon.summonData.types = [ type ].concat(type2 !== null ? [ type2 ] : []);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
getTriggerMessage(pokemon: Pokemon, ...args: any[]): string {
|
||||
return getPokemonMessage(pokemon, `'s ${pokemon.getAbility().name}\nmade it the ${Type[pokemon.getTypes()[0]]} type!`);
|
||||
}
|
||||
}
|
||||
|
||||
export class PostDefendContactApplyStatusEffectAbAttr extends PostDefendAbAttr {
|
||||
private chance: integer;
|
||||
private effects: StatusEffect[];
|
||||
|
@ -1104,7 +1123,8 @@ export function initAbilities() {
|
|||
.attr(ProtectStatAttr),
|
||||
new Ability(Abilities.CLOUD_NINE, "Cloud Nine", "Eliminates the effects of non-severe weather.", 3)
|
||||
.attr(SuppressWeatherEffectAbAttr),
|
||||
new Ability(Abilities.COLOR_CHANGE, "Color Change (N)", "Changes the POKéMON's type to the foe's move.", 3),
|
||||
new Ability(Abilities.COLOR_CHANGE, "Color Change", "Changes the POKéMON's type to the foe's move.", 3)
|
||||
.attr(PostDefendTypeChangeAbAttr),
|
||||
new Ability(Abilities.COMPOUND_EYES, "Compound Eyes", "The POKéMON's accuracy is boosted.", 3)
|
||||
.attr(BattleStatMultiplierAbAttr, BattleStat.ACC, 1.3),
|
||||
new Ability(Abilities.CUTE_CHARM, "Cute Charm", "Contact with the POKéMON may cause infatuation.", 3)
|
||||
|
|
|
@ -3,7 +3,7 @@ import { DamagePhase, EnemyMovePhase, ObtainStatusEffectPhase, PlayerMovePhase,
|
|||
import { BattleStat } from "./battle-stat";
|
||||
import { BattlerTagType } from "./battler-tag";
|
||||
import { getPokemonMessage } from "../messages";
|
||||
import Pokemon, { EnemyPokemon, MoveResult, PlayerPokemon, PokemonMove, TurnMove } from "../pokemon";
|
||||
import Pokemon, { AttackMoveResult, EnemyPokemon, MoveResult, PlayerPokemon, PokemonMove, TurnMove } from "../pokemon";
|
||||
import { StatusEffect, getStatusEffectDescriptor } from "./status-effect";
|
||||
import { Type } from "./type";
|
||||
import * as Utils from "../utils";
|
||||
|
@ -847,6 +847,29 @@ export class TargetHalfHpDamageAttr extends FixedDamageAttr {
|
|||
}
|
||||
}
|
||||
|
||||
type MoveFilter = (move: Move) => boolean;
|
||||
|
||||
export class CounterDamageAttr extends FixedDamageAttr {
|
||||
private moveFilter: MoveFilter;
|
||||
|
||||
constructor(moveFilter: MoveFilter) {
|
||||
super(0);
|
||||
|
||||
this.moveFilter = moveFilter;
|
||||
}
|
||||
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
const damage = user.turnData.attacksReceived.filter(ar => this.moveFilter(allMoves[ar.move])).reduce((total: integer, ar: AttackMoveResult) => total + ar.damage, 0);
|
||||
(args[0] as Utils.IntegerHolder).value = Math.max(damage * 2, 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
getCondition(): MoveCondition {
|
||||
return (user: Pokemon, target: Pokemon, move: Move) => !!user.turnData.attacksReceived.filter(ar => this.moveFilter(allMoves[ar.move])).length;
|
||||
}
|
||||
}
|
||||
|
||||
export class RecoilAttr extends MoveEffectAttr {
|
||||
private useHp: boolean;
|
||||
|
||||
|
@ -1460,11 +1483,11 @@ export class DisableMoveAttr extends MoveEffectAttr {
|
|||
if (turnMove.virtual)
|
||||
continue;
|
||||
|
||||
const moveIndex = target.moveset.findIndex(m => m.moveId === turnMove.move);
|
||||
const moveIndex = target.getMoveset().findIndex(m => m.moveId === turnMove.move);
|
||||
if (moveIndex === -1)
|
||||
return false;
|
||||
|
||||
const disabledMove = target.moveset[moveIndex];
|
||||
const disabledMove = target.getMoveset()[moveIndex];
|
||||
disabledMove.disableTurns = 4;
|
||||
|
||||
user.scene.queueMessage(getPokemonMessage(target, `'s ${disabledMove.getName()}\nwas disabled!`));
|
||||
|
@ -1484,7 +1507,7 @@ export class DisableMoveAttr extends MoveEffectAttr {
|
|||
if (turnMove.virtual)
|
||||
continue;
|
||||
|
||||
const move = target.moveset.find(m => m.moveId === turnMove.move);
|
||||
const move = target.getMoveset().find(m => m.moveId === turnMove.move);
|
||||
if (!move)
|
||||
continue;
|
||||
|
||||
|
@ -1733,7 +1756,7 @@ export class RandomMovesetMoveAttr extends OverrideMoveEffectAttr {
|
|||
}
|
||||
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
const moveset = (!this.enemyMoveset ? user : target).moveset;
|
||||
const moveset = (!this.enemyMoveset ? user : target).getMoveset();
|
||||
const moves = moveset.filter(m => !m.getMove().hasFlag(MoveFlags.IGNORE_VIRTUAL));
|
||||
if (moves.length) {
|
||||
const move = moves[Utils.randInt(moves.length)];
|
||||
|
@ -1805,6 +1828,32 @@ export class CopyMoveAttr extends OverrideMoveEffectAttr {
|
|||
}
|
||||
}
|
||||
|
||||
export class MovesetCopyMoveAttr extends OverrideMoveEffectAttr {
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
const targetMoves = target.getMoveHistory().filter(m => !m.virtual);
|
||||
if (!targetMoves.length)
|
||||
return false;
|
||||
|
||||
const copiedMove = allMoves[targetMoves[0].move];
|
||||
|
||||
const thisMoveIndex = user.getMoveset().findIndex(m => m.moveId === move.id);
|
||||
|
||||
if (thisMoveIndex === -1)
|
||||
return false;
|
||||
|
||||
user.summonData.moveset = user.getMoveset().slice(0);
|
||||
user.summonData.moveset[thisMoveIndex] = new PokemonMove(copiedMove.id, 0, 0);
|
||||
|
||||
user.scene.queueMessage(getPokemonMessage(user, ` copied\n${copiedMove.name}!`));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
getCondition(): MoveCondition {
|
||||
return targetMoveCopiableCondition;
|
||||
}
|
||||
}
|
||||
|
||||
export class SketchAttr extends MoveEffectAttr {
|
||||
constructor() {
|
||||
super(true);
|
||||
|
@ -1820,12 +1869,12 @@ export class SketchAttr extends MoveEffectAttr {
|
|||
|
||||
const sketchedMove = allMoves[targetMoves[0].move];
|
||||
|
||||
const sketchIndex = user.moveset.findIndex(m => m.moveId === move.id);
|
||||
const sketchIndex = user.getMoveset().findIndex(m => m.moveId === move.id);
|
||||
|
||||
if (sketchIndex === -1)
|
||||
return false;
|
||||
|
||||
user.moveset[sketchIndex] = new PokemonMove(sketchedMove.id, 0, 0);
|
||||
user.setMove(sketchIndex, sketchedMove.id);
|
||||
|
||||
user.scene.queueMessage(getPokemonMessage(user, ` sketched\n${sketchedMove.name}!`));
|
||||
|
||||
|
@ -1843,7 +1892,7 @@ export class SketchAttr extends MoveEffectAttr {
|
|||
|
||||
const sketchableMove = targetMoves[0];
|
||||
|
||||
if (user.moveset.find(m => m.moveId === sketchableMove.move))
|
||||
if (user.getMoveset().find(m => m.moveId === sketchableMove.move))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
@ -2034,7 +2083,8 @@ export function initMoves() {
|
|||
.attr(RecoilAttr),
|
||||
new AttackMove(Moves.LOW_KICK, "Low Kick", Type.FIGHTING, MoveCategory.PHYSICAL, -1, 100, 20, 12, "The heavier the opponent, the stronger the attack.", -1, 0, 1)
|
||||
.attr(WeightPowerAttr),
|
||||
new AttackMove(Moves.COUNTER, "Counter (N)", Type.FIGHTING, MoveCategory.PHYSICAL, -1, 100, 20, -1, "When hit by a Physical Attack, user strikes back with 2x power.", -1, -5, 1)
|
||||
new AttackMove(Moves.COUNTER, "Counter", Type.FIGHTING, MoveCategory.PHYSICAL, -1, 100, 20, -1, "When hit by a Physical Attack, user strikes back with 2x power.", -1, -5, 1)
|
||||
.attr(CounterDamageAttr, (move: Move) => move.category === MoveCategory.PHYSICAL)
|
||||
.target(MoveTarget.ATTACKER),
|
||||
new AttackMove(Moves.SEISMIC_TOSS, "Seismic Toss", Type.FIGHTING, MoveCategory.PHYSICAL, -1, 100, 20, -1, "Inflicts damage equal to user's level (maximum 150).", -1, 0, 1)
|
||||
.attr(LevelPowerAttr),
|
||||
|
@ -2114,7 +2164,7 @@ export function initMoves() {
|
|||
new AttackMove(Moves.NIGHT_SHADE, "Night Shade", Type.GHOST, MoveCategory.SPECIAL, -1, 100, 15, 42, "Inflicts damage equal to user's level (maximum 150).", -1, 0, 1)
|
||||
.attr(LevelPowerAttr),
|
||||
new StatusMove(Moves.MIMIC, "Mimic", Type.NORMAL, -1, 10, -1, "Copies the opponent's last move.", -1, 0, 1)
|
||||
.attr(CopyMoveAttr)
|
||||
.attr(MovesetCopyMoveAttr)
|
||||
.ignoresVirtual(),
|
||||
new StatusMove(Moves.SCREECH, "Screech", Type.NORMAL, 85, 40, -1, "Sharply lowers opponent's Defense.", -1, 0, 1)
|
||||
.attr(StatChangeAttr, BattleStat.DEF, -2),
|
||||
|
@ -2150,7 +2200,8 @@ export function initMoves() {
|
|||
new SelfStatusMove(Moves.METRONOME, "Metronome", Type.NORMAL, -1, 10, 80, "User performs almost any move in the game at random.", -1, 0, 1)
|
||||
.attr(RandomMoveAttr)
|
||||
.ignoresVirtual(),
|
||||
new SelfStatusMove(Moves.MIRROR_MOVE, "Mirror Move (N)", Type.FLYING, -1, 20, -1, "User performs the opponent's last move.", -1, 0, 1)
|
||||
new SelfStatusMove(Moves.MIRROR_MOVE, "Mirror Move", Type.FLYING, -1, 20, -1, "User performs the opponent's last move.", -1, 0, 1)
|
||||
.attr(CopyMoveAttr)
|
||||
.ignoresVirtual(),
|
||||
new AttackMove(Moves.SELF_DESTRUCT, "Self-Destruct", Type.NORMAL, MoveCategory.PHYSICAL, 200, 100, 5, -1, "User faints.", -1, 0, 1)
|
||||
.attr(SacrificialAttr)
|
||||
|
@ -2434,7 +2485,8 @@ export function initMoves() {
|
|||
.target(MoveTarget.BOTH_SIDES),
|
||||
new AttackMove(Moves.CRUNCH, "Crunch", Type.DARK, MoveCategory.PHYSICAL, 80, 100, 15, 108, "May lower opponent's Defense.", 20, 0, 2)
|
||||
.attr(StatChangeAttr, BattleStat.DEF, -1),
|
||||
new AttackMove(Moves.MIRROR_COAT, "Mirror Coat (N)", Type.PSYCHIC, MoveCategory.SPECIAL, -1, 100, 20, -1, "When hit by a Special Attack, user strikes back with 2x power.", -1, -5, 2)
|
||||
new AttackMove(Moves.MIRROR_COAT, "Mirror Coat", Type.PSYCHIC, MoveCategory.SPECIAL, -1, 100, 20, -1, "When hit by a Special Attack, user strikes back with 2x power.", -1, -5, 2)
|
||||
.attr(CounterDamageAttr, (move: Move) => move.category === MoveCategory.SPECIAL)
|
||||
.target(MoveTarget.ATTACKER),
|
||||
new SelfStatusMove(Moves.PSYCH_UP, "Psych Up (N)", Type.NORMAL, -1, 10, -1, "Copies the opponent's stat changes.", -1, 0, 2),
|
||||
new AttackMove(Moves.EXTREME_SPEED, "Extreme Speed", Type.NORMAL, MoveCategory.PHYSICAL, 80, 100, 5, -1, "User attacks first.", -1, 2, 2),
|
||||
|
@ -2721,7 +2773,7 @@ export function initMoves() {
|
|||
new StatusMove(Moves.GUARD_SWAP, "Guard Swap (N)", Type.PSYCHIC, -1, 10, -1, "User and opponent swap Defense and Special Defense.", -1, 0, 4),
|
||||
new AttackMove(Moves.PUNISHMENT, "Punishment (N)", Type.DARK, MoveCategory.PHYSICAL, -1, 100, 5, -1, "Power increases when opponent's stats have been raised.", -1, 0, 4),
|
||||
new AttackMove(Moves.LAST_RESORT, "Last Resort", Type.NORMAL, MoveCategory.PHYSICAL, 140, 100, 5, -1, "Can only be used after all other moves are used.", -1, 0, 4)
|
||||
.condition((user: Pokemon, target: Pokemon, move: Move) => !user.moveset.filter(m => m.moveId !== move.id && m.getPpRatio() > 0).length),
|
||||
.condition((user: Pokemon, target: Pokemon, move: Move) => !user.getMoveset().filter(m => m.moveId !== move.id && m.getPpRatio() > 0).length),
|
||||
new StatusMove(Moves.WORRY_SEED, "Worry Seed (N)", Type.GRASS, 100, 10, -1, "Changes the opponent's Ability to Insomnia.", -1, 0, 4),
|
||||
new AttackMove(Moves.SUCKER_PUNCH, "Sucker Punch (N)", Type.DARK, MoveCategory.PHYSICAL, 70, 100, 5, -1, "User attacks first, but only works if opponent is readying an attack.", -1, 0, 4),
|
||||
new StatusMove(Moves.TOXIC_SPIKES, "Toxic Spikes", Type.POISON, -1, 20, 91, "Poisons opponents when they switch into battle.", -1, 0, 4)
|
||||
|
|
|
@ -185,7 +185,7 @@ export class PokemonAllMovePpRestoreModifierType extends PokemonModifierType {
|
|||
constructor(name: string, restorePoints: integer, iconImage?: string) {
|
||||
super(name, `Restore ${restorePoints > -1 ? restorePoints : 'all'} PP for all of one POKéMON's moves`, (_type, args) => new Modifiers.PokemonAllMovePpRestoreModifier(this, (args[0] as PlayerPokemon).id, this.restorePoints),
|
||||
(pokemon: PlayerPokemon) => {
|
||||
if (!pokemon.moveset.filter(m => m.ppUsed).length)
|
||||
if (!pokemon.getMoveset().filter(m => m.ppUsed).length)
|
||||
return PartyUiHandler.NoEffectMessage;
|
||||
return null;
|
||||
}, iconImage, 'elixir');
|
||||
|
@ -361,7 +361,7 @@ export class TmModifierType extends PokemonModifierType {
|
|||
constructor(moveId: Moves) {
|
||||
super(`TM${Utils.padInt(Object.keys(tmSpecies).indexOf(moveId.toString()) + 1, 3)} - ${allMoves[moveId].name}`, `Teach ${allMoves[moveId].name} to a POKéMON`, (_type, args) => new Modifiers.TmModifier(this, (args[0] as PlayerPokemon).id),
|
||||
(pokemon: PlayerPokemon) => {
|
||||
if (pokemon.compatibleTms.indexOf(moveId) === -1 || pokemon.moveset.filter(m => m?.moveId === moveId).length)
|
||||
if (pokemon.compatibleTms.indexOf(moveId) === -1 || pokemon.getMoveset().filter(m => m?.moveId === moveId).length)
|
||||
return PartyUiHandler.NoEffectMessage;
|
||||
return null;
|
||||
}, `tm_${Type[allMoves[moveId].type].toLowerCase()}`, 'tm');
|
||||
|
@ -424,7 +424,7 @@ class AttackTypeBoosterModifierTypeGenerator extends ModifierTypeGenerator {
|
|||
if (pregenArgs)
|
||||
return new AttackTypeBoosterModifierType(pregenArgs[0] as Type, 20);
|
||||
|
||||
const attackMoveTypes = party.map(p => p.moveset.map(m => m.getMove()).filter(m => m instanceof AttackMove).map(m => m.type)).flat();
|
||||
const attackMoveTypes = party.map(p => p.getMoveset().map(m => m.getMove()).filter(m => m instanceof AttackMove).map(m => m.type)).flat();
|
||||
const attackMoveTypeWeights = new Map<Type, integer>();
|
||||
let totalWeight = 0;
|
||||
for (let t of attackMoveTypes) {
|
||||
|
@ -648,11 +648,11 @@ const modifierPool = {
|
|||
return thresholdPartyMemberCount;
|
||||
}),
|
||||
new WeightedModifierType(modifierTypes.ETHER, (party: Pokemon[]) => {
|
||||
const thresholdPartyMemberCount = Math.min(party.filter(p => p.hp && p.moveset.filter(m => (m.getMove().pp - m.ppUsed) <= 5).length).length, 3);
|
||||
const thresholdPartyMemberCount = Math.min(party.filter(p => p.hp && p.getMoveset().filter(m => (m.getMove().pp - m.ppUsed) <= 5).length).length, 3);
|
||||
return thresholdPartyMemberCount * 3;
|
||||
}),
|
||||
new WeightedModifierType(modifierTypes.MAX_ETHER, (party: Pokemon[]) => {
|
||||
const thresholdPartyMemberCount = Math.min(party.filter(p => p.hp && p.moveset.filter(m => (m.getMove().pp - m.ppUsed) <= 5).length).length, 3);
|
||||
const thresholdPartyMemberCount = Math.min(party.filter(p => p.hp && p.getMoveset().filter(m => (m.getMove().pp - m.ppUsed) <= 5).length).length, 3);
|
||||
return thresholdPartyMemberCount;
|
||||
}),
|
||||
new WeightedModifierType(modifierTypes.TEMP_STAT_BOOSTER, 4),
|
||||
|
@ -685,11 +685,11 @@ const modifierPool = {
|
|||
return thresholdPartyMemberCount;
|
||||
}),
|
||||
new WeightedModifierType(modifierTypes.ELIXIR, (party: Pokemon[]) => {
|
||||
const thresholdPartyMemberCount = Math.min(party.filter(p => p.hp && p.moveset.filter(m => (m.getMove().pp - m.ppUsed) <= 5).length).length, 3);
|
||||
const thresholdPartyMemberCount = Math.min(party.filter(p => p.hp && p.getMoveset().filter(m => (m.getMove().pp - m.ppUsed) <= 5).length).length, 3);
|
||||
return thresholdPartyMemberCount * 3;
|
||||
}),
|
||||
new WeightedModifierType(modifierTypes.MAX_ELIXIR, (party: Pokemon[]) => {
|
||||
const thresholdPartyMemberCount = Math.min(party.filter(p => p.hp && p.moveset.filter(m => (m.getMove().pp - m.ppUsed) <= 5).length).length, 3);
|
||||
const thresholdPartyMemberCount = Math.min(party.filter(p => p.hp && p.getMoveset().filter(m => (m.getMove().pp - m.ppUsed) <= 5).length).length, 3);
|
||||
return thresholdPartyMemberCount;
|
||||
}),
|
||||
new WeightedModifierType(modifierTypes.MAP, (party: Pokemon[]) => {
|
||||
|
|
|
@ -699,7 +699,7 @@ export class PokemonPpRestoreModifier extends ConsumablePokemonMoveModifier {
|
|||
|
||||
apply(args: any[]): boolean {
|
||||
const pokemon = args[0] as Pokemon;
|
||||
const move = pokemon.moveset[this.moveIndex];
|
||||
const move = pokemon.getMoveset()[this.moveIndex];
|
||||
move.ppUsed = this.restorePoints >= -1 ? Math.max(move.ppUsed - this.restorePoints, 0) : 0;
|
||||
|
||||
return true;
|
||||
|
@ -717,7 +717,7 @@ export class PokemonAllMovePpRestoreModifier extends ConsumablePokemonModifier {
|
|||
|
||||
apply(args: any[]): boolean {
|
||||
const pokemon = args[0] as Pokemon;
|
||||
for (let move of pokemon.moveset)
|
||||
for (let move of pokemon.getMoveset())
|
||||
move.ppUsed = this.restorePoints >= -1 ? Math.max(move.ppUsed - this.restorePoints, 0) : 0;
|
||||
|
||||
return true;
|
||||
|
|
|
@ -181,7 +181,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
|
||||
loadAssets(): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
const moveIds = this.moveset.map(m => m.getMove().id);
|
||||
const moveIds = this.getMoveset().map(m => m.getMove().id);
|
||||
Promise.allSettled(moveIds.map(m => initMoveAnim(m)))
|
||||
.then(() => {
|
||||
loadMoveAnimAssets(this.scene, moveIds);
|
||||
|
@ -320,6 +320,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
return Math.floor((this.hp / this.getMaxHp()) * 100) / 100;
|
||||
}
|
||||
|
||||
getMoveset(): PokemonMove[] {
|
||||
if (this.summonData?.moveset)
|
||||
return this.summonData.moveset;
|
||||
return this.moveset;
|
||||
}
|
||||
|
||||
getTypes(): Type[] {
|
||||
const types = [];
|
||||
|
||||
|
@ -395,6 +401,13 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
setMove(moveIndex: integer, moveId: Moves): void {
|
||||
const move = moveId ? new PokemonMove(moveId) : null;
|
||||
this.moveset[moveId] = move;
|
||||
if (this.summonData.moveset)
|
||||
this.summonData.moveset[moveIndex] = move;
|
||||
}
|
||||
|
||||
generateAndPopulateMoveset(): void {
|
||||
this.moveset = [];
|
||||
|
@ -434,8 +447,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
}
|
||||
|
||||
trySelectMove(moveIndex: integer, ignorePp?: boolean): boolean {
|
||||
const move = this.moveset.length > moveIndex
|
||||
? this.moveset[moveIndex]
|
||||
const move = this.getMoveset().length > moveIndex
|
||||
? this.getMoveset()[moveIndex]
|
||||
: null;
|
||||
return move?.isUsable(ignorePp);
|
||||
}
|
||||
|
@ -576,6 +589,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
this.scene.queueMessage('A critical hit!');
|
||||
this.damage(damage);
|
||||
source.turnData.damageDealt += damage;
|
||||
this.turnData.attacksReceived.unshift({ move: move.id, result: result as DamageResult, damage: damage, sourceId: source.id });
|
||||
}
|
||||
|
||||
switch (result) {
|
||||
|
@ -1023,7 +1037,7 @@ export class EnemyPokemon extends Pokemon {
|
|||
|
||||
getNextMove(): QueuedMove {
|
||||
const queuedMove = this.getMoveQueue().length
|
||||
? this.moveset.find(m => m.moveId === this.getMoveQueue()[0].move)
|
||||
? this.getMoveset().find(m => m.moveId === this.getMoveQueue()[0].move)
|
||||
: null;
|
||||
if (queuedMove) {
|
||||
if (queuedMove.isUsable(this.getMoveQueue()[0].ignorePP))
|
||||
|
@ -1034,7 +1048,7 @@ export class EnemyPokemon extends Pokemon {
|
|||
}
|
||||
}
|
||||
|
||||
const movePool = this.moveset.filter(m => m.isUsable());
|
||||
const movePool = this.getMoveset().filter(m => m.isUsable());
|
||||
if (movePool.length) {
|
||||
if (movePool.length === 1)
|
||||
return { move: movePool[0].moveId };
|
||||
|
@ -1139,10 +1153,18 @@ export interface QueuedMove {
|
|||
ignorePP?: boolean;
|
||||
}
|
||||
|
||||
export interface AttackMoveResult {
|
||||
move: Moves;
|
||||
result: DamageResult;
|
||||
damage: integer;
|
||||
sourceId: integer;
|
||||
}
|
||||
|
||||
export class PokemonSummonData {
|
||||
public battleStats: integer[] = [ 0, 0, 0, 0, 0, 0, 0 ];
|
||||
public moveQueue: QueuedMove[] = [];
|
||||
public tags: BattlerTag[] = [];
|
||||
public moveset: PokemonMove[];
|
||||
public types: Type[];
|
||||
}
|
||||
|
||||
|
@ -1156,6 +1178,7 @@ export class PokemonTurnData {
|
|||
public hitCount: integer;
|
||||
public hitsLeft: integer;
|
||||
public damageDealt: integer = 0;
|
||||
public attacksReceived: AttackMoveResult[] = [];
|
||||
}
|
||||
|
||||
export enum AiType {
|
||||
|
|
|
@ -63,7 +63,7 @@ export function initAutoPlay() {
|
|||
|
||||
const getMaxMoveEffectiveness = (attacker: Pokemon, defender: Pokemon) => {
|
||||
let maxEffectiveness = 0.5;
|
||||
for (let m of attacker.moveset) {
|
||||
for (let m of attacker.getMoveset()) {
|
||||
const moveType = m.getMove().type;
|
||||
const effectiveness = defender.getAttackMoveEffectiveness(moveType);
|
||||
if (effectiveness > maxEffectiveness)
|
||||
|
@ -129,7 +129,7 @@ export function initAutoPlay() {
|
|||
playerPokemon.aiType = AiType.SMART;
|
||||
thisArg.time.delayedCall(20, () => {
|
||||
const nextMove = playerPokemon.getNextMove() as PokemonMove;
|
||||
fightUiHandler.setCursor(playerPokemon.moveset.indexOf(nextMove));
|
||||
fightUiHandler.setCursor(playerPokemon.getMoveset().indexOf(nextMove));
|
||||
thisArg.time.delayedCall(20, () => this.processInput(Button.ACTION));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -65,6 +65,7 @@ export default class PokemonData {
|
|||
this.summonData.battleStats = source.summonData.battleStats;
|
||||
this.summonData.moveQueue = source.summonData.moveQueue;
|
||||
this.summonData.tags = []; // TODO
|
||||
this.summonData.moveset = source.summonData.moveset;
|
||||
this.summonData.types = source.summonData.types;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ export default class FightUiHandler extends UiHandler {
|
|||
ui.add(this.cursorObj);
|
||||
}
|
||||
|
||||
const moveset = this.scene.getPlayerPokemon().moveset;
|
||||
const moveset = this.scene.getPlayerPokemon().getMoveset();
|
||||
|
||||
const hasMove = cursor < moveset.length;
|
||||
|
||||
|
@ -114,7 +114,7 @@ export default class FightUiHandler extends UiHandler {
|
|||
}
|
||||
|
||||
displayMoves() {
|
||||
const moveset = this.scene.getPlayerPokemon().moveset;
|
||||
const moveset = this.scene.getPlayerPokemon().getMoveset();
|
||||
for (let m = 0; m < 4; m++) {
|
||||
const moveText = addTextObject(this.scene, m % 2 === 0 ? 0 : 100, m < 2 ? 0 : 16, '-', TextStyle.WINDOW);
|
||||
if (m < moveset.length)
|
||||
|
|
Loading…
Reference in New Issue