Add charging moves and tag system
This commit is contained in:
parent
e3f7603f22
commit
791bf3cc49
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"id": 2004,
|
"id": 2006,
|
||||||
"graphic": "PRAS- Status",
|
"graphic": "PRAS- Status",
|
||||||
"frames": [
|
"frames": [
|
||||||
[
|
[
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"id": 2006,
|
"id": 2005,
|
||||||
"graphic": "PRAS- Status",
|
"graphic": "PRAS- Status",
|
||||||
"frames": [
|
"frames": [
|
||||||
[
|
[
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"id": 2005,
|
"id": 2003,
|
||||||
"graphic": "PRAS- Status",
|
"graphic": "PRAS- Status",
|
||||||
"frames": [
|
"frames": [
|
||||||
[
|
[
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"id": 2002,
|
"id": 2001,
|
||||||
"graphic": "PRAS- Status",
|
"graphic": "PRAS- Status",
|
||||||
"frames": [
|
"frames": [
|
||||||
[
|
[
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"id": 2001,
|
"id": 2004,
|
||||||
"graphic": "PRAS- Status",
|
"graphic": "PRAS- Status",
|
||||||
"frames": [
|
"frames": [
|
||||||
[
|
[
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"id": 2003,
|
"id": 2002,
|
||||||
"graphic": "PRAS- Poison",
|
"graphic": "PRAS- Poison",
|
||||||
"frames": [
|
"frames": [
|
||||||
[
|
[
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,8 +1,9 @@
|
||||||
//import { battleAnimRawData } from "./battle-anim-raw-data";
|
//import { battleAnimRawData } from "./battle-anim-raw-data";
|
||||||
import BattleScene from "./battle-scene";
|
import BattleScene from "./battle-scene";
|
||||||
import { Moves } from "./move";
|
import { ChargeAttr, Moves, allMoves } from "./move";
|
||||||
import Pokemon, { EnemyPokemon, PlayerPokemon } from "./pokemon";
|
import Pokemon, { EnemyPokemon, PlayerPokemon } from "./pokemon";
|
||||||
import * as Utils from "./utils";
|
import * as Utils from "./utils";
|
||||||
|
//import fs from 'vite-plugin-fs/browser';
|
||||||
|
|
||||||
export enum AnimFrameTarget {
|
export enum AnimFrameTarget {
|
||||||
USER,
|
USER,
|
||||||
|
@ -337,7 +338,7 @@ class AnimTimedAddBgEvent extends AnimTimedBgEvent {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const moveAnims = new Map<Moves, Anim | [Anim, Anim]>();
|
export const moveAnims = new Map<Moves, Anim | [Anim, Anim]>();
|
||||||
export const chargeAnims = new Map<ChargeAnim, Anim>();
|
export const chargeAnims = new Map<ChargeAnim, Anim | [Anim, Anim]>();
|
||||||
export const commonAnims = new Map<CommonAnim, Anim>();
|
export const commonAnims = new Map<CommonAnim, Anim>();
|
||||||
|
|
||||||
export function initCommonAnims(): Promise<void> {
|
export function initCommonAnims(): Promise<void> {
|
||||||
|
@ -378,6 +379,39 @@ export function initMoveAnim(move: Moves): Promise<void> {
|
||||||
populateMoveAnim(move, ba[1]);
|
populateMoveAnim(move, ba[1]);
|
||||||
} else
|
} else
|
||||||
populateMoveAnim(move, ba);
|
populateMoveAnim(move, ba);
|
||||||
|
const chargeAttr = allMoves[move - 1].getAttrs(ChargeAttr) as ChargeAttr[];
|
||||||
|
if (chargeAttr.length)
|
||||||
|
initMoveChargeAnim(chargeAttr[0].chargeAnim).then(() => resolve());
|
||||||
|
else
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function initMoveChargeAnim(chargeAnim: ChargeAnim): Promise<void> {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
if (chargeAnims.has(chargeAnim)) {
|
||||||
|
if (chargeAnims.get(chargeAnim) !== null)
|
||||||
|
resolve();
|
||||||
|
else {
|
||||||
|
let loadedCheckTimer = setInterval(() => {
|
||||||
|
if (chargeAnims.get(chargeAnim) !== null) {
|
||||||
|
clearInterval(loadedCheckTimer);
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
}, 50);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
chargeAnims.set(chargeAnim, null);
|
||||||
|
fetch(`./battle-anims/${ChargeAnim[chargeAnim].toLowerCase().replace(/\_/g, '-')}.json`)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(ca => {
|
||||||
|
if (Array.isArray(ca)) {
|
||||||
|
populateMoveChargeAnim(chargeAnim, ca[0]);
|
||||||
|
populateMoveChargeAnim(chargeAnim, ca[1]);
|
||||||
|
} else
|
||||||
|
populateMoveChargeAnim(chargeAnim, ca);
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -393,6 +427,15 @@ function populateMoveAnim(move: Moves, animSource: any) {
|
||||||
moveAnims.set(move, [ moveAnims.get(move) as Anim, moveAnim ]);
|
moveAnims.set(move, [ moveAnims.get(move) as Anim, moveAnim ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function populateMoveChargeAnim(chargeAnim: ChargeAnim, animSource: any) {
|
||||||
|
const moveChargeAnim = new Anim(animSource);
|
||||||
|
if (chargeAnims.get(chargeAnim) === null) {
|
||||||
|
chargeAnims.set(chargeAnim, moveChargeAnim);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
chargeAnims.set(chargeAnim, [ chargeAnims.get(chargeAnim) as Anim, moveChargeAnim ]);
|
||||||
|
}
|
||||||
|
|
||||||
export function loadCommonAnimAssets(scene: BattleScene, startLoad?: boolean): Promise<void> {
|
export function loadCommonAnimAssets(scene: BattleScene, startLoad?: boolean): Promise<void> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
loadAnimAssets(scene, Array.from(commonAnims.values()), startLoad).then(() => resolve());
|
loadAnimAssets(scene, Array.from(commonAnims.values()), startLoad).then(() => resolve());
|
||||||
|
@ -404,9 +447,16 @@ export function loadMoveAnimAssets(scene: BattleScene, moveIds: Moves[], startLo
|
||||||
const moveAnimations = moveIds.map(m => {
|
const moveAnimations = moveIds.map(m => {
|
||||||
const anims = moveAnims.get(m);
|
const anims = moveAnims.get(m);
|
||||||
if (anims instanceof Anim)
|
if (anims instanceof Anim)
|
||||||
return anims as Anim;
|
return anims;
|
||||||
return anims[0] as Anim;
|
return anims[0];
|
||||||
});
|
});
|
||||||
|
for (let moveId of moveIds) {
|
||||||
|
const chargeAttr = allMoves[moveId - 1].getAttrs(ChargeAttr) as ChargeAttr[];
|
||||||
|
if (chargeAttr.length) {
|
||||||
|
const moveChargeAnims = chargeAnims.get(chargeAttr[0].chargeAnim);
|
||||||
|
moveAnimations.push(moveChargeAnims instanceof Anim ? moveChargeAnims : moveChargeAnims[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
loadAnimAssets(scene, moveAnimations, startLoad).then(() => resolve());
|
loadAnimAssets(scene, moveAnimations, startLoad).then(() => resolve());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -457,14 +507,18 @@ export abstract class BattleAnim {
|
||||||
abstract isReverseCoords(): boolean;
|
abstract isReverseCoords(): boolean;
|
||||||
|
|
||||||
play(scene: BattleScene, callback?: Function) {
|
play(scene: BattleScene, callback?: Function) {
|
||||||
|
const isOppAnim = this.isOppAnim();
|
||||||
|
const user = !isOppAnim ? this.user : this.target;
|
||||||
|
const target = !isOppAnim ? this.target : this.user;
|
||||||
|
|
||||||
const anim = this.getAnim();
|
const anim = this.getAnim();
|
||||||
|
|
||||||
const userInitialX = this.user.x;
|
const userInitialX = user.x;
|
||||||
const userInitialY = this.user.y;
|
const userInitialY = user.y;
|
||||||
const userHalfHeight = this.user.getSprite().displayHeight / 2;
|
const userHalfHeight = user.getSprite().displayHeight / 2;
|
||||||
const targetInitialX = this.target.x;
|
const targetInitialX = target.x;
|
||||||
const targetInitialY = this.target.y;
|
const targetInitialY = target.y;
|
||||||
const targetHalfHeight = this.target.getSprite().displayHeight / 2;
|
const targetHalfHeight = target.getSprite().displayHeight / 2;
|
||||||
|
|
||||||
const coordMultiplier = this.isReverseCoords() ? -1 : 1;
|
const coordMultiplier = this.isReverseCoords() ? -1 : 1;
|
||||||
|
|
||||||
|
@ -483,10 +537,10 @@ export abstract class BattleAnim {
|
||||||
for (let frame of spriteFrames) {
|
for (let frame of spriteFrames) {
|
||||||
switch (frame.target) {
|
switch (frame.target) {
|
||||||
case AnimFrameTarget.USER:
|
case AnimFrameTarget.USER:
|
||||||
this.user.setPosition(userInitialX + frame.x * coordMultiplier, userInitialY + frame.y * coordMultiplier);
|
user.setPosition(userInitialX + frame.x * coordMultiplier, userInitialY + frame.y * coordMultiplier);
|
||||||
break;
|
break;
|
||||||
case AnimFrameTarget.TARGET:
|
case AnimFrameTarget.TARGET:
|
||||||
this.target.setPosition(targetInitialX + frame.x * coordMultiplier, targetInitialY + frame.y * coordMultiplier);
|
target.setPosition(targetInitialX + frame.x * coordMultiplier, targetInitialY + frame.y * coordMultiplier);
|
||||||
break;
|
break;
|
||||||
case AnimFrameTarget.GRAPHIC:
|
case AnimFrameTarget.GRAPHIC:
|
||||||
if (g === sprites.length) {
|
if (g === sprites.length) {
|
||||||
|
@ -498,16 +552,13 @@ export abstract class BattleAnim {
|
||||||
moveSprite.setFrame(frame.graphicFrame);
|
moveSprite.setFrame(frame.graphicFrame);
|
||||||
const xProgress = Math.min(Math.max(frame.x, 0) / 128, 1);
|
const xProgress = Math.min(Math.max(frame.x, 0) / 128, 1);
|
||||||
const yOffset = ((userHalfHeight * (1 - xProgress)) + (targetHalfHeight * xProgress)) * -1;
|
const yOffset = ((userHalfHeight * (1 - xProgress)) + (targetHalfHeight * xProgress)) * -1;
|
||||||
const isOppAnim = this.isOppAnim();
|
|
||||||
moveSprite.setPosition((!isOppAnim ? userInitialX : targetInitialX) + frame.x * coordMultiplier, (!isOppAnim ? userInitialY : targetInitialY) + yOffset + frame.y * coordMultiplier);
|
moveSprite.setPosition((!isOppAnim ? userInitialX : targetInitialX) + frame.x * coordMultiplier, (!isOppAnim ? userInitialY : targetInitialY) + yOffset + frame.y * coordMultiplier);
|
||||||
moveSprite.setAlpha(frame.opacity);
|
moveSprite.setAlpha(frame.opacity);
|
||||||
moveSprite.setAngle(-frame.angle * coordMultiplier);
|
moveSprite.setAngle(-frame.angle * coordMultiplier);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (frame.target !== AnimFrameTarget.GRAPHIC) {
|
if (frame.target !== AnimFrameTarget.GRAPHIC) {
|
||||||
const pokemon = frame.target === AnimFrameTarget.USER
|
const pokemon = frame.target === AnimFrameTarget.USER ? user : target;
|
||||||
? this.user
|
|
||||||
: this.target;
|
|
||||||
pokemon.setAlpha(frame.opacity);
|
pokemon.setAlpha(frame.opacity);
|
||||||
pokemon.setAngle(-frame.angle * coordMultiplier);
|
pokemon.setAngle(-frame.angle * coordMultiplier);
|
||||||
const zoomScaleX = frame.zoomX / 100;
|
const zoomScaleX = frame.zoomX / 100;
|
||||||
|
@ -530,22 +581,26 @@ export abstract class BattleAnim {
|
||||||
r--;
|
r--;
|
||||||
},
|
},
|
||||||
onComplete: () => {
|
onComplete: () => {
|
||||||
this.user.setPosition(userInitialX, userInitialY);
|
const cleanUpAndComplete = () => {
|
||||||
this.user.setAlpha(1);
|
user.setPosition(userInitialX, userInitialY);
|
||||||
this.user.setAngle(0);
|
user.setAlpha(1);
|
||||||
this.target.setPosition(targetInitialX, targetInitialY);
|
user.setAngle(0);
|
||||||
this.target.setAlpha(1);
|
target.setPosition(targetInitialX, targetInitialY);
|
||||||
this.target.setAngle(0);
|
target.setAlpha(1);
|
||||||
|
target.setAngle(0);
|
||||||
|
if (callback)
|
||||||
|
callback();
|
||||||
|
};
|
||||||
for (let ms of sprites)
|
for (let ms of sprites)
|
||||||
ms.destroy();
|
ms.destroy();
|
||||||
if (r && callback) {
|
if (r) {
|
||||||
scene.tweens.addCounter({
|
scene.tweens.addCounter({
|
||||||
duration: r,
|
duration: r,
|
||||||
useFrames: true,
|
useFrames: true,
|
||||||
onComplete: () => callback()
|
onComplete: () => cleanUpAndComplete()
|
||||||
});
|
});
|
||||||
} else if (callback)
|
} else
|
||||||
callback();
|
cleanUpAndComplete();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -597,6 +652,22 @@ export class MoveAnim extends BattleAnim {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class MoveChargeAnim extends MoveAnim {
|
||||||
|
private chargeAnim: ChargeAnim;
|
||||||
|
|
||||||
|
constructor(chargeAnim: ChargeAnim, move: Moves, user: Pokemon, target: Pokemon) {
|
||||||
|
super(move, user, target);
|
||||||
|
|
||||||
|
this.chargeAnim = chargeAnim;
|
||||||
|
}
|
||||||
|
|
||||||
|
getAnim(): Anim {
|
||||||
|
return chargeAnims.get(this.chargeAnim) instanceof Anim
|
||||||
|
? chargeAnims.get(this.chargeAnim) as Anim
|
||||||
|
: chargeAnims.get(this.chargeAnim)[this.user instanceof PlayerPokemon ? 0 : 1] as Anim;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function populateAnims() {
|
export function populateAnims() {
|
||||||
return;
|
return;
|
||||||
const commonAnimNames = Utils.getEnumKeys(CommonAnim).map(k => k.toLowerCase());
|
const commonAnimNames = Utils.getEnumKeys(CommonAnim).map(k => k.toLowerCase());
|
||||||
|
@ -605,7 +676,7 @@ export function populateAnims() {
|
||||||
const chargeAnimNames = Utils.getEnumKeys(ChargeAnim).map(k => k.toLowerCase());
|
const chargeAnimNames = Utils.getEnumKeys(ChargeAnim).map(k => k.toLowerCase());
|
||||||
const chargeAnimMatchNames = chargeAnimNames.map(k => k.replace(/\_/g, ' '));
|
const chargeAnimMatchNames = chargeAnimNames.map(k => k.replace(/\_/g, ' '));
|
||||||
const chargeAnimIds = Utils.getEnumValues(ChargeAnim) as ChargeAnim[];
|
const chargeAnimIds = Utils.getEnumValues(ChargeAnim) as ChargeAnim[];
|
||||||
const commonNamePattern = /name: (?:Common:)?(.*)/;
|
const commonNamePattern = /name: (?:Common:)?(Opp )?(.*)/;
|
||||||
const moveNameToId = {};
|
const moveNameToId = {};
|
||||||
for (let move of Utils.getEnumValues(Moves)) {
|
for (let move of Utils.getEnumValues(Moves)) {
|
||||||
const moveName = Moves[move].toUpperCase().replace(/\_/g, '');
|
const moveName = Moves[move].toUpperCase().replace(/\_/g, '');
|
||||||
|
@ -620,7 +691,7 @@ export function populateAnims() {
|
||||||
let chargeAnimId: ChargeAnim;
|
let chargeAnimId: ChargeAnim;
|
||||||
if (!fields[1].startsWith('name: Move:') && !(isOppMove = fields[1].startsWith('name: OppMove:'))) {
|
if (!fields[1].startsWith('name: Move:') && !(isOppMove = fields[1].startsWith('name: OppMove:'))) {
|
||||||
const nameMatch = commonNamePattern.exec(fields[1]);
|
const nameMatch = commonNamePattern.exec(fields[1]);
|
||||||
const name = nameMatch[1].toLowerCase();
|
const name = nameMatch[2].toLowerCase();
|
||||||
if (commonAnimMatchNames.indexOf(name) > -1)
|
if (commonAnimMatchNames.indexOf(name) > -1)
|
||||||
commonAnimId = commonAnimIds[commonAnimMatchNames.indexOf(name)];
|
commonAnimId = commonAnimIds[commonAnimMatchNames.indexOf(name)];
|
||||||
else if (chargeAnimMatchNames.indexOf(name) > -1)
|
else if (chargeAnimMatchNames.indexOf(name) > -1)
|
||||||
|
@ -635,7 +706,7 @@ export function populateAnims() {
|
||||||
if (commonAnimId)
|
if (commonAnimId)
|
||||||
commonAnims.set(commonAnimId, anim);
|
commonAnims.set(commonAnimId, anim);
|
||||||
else if (chargeAnimId)
|
else if (chargeAnimId)
|
||||||
chargeAnims.set(chargeAnimId, anim);
|
chargeAnims.set(chargeAnimId, !isOppMove ? anim : [ chargeAnims.get(chargeAnimId) as Anim, anim ]);
|
||||||
else
|
else
|
||||||
moveAnims.set(moveNameToId[animName], !isOppMove ? anim : [ moveAnims.get(moveNameToId[animName]) as Anim, anim ]);
|
moveAnims.set(moveNameToId[animName], !isOppMove ? anim : [ moveAnims.get(moveNameToId[animName]) as Anim, anim ]);
|
||||||
for (let f = 0; f < fields.length; f++) {
|
for (let f = 0; f < fields.length; f++) {
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import BattleScene from "./battle-scene";
|
import BattleScene from "./battle-scene";
|
||||||
import { default as Pokemon, PlayerPokemon, EnemyPokemon, PokemonMove } from "./pokemon";
|
import { default as Pokemon, PlayerPokemon, EnemyPokemon, PokemonMove, MoveResult } from "./pokemon";
|
||||||
import * as Utils from './utils';
|
import * as Utils from './utils';
|
||||||
import { allMoves, applyMoveAttrs, MissEffectAttr, MoveCategory, MoveHitEffectAttr, Moves, MultiHitAttr } from "./move";
|
import { allMoves, applyMoveAttrs, ChargeAttr, HitsTagAttr, MissEffectAttr, MoveCategory, MoveEffectAttr, MoveHitEffectAttr, Moves, MultiHitAttr, OverrideMoveEffectAttr } from "./move";
|
||||||
import { Mode } from './ui/ui';
|
import { Mode } from './ui/ui';
|
||||||
import { Command } from "./ui/command-ui-handler";
|
import { Command } from "./ui/command-ui-handler";
|
||||||
import { Stat } from "./pokemon-stat";
|
import { Stat } from "./pokemon-stat";
|
||||||
import { ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier } from "./modifier";
|
import { ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier } from "./modifier";
|
||||||
import PartyUiHandler, { PartyOption, PartyUiMode } from "./ui/party-ui-handler";
|
import PartyUiHandler, { PartyOption, PartyUiMode } from "./ui/party-ui-handler";
|
||||||
import { doPokeballBounceAnim, getPokeballAtlasKey, getPokeballCatchMultiplier, getPokeballTintColor, PokeballType } from "./pokeball";
|
import { doPokeballBounceAnim, getPokeballAtlasKey, getPokeballCatchMultiplier, getPokeballTintColor, PokeballType } from "./pokeball";
|
||||||
import { CommonAnim, CommonBattleAnim, MoveAnim, initMoveAnim, loadMoveAnimAssets } from "./battle-anims";
|
import { ChargeAnim, CommonAnim, CommonBattleAnim, MoveAnim, chargeAnims, initMoveAnim, loadMoveAnimAssets } from "./battle-anims";
|
||||||
import { StatusEffect, getStatusEffectActivationText, getStatusEffectHealText, getStatusEffectObtainText, getStatusEffectOverlapText } from "./status-effect";
|
import { StatusEffect, getStatusEffectActivationText, getStatusEffectHealText, getStatusEffectObtainText, getStatusEffectOverlapText } from "./status-effect";
|
||||||
import { SummaryUiMode } from "./ui/summary-ui-handler";
|
import { SummaryUiMode } from "./ui/summary-ui-handler";
|
||||||
import EvolutionSceneHandler from "./ui/evolution-scene-handler";
|
import EvolutionSceneHandler from "./ui/evolution-scene-handler";
|
||||||
|
@ -19,6 +19,7 @@ import { Biome, biomeLinks } from "./biome";
|
||||||
import { ModifierTypeOption, PokemonModifierType, PokemonMoveModifierType, getModifierTypeOptionsForWave, regenerateModifierPoolThresholds } from "./modifier-type";
|
import { ModifierTypeOption, PokemonModifierType, PokemonMoveModifierType, getModifierTypeOptionsForWave, regenerateModifierPoolThresholds } from "./modifier-type";
|
||||||
import PokemonSpecies from "./pokemon-species";
|
import PokemonSpecies from "./pokemon-species";
|
||||||
import SoundFade from "phaser3-rex-plugins/plugins/soundfade";
|
import SoundFade from "phaser3-rex-plugins/plugins/soundfade";
|
||||||
|
import { BattleTagLapseType } from "./battle-tag";
|
||||||
|
|
||||||
export class SelectStarterPhase extends BattlePhase {
|
export class SelectStarterPhase extends BattlePhase {
|
||||||
constructor(scene: BattleScene) {
|
constructor(scene: BattleScene) {
|
||||||
|
@ -395,12 +396,17 @@ export class CommandPhase extends BattlePhase {
|
||||||
start() {
|
start() {
|
||||||
super.start();
|
super.start();
|
||||||
|
|
||||||
this.scene.ui.setMode(Mode.COMMAND).then(() => {
|
const playerPokemon = this.scene.getPlayerPokemon();
|
||||||
this.scene.currentBattle.addParticipant(this.scene.getPlayerPokemon());
|
|
||||||
|
|
||||||
this.scene.getPlayerPokemon().resetTurnData();
|
this.scene.currentBattle.addParticipant(playerPokemon);
|
||||||
this.scene.getEnemyPokemon().resetTurnData();
|
|
||||||
});
|
playerPokemon.resetTurnData();
|
||||||
|
this.scene.getEnemyPokemon().resetTurnData();
|
||||||
|
|
||||||
|
if (playerPokemon.summonData.moveQueue.length)
|
||||||
|
this.handleCommand(Command.FIGHT, playerPokemon.moveset.findIndex(m => m.moveId === playerPokemon.summonData.moveQueue[0].move));
|
||||||
|
else
|
||||||
|
this.scene.ui.setMode(Mode.COMMAND);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleCommand(command: Command, cursor: integer): boolean {
|
handleCommand(command: Command, cursor: integer): boolean {
|
||||||
|
@ -454,6 +460,8 @@ export class CommandPhase extends BattlePhase {
|
||||||
for (let sef of statusEffectPhases)
|
for (let sef of statusEffectPhases)
|
||||||
this.scene.pushPhase(sef);
|
this.scene.pushPhase(sef);
|
||||||
|
|
||||||
|
this.scene.pushPhase(new TurnEndPhase(this.scene));
|
||||||
|
|
||||||
this.end();
|
this.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -465,6 +473,19 @@ export class CommandPhase extends BattlePhase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class TurnEndPhase extends BattlePhase {
|
||||||
|
constructor(scene: BattleScene) {
|
||||||
|
super(scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
this.scene.getPlayerPokemon().lapseTags(BattleTagLapseType.TURN_END);
|
||||||
|
this.scene.getEnemyPokemon().lapseTags(BattleTagLapseType.TURN_END);
|
||||||
|
|
||||||
|
this.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export abstract class PokemonPhase extends BattlePhase {
|
export abstract class PokemonPhase extends BattlePhase {
|
||||||
protected player: boolean;
|
protected player: boolean;
|
||||||
|
|
||||||
|
@ -522,7 +543,8 @@ abstract class MovePhase extends BattlePhase {
|
||||||
}
|
}
|
||||||
if (!this.move)
|
if (!this.move)
|
||||||
console.log(this.pokemon.moveset);
|
console.log(this.pokemon.moveset);
|
||||||
this.move.ppUsed++;
|
if (this.pokemon.summonData.moveQueue.length && !this.pokemon.summonData.moveQueue.shift().ignorePP)
|
||||||
|
this.move.ppUsed++;
|
||||||
this.scene.unshiftPhase(new MessagePhase(this.scene, `${this.pokemon.name} used\n${this.move.getName()}!`, 500));
|
this.scene.unshiftPhase(new MessagePhase(this.scene, `${this.pokemon.name} used\n${this.move.getName()}!`, 500));
|
||||||
this.scene.unshiftPhase(this.getEffectPhase());
|
this.scene.unshiftPhase(this.getEffectPhase());
|
||||||
this.end();
|
this.end();
|
||||||
|
@ -608,35 +630,53 @@ abstract class MoveEffectPhase extends PokemonPhase {
|
||||||
const user = this.getUserPokemon();
|
const user = this.getUserPokemon();
|
||||||
const target = this.getTargetPokemon();
|
const target = this.getTargetPokemon();
|
||||||
|
|
||||||
if (user.turnData.hitsLeft === undefined) {
|
const overridden = new Utils.BooleanHolder(false);
|
||||||
const hitCount = new Utils.IntegerHolder(1);
|
|
||||||
applyMoveAttrs(MultiHitAttr, this.scene, user, target, this.move.getMove(), hitCount);
|
|
||||||
user.turnData.hitCount = 0;
|
|
||||||
user.turnData.hitsLeft = user.turnData.hitsTotal = hitCount.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.hitCheck()) {
|
applyMoveAttrs(OverrideMoveEffectAttr, this.scene, user, target, this.move.getMove(), overridden).then(() => {
|
||||||
this.scene.unshiftPhase(new MessagePhase(this.scene, `${!this.player ? 'Foe ' : ''}${user.name}'s\nattack missed!`));
|
|
||||||
applyMoveAttrs(MissEffectAttr, this.scene, user, target, this.move.getMove());
|
|
||||||
this.end();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
new MoveAnim(this.move.getMove().id as Moves, user, target).play(this.scene, () => {
|
if (overridden.value) {
|
||||||
this.getTargetPokemon().apply(this.getUserPokemon(), this.move, () => {
|
|
||||||
++user.turnData.hitCount;
|
|
||||||
if (this.getTargetPokemon().hp)
|
|
||||||
applyMoveAttrs(MoveHitEffectAttr, this.scene, user, target, this.move.getMove());
|
|
||||||
this.end();
|
this.end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
user.lapseTags(BattleTagLapseType.MOVE);
|
||||||
|
|
||||||
|
if (user.turnData.hitsLeft === undefined) {
|
||||||
|
const hitCount = new Utils.IntegerHolder(1);
|
||||||
|
applyMoveAttrs(MultiHitAttr, this.scene, user, target, this.move.getMove(), hitCount);
|
||||||
|
user.turnData.hitCount = 0;
|
||||||
|
user.turnData.hitsLeft = user.turnData.hitsTotal = hitCount.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.hitCheck()) {
|
||||||
|
this.scene.unshiftPhase(new MessagePhase(this.scene, `${!this.player ? 'Foe ' : ''}${user.name}'s\nattack missed!`));
|
||||||
|
user.summonData.moveHistory.push({ move: this.move.moveId, result: MoveResult.MISSED });
|
||||||
|
applyMoveAttrs(MissEffectAttr, this.scene, user, target, this.move.getMove());
|
||||||
|
this.end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
new MoveAnim(this.move.getMove().id as Moves, user, target).play(this.scene, () => {
|
||||||
|
target.apply(user, this.move).then(result => {
|
||||||
|
++user.turnData.hitCount;
|
||||||
|
user.summonData.moveHistory.push({ move: this.move.moveId, result: result });
|
||||||
|
if (user.hp <= 0) {
|
||||||
|
this.scene.pushPhase(new FaintPhase(this.scene, this.player));
|
||||||
|
target.resetBattleSummonData();
|
||||||
|
}
|
||||||
|
if (target.hp <= 0) {
|
||||||
|
this.scene.pushPhase(new FaintPhase(this.scene, !this.player));
|
||||||
|
this.getUserPokemon().resetBattleSummonData();
|
||||||
|
}
|
||||||
|
if (target.hp) {
|
||||||
|
applyMoveAttrs(MoveEffectAttr, this.scene, 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
|
||||||
|
if (!this.move.getMove().getAttrs(ChargeAttr).filter(ca => (ca as ChargeAttr).chargeEffect).length)
|
||||||
|
applyMoveAttrs(MoveHitEffectAttr, this.scene, user, target, this.move.getMove());
|
||||||
|
}
|
||||||
|
this.end();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
if (this.getUserPokemon().hp <= 0) {
|
|
||||||
this.scene.pushPhase(new FaintPhase(this.scene, this.player));
|
|
||||||
this.getTargetPokemon().resetBattleSummonData();
|
|
||||||
}
|
|
||||||
if (this.getTargetPokemon().hp <= 0) {
|
|
||||||
this.scene.pushPhase(new FaintPhase(this.scene, !this.player));
|
|
||||||
this.getUserPokemon().resetBattleSummonData();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -644,13 +684,23 @@ abstract class MoveEffectPhase extends PokemonPhase {
|
||||||
const user = this.getUserPokemon();
|
const user = this.getUserPokemon();
|
||||||
if (--user.turnData.hitsLeft && this.getTargetPokemon().hp)
|
if (--user.turnData.hitsLeft && this.getTargetPokemon().hp)
|
||||||
this.scene.unshiftPhase(this.getNewHitPhase());
|
this.scene.unshiftPhase(this.getNewHitPhase());
|
||||||
else if (user.turnData.hitsTotal > 1)
|
else {
|
||||||
this.scene.unshiftPhase(new MessagePhase(this.scene, `Hit ${user.turnData.hitCount} time(s)!`));
|
if (user.turnData.hitsTotal > 1)
|
||||||
|
this.scene.unshiftPhase(new MessagePhase(this.scene, `Hit ${user.turnData.hitCount} time(s)!`));
|
||||||
|
}
|
||||||
|
|
||||||
super.end();
|
super.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
hitCheck(): boolean {
|
hitCheck(): boolean {
|
||||||
|
// Check if not self targeting for this
|
||||||
|
|
||||||
|
const hiddenTag = this.getTargetPokemon().getTag(t => t.isHidden());
|
||||||
|
if (hiddenTag) {
|
||||||
|
if (!this.move.getMove().getAttrs(HitsTagAttr).filter(hta => (hta as HitsTagAttr).tagType === hiddenTag.tagType).length)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.move.getMove().category !== MoveCategory.STATUS) {
|
if (this.move.getMove().category !== MoveCategory.STATUS) {
|
||||||
const userAccuracyLevel = this.getUserPokemon().summonData.battleStats[BattleStat.ACC];
|
const userAccuracyLevel = this.getUserPokemon().summonData.battleStats[BattleStat.ACC];
|
||||||
const targetEvasionLevel = this.getTargetPokemon().summonData.battleStats[BattleStat.EVA];
|
const targetEvasionLevel = this.getTargetPokemon().summonData.battleStats[BattleStat.EVA];
|
||||||
|
@ -890,6 +940,9 @@ export class FaintPhase extends PokemonPhase {
|
||||||
}
|
}
|
||||||
|
|
||||||
const pokemon = this.getPokemon();
|
const pokemon = this.getPokemon();
|
||||||
|
|
||||||
|
pokemon.lapseTags(BattleTagLapseType.FAINT);
|
||||||
|
|
||||||
pokemon.faintCry(() => {
|
pokemon.faintCry(() => {
|
||||||
pokemon.hideInfo();
|
pokemon.hideInfo();
|
||||||
this.scene.sound.play('faint');
|
this.scene.sound.play('faint');
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
export enum BattleTagType {
|
||||||
|
NONE,
|
||||||
|
FLYING,
|
||||||
|
UNDERGROUND
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum BattleTagLapseType {
|
||||||
|
FAINT,
|
||||||
|
MOVE,
|
||||||
|
TURN_END
|
||||||
|
}
|
||||||
|
|
||||||
|
export class BattleTag {
|
||||||
|
public tagType: BattleTagType;
|
||||||
|
public lapseType: BattleTagLapseType;
|
||||||
|
public turnCount: integer;
|
||||||
|
|
||||||
|
constructor(tagType: BattleTagType, lapseType: BattleTagLapseType, turnCount: integer) {
|
||||||
|
this.tagType = tagType;
|
||||||
|
this.lapseType = lapseType;
|
||||||
|
this.turnCount = turnCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
isHidden() {
|
||||||
|
switch (this.tagType) {
|
||||||
|
case BattleTagType.FLYING:
|
||||||
|
case BattleTagType.UNDERGROUND:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
122
src/move.ts
122
src/move.ts
|
@ -1,8 +1,10 @@
|
||||||
|
import { ChargeAnim, MoveChargeAnim } from "./battle-anims";
|
||||||
import { MessagePhase, ObtainStatusEffectPhase, StatChangePhase } from "./battle-phases";
|
import { MessagePhase, ObtainStatusEffectPhase, StatChangePhase } from "./battle-phases";
|
||||||
import BattleScene from "./battle-scene";
|
import BattleScene from "./battle-scene";
|
||||||
import { BattleStat } from "./battle-stat";
|
import { BattleStat } from "./battle-stat";
|
||||||
import Pokemon, { PlayerPokemon } from "./pokemon";
|
import Pokemon, { EnemyPokemon, MoveResult, PlayerPokemon, TurnMove } from "./pokemon";
|
||||||
import { StatusEffect, getStatusEffectOverlapText } from "./status-effect";
|
import { BattleTagLapseType, BattleTagType } from "./battle-tag";
|
||||||
|
import { StatusEffect } from "./status-effect";
|
||||||
import { Type } from "./type";
|
import { Type } from "./type";
|
||||||
import * as Utils from "./utils";
|
import * as Utils from "./utils";
|
||||||
|
|
||||||
|
@ -615,11 +617,14 @@ const enum MoveEffectText {
|
||||||
type MoveAttrFunc = (scene: BattleScene, user: Pokemon, target: Pokemon, move: Move) => void;
|
type MoveAttrFunc = (scene: BattleScene, user: Pokemon, target: Pokemon, move: Move) => void;
|
||||||
|
|
||||||
export abstract class MoveAttr {
|
export abstract class MoveAttr {
|
||||||
apply(scene: BattleScene, user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
apply(scene: BattleScene, user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean | Promise<boolean> {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class MoveEffectAttr extends MoveAttr {
|
||||||
|
}
|
||||||
|
|
||||||
export class MoveHitEffectAttr extends MoveAttr {
|
export class MoveHitEffectAttr extends MoveAttr {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -700,21 +705,45 @@ class OneHitKOAttr extends MoveHitEffectAttr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChargeAttr extends MoveAttr {
|
export class OverrideMoveEffectAttr extends MoveAttr { }
|
||||||
private chargeEffect: boolean;
|
|
||||||
|
|
||||||
constructor(chargeEffect?: boolean) {
|
export class ChargeAttr extends OverrideMoveEffectAttr {
|
||||||
|
public chargeAnim: ChargeAnim;
|
||||||
|
private chargeText: string;
|
||||||
|
private tagType: BattleTagType;
|
||||||
|
public chargeEffect: boolean;
|
||||||
|
|
||||||
|
constructor(chargeAnim: ChargeAnim, chargeText: string, tagType?: BattleTagType, chargeEffect?: boolean) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
this.chargeAnim = chargeAnim;
|
||||||
|
this.chargeText = chargeText;
|
||||||
|
this.tagType = tagType;
|
||||||
this.chargeEffect = !!chargeEffect;
|
this.chargeEffect = !!chargeEffect;
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(scene: BattleScene, user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
apply(scene: BattleScene, user: Pokemon, target: Pokemon, move: Move, args: any[]): Promise<boolean> {
|
||||||
return true;
|
return new Promise(resolve => {
|
||||||
|
const lastMove = user.getLastXMoves(1) as TurnMove[];
|
||||||
|
if (!lastMove.length || lastMove[0].move !== move.id || lastMove[0].result !== MoveResult.OTHER) {
|
||||||
|
(args[0] as Utils.BooleanHolder).value = true;
|
||||||
|
new MoveChargeAnim(this.chargeAnim, move.id, user, target).play(scene, () => {
|
||||||
|
scene.unshiftPhase(new MessagePhase(scene, `${user instanceof EnemyPokemon ? 'Foe ' : ''}${user.name} ${this.chargeText}`));
|
||||||
|
if (this.tagType)
|
||||||
|
user.addTag(this.tagType, BattleTagLapseType.MOVE);
|
||||||
|
if (this.chargeEffect)
|
||||||
|
applyMoveAttrs(MoveEffectAttr, scene, user, target, move);
|
||||||
|
user.summonData.moveHistory.push({ move: move.id, result: MoveResult.OTHER });
|
||||||
|
user.summonData.moveQueue.push({ move: move.id, ignorePP: true });
|
||||||
|
resolve(true);
|
||||||
|
});
|
||||||
|
} else
|
||||||
|
resolve(true);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class StatChangeAttr extends MoveHitEffectAttr {
|
export class StatChangeAttr extends MoveEffectAttr {
|
||||||
public stats: BattleStat[];
|
public stats: BattleStat[];
|
||||||
public levels: integer;
|
public levels: integer;
|
||||||
public selfTarget: boolean;
|
public selfTarget: boolean;
|
||||||
|
@ -758,13 +787,31 @@ export class MissEffectAttr extends MoveAttr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function applyMoveAttrs(attrType: { new(...args: any[]): MoveAttr }, scene: BattleScene, user: Pokemon, target: Pokemon, move: Move, ...args: any[]): void {
|
export class HitsTagAttr extends MoveAttr {
|
||||||
const moveAttrs = move.attrs.filter(a => a instanceof attrType);
|
public tagType: BattleTagType;
|
||||||
for (let attr of moveAttrs) {
|
public doubleDamage: boolean;
|
||||||
attr.apply(scene, user, target, move, args);
|
|
||||||
|
constructor(tagType: BattleTagType, doubleDamage?: boolean) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.tagType = tagType;
|
||||||
|
this.doubleDamage = !!doubleDamage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function applyMoveAttrs(attrType: { new(...args: any[]): MoveAttr }, scene: BattleScene, user: Pokemon, target: Pokemon, move: Move, ...args: any[]): Promise<void> {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
const attrPromises: Promise<boolean>[] = [];
|
||||||
|
const moveAttrs = move.attrs.filter(a => a instanceof attrType);
|
||||||
|
for (let attr of moveAttrs) {
|
||||||
|
const result = attr.apply(scene, user, target, move, args);
|
||||||
|
if (result instanceof Promise<boolean>)
|
||||||
|
attrPromises.push(result);
|
||||||
|
}
|
||||||
|
Promise.allSettled(attrPromises).then(() => resolve());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export const allMoves = [
|
export const allMoves = [
|
||||||
new Move(Moves.POUND, "Pound", Type.NORMAL, MoveCategory.PHYSICAL, 40, 100, 35, -1, "", -1, 1),
|
new Move(Moves.POUND, "Pound", Type.NORMAL, MoveCategory.PHYSICAL, 40, 100, 35, -1, "", -1, 1),
|
||||||
new Move(Moves.KARATE_CHOP, "Karate Chop", Type.FIGHTING, MoveCategory.PHYSICAL, 50, 100, 25, -1, "High critical hit ratio.", -1, 1, new HighCritAttr()),
|
new Move(Moves.KARATE_CHOP, "Karate Chop", Type.FIGHTING, MoveCategory.PHYSICAL, 50, 100, 25, -1, "High critical hit ratio.", -1, 1, new HighCritAttr()),
|
||||||
|
@ -778,13 +825,16 @@ export const allMoves = [
|
||||||
new Move(Moves.SCRATCH, "Scratch", Type.NORMAL, MoveCategory.PHYSICAL, 40, 100, 35, -1, "", -1, 1),
|
new Move(Moves.SCRATCH, "Scratch", Type.NORMAL, MoveCategory.PHYSICAL, 40, 100, 35, -1, "", -1, 1),
|
||||||
new Move(Moves.VISE_GRIP, "Vise Grip", Type.NORMAL, MoveCategory.PHYSICAL, 55, 100, 30, -1, "", -1, 1),
|
new Move(Moves.VISE_GRIP, "Vise Grip", Type.NORMAL, MoveCategory.PHYSICAL, 55, 100, 30, -1, "", -1, 1),
|
||||||
new Move(Moves.GUILLOTINE, "Guillotine", Type.NORMAL, MoveCategory.PHYSICAL, -1, 30, 5, -1, "One-Hit-KO, if it hits.", -1, 1, new OneHitKOAttr()),
|
new Move(Moves.GUILLOTINE, "Guillotine", Type.NORMAL, MoveCategory.PHYSICAL, -1, 30, 5, -1, "One-Hit-KO, if it hits.", -1, 1, new OneHitKOAttr()),
|
||||||
new Move(Moves.RAZOR_WIND, "Razor Wind", Type.NORMAL, MoveCategory.SPECIAL, 80, 100, 10, -1, "Charges on first turn, attacks on second. High critical hit ratio.", -1, 1, new ChargeAttr(), new HighCritAttr()),
|
new Move(Moves.RAZOR_WIND, "Razor Wind", Type.NORMAL, MoveCategory.SPECIAL, 80, 100, 10, -1, "Charges on first turn, attacks on second. High critical hit ratio.", -1, 1,
|
||||||
|
new ChargeAttr(ChargeAnim.RAZOR_WIND_CHARGING, 'whipped\nup a whirlwind!'), new HighCritAttr()),
|
||||||
new Move(Moves.SWORDS_DANCE, "Swords Dance", Type.NORMAL, MoveCategory.STATUS, -1, -1, 20, 88, "Sharply raises user's Attack.", -1, 1, new StatChangeAttr(BattleStat.ATK, 2, true)),
|
new Move(Moves.SWORDS_DANCE, "Swords Dance", Type.NORMAL, MoveCategory.STATUS, -1, -1, 20, 88, "Sharply raises user's Attack.", -1, 1, new StatChangeAttr(BattleStat.ATK, 2, true)),
|
||||||
new Move(Moves.CUT, "Cut", Type.NORMAL, MoveCategory.PHYSICAL, 50, 95, 30, -1, "", -1, 1),
|
new Move(Moves.CUT, "Cut", Type.NORMAL, MoveCategory.PHYSICAL, 50, 95, 30, -1, "", -1, 1),
|
||||||
new Move(Moves.GUST, "Gust", Type.FLYING, MoveCategory.SPECIAL, 40, 100, 35, -1, "Hits Pokémon using Fly/Bounce/Sky Drop with double power.", -1, 1), // TODO
|
new Move(Moves.GUST, "Gust", Type.FLYING, MoveCategory.SPECIAL, 40, 100, 35, -1, "Hits Pokémon using Fly/Bounce/Sky Drop with double power.", -1, 1,
|
||||||
|
new HitsTagAttr(BattleTagType.FLYING, true)),
|
||||||
new Move(Moves.WING_ATTACK, "Wing Attack", Type.FLYING, MoveCategory.PHYSICAL, 60, 100, 35, -1, "", -1, 1),
|
new Move(Moves.WING_ATTACK, "Wing Attack", Type.FLYING, MoveCategory.PHYSICAL, 60, 100, 35, -1, "", -1, 1),
|
||||||
new Move(Moves.WHIRLWIND, "Whirlwind", Type.NORMAL, MoveCategory.STATUS, -1, -1, 20, -1, "In battles, the opponent switches. In the wild, the Pokémon runs.", -1, 1), // TODO
|
new Move(Moves.WHIRLWIND, "Whirlwind", Type.NORMAL, MoveCategory.STATUS, -1, -1, 20, -1, "In battles, the opponent switches. In the wild, the Pokémon runs.", -1, 1), // TODO
|
||||||
new Move(Moves.FLY, "Fly", Type.FLYING, MoveCategory.PHYSICAL, 90, 95, 15, 97, "Flies up on first turn, attacks on second turn.", -1, 1, new ChargeAttr()),
|
new Move(Moves.FLY, "Fly", Type.FLYING, MoveCategory.PHYSICAL, 90, 95, 15, 97, "Flies up on first turn, attacks on second turn.", -1, 1,
|
||||||
|
new ChargeAttr(ChargeAnim.FLY_CHARGING, 'flew\nup high!', BattleTagType.FLYING)),
|
||||||
new Move(Moves.BIND, "Bind", Type.NORMAL, MoveCategory.PHYSICAL, 15, 85, 20, -1, "Traps opponent, damaging them for 4-5 turns.", 100, 1), // TODO
|
new Move(Moves.BIND, "Bind", Type.NORMAL, MoveCategory.PHYSICAL, 15, 85, 20, -1, "Traps opponent, damaging them for 4-5 turns.", 100, 1), // TODO
|
||||||
new Move(Moves.SLAM, "Slam", Type.NORMAL, MoveCategory.PHYSICAL, 80, 75, 20, -1, "", -1, 1),
|
new Move(Moves.SLAM, "Slam", Type.NORMAL, MoveCategory.PHYSICAL, 80, 75, 20, -1, "", -1, 1),
|
||||||
new Move(Moves.VINE_WHIP, "Vine Whip", Type.GRASS, MoveCategory.PHYSICAL, 45, 100, 25, -1, "", -1, 1),
|
new Move(Moves.VINE_WHIP, "Vine Whip", Type.GRASS, MoveCategory.PHYSICAL, 45, 100, 25, -1, "", -1, 1),
|
||||||
|
@ -842,7 +892,8 @@ export const allMoves = [
|
||||||
new Move(Moves.GROWTH, "Growth", Type.NORMAL, MoveCategory.STATUS, -1, -1, 20, -1, "Raises user's Attack and Special Attack.", -1, 1,
|
new Move(Moves.GROWTH, "Growth", Type.NORMAL, MoveCategory.STATUS, -1, -1, 20, -1, "Raises user's Attack and Special Attack.", -1, 1,
|
||||||
new StatChangeAttr([ BattleStat.ATK, BattleStat.SPATK ], 1, true)),
|
new StatChangeAttr([ BattleStat.ATK, BattleStat.SPATK ], 1, true)),
|
||||||
new Move(Moves.RAZOR_LEAF, "Razor Leaf", Type.GRASS, MoveCategory.PHYSICAL, 55, 95, 25, -1, "High critical hit ratio.", -1, 1),
|
new Move(Moves.RAZOR_LEAF, "Razor Leaf", Type.GRASS, MoveCategory.PHYSICAL, 55, 95, 25, -1, "High critical hit ratio.", -1, 1),
|
||||||
new Move(Moves.SOLAR_BEAM, "Solar Beam", Type.GRASS, MoveCategory.SPECIAL, 120, 100, 10, 168, "Charges on first turn, attacks on second.", -1, 1),
|
new Move(Moves.SOLAR_BEAM, "Solar Beam", Type.GRASS, MoveCategory.SPECIAL, 120, 100, 10, 168, "Charges on first turn, attacks on second.", -1, 1,
|
||||||
|
new ChargeAttr(ChargeAnim.SOLAR_BEAM_CHARGING, 'took\nin sunlight!')),
|
||||||
new Move(Moves.POISON_POWDER, "Poison Powder", Type.POISON, MoveCategory.STATUS, -1, 75, 35, -1, "Poisons opponent.", -1, 1, new StatusEffectAttr(StatusEffect.POISON)),
|
new Move(Moves.POISON_POWDER, "Poison Powder", Type.POISON, MoveCategory.STATUS, -1, 75, 35, -1, "Poisons opponent.", -1, 1, new StatusEffectAttr(StatusEffect.POISON)),
|
||||||
new Move(Moves.STUN_SPORE, "Stun Spore", Type.GRASS, MoveCategory.STATUS, -1, 75, 30, -1, "Paralyzes opponent.", -1, 1, new StatusEffectAttr(StatusEffect.PARALYSIS)),
|
new Move(Moves.STUN_SPORE, "Stun Spore", Type.GRASS, MoveCategory.STATUS, -1, 75, 30, -1, "Paralyzes opponent.", -1, 1, new StatusEffectAttr(StatusEffect.PARALYSIS)),
|
||||||
new Move(Moves.SLEEP_POWDER, "Sleep Powder", Type.GRASS, MoveCategory.STATUS, -1, 75, 15, -1, "Puts opponent to sleep.", -1, 1, new StatusEffectAttr(StatusEffect.SLEEP)),
|
new Move(Moves.SLEEP_POWDER, "Sleep Powder", Type.GRASS, MoveCategory.STATUS, -1, 75, 15, -1, "Puts opponent to sleep.", -1, 1, new StatusEffectAttr(StatusEffect.SLEEP)),
|
||||||
|
@ -855,9 +906,11 @@ export const allMoves = [
|
||||||
new Move(Moves.THUNDER_WAVE, "Thunder Wave", Type.ELECTRIC, MoveCategory.STATUS, -1, 90, 20, 82, "Paralyzes opponent.", -1, 1, new StatusEffectAttr(StatusEffect.PARALYSIS)),
|
new Move(Moves.THUNDER_WAVE, "Thunder Wave", Type.ELECTRIC, MoveCategory.STATUS, -1, 90, 20, 82, "Paralyzes opponent.", -1, 1, new StatusEffectAttr(StatusEffect.PARALYSIS)),
|
||||||
new Move(Moves.THUNDER, "Thunder", Type.ELECTRIC, MoveCategory.SPECIAL, 110, 70, 10, 166, "May paralyze opponent.", 30, 1, new StatusEffectAttr(StatusEffect.PARALYSIS)),
|
new Move(Moves.THUNDER, "Thunder", Type.ELECTRIC, MoveCategory.SPECIAL, 110, 70, 10, 166, "May paralyze opponent.", 30, 1, new StatusEffectAttr(StatusEffect.PARALYSIS)),
|
||||||
new Move(Moves.ROCK_THROW, "Rock Throw", Type.ROCK, MoveCategory.PHYSICAL, 50, 90, 15, -1, "", -1, 1),
|
new Move(Moves.ROCK_THROW, "Rock Throw", Type.ROCK, MoveCategory.PHYSICAL, 50, 90, 15, -1, "", -1, 1),
|
||||||
new Move(Moves.EARTHQUAKE, "Earthquake", Type.GROUND, MoveCategory.PHYSICAL, 100, 100, 10, 149, "Power is doubled if opponent is underground from using Dig.", -1, 1),
|
new Move(Moves.EARTHQUAKE, "Earthquake", Type.GROUND, MoveCategory.PHYSICAL, 100, 100, 10, 149, "Power is doubled if opponent is underground from using Dig.", -1, 1,
|
||||||
|
new HitsTagAttr(BattleTagType.UNDERGROUND, true)),
|
||||||
new Move(Moves.FISSURE, "Fissure", Type.GROUND, MoveCategory.PHYSICAL, -1, 30, 5, -1, "One-Hit-KO, if it hits.", -1, 1, new OneHitKOAttr()),
|
new Move(Moves.FISSURE, "Fissure", Type.GROUND, MoveCategory.PHYSICAL, -1, 30, 5, -1, "One-Hit-KO, if it hits.", -1, 1, new OneHitKOAttr()),
|
||||||
new Move(Moves.DIG, "Dig", Type.GROUND, MoveCategory.PHYSICAL, 80, 100, 10, 55, "Digs underground on first turn, attacks on second. Can also escape from caves.", -1, 1),
|
new Move(Moves.DIG, "Dig", Type.GROUND, MoveCategory.PHYSICAL, 80, 100, 10, 55, "Digs underground on first turn, attacks on second. Can also escape from caves.", -1, 1,
|
||||||
|
new ChargeAttr(ChargeAnim.DIG_CHARGING, 'dug a hole!', BattleTagType.UNDERGROUND)),
|
||||||
new Move(Moves.TOXIC, "Toxic", Type.POISON, MoveCategory.STATUS, -1, 90, 10, -1, "Badly poisons opponent.", -1, 1, new StatusEffectAttr(StatusEffect.TOXIC)),
|
new Move(Moves.TOXIC, "Toxic", Type.POISON, MoveCategory.STATUS, -1, 90, 10, -1, "Badly poisons opponent.", -1, 1, new StatusEffectAttr(StatusEffect.TOXIC)),
|
||||||
new Move(Moves.CONFUSION, "Confusion", Type.PSYCHIC, MoveCategory.SPECIAL, 50, 100, 25, -1, "May confuse opponent.", 10, 1), // TODO
|
new Move(Moves.CONFUSION, "Confusion", Type.PSYCHIC, MoveCategory.SPECIAL, 50, 100, 25, -1, "May confuse opponent.", 10, 1), // TODO
|
||||||
new Move(Moves.PSYCHIC, "Psychic", Type.PSYCHIC, MoveCategory.SPECIAL, 90, 100, 10, 120, "May lower opponent's Special Defense.", 10, 1, new StatChangeAttr(BattleStat.SPDEF, -1)),
|
new Move(Moves.PSYCHIC, "Psychic", Type.PSYCHIC, MoveCategory.SPECIAL, 90, 100, 10, 120, "May lower opponent's Special Defense.", 10, 1, new StatChangeAttr(BattleStat.SPDEF, -1)),
|
||||||
|
@ -896,7 +949,8 @@ export const allMoves = [
|
||||||
new Move(Moves.WATERFALL, "Waterfall", Type.WATER, MoveCategory.PHYSICAL, 80, 100, 15, 77, "May cause flinching.", 20, 1, new FlinchAttr()),
|
new Move(Moves.WATERFALL, "Waterfall", Type.WATER, MoveCategory.PHYSICAL, 80, 100, 15, 77, "May cause flinching.", 20, 1, new FlinchAttr()),
|
||||||
new Move(Moves.CLAMP, "Clamp", Type.WATER, MoveCategory.PHYSICAL, 35, 85, 15, -1, "Traps opponent, damaging them for 4-5 turns.", 100, 1),
|
new Move(Moves.CLAMP, "Clamp", Type.WATER, MoveCategory.PHYSICAL, 35, 85, 15, -1, "Traps opponent, damaging them for 4-5 turns.", 100, 1),
|
||||||
new Move(Moves.SWIFT, "Swift", Type.NORMAL, MoveCategory.SPECIAL, 60, 999, 20, 32, "Ignores Accuracy and Evasiveness.", -1, 1),
|
new Move(Moves.SWIFT, "Swift", Type.NORMAL, MoveCategory.SPECIAL, 60, 999, 20, 32, "Ignores Accuracy and Evasiveness.", -1, 1),
|
||||||
new Move(Moves.SKULL_BASH, "Skull Bash", Type.NORMAL, MoveCategory.PHYSICAL, 130, 100, 10, -1, "Raises Defense on first turn, attacks on second.", 100, 1, new ChargeAttr(true), new StatChangeAttr(BattleStat.DEF, 1, true)),
|
new Move(Moves.SKULL_BASH, "Skull Bash", Type.NORMAL, MoveCategory.PHYSICAL, 130, 100, 10, -1, "Raises Defense on first turn, attacks on second.", 100, 1,
|
||||||
|
new ChargeAttr(ChargeAnim.SKULL_BASH_CHARGING, 'lowered\nits head!', null, true), new StatChangeAttr(BattleStat.DEF, 1, true)),
|
||||||
new Move(Moves.SPIKE_CANNON, "Spike Cannon", Type.NORMAL, MoveCategory.PHYSICAL, 20, 100, 15, -1, "Hits 2-5 times in one turn.", -1, 1, new MultiHitAttr()),
|
new Move(Moves.SPIKE_CANNON, "Spike Cannon", Type.NORMAL, MoveCategory.PHYSICAL, 20, 100, 15, -1, "Hits 2-5 times in one turn.", -1, 1, new MultiHitAttr()),
|
||||||
new Move(Moves.CONSTRICT, "Constrict", Type.NORMAL, MoveCategory.PHYSICAL, 10, 100, 35, -1, "May lower opponent's Speed by one stage.", 10, 1, new StatChangeAttr(BattleStat.SPD, -1)),
|
new Move(Moves.CONSTRICT, "Constrict", Type.NORMAL, MoveCategory.PHYSICAL, 10, 100, 35, -1, "May lower opponent's Speed by one stage.", 10, 1, new StatChangeAttr(BattleStat.SPD, -1)),
|
||||||
new Move(Moves.AMNESIA, "Amnesia", Type.PSYCHIC, MoveCategory.STATUS, -1, -1, 20, 128, "Sharply raises user's Special Defense.", -1, 1, new StatChangeAttr(BattleStat.SPDEF, 2, true)),
|
new Move(Moves.AMNESIA, "Amnesia", Type.PSYCHIC, MoveCategory.STATUS, -1, -1, 20, 128, "Sharply raises user's Special Defense.", -1, 1, new StatChangeAttr(BattleStat.SPDEF, 2, true)),
|
||||||
|
@ -910,7 +964,8 @@ export const allMoves = [
|
||||||
new Move(Moves.BARRAGE, "Barrage", Type.NORMAL, MoveCategory.PHYSICAL, 15, 85, 20, -1, "Hits 2-5 times in one turn.", -1, 1, new MultiHitAttr()),
|
new Move(Moves.BARRAGE, "Barrage", Type.NORMAL, MoveCategory.PHYSICAL, 15, 85, 20, -1, "Hits 2-5 times in one turn.", -1, 1, new MultiHitAttr()),
|
||||||
new Move(Moves.LEECH_LIFE, "Leech Life", Type.BUG, MoveCategory.PHYSICAL, 80, 100, 10, 95, "User recovers half the HP inflicted on opponent.", -1, 1),
|
new Move(Moves.LEECH_LIFE, "Leech Life", Type.BUG, MoveCategory.PHYSICAL, 80, 100, 10, 95, "User recovers half the HP inflicted on opponent.", -1, 1),
|
||||||
new Move(Moves.LOVELY_KISS, "Lovely Kiss", Type.NORMAL, MoveCategory.STATUS, -1, 75, 10, -1, "Puts opponent to sleep.", -1, 1, new StatusEffectAttr(StatusEffect.SLEEP)),
|
new Move(Moves.LOVELY_KISS, "Lovely Kiss", Type.NORMAL, MoveCategory.STATUS, -1, 75, 10, -1, "Puts opponent to sleep.", -1, 1, new StatusEffectAttr(StatusEffect.SLEEP)),
|
||||||
new Move(Moves.SKY_ATTACK, "Sky Attack", Type.FLYING, MoveCategory.PHYSICAL, 140, 90, 5, -1, "Charges on first turn, attacks on second. May cause flinching. High critical hit ratio.", 30, 1, new ChargeAttr(), new HighCritAttr(), new FlinchAttr()),
|
new Move(Moves.SKY_ATTACK, "Sky Attack", Type.FLYING, MoveCategory.PHYSICAL, 140, 90, 5, -1, "Charges on first turn, attacks on second. May cause flinching. High critical hit ratio.", 30, 1,
|
||||||
|
new ChargeAttr(ChargeAnim.SKY_ATTACK_CHARGING, 'is glowing!'), new HighCritAttr(), new FlinchAttr()),
|
||||||
new Move(Moves.TRANSFORM, "Transform", Type.NORMAL, MoveCategory.STATUS, -1, -1, 10, -1, "User takes on the form and attacks of the opponent.", -1, 1),
|
new Move(Moves.TRANSFORM, "Transform", Type.NORMAL, MoveCategory.STATUS, -1, -1, 10, -1, "User takes on the form and attacks of the opponent.", -1, 1),
|
||||||
new Move(Moves.BUBBLE, "Bubble", Type.WATER, MoveCategory.SPECIAL, 40, 100, 30, -1, "May lower opponent's Speed.", 10, 1, new StatChangeAttr(BattleStat.SPD, -1)),
|
new Move(Moves.BUBBLE, "Bubble", Type.WATER, MoveCategory.SPECIAL, 40, 100, 30, -1, "May lower opponent's Speed.", 10, 1, new StatChangeAttr(BattleStat.SPD, -1)),
|
||||||
new Move(Moves.DIZZY_PUNCH, "Dizzy Punch", Type.NORMAL, MoveCategory.PHYSICAL, 70, 100, 10, -1, "May confuse opponent.", 20, 1), // TODO
|
new Move(Moves.DIZZY_PUNCH, "Dizzy Punch", Type.NORMAL, MoveCategory.PHYSICAL, 70, 100, 10, -1, "May confuse opponent.", 20, 1), // TODO
|
||||||
|
@ -1007,7 +1062,8 @@ export const allMoves = [
|
||||||
new Move(Moves.MOONLIGHT, "Moonlight", Type.FAIRY, MoveCategory.STATUS, -1, -1, 5, -1, "User recovers HP. Amount varies with the weather.", -1, 2),
|
new Move(Moves.MOONLIGHT, "Moonlight", Type.FAIRY, MoveCategory.STATUS, -1, -1, 5, -1, "User recovers HP. Amount varies with the weather.", -1, 2),
|
||||||
new Move(Moves.HIDDEN_POWER, "Hidden Power", Type.NORMAL, MoveCategory.SPECIAL, 60, 100, 15, -1, "Type and power depends on user's IVs.", -1, 2),
|
new Move(Moves.HIDDEN_POWER, "Hidden Power", Type.NORMAL, MoveCategory.SPECIAL, 60, 100, 15, -1, "Type and power depends on user's IVs.", -1, 2),
|
||||||
new Move(Moves.CROSS_CHOP, "Cross Chop", Type.FIGHTING, MoveCategory.PHYSICAL, 100, 80, 5, -1, "High critical hit ratio.", -1, 2, new HighCritAttr()),
|
new Move(Moves.CROSS_CHOP, "Cross Chop", Type.FIGHTING, MoveCategory.PHYSICAL, 100, 80, 5, -1, "High critical hit ratio.", -1, 2, new HighCritAttr()),
|
||||||
new Move(Moves.TWISTER, "Twister", Type.DRAGON, MoveCategory.SPECIAL, 40, 100, 20, -1, "May cause flinching. Hits Pokémon using Fly/Bounce with double power.", 20, 2, new FlinchAttr()), // TODO
|
new Move(Moves.TWISTER, "Twister", Type.DRAGON, MoveCategory.SPECIAL, 40, 100, 20, -1, "May cause flinching. Hits Pokémon using Fly/Bounce with double power.", 20, 2,
|
||||||
|
new HitsTagAttr(BattleTagType.FLYING, true), new FlinchAttr()), // TODO
|
||||||
new Move(Moves.RAIN_DANCE, "Rain Dance", Type.WATER, MoveCategory.STATUS, -1, -1, 5, 50, "Makes it rain for 5 turns.", -1, 2),
|
new Move(Moves.RAIN_DANCE, "Rain Dance", Type.WATER, MoveCategory.STATUS, -1, -1, 5, 50, "Makes it rain for 5 turns.", -1, 2),
|
||||||
new Move(Moves.SUNNY_DAY, "Sunny Day", Type.FIRE, MoveCategory.STATUS, -1, -1, 5, 49, "Makes it sunny for 5 turns.", -1, 2),
|
new Move(Moves.SUNNY_DAY, "Sunny Day", Type.FIRE, MoveCategory.STATUS, -1, -1, 5, 49, "Makes it sunny for 5 turns.", -1, 2),
|
||||||
new Move(Moves.CRUNCH, "Crunch", Type.DARK, MoveCategory.PHYSICAL, 80, 100, 15, 108, "May lower opponent's Defense.", 20, 2, new StatChangeAttr(BattleStat.DEF, -1)),
|
new Move(Moves.CRUNCH, "Crunch", Type.DARK, MoveCategory.PHYSICAL, 80, 100, 15, 108, "May lower opponent's Defense.", 20, 2, new StatChangeAttr(BattleStat.DEF, -1)),
|
||||||
|
@ -1062,7 +1118,8 @@ export const allMoves = [
|
||||||
new Move(Moves.GRUDGE, "Grudge", Type.GHOST, MoveCategory.STATUS, -1, -1, 5, -1, "If the users faints after using this move, the PP for the opponent's last move is depleted.", -1, 3),
|
new Move(Moves.GRUDGE, "Grudge", Type.GHOST, MoveCategory.STATUS, -1, -1, 5, -1, "If the users faints after using this move, the PP for the opponent's last move is depleted.", -1, 3),
|
||||||
new Move(Moves.SNATCH, "Snatch", Type.DARK, MoveCategory.STATUS, -1, -1, 10, -1, "Steals the effects of the opponent's next move.", -1, 3),
|
new Move(Moves.SNATCH, "Snatch", Type.DARK, MoveCategory.STATUS, -1, -1, 10, -1, "Steals the effects of the opponent's next move.", -1, 3),
|
||||||
new Move(Moves.SECRET_POWER, "Secret Power", Type.NORMAL, MoveCategory.PHYSICAL, 70, 100, 20, -1, "Effects of the attack vary with the location.", 30, 3),
|
new Move(Moves.SECRET_POWER, "Secret Power", Type.NORMAL, MoveCategory.PHYSICAL, 70, 100, 20, -1, "Effects of the attack vary with the location.", 30, 3),
|
||||||
new Move(Moves.DIVE, "Dive", Type.WATER, MoveCategory.PHYSICAL, 80, 100, 10, -1, "Dives underwater on first turn, attacks on second turn.", -1, 3, new ChargeAttr()),
|
new Move(Moves.DIVE, "Dive", Type.WATER, MoveCategory.PHYSICAL, 80, 100, 10, -1, "Dives underwater on first turn, attacks on second turn.", -1, 3,
|
||||||
|
new ChargeAttr(ChargeAnim.DIVE_CHARGING, 'hid\nunderwater!')),
|
||||||
new Move(Moves.ARM_THRUST, "Arm Thrust", Type.FIGHTING, MoveCategory.PHYSICAL, 15, 100, 20, -1, "Hits 2-5 times in one turn.", -1, 3, new MultiHitAttr()),
|
new Move(Moves.ARM_THRUST, "Arm Thrust", Type.FIGHTING, MoveCategory.PHYSICAL, 15, 100, 20, -1, "Hits 2-5 times in one turn.", -1, 3, new MultiHitAttr()),
|
||||||
new Move(Moves.CAMOUFLAGE, "Camouflage", Type.NORMAL, MoveCategory.STATUS, -1, -1, 20, -1, "Changes user's type according to the location.", -1, 3),
|
new Move(Moves.CAMOUFLAGE, "Camouflage", Type.NORMAL, MoveCategory.STATUS, -1, -1, 20, -1, "Changes user's type according to the location.", -1, 3),
|
||||||
new Move(Moves.TAIL_GLOW, "Tail Glow", Type.BUG, MoveCategory.STATUS, -1, -1, 20, -1, "Drastically raises user's Special Attack.", -1, 3, new StatChangeAttr(BattleStat.SPATK, 3, true)),
|
new Move(Moves.TAIL_GLOW, "Tail Glow", Type.BUG, MoveCategory.STATUS, -1, -1, 20, -1, "Drastically raises user's Special Attack.", -1, 3, new StatChangeAttr(BattleStat.SPATK, 3, true)),
|
||||||
|
@ -1101,7 +1158,7 @@ export const allMoves = [
|
||||||
new Move(Moves.SIGNAL_BEAM, "Signal Beam", Type.BUG, MoveCategory.SPECIAL, 75, 100, 15, -1, "May confuse opponent.", 10, 3), // TODO
|
new Move(Moves.SIGNAL_BEAM, "Signal Beam", Type.BUG, MoveCategory.SPECIAL, 75, 100, 15, -1, "May confuse opponent.", 10, 3), // TODO
|
||||||
new Move(Moves.SHADOW_PUNCH, "Shadow Punch", Type.GHOST, MoveCategory.PHYSICAL, 60, 999, 20, -1, "Ignores Accuracy and Evasiveness.", -1, 3),
|
new Move(Moves.SHADOW_PUNCH, "Shadow Punch", Type.GHOST, MoveCategory.PHYSICAL, 60, 999, 20, -1, "Ignores Accuracy and Evasiveness.", -1, 3),
|
||||||
new Move(Moves.EXTRASENSORY, "Extrasensory", Type.PSYCHIC, MoveCategory.SPECIAL, 80, 100, 20, -1, "May cause flinching.", 10, 3, new FlinchAttr()),
|
new Move(Moves.EXTRASENSORY, "Extrasensory", Type.PSYCHIC, MoveCategory.SPECIAL, 80, 100, 20, -1, "May cause flinching.", 10, 3, new FlinchAttr()),
|
||||||
new Move(Moves.SKY_UPPERCUT, "Sky Uppercut", Type.FIGHTING, MoveCategory.PHYSICAL, 85, 90, 15, -1, "Hits the opponent, even during Fly.", -1, 3),
|
new Move(Moves.SKY_UPPERCUT, "Sky Uppercut", Type.FIGHTING, MoveCategory.PHYSICAL, 85, 90, 15, -1, "Hits the opponent, even during Fly.", -1, 3, new HitsTagAttr(BattleTagType.FLYING)),
|
||||||
new Move(Moves.SAND_TOMB, "Sand Tomb", Type.GROUND, MoveCategory.PHYSICAL, 35, 85, 15, -1, "Traps opponent, damaging them for 4-5 turns.", 100, 3),
|
new Move(Moves.SAND_TOMB, "Sand Tomb", Type.GROUND, MoveCategory.PHYSICAL, 35, 85, 15, -1, "Traps opponent, damaging them for 4-5 turns.", 100, 3),
|
||||||
new Move(Moves.SHEER_COLD, "Sheer Cold", Type.ICE, MoveCategory.SPECIAL, -1, 30, 5, -1, "One-Hit-KO, if it hits.", -1, 3),
|
new Move(Moves.SHEER_COLD, "Sheer Cold", Type.ICE, MoveCategory.SPECIAL, -1, 30, 5, -1, "One-Hit-KO, if it hits.", -1, 3),
|
||||||
new Move(Moves.MUDDY_WATER, "Muddy Water", Type.WATER, MoveCategory.SPECIAL, 90, 85, 10, -1, "May lower opponent's Accuracy.", 30, 3, new StatChangeAttr(BattleStat.ACC, -1)),
|
new Move(Moves.MUDDY_WATER, "Muddy Water", Type.WATER, MoveCategory.SPECIAL, 90, 85, 10, -1, "May lower opponent's Accuracy.", 30, 3, new StatChangeAttr(BattleStat.ACC, -1)),
|
||||||
|
@ -1115,7 +1172,8 @@ export const allMoves = [
|
||||||
new Move(Moves.FRENZY_PLANT, "Frenzy Plant", Type.GRASS, MoveCategory.SPECIAL, 150, 90, 5, 155, "User must recharge next turn.", -1, 3),
|
new Move(Moves.FRENZY_PLANT, "Frenzy Plant", Type.GRASS, MoveCategory.SPECIAL, 150, 90, 5, 155, "User must recharge next turn.", -1, 3),
|
||||||
new Move(Moves.BULK_UP, "Bulk Up", Type.FIGHTING, MoveCategory.STATUS, -1, -1, 20, 64, "Raises user's Attack and Defense.", -1, 3,
|
new Move(Moves.BULK_UP, "Bulk Up", Type.FIGHTING, MoveCategory.STATUS, -1, -1, 20, 64, "Raises user's Attack and Defense.", -1, 3,
|
||||||
new StatChangeAttr([ BattleStat.ATK, BattleStat.DEF ], 1, true)),
|
new StatChangeAttr([ BattleStat.ATK, BattleStat.DEF ], 1, true)),
|
||||||
new Move(Moves.BOUNCE, "Bounce", Type.FLYING, MoveCategory.PHYSICAL, 85, 85, 5, -1, "Springs up on first turn, attacks on second. May paralyze opponent.", 30, 3, new ChargeAttr(), new StatusEffectAttr(StatusEffect.PARALYSIS)),
|
new Move(Moves.BOUNCE, "Bounce", Type.FLYING, MoveCategory.PHYSICAL, 85, 85, 5, -1, "Springs up on first turn, attacks on second. May paralyze opponent.", 30, 3,
|
||||||
|
new ChargeAttr(ChargeAnim.BOUNCE_CHARGING, 'sprang up!', BattleTagType.FLYING), new StatusEffectAttr(StatusEffect.PARALYSIS)),
|
||||||
new Move(Moves.MUD_SHOT, "Mud Shot", Type.GROUND, MoveCategory.SPECIAL, 55, 95, 15, 35, "Lowers opponent's Speed.", 100, 3, new StatChangeAttr(BattleStat.SPD, -1)),
|
new Move(Moves.MUD_SHOT, "Mud Shot", Type.GROUND, MoveCategory.SPECIAL, 55, 95, 15, 35, "Lowers opponent's Speed.", 100, 3, new StatChangeAttr(BattleStat.SPD, -1)),
|
||||||
new Move(Moves.POISON_TAIL, "Poison Tail", Type.POISON, MoveCategory.PHYSICAL, 50, 100, 25, 26, "High critical hit ratio. May poison opponent.", 10, 3, new HighCritAttr(), new StatusEffectAttr(StatusEffect.POISON)),
|
new Move(Moves.POISON_TAIL, "Poison Tail", Type.POISON, MoveCategory.PHYSICAL, 50, 100, 25, 26, "High critical hit ratio. May poison opponent.", 10, 3, new HighCritAttr(), new StatusEffectAttr(StatusEffect.POISON)),
|
||||||
new Move(Moves.COVET, "Covet", Type.NORMAL, MoveCategory.PHYSICAL, 60, 100, 25, -1, "Opponent's item is stolen by the user.", -1, 3),
|
new Move(Moves.COVET, "Covet", Type.NORMAL, MoveCategory.PHYSICAL, 60, 100, 25, -1, "Opponent's item is stolen by the user.", -1, 3),
|
||||||
|
@ -1131,7 +1189,8 @@ export const allMoves = [
|
||||||
new Move(Moves.ROCK_BLAST, "Rock Blast", Type.ROCK, MoveCategory.PHYSICAL, 25, 90, 10, 76, "Hits 2-5 times in one turn.", -1, 3, new MultiHitAttr()),
|
new Move(Moves.ROCK_BLAST, "Rock Blast", Type.ROCK, MoveCategory.PHYSICAL, 25, 90, 10, 76, "Hits 2-5 times in one turn.", -1, 3, new MultiHitAttr()),
|
||||||
new Move(Moves.SHOCK_WAVE, "Shock Wave", Type.ELECTRIC, MoveCategory.SPECIAL, 60, 999, 20, -1, "Ignores Accuracy and Evasiveness.", -1, 3),
|
new Move(Moves.SHOCK_WAVE, "Shock Wave", Type.ELECTRIC, MoveCategory.SPECIAL, 60, 999, 20, -1, "Ignores Accuracy and Evasiveness.", -1, 3),
|
||||||
new Move(Moves.WATER_PULSE, "Water Pulse", Type.WATER, MoveCategory.SPECIAL, 60, 100, 20, 11, "May confuse opponent.", 20, 3),
|
new Move(Moves.WATER_PULSE, "Water Pulse", Type.WATER, MoveCategory.SPECIAL, 60, 100, 20, 11, "May confuse opponent.", 20, 3),
|
||||||
new Move(Moves.DOOM_DESIRE, "Doom Desire", Type.STEEL, MoveCategory.SPECIAL, 140, 100, 5, -1, "Damage occurs 2 turns later.", -1, 3),
|
new Move(Moves.DOOM_DESIRE, "Doom Desire", Type.STEEL, MoveCategory.SPECIAL, 140, 100, 5, -1, "Damage occurs 2 turns later.", -1, 3,
|
||||||
|
new ChargeAttr(ChargeAnim.DOOM_DESIRE_CHARGING, 'chose\nDOOM DESIRE as its destiny!')),
|
||||||
new Move(Moves.PSYCHO_BOOST, "Psycho Boost", Type.PSYCHIC, MoveCategory.SPECIAL, 140, 90, 5, -1, "Sharply lowers user's Special Attack.", 100, 3, new StatChangeAttr(BattleStat.SPATK, -2, true)),
|
new Move(Moves.PSYCHO_BOOST, "Psycho Boost", Type.PSYCHIC, MoveCategory.SPECIAL, 140, 90, 5, -1, "Sharply lowers user's Special Attack.", 100, 3, new StatChangeAttr(BattleStat.SPATK, -2, true)),
|
||||||
new Move(Moves.ROOST, "Roost", Type.FLYING, MoveCategory.STATUS, -1, -1, 5, -1, "User recovers half of its max HP and loses the Flying type temporarily.", -1, 4),
|
new Move(Moves.ROOST, "Roost", Type.FLYING, MoveCategory.STATUS, -1, -1, 5, -1, "User recovers half of its max HP and loses the Flying type temporarily.", -1, 4),
|
||||||
new Move(Moves.GRAVITY, "Gravity", Type.PSYCHIC, MoveCategory.STATUS, -1, -1, 5, -1, "Prevents moves like Fly and Bounce and the Ability Levitate for 5 turns.", -1, 4),
|
new Move(Moves.GRAVITY, "Gravity", Type.PSYCHIC, MoveCategory.STATUS, -1, -1, 5, -1, "Prevents moves like Fly and Bounce and the Ability Levitate for 5 turns.", -1, 4),
|
||||||
|
@ -1249,7 +1308,8 @@ export const allMoves = [
|
||||||
new Move(Moves.SEED_FLARE, "Seed Flare", Type.GRASS, MoveCategory.SPECIAL, 120, 85, 5, -1, "May lower opponent's Special Defense.", 40, 4, new StatChangeAttr(BattleStat.SPDEF, -1)),
|
new Move(Moves.SEED_FLARE, "Seed Flare", Type.GRASS, MoveCategory.SPECIAL, 120, 85, 5, -1, "May lower opponent's Special Defense.", 40, 4, new StatChangeAttr(BattleStat.SPDEF, -1)),
|
||||||
new Move(Moves.OMINOUS_WIND, "Ominous Wind", Type.GHOST, MoveCategory.SPECIAL, 60, 100, 5, -1, "May raise all user's stats at once.", 10, 4,
|
new Move(Moves.OMINOUS_WIND, "Ominous Wind", Type.GHOST, MoveCategory.SPECIAL, 60, 100, 5, -1, "May raise all user's stats at once.", 10, 4,
|
||||||
new StatChangeAttr([ BattleStat.ATK, BattleStat.DEF, BattleStat.SPATK, BattleStat.SPDEF, BattleStat.SPD ], 1, true)),
|
new StatChangeAttr([ BattleStat.ATK, BattleStat.DEF, BattleStat.SPATK, BattleStat.SPDEF, BattleStat.SPD ], 1, true)),
|
||||||
new Move(Moves.SHADOW_FORCE, "Shadow Force", Type.GHOST, MoveCategory.PHYSICAL, 120, 100, 5, -1, "Disappears on first turn, attacks on second. Can strike through Protect/Detect.", -1, 4),
|
new Move(Moves.SHADOW_FORCE, "Shadow Force", Type.GHOST, MoveCategory.PHYSICAL, 120, 100, 5, -1, "Disappears on first turn, attacks on second. Can strike through Protect/Detect.", -1, 4,
|
||||||
|
new ChargeAttr(ChargeAnim.SHADOW_FORCE_CHARGING, 'vanished\ninstantly!')),
|
||||||
new Move(Moves.HONE_CLAWS, "Hone Claws", Type.DARK, MoveCategory.STATUS, -1, -1, 15, -1, "Raises user's Attack and Accuracy.", -1, 5,
|
new Move(Moves.HONE_CLAWS, "Hone Claws", Type.DARK, MoveCategory.STATUS, -1, -1, 15, -1, "Raises user's Attack and Accuracy.", -1, 5,
|
||||||
new StatChangeAttr([ BattleStat.ATK, BattleStat.ACC ], 1, true)),
|
new StatChangeAttr([ BattleStat.ATK, BattleStat.ACC ], 1, true)),
|
||||||
new Move(Moves.WIDE_GUARD, "Wide Guard", Type.ROCK, MoveCategory.STATUS, -1, -1, 10, -1, "Protects the user's team from multi-target attacks.", -1, 5),
|
new Move(Moves.WIDE_GUARD, "Wide Guard", Type.ROCK, MoveCategory.STATUS, -1, -1, 10, -1, "Protects the user's team from multi-target attacks.", -1, 5),
|
||||||
|
@ -1262,7 +1322,7 @@ export const allMoves = [
|
||||||
new Move(Moves.RAGE_POWDER, "Rage Powder", Type.BUG, MoveCategory.STATUS, -1, -1, 20, -1, "Forces attacks to hit user, not team-mates.", -1, 5),
|
new Move(Moves.RAGE_POWDER, "Rage Powder", Type.BUG, MoveCategory.STATUS, -1, -1, 20, -1, "Forces attacks to hit user, not team-mates.", -1, 5),
|
||||||
new Move(Moves.TELEKINESIS, "Telekinesis", Type.PSYCHIC, MoveCategory.STATUS, -1, -1, 15, -1, "Ignores opponent's Evasiveness for three turns, add Ground immunity.", -1, 5),
|
new Move(Moves.TELEKINESIS, "Telekinesis", Type.PSYCHIC, MoveCategory.STATUS, -1, -1, 15, -1, "Ignores opponent's Evasiveness for three turns, add Ground immunity.", -1, 5),
|
||||||
new Move(Moves.MAGIC_ROOM, "Magic Room", Type.PSYCHIC, MoveCategory.STATUS, -1, -1, 10, -1, "Suppresses the effects of held items for five turns.", -1, 5),
|
new Move(Moves.MAGIC_ROOM, "Magic Room", Type.PSYCHIC, MoveCategory.STATUS, -1, -1, 10, -1, "Suppresses the effects of held items for five turns.", -1, 5),
|
||||||
new Move(Moves.SMACK_DOWN, "Smack Down", Type.ROCK, MoveCategory.PHYSICAL, 50, 100, 15, -1, "Makes Flying-type Pokémon vulnerable to Ground moves.", 100, 5),
|
new Move(Moves.SMACK_DOWN, "Smack Down", Type.ROCK, MoveCategory.PHYSICAL, 50, 100, 15, -1, "Makes Flying-type Pokémon vulnerable to Ground moves.", 100, 5), // TODO, logic with fly
|
||||||
new Move(Moves.STORM_THROW, "Storm Throw", Type.FIGHTING, MoveCategory.PHYSICAL, 60, 100, 10, -1, "Always results in a critical hit.", 100, 5), // TODO
|
new Move(Moves.STORM_THROW, "Storm Throw", Type.FIGHTING, MoveCategory.PHYSICAL, 60, 100, 10, -1, "Always results in a critical hit.", 100, 5), // TODO
|
||||||
new Move(Moves.FLAME_BURST, "Flame Burst", Type.FIRE, MoveCategory.SPECIAL, 70, 100, 15, -1, "May also injure nearby Pokémon.", -1, 5),
|
new Move(Moves.FLAME_BURST, "Flame Burst", Type.FIRE, MoveCategory.SPECIAL, 70, 100, 15, -1, "May also injure nearby Pokémon.", -1, 5),
|
||||||
new Move(Moves.SLUDGE_WAVE, "Sludge Wave", Type.POISON, MoveCategory.SPECIAL, 95, 100, 10, -1, "May poison opponent.", 10, 5, new StatusEffectAttr(StatusEffect.POISON)),
|
new Move(Moves.SLUDGE_WAVE, "Sludge Wave", Type.POISON, MoveCategory.SPECIAL, 95, 100, 10, -1, "May poison opponent.", 10, 5, new StatusEffectAttr(StatusEffect.POISON)),
|
||||||
|
@ -1293,7 +1353,8 @@ export const allMoves = [
|
||||||
new StatChangeAttr([ BattleStat.ATK, BattleStat.SPATK ], 2, true), new StatChangeAttr([ BattleStat.DEF, BattleStat.SPDEF ], -1, true)),
|
new StatChangeAttr([ BattleStat.ATK, BattleStat.SPATK ], 2, true), new StatChangeAttr([ BattleStat.DEF, BattleStat.SPDEF ], -1, true)),
|
||||||
new Move(Moves.HEAL_PULSE, "Heal Pulse", Type.PSYCHIC, MoveCategory.STATUS, -1, -1, 10, -1, "Restores half the target's max HP.", -1, 5),
|
new Move(Moves.HEAL_PULSE, "Heal Pulse", Type.PSYCHIC, MoveCategory.STATUS, -1, -1, 10, -1, "Restores half the target's max HP.", -1, 5),
|
||||||
new Move(Moves.HEX, "Hex", Type.GHOST, MoveCategory.SPECIAL, 65, 100, 10, 29, "Inflicts more damage if the target has a status condition.", -1, 5),
|
new Move(Moves.HEX, "Hex", Type.GHOST, MoveCategory.SPECIAL, 65, 100, 10, 29, "Inflicts more damage if the target has a status condition.", -1, 5),
|
||||||
new Move(Moves.SKY_DROP, "Sky Drop", Type.FLYING, MoveCategory.PHYSICAL, 60, 100, 10, -1, "Takes opponent into the air on first turn, drops them on second turn.", -1, 5),
|
new Move(Moves.SKY_DROP, "Sky Drop", Type.FLYING, MoveCategory.PHYSICAL, 60, 100, 10, -1, "Takes opponent into the air on first turn, drops them on second turn.", -1, 5,
|
||||||
|
new ChargeAttr(ChargeAnim.SKY_DROP_CHARGING, 'took {TARGET}\ninto the sky!', BattleTagType.FLYING)), // TODO: Add 2nd turn message
|
||||||
new Move(Moves.SHIFT_GEAR, "Shift Gear", Type.STEEL, MoveCategory.STATUS, -1, -1, 10, -1, "Raises user's Attack and sharply raises Speed.", -1, 5,
|
new Move(Moves.SHIFT_GEAR, "Shift Gear", Type.STEEL, MoveCategory.STATUS, -1, -1, 10, -1, "Raises user's Attack and sharply raises Speed.", -1, 5,
|
||||||
new StatChangeAttr(BattleStat.ATK, 1, true), new StatChangeAttr(BattleStat.SPD, 2, true)),
|
new StatChangeAttr(BattleStat.ATK, 1, true), new StatChangeAttr(BattleStat.SPD, 2, true)),
|
||||||
new Move(Moves.CIRCLE_THROW, "Circle Throw", Type.FIGHTING, MoveCategory.PHYSICAL, 60, 90, 10, -1, "In battles, the opponent switches. In the wild, the Pokémon runs.", -1, 5),
|
new Move(Moves.CIRCLE_THROW, "Circle Throw", Type.FIGHTING, MoveCategory.PHYSICAL, 60, 90, 10, -1, "In battles, the opponent switches. In the wild, the Pokémon runs.", -1, 5),
|
||||||
|
@ -1342,7 +1403,8 @@ export const allMoves = [
|
||||||
new Move(Moves.BLUE_FLARE, "Blue Flare", Type.FIRE, MoveCategory.SPECIAL, 130, 85, 5, -1, "May burn opponent.", 20, 5, new StatusEffectAttr(StatusEffect.BURN)),
|
new Move(Moves.BLUE_FLARE, "Blue Flare", Type.FIRE, MoveCategory.SPECIAL, 130, 85, 5, -1, "May burn opponent.", 20, 5, new StatusEffectAttr(StatusEffect.BURN)),
|
||||||
new Move(Moves.FIERY_DANCE, "Fiery Dance", Type.FIRE, MoveCategory.SPECIAL, 80, 100, 10, -1, "May raise user's Special Attack.", 50, 5, new StatChangeAttr(BattleStat.SPATK, 1, true)),
|
new Move(Moves.FIERY_DANCE, "Fiery Dance", Type.FIRE, MoveCategory.SPECIAL, 80, 100, 10, -1, "May raise user's Special Attack.", 50, 5, new StatChangeAttr(BattleStat.SPATK, 1, true)),
|
||||||
new Move(Moves.FREEZE_SHOCK, "Freeze Shock", Type.ICE, MoveCategory.PHYSICAL, 140, 90, 5, -1, "Charges on first turn, attacks on second. May paralyze opponent.", 30, 5, new StatusEffectAttr(StatusEffect.PARALYSIS)),
|
new Move(Moves.FREEZE_SHOCK, "Freeze Shock", Type.ICE, MoveCategory.PHYSICAL, 140, 90, 5, -1, "Charges on first turn, attacks on second. May paralyze opponent.", 30, 5, new StatusEffectAttr(StatusEffect.PARALYSIS)),
|
||||||
new Move(Moves.ICE_BURN, "Ice Burn", Type.ICE, MoveCategory.SPECIAL, 140, 90, 5, -1, "Charges on first turn, attacks on second. May burn opponent.", 30, 5, new StatusEffectAttr(StatusEffect.BURN)),
|
new Move(Moves.ICE_BURN, "Ice Burn", Type.ICE, MoveCategory.SPECIAL, 140, 90, 5, -1, "Charges on first turn, attacks on second. May burn opponent.", 30, 5,
|
||||||
|
new ChargeAttr(ChargeAnim.ICE_BURN_CHARGING, 'became cloaked\nin freezing air!'), new StatusEffectAttr(StatusEffect.BURN)),
|
||||||
new Move(Moves.SNARL, "Snarl", Type.DARK, MoveCategory.SPECIAL, 55, 95, 15, 30, "Lowers opponent's Special Attack.", 100, 5, new StatChangeAttr(BattleStat.SPATK, -1)),
|
new Move(Moves.SNARL, "Snarl", Type.DARK, MoveCategory.SPECIAL, 55, 95, 15, 30, "Lowers opponent's Special Attack.", 100, 5, new StatChangeAttr(BattleStat.SPATK, -1)),
|
||||||
new Move(Moves.ICICLE_CRASH, "Icicle Crash", Type.ICE, MoveCategory.PHYSICAL, 85, 90, 10, -1, "May cause flinching.", 30, 5, new FlinchAttr()),
|
new Move(Moves.ICICLE_CRASH, "Icicle Crash", Type.ICE, MoveCategory.PHYSICAL, 85, 90, 10, -1, "May cause flinching.", 30, 5, new FlinchAttr()),
|
||||||
new Move(Moves.V_CREATE, "V-create", Type.FIRE, MoveCategory.PHYSICAL, 180, 95, 5, -1, "Lowers user's Defense, Special Defense and Speed.", 100, 5,
|
new Move(Moves.V_CREATE, "V-create", Type.FIRE, MoveCategory.PHYSICAL, 180, 95, 5, -1, "Lowers user's Defense, Special Defense and Speed.", 100, 5,
|
||||||
|
|
241
src/pokemon.ts
241
src/pokemon.ts
|
@ -1,7 +1,7 @@
|
||||||
import Phaser from 'phaser';
|
import Phaser from 'phaser';
|
||||||
import BattleScene from './battle-scene';
|
import BattleScene from './battle-scene';
|
||||||
import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from './battle-info';
|
import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from './battle-info';
|
||||||
import { default as Move, allMoves, MoveCategory, Moves, StatChangeAttr, applyMoveAttrs, HighCritAttr } from './move';
|
import { default as Move, allMoves, MoveCategory, Moves, StatChangeAttr, applyMoveAttrs, HighCritAttr, HitsTagAttr } from './move';
|
||||||
import { pokemonLevelMoves } from './pokemon-level-moves';
|
import { pokemonLevelMoves } from './pokemon-level-moves';
|
||||||
import { default as PokemonSpecies, getPokemonSpecies } from './pokemon-species';
|
import { default as PokemonSpecies, getPokemonSpecies } from './pokemon-species';
|
||||||
import * as Utils from './utils';
|
import * as Utils from './utils';
|
||||||
|
@ -17,6 +17,7 @@ import { tmSpecies } from './tms';
|
||||||
import { pokemonEvolutions, SpeciesEvolution, SpeciesEvolutionCondition } from './pokemon-evolutions';
|
import { pokemonEvolutions, SpeciesEvolution, SpeciesEvolutionCondition } from './pokemon-evolutions';
|
||||||
import { MessagePhase, StatChangePhase } from './battle-phases';
|
import { MessagePhase, StatChangePhase } from './battle-phases';
|
||||||
import { BattleStat } from './battle-stat';
|
import { BattleStat } from './battle-stat';
|
||||||
|
import { BattleTag, BattleTagLapseType, BattleTagType } from './battle-tag';
|
||||||
|
|
||||||
export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
public id: integer;
|
public id: integer;
|
||||||
|
@ -409,93 +410,138 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
this.levelExp = this.exp - getLevelTotalExp(this.level, this.species.growthRate);
|
this.levelExp = this.exp - getLevelTotalExp(this.level, this.species.growthRate);
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(source: Pokemon, battlerMove: PokemonMove, callback?: Function) {
|
apply(source: Pokemon, battlerMove: PokemonMove): Promise<MoveResult> {
|
||||||
const battleScene = this.scene as BattleScene;
|
return new Promise(resolve => {
|
||||||
let result: integer;
|
const battleScene = this.scene as BattleScene;
|
||||||
let success = false;
|
let result: MoveResult = MoveResult.STATUS;
|
||||||
const move = battlerMove.getMove();
|
let success = false;
|
||||||
const moveCategory = move.category;
|
const move = battlerMove.getMove();
|
||||||
let damage = 0;
|
const moveCategory = move.category;
|
||||||
switch (moveCategory) {
|
let damage = 0;
|
||||||
case MoveCategory.PHYSICAL:
|
switch (moveCategory) {
|
||||||
case MoveCategory.SPECIAL:
|
case MoveCategory.PHYSICAL:
|
||||||
const isPhysical = moveCategory === MoveCategory.PHYSICAL;
|
case MoveCategory.SPECIAL:
|
||||||
const critChance = new Utils.IntegerHolder(16);
|
const isPhysical = moveCategory === MoveCategory.PHYSICAL;
|
||||||
applyMoveAttrs(HighCritAttr, this.scene as BattleScene, source, this, move, critChance);
|
const critChance = new Utils.IntegerHolder(16);
|
||||||
const isCritical = Utils.randInt(critChance.value) === 0;
|
applyMoveAttrs(HighCritAttr, this.scene as BattleScene, source, this, move, critChance);
|
||||||
const sourceAtk = source.getBattleStat(isPhysical ? Stat.ATK : Stat.SPATK);
|
const isCritical = Utils.randInt(critChance.value) === 0;
|
||||||
const targetDef = this.getBattleStat(isPhysical ? Stat.DEF : Stat.SPDEF);
|
const sourceAtk = source.getBattleStat(isPhysical ? Stat.ATK : Stat.SPATK);
|
||||||
const stabMultiplier = source.species.type1 === move.type || (source.species.type2 > -1 && source.species.type2 === move.type) ? 1.5 : 1;
|
const targetDef = this.getBattleStat(isPhysical ? Stat.DEF : Stat.SPDEF);
|
||||||
const typeMultiplier = getTypeDamageMultiplier(move.type, this.species.type1) * (this.species.type2 > -1 ? getTypeDamageMultiplier(move.type, this.species.type2) : 1);
|
const stabMultiplier = source.species.type1 === move.type || (source.species.type2 > -1 && source.species.type2 === move.type) ? 1.5 : 1;
|
||||||
const criticalMultiplier = isCritical ? 2 : 1;
|
const typeMultiplier = getTypeDamageMultiplier(move.type, this.species.type1) * (this.species.type2 > -1 ? getTypeDamageMultiplier(move.type, this.species.type2) : 1);
|
||||||
damage = Math.ceil(((((2 * source.level / 5 + 2) * move.power * sourceAtk / targetDef) / 50) + 2) * stabMultiplier * typeMultiplier * ((Utils.randInt(15) + 85) / 100)) * criticalMultiplier;
|
const criticalMultiplier = isCritical ? 2 : 1;
|
||||||
if (isPhysical && source.status && source.status.effect === StatusEffect.BURN)
|
damage = Math.ceil(((((2 * source.level / 5 + 2) * move.power * sourceAtk / targetDef) / 50) + 2) * stabMultiplier * typeMultiplier * ((Utils.randInt(15) + 85) / 100)) * criticalMultiplier;
|
||||||
damage = Math.floor(damage / 2);
|
if (isPhysical && source.status && source.status.effect === StatusEffect.BURN)
|
||||||
console.log('damage', damage, move.name, move.power, sourceAtk, targetDef);
|
damage = Math.floor(damage / 2);
|
||||||
if (damage) {
|
move.getAttrs(HitsTagAttr).map(hta => hta as HitsTagAttr).filter(hta => hta.doubleDamage).forEach(hta => {
|
||||||
this.hp = Math.max(this.hp - damage, 0);
|
if (this.getTag(hta.tagType)) {
|
||||||
if (isCritical)
|
console.log('ye');
|
||||||
battleScene.unshiftPhase(new MessagePhase(battleScene, 'A critical hit!'));
|
damage *= 2;
|
||||||
}
|
|
||||||
if (typeMultiplier >= 2)
|
|
||||||
result = MoveResult.SUPER_EFFECTIVE;
|
|
||||||
else if (typeMultiplier >= 1)
|
|
||||||
result = MoveResult.EFFECTIVE;
|
|
||||||
else if (typeMultiplier > 0)
|
|
||||||
result = MoveResult.NOT_VERY_EFFECTIVE;
|
|
||||||
else
|
|
||||||
result = MoveResult.NO_EFFECT;
|
|
||||||
|
|
||||||
switch (result) {
|
|
||||||
case MoveResult.EFFECTIVE:
|
|
||||||
this.scene.sound.play('hit');
|
|
||||||
success = true;
|
|
||||||
break;
|
|
||||||
case MoveResult.SUPER_EFFECTIVE:
|
|
||||||
this.scene.sound.play('hit_strong');
|
|
||||||
battleScene.unshiftPhase(new MessagePhase(battleScene, 'It\'s super effective!'));
|
|
||||||
success = true;
|
|
||||||
break;
|
|
||||||
case MoveResult.NOT_VERY_EFFECTIVE:
|
|
||||||
this.scene.sound.play('hit_weak');
|
|
||||||
battleScene.unshiftPhase(new MessagePhase(battleScene, 'It\'s not very effective!'))
|
|
||||||
success = true;
|
|
||||||
break;
|
|
||||||
case MoveResult.NO_EFFECT:
|
|
||||||
battleScene.unshiftPhase(new MessagePhase(battleScene, `It doesn\'t affect ${this.name}!`))
|
|
||||||
success = true;
|
|
||||||
break;
|
|
||||||
case MoveCategory.STATUS:
|
|
||||||
result = MoveResult.OTHER;
|
|
||||||
success = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (success) {
|
|
||||||
if (result <= MoveResult.NOT_VERY_EFFECTIVE) {
|
|
||||||
const flashTimer = this.scene.time.addEvent({
|
|
||||||
delay: 100,
|
|
||||||
repeat: 5,
|
|
||||||
startAt: 200,
|
|
||||||
callback: () => {
|
|
||||||
this.getSprite().setVisible(flashTimer.repeatCount % 2 === 0);
|
|
||||||
if (!flashTimer.repeatCount) {
|
|
||||||
this.battleInfo.updateInfo(this).then(() => {
|
|
||||||
if (callback)
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
console.log('damage', damage, move.name, move.power, sourceAtk, targetDef);
|
||||||
|
if (damage) {
|
||||||
|
this.hp = Math.max(this.hp - damage, 0);
|
||||||
|
if (isCritical)
|
||||||
|
battleScene.unshiftPhase(new MessagePhase(battleScene, 'A critical hit!'));
|
||||||
}
|
}
|
||||||
});
|
if (typeMultiplier >= 2)
|
||||||
} else {
|
result = MoveResult.SUPER_EFFECTIVE;
|
||||||
this.battleInfo.updateInfo(this).then(() => {
|
else if (typeMultiplier >= 1)
|
||||||
if (callback)
|
result = MoveResult.EFFECTIVE;
|
||||||
callback();
|
else if (typeMultiplier > 0)
|
||||||
});
|
result = MoveResult.NOT_VERY_EFFECTIVE;
|
||||||
|
else
|
||||||
|
result = MoveResult.NO_EFFECT;
|
||||||
|
|
||||||
|
switch (result) {
|
||||||
|
case MoveResult.EFFECTIVE:
|
||||||
|
this.scene.sound.play('hit');
|
||||||
|
success = true;
|
||||||
|
break;
|
||||||
|
case MoveResult.SUPER_EFFECTIVE:
|
||||||
|
this.scene.sound.play('hit_strong');
|
||||||
|
battleScene.unshiftPhase(new MessagePhase(battleScene, 'It\'s super effective!'));
|
||||||
|
success = true;
|
||||||
|
break;
|
||||||
|
case MoveResult.NOT_VERY_EFFECTIVE:
|
||||||
|
this.scene.sound.play('hit_weak');
|
||||||
|
battleScene.unshiftPhase(new MessagePhase(battleScene, 'It\'s not very effective!'))
|
||||||
|
success = true;
|
||||||
|
break;
|
||||||
|
case MoveResult.NO_EFFECT:
|
||||||
|
battleScene.unshiftPhase(new MessagePhase(battleScene, `It doesn\'t affect ${this.name}!`))
|
||||||
|
success = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MoveCategory.STATUS:
|
||||||
|
result = MoveResult.STATUS;
|
||||||
|
success = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
if (result <= MoveResult.NOT_VERY_EFFECTIVE) {
|
||||||
|
const flashTimer = this.scene.time.addEvent({
|
||||||
|
delay: 100,
|
||||||
|
repeat: 5,
|
||||||
|
startAt: 200,
|
||||||
|
callback: () => {
|
||||||
|
this.getSprite().setVisible(flashTimer.repeatCount % 2 === 0);
|
||||||
|
if (!flashTimer.repeatCount) {
|
||||||
|
this.battleInfo.updateInfo(this).then(() => resolve(result));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.battleInfo.updateInfo(this).then(() => resolve(result));
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
resolve(result);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
addTag(tagType: BattleTagType, lapseType: BattleTagLapseType, turnCount?: integer): boolean {
|
||||||
|
if (this.getTag(tagType))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const newTag = new BattleTag(tagType, lapseType || BattleTagLapseType.FAINT, turnCount || 1);
|
||||||
|
this.summonData.tags.push(newTag);
|
||||||
|
if (newTag.isHidden())
|
||||||
|
this.setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
getTag(tagFilter: BattleTagType | ((tag: BattleTag) => boolean)): BattleTag {
|
||||||
|
return typeof(tagFilter) === 'number'
|
||||||
|
? this.summonData.tags.find(t => t.tagType === tagFilter)
|
||||||
|
: this.summonData.tags.find(t => tagFilter(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
getTags(tagFilter: BattleTagType | ((tag: BattleTag) => boolean)): BattleTag[] {
|
||||||
|
return typeof(tagFilter) === 'number'
|
||||||
|
? this.summonData.tags.filter(t => t.tagType === tagFilter)
|
||||||
|
: this.summonData.tags.filter(t => tagFilter(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
lapseTags(lapseType: BattleTagLapseType) {
|
||||||
|
const tags = this.summonData.tags;
|
||||||
|
tags.filter(t => lapseType === BattleTagLapseType.FAINT || ((t.lapseType === lapseType) && !(--t.turnCount))).forEach(t => tags.splice(tags.indexOf(t), 1));
|
||||||
|
const visible = !this.getTag(t => t.isHidden());
|
||||||
|
if (visible && !this.visible) {
|
||||||
|
// Wait 2 frames before setting visible for battle animations that don't immediately show the sprite invisible
|
||||||
|
this.scene.tweens.addCounter({
|
||||||
|
duration: 2,
|
||||||
|
useFrames: true,
|
||||||
|
onComplete: () => this.setVisible(true)
|
||||||
|
});
|
||||||
} else
|
} else
|
||||||
callback();
|
this.setVisible(visible);
|
||||||
|
}
|
||||||
|
|
||||||
|
getLastXMoves(turnCount?: integer): TurnMove[] {
|
||||||
|
const moveHistory = this.summonData.moveHistory;
|
||||||
|
return moveHistory.slice(Math.max(moveHistory.length - (turnCount || 1), 0), moveHistory.length).reverse();
|
||||||
}
|
}
|
||||||
|
|
||||||
cry(soundConfig?: Phaser.Types.Sound.SoundConfig): integer {
|
cry(soundConfig?: Phaser.Types.Sound.SoundConfig): integer {
|
||||||
|
@ -731,6 +777,12 @@ export class EnemyPokemon extends Pokemon {
|
||||||
}
|
}
|
||||||
|
|
||||||
getNextMove(): PokemonMove {
|
getNextMove(): PokemonMove {
|
||||||
|
const queuedMove = this.summonData.moveQueue.length
|
||||||
|
? this.moveset.find(m => m.moveId === this.summonData.moveQueue[0].move)
|
||||||
|
: null;
|
||||||
|
if (queuedMove && (this.summonData.moveQueue[0].ignorePP || queuedMove.isUsable()))
|
||||||
|
return queuedMove;
|
||||||
|
|
||||||
const movePool = this.moveset.filter(m => m.isUsable());
|
const movePool = this.moveset.filter(m => m.isUsable());
|
||||||
if (movePool.length) {
|
if (movePool.length) {
|
||||||
if (movePool.length === 1)
|
if (movePool.length === 1)
|
||||||
|
@ -823,8 +875,22 @@ export class EnemyPokemon extends Pokemon {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface TurnMove {
|
||||||
|
move: Moves;
|
||||||
|
result: MoveResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface QueuedMove {
|
||||||
|
move: Moves;
|
||||||
|
ignorePP?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export class PokemonSummonData {
|
export class PokemonSummonData {
|
||||||
public battleStats: integer[] = [ 0, 0, 0, 0, 0, 0, 0 ];
|
public battleStats: integer[] = [ 0, 0, 0, 0, 0, 0, 0 ];
|
||||||
|
public moveHistory: TurnMove[] = [];
|
||||||
|
public moveQueue: QueuedMove[] = [];
|
||||||
|
public tags: BattleTag[] = [];
|
||||||
|
public charging: boolean;
|
||||||
public confusionTurns: integer;
|
public confusionTurns: integer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -850,16 +916,19 @@ export enum MoveResult {
|
||||||
SUPER_EFFECTIVE,
|
SUPER_EFFECTIVE,
|
||||||
NOT_VERY_EFFECTIVE,
|
NOT_VERY_EFFECTIVE,
|
||||||
NO_EFFECT,
|
NO_EFFECT,
|
||||||
|
STATUS,
|
||||||
|
FAILED,
|
||||||
|
MISSED,
|
||||||
OTHER
|
OTHER
|
||||||
};
|
};
|
||||||
|
|
||||||
export class PokemonMove {
|
export class PokemonMove {
|
||||||
public moveId: integer;
|
public moveId: Moves;
|
||||||
public ppUsed: integer;
|
public ppUsed: integer;
|
||||||
public ppUp: integer;
|
public ppUp: integer;
|
||||||
public disableTurns: integer;
|
public disableTurns: integer;
|
||||||
|
|
||||||
constructor(moveId: integer, ppUsed: integer, ppUp: integer) {
|
constructor(moveId: Moves, ppUsed: integer, ppUp: integer) {
|
||||||
this.moveId = moveId;
|
this.moveId = moveId;
|
||||||
this.ppUsed = ppUsed;
|
this.ppUsed = ppUsed;
|
||||||
this.ppUp = ppUp;
|
this.ppUp = ppUp;
|
||||||
|
|
Loading…
Reference in New Issue