Add logic for disable move
parent
da0d607f26
commit
52a28ed95a
|
@ -449,9 +449,17 @@ export class CommandPhase extends BattlePhase {
|
||||||
playerPokemon.resetTurnData();
|
playerPokemon.resetTurnData();
|
||||||
this.scene.getEnemyPokemon().resetTurnData();
|
this.scene.getEnemyPokemon().resetTurnData();
|
||||||
|
|
||||||
if (playerPokemon.summonData.moveQueue.length)
|
while (playerPokemon.summonData.moveQueue.length && playerPokemon.summonData.moveQueue[0]
|
||||||
this.handleCommand(Command.FIGHT, playerPokemon.moveset.findIndex(m => m.moveId === playerPokemon.summonData.moveQueue[0].move));
|
&& !playerPokemon.moveset[playerPokemon.moveset.findIndex(m => m.moveId === playerPokemon.summonData.moveQueue[0].move)]
|
||||||
else
|
.isUsable(playerPokemon.summonData.moveQueue[0].ignorePP))
|
||||||
|
playerPokemon.summonData.moveQueue.shift();
|
||||||
|
|
||||||
|
if (playerPokemon.summonData.moveQueue.length) {
|
||||||
|
const queuedMove = playerPokemon.summonData.moveQueue[0];
|
||||||
|
const moveIndex = playerPokemon.moveset.findIndex(m => m.moveId === queuedMove.move);
|
||||||
|
if (playerPokemon.moveset[moveIndex].isUsable(queuedMove.ignorePP))
|
||||||
|
this.handleCommand(Command.FIGHT, moveIndex);
|
||||||
|
} else
|
||||||
this.scene.ui.setMode(Mode.COMMAND);
|
this.scene.ui.setMode(Mode.COMMAND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -492,7 +500,12 @@ export class CommandPhase extends BattlePhase {
|
||||||
const playerPhase = new PlayerMovePhase(this.scene, playerPokemon, playerMove);
|
const playerPhase = new PlayerMovePhase(this.scene, playerPokemon, playerMove);
|
||||||
this.scene.pushPhase(playerPhase);
|
this.scene.pushPhase(playerPhase);
|
||||||
success = true;
|
success = true;
|
||||||
|
} else if (cursor < playerPokemon.moveset.length) {
|
||||||
|
const move = playerPokemon.moveset[cursor];
|
||||||
|
if (move.isDisabled())
|
||||||
|
this.scene.ui.showText(`${move.getName()} is disabled!`);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case Command.BALL:
|
case Command.BALL:
|
||||||
if (cursor < 4) {
|
if (cursor < 4) {
|
||||||
|
@ -558,15 +571,31 @@ export class TurnEndPhase extends BattlePhase {
|
||||||
const playerPokemon = this.scene.getPlayerPokemon();
|
const playerPokemon = this.scene.getPlayerPokemon();
|
||||||
const enemyPokemon = this.scene.getEnemyPokemon();
|
const enemyPokemon = this.scene.getEnemyPokemon();
|
||||||
|
|
||||||
if (playerPokemon) {
|
const handlePokemon = (pokemon: Pokemon) => {
|
||||||
playerPokemon.lapseTags(BattleTagLapseType.TURN_END);
|
if (!pokemon)
|
||||||
playerPokemon.battleSummonData.turnCount++;
|
return;
|
||||||
|
|
||||||
|
pokemon.lapseTags(BattleTagLapseType.TURN_END);
|
||||||
|
|
||||||
|
const disabledMoves = pokemon.moveset.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!`));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enemyPokemon) {
|
pokemon.battleSummonData.turnCount++;
|
||||||
enemyPokemon.lapseTags(BattleTagLapseType.TURN_END);
|
};
|
||||||
enemyPokemon.battleSummonData.turnCount++;
|
|
||||||
}
|
const playerSpeed = playerPokemon?.getBattleStat(Stat.SPD) || 0;
|
||||||
|
const enemySpeed = enemyPokemon?.getBattleStat(Stat.SPD) || 0;
|
||||||
|
|
||||||
|
const isDelayed = playerSpeed < enemySpeed || (playerSpeed === enemySpeed && Utils.randInt(2) === 1);
|
||||||
|
|
||||||
|
if (!isDelayed)
|
||||||
|
handlePokemon(playerPokemon);
|
||||||
|
handlePokemon(enemyPokemon);
|
||||||
|
if (isDelayed)
|
||||||
|
handlePokemon(playerPokemon);
|
||||||
|
|
||||||
if (this.scene.arena.weather && !this.scene.arena.weather.lapse())
|
if (this.scene.arena.weather && !this.scene.arena.weather.lapse())
|
||||||
this.scene.arena.trySetWeather(WeatherType.NONE, false);
|
this.scene.arena.trySetWeather(WeatherType.NONE, false);
|
||||||
|
@ -655,7 +684,7 @@ export abstract class MovePhase extends BattlePhase {
|
||||||
abstract getEffectPhase(): MoveEffectPhase;
|
abstract getEffectPhase(): MoveEffectPhase;
|
||||||
|
|
||||||
canMove(): boolean {
|
canMove(): boolean {
|
||||||
return !!this.pokemon.hp;
|
return !!this.pokemon.hp && this.move.isUsable();
|
||||||
}
|
}
|
||||||
|
|
||||||
cancel(): void {
|
cancel(): void {
|
||||||
|
@ -665,6 +694,8 @@ export abstract class MovePhase extends BattlePhase {
|
||||||
start() {
|
start() {
|
||||||
super.start();
|
super.start();
|
||||||
|
|
||||||
|
console.log(Moves[this.move.moveId]);
|
||||||
|
|
||||||
const target = this.pokemon.isPlayer() ? this.scene.getEnemyPokemon() : this.scene.getPlayerPokemon();
|
const target = this.pokemon.isPlayer() ? this.scene.getEnemyPokemon() : this.scene.getPlayerPokemon();
|
||||||
|
|
||||||
if (!this.followUp && this.canMove())
|
if (!this.followUp && this.canMove())
|
||||||
|
@ -685,7 +716,7 @@ export abstract class MovePhase extends BattlePhase {
|
||||||
if (!failed.value && this.scene.arena.isMoveWeatherCancelled(this.move.getMove()))
|
if (!failed.value && this.scene.arena.isMoveWeatherCancelled(this.move.getMove()))
|
||||||
failed.value = true;
|
failed.value = true;
|
||||||
if (failed.value) {
|
if (failed.value) {
|
||||||
this.pokemon.summonData.moveHistory.push({ move: this.move.moveId, result: MoveResult.FAILED });
|
this.pokemon.summonData.moveHistory.push({ move: this.move.moveId, result: MoveResult.FAILED, virtual: this.move.virtual });
|
||||||
this.scene.unshiftPhase(new MessagePhase(this.scene, 'But it failed!'));
|
this.scene.unshiftPhase(new MessagePhase(this.scene, 'But it failed!'));
|
||||||
} else
|
} else
|
||||||
this.scene.unshiftPhase(this.getEffectPhase());
|
this.scene.unshiftPhase(this.getEffectPhase());
|
||||||
|
@ -694,6 +725,8 @@ export abstract class MovePhase extends BattlePhase {
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!this.canMove()) {
|
if (!this.canMove()) {
|
||||||
|
if (this.move.isDisabled())
|
||||||
|
this.scene.unshiftPhase(new MessagePhase(this.scene, `${this.move.getName()} is disabled!`));
|
||||||
this.end();
|
this.end();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -805,7 +838,7 @@ abstract class MoveEffectPhase extends PokemonPhase {
|
||||||
|
|
||||||
if (!this.hitCheck()) {
|
if (!this.hitCheck()) {
|
||||||
this.scene.unshiftPhase(new MessagePhase(this.scene, getPokemonMessage(user, '\'s\nattack missed!')));
|
this.scene.unshiftPhase(new MessagePhase(this.scene, getPokemonMessage(user, '\'s\nattack missed!')));
|
||||||
user.summonData.moveHistory.push({ move: this.move.moveId, result: MoveResult.MISSED });
|
user.summonData.moveHistory.push({ move: this.move.moveId, result: MoveResult.MISSED, virtual: this.move.virtual });
|
||||||
applyMoveAttrs(MissEffectAttr, user, target, this.move.getMove());
|
applyMoveAttrs(MissEffectAttr, user, target, this.move.getMove());
|
||||||
this.end();
|
this.end();
|
||||||
return;
|
return;
|
||||||
|
@ -816,7 +849,7 @@ abstract class MoveEffectPhase extends PokemonPhase {
|
||||||
new MoveAnim(this.move.getMove().id as Moves, user, target).play(this.scene, () => {
|
new MoveAnim(this.move.getMove().id as Moves, user, target).play(this.scene, () => {
|
||||||
const result = !isProtected ? target.apply(user, this.move) : MoveResult.NO_EFFECT;
|
const result = !isProtected ? target.apply(user, this.move) : MoveResult.NO_EFFECT;
|
||||||
++user.turnData.hitCount;
|
++user.turnData.hitCount;
|
||||||
user.summonData.moveHistory.push({ move: this.move.moveId, result: result });
|
user.summonData.moveHistory.push({ move: this.move.moveId, result: result, virtual: this.move.virtual });
|
||||||
applyMoveAttrs(MoveEffectAttr, user, target, this.move.getMove());
|
applyMoveAttrs(MoveEffectAttr, user, target, this.move.getMove());
|
||||||
// Charge attribute with charge effect takes all effect attributes and applies them to charge stage, so ignore them if this is present
|
// Charge attribute with charge effect takes all effect attributes and applies them to charge stage, so ignore them if this is present
|
||||||
if (!isProtected && target.hp && !this.move.getMove().getAttrs(ChargeAttr).filter(ca => (ca as ChargeAttr).chargeEffect).length)
|
if (!isProtected && target.hp && !this.move.getMove().getAttrs(ChargeAttr).filter(ca => (ca as ChargeAttr).chargeEffect).length)
|
||||||
|
|
|
@ -10,13 +10,14 @@ import { PokeballType } from './pokeball';
|
||||||
import { Species } from './species';
|
import { Species } from './species';
|
||||||
import { initAutoPlay } from './auto-play';
|
import { initAutoPlay } from './auto-play';
|
||||||
import { Battle } from './battle';
|
import { Battle } from './battle';
|
||||||
import { initCommonAnims, loadCommonAnimAssets, populateAnims } from './battle-anims';
|
import { initCommonAnims, initMoveAnim, loadCommonAnimAssets, loadMoveAnimAssets, populateAnims } from './battle-anims';
|
||||||
import { BattlePhase } from './battle-phase';
|
import { BattlePhase } from './battle-phase';
|
||||||
import { initGameSpeed } from './game-speed';
|
import { initGameSpeed } from './game-speed';
|
||||||
import { Arena } from './arena';
|
import { Arena } from './arena';
|
||||||
import { GameData } from './game-data';
|
import { GameData } from './game-data';
|
||||||
import StarterSelectUiHandler from './ui/starter-select-ui-handler';
|
import StarterSelectUiHandler from './ui/starter-select-ui-handler';
|
||||||
import { TextStyle, addTextObject } from './text';
|
import { TextStyle, addTextObject } from './text';
|
||||||
|
import { Moves } from './move';
|
||||||
|
|
||||||
const enableAuto = true;
|
const enableAuto = true;
|
||||||
export const startingLevel = 5;
|
export const startingLevel = 5;
|
||||||
|
@ -363,7 +364,11 @@ export default class BattleScene extends Phaser.Scene {
|
||||||
|
|
||||||
ui.setup();
|
ui.setup();
|
||||||
|
|
||||||
Promise.all([ Promise.all(loadPokemonAssets), initCommonAnims().then(() => loadCommonAnimAssets(this, true)) ]).then(() => {
|
Promise.all([
|
||||||
|
Promise.all(loadPokemonAssets),
|
||||||
|
initCommonAnims().then(() => loadCommonAnimAssets(this, true)),
|
||||||
|
initMoveAnim(Moves.STRUGGLE).then(() => loadMoveAnimAssets(this, [ Moves.STRUGGLE ], true))
|
||||||
|
]).then(() => {
|
||||||
if (enableAuto)
|
if (enableAuto)
|
||||||
initAutoPlay.apply(this);
|
initAutoPlay.apply(this);
|
||||||
|
|
||||||
|
|
62
src/move.ts
62
src/move.ts
|
@ -1184,6 +1184,60 @@ export class MissEffectAttr extends MoveAttr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class DisableMoveAttr extends MoveEffectAttr {
|
||||||
|
constructor() {
|
||||||
|
super(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||||
|
if (!super.apply(user, target, move, args))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const moveQueue = target.getLastXMoves();
|
||||||
|
let turnMove: TurnMove;
|
||||||
|
while (moveQueue.length) {
|
||||||
|
turnMove = moveQueue.shift();
|
||||||
|
if (turnMove.virtual)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const moveIndex = target.moveset.findIndex(m => m.moveId === turnMove.move);
|
||||||
|
if (moveIndex === -1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const disabledMove = target.moveset[moveIndex];
|
||||||
|
disabledMove.disableTurns = 4;
|
||||||
|
|
||||||
|
console.log(disabledMove);
|
||||||
|
|
||||||
|
user.scene.unshiftPhase(new MessagePhase(user.scene, getPokemonMessage(target, `'s ${disabledMove.getName()}\nwas disabled!`)))
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DisableMoveConditionalMoveAttr extends ConditionalMoveAttr {
|
||||||
|
constructor() {
|
||||||
|
super((user: Pokemon, target: Pokemon, move: Move) => {
|
||||||
|
const moveQueue = target.getLastXMoves();
|
||||||
|
let turnMove: TurnMove;
|
||||||
|
while (moveQueue.length) {
|
||||||
|
turnMove = moveQueue.shift();
|
||||||
|
if (turnMove.virtual)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const move = target.moveset.find(m => m.moveId === turnMove.move);
|
||||||
|
if (!move)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return !move.isDisabled();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class FrenzyAttr extends MoveEffectAttr {
|
export class FrenzyAttr extends MoveEffectAttr {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(true);
|
super(true);
|
||||||
|
@ -1302,16 +1356,12 @@ export class RandomMovesetMoveAttr extends OverrideMoveEffectAttr {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class RandomMoveAttr extends OverrideMoveEffectAttr {
|
export class RandomMoveAttr extends OverrideMoveEffectAttr {
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): Promise<boolean> {
|
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): Promise<boolean> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
const moveIds = Utils.getEnumValues(Moves).filter(m => m !== move.id);
|
const moveIds = Utils.getEnumValues(Moves).filter(m => m !== move.id);
|
||||||
const moveId = moveIds[Utils.randInt(moveIds.length)];
|
const moveId = moveIds[Utils.randInt(moveIds.length)];
|
||||||
user.summonData.moveQueue.push({ move: moveId, ignorePP: true });
|
user.summonData.moveQueue.push({ move: moveId, ignorePP: true });
|
||||||
user.scene.unshiftPhase(user.isPlayer() ? new PlayerMovePhase(user.scene, user as PlayerPokemon, new PokemonMove(moveId), true) : new EnemyMovePhase(user.scene, user as EnemyPokemon, new PokemonMove(moveId), true));
|
user.scene.unshiftPhase(user.isPlayer() ? new PlayerMovePhase(user.scene, user as PlayerPokemon, new PokemonMove(moveId, 0, 0, true), true) : new EnemyMovePhase(user.scene, user as EnemyPokemon, new PokemonMove(moveId, 0, 0, true), true));
|
||||||
initMoveAnim(moveId).then(() => {
|
initMoveAnim(moveId).then(() => {
|
||||||
loadMoveAnimAssets(user.scene, [ moveId ], true)
|
loadMoveAnimAssets(user.scene, [ moveId ], true)
|
||||||
.then(() => resolve(true));
|
.then(() => resolve(true));
|
||||||
|
@ -1374,7 +1424,7 @@ export const allMoves = [
|
||||||
new StatusMove(Moves.SING, "Sing", Type.NORMAL, 55, 15, -1, "Puts opponent to sleep.", -1, 0, 1, new StatusEffectAttr(StatusEffect.SLEEP)),
|
new StatusMove(Moves.SING, "Sing", Type.NORMAL, 55, 15, -1, "Puts opponent to sleep.", -1, 0, 1, new StatusEffectAttr(StatusEffect.SLEEP)),
|
||||||
new StatusMove(Moves.SUPERSONIC, "Supersonic", Type.NORMAL, 55, 20, -1, "Confuses opponent.", -1, 0, 1, new ConfuseAttr()),
|
new StatusMove(Moves.SUPERSONIC, "Supersonic", Type.NORMAL, 55, 20, -1, "Confuses opponent.", -1, 0, 1, new ConfuseAttr()),
|
||||||
new AttackMove(Moves.SONIC_BOOM, "Sonic Boom", Type.NORMAL, MoveCategory.SPECIAL, -1, 90, 20, -1, "Always inflicts 20 HP.", -1, 0, 1, new FixedDamageAttr(20)),
|
new AttackMove(Moves.SONIC_BOOM, "Sonic Boom", Type.NORMAL, MoveCategory.SPECIAL, -1, 90, 20, -1, "Always inflicts 20 HP.", -1, 0, 1, new FixedDamageAttr(20)),
|
||||||
new StatusMove(Moves.DISABLE, "Disable", Type.NORMAL, 100, 20, -1, "Opponent can't use its last attack for a few turns.", -1, 0, 1),
|
new StatusMove(Moves.DISABLE, "Disable", Type.NORMAL, 100, 20, -1, "Opponent can't use its last attack for a few turns.", -1, 0, 1, new DisableMoveConditionalMoveAttr(), new DisableMoveAttr()),
|
||||||
new AttackMove(Moves.ACID, "Acid", Type.POISON, MoveCategory.SPECIAL, 40, 100, 30, -1, "May lower opponent's Special Defense.", 10, 0, 1, new StatChangeAttr(BattleStat.SPDEF, -1)),
|
new AttackMove(Moves.ACID, "Acid", Type.POISON, MoveCategory.SPECIAL, 40, 100, 30, -1, "May lower opponent's Special Defense.", 10, 0, 1, new StatChangeAttr(BattleStat.SPDEF, -1)),
|
||||||
new AttackMove(Moves.EMBER, "Ember", Type.FIRE, MoveCategory.SPECIAL, 40, 100, 25, -1, "May burn opponent.", 10, 0, 1, new StatusEffectAttr(StatusEffect.BURN)),
|
new AttackMove(Moves.EMBER, "Ember", Type.FIRE, MoveCategory.SPECIAL, 40, 100, 25, -1, "May burn opponent.", 10, 0, 1, new StatusEffectAttr(StatusEffect.BURN)),
|
||||||
new AttackMove(Moves.FLAMETHROWER, "Flamethrower", Type.FIRE, MoveCategory.SPECIAL, 90, 100, 15, 125, "May burn opponent.", 10, 0, 1, new StatusEffectAttr(StatusEffect.BURN)),
|
new AttackMove(Moves.FLAMETHROWER, "Flamethrower", Type.FIRE, MoveCategory.SPECIAL, 90, 100, 15, 125, "May burn opponent.", 10, 0, 1, new StatusEffectAttr(StatusEffect.BURN)),
|
||||||
|
|
|
@ -874,8 +874,14 @@ export class EnemyPokemon extends Pokemon {
|
||||||
const queuedMove = this.summonData.moveQueue.length
|
const queuedMove = this.summonData.moveQueue.length
|
||||||
? this.moveset.find(m => m.moveId === this.summonData.moveQueue[0].move)
|
? this.moveset.find(m => m.moveId === this.summonData.moveQueue[0].move)
|
||||||
: null;
|
: null;
|
||||||
if (queuedMove && (this.summonData.moveQueue[0].ignorePP || queuedMove.isUsable()))
|
if (queuedMove) {
|
||||||
|
if (queuedMove.isUsable(this.summonData.moveQueue[0].ignorePP))
|
||||||
return queuedMove;
|
return queuedMove;
|
||||||
|
else {
|
||||||
|
this.summonData.moveQueue.shift();
|
||||||
|
return this.getNextMove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const movePool = this.moveset.filter(m => m.isUsable());
|
const movePool = this.moveset.filter(m => m.isUsable());
|
||||||
if (movePool.length) {
|
if (movePool.length) {
|
||||||
|
@ -949,6 +955,7 @@ export class EnemyPokemon extends Pokemon {
|
||||||
return sortedMovePool[r];
|
return sortedMovePool[r];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new PokemonMove(Moves.STRUGGLE, 0, 0);
|
return new PokemonMove(Moves.STRUGGLE, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -973,6 +980,7 @@ export class EnemyPokemon extends Pokemon {
|
||||||
export interface TurnMove {
|
export interface TurnMove {
|
||||||
move: Moves;
|
move: Moves;
|
||||||
result: MoveResult;
|
result: MoveResult;
|
||||||
|
virtual?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface QueuedMove {
|
export interface QueuedMove {
|
||||||
|
@ -1022,19 +1030,25 @@ export class PokemonMove {
|
||||||
public moveId: Moves;
|
public moveId: Moves;
|
||||||
public ppUsed: integer;
|
public ppUsed: integer;
|
||||||
public ppUp: integer;
|
public ppUp: integer;
|
||||||
|
public virtual: boolean;
|
||||||
public disableTurns: integer;
|
public disableTurns: integer;
|
||||||
|
|
||||||
constructor(moveId: Moves, ppUsed?: integer, ppUp?: integer) {
|
constructor(moveId: Moves, ppUsed?: integer, ppUp?: integer, virtual?: boolean) {
|
||||||
this.moveId = moveId;
|
this.moveId = moveId;
|
||||||
this.ppUsed = ppUsed || 0;
|
this.ppUsed = ppUsed || 0;
|
||||||
this.ppUp = ppUp || 0;
|
this.ppUp = ppUp || 0;
|
||||||
|
this.virtual = !!virtual;
|
||||||
this.disableTurns = 0;
|
this.disableTurns = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
isUsable(): boolean {
|
isUsable(ignorePp?: boolean): boolean {
|
||||||
if (this.disableTurns > 0)
|
if (this.isDisabled())
|
||||||
return false;
|
return false;
|
||||||
return this.ppUsed < this.getMove().pp + this.ppUp;
|
return ignorePp || this.ppUsed < this.getMove().pp + this.ppUp || this.getMove().pp === -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
isDisabled(): boolean {
|
||||||
|
return !!this.disableTurns;
|
||||||
}
|
}
|
||||||
|
|
||||||
getMove(): Move {
|
getMove(): Move {
|
||||||
|
|
Loading…
Reference in New Issue