Add status effects
parent
3f9fbc1267
commit
b0ecb9d5f5
|
@ -9,13 +9,10 @@
|
|||
- Moves
|
||||
- Move logic
|
||||
- Can't use when PP consumed
|
||||
- Multi hit moves should still show 1 time(s) when hitting once
|
||||
- Abilities
|
||||
- Ability logic
|
||||
- Ability activation indicator (?)
|
||||
- Natures
|
||||
- Status effects
|
||||
- Status effect animation
|
||||
- EXP logic
|
||||
- Fix algorithm (currently inaccurate)
|
||||
- Pokemon summary screen
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
"image": "statuses.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 44,
|
||||
"h": 30
|
||||
"w": 20,
|
||||
"h": 56
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
|
@ -24,8 +24,8 @@
|
|||
"h": 8
|
||||
},
|
||||
"frame": {
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 20,
|
||||
"h": 8
|
||||
}
|
||||
|
@ -45,8 +45,8 @@
|
|||
"h": 8
|
||||
},
|
||||
"frame": {
|
||||
"x": 1,
|
||||
"y": 11,
|
||||
"x": 0,
|
||||
"y": 8,
|
||||
"w": 20,
|
||||
"h": 8
|
||||
}
|
||||
|
@ -66,8 +66,8 @@
|
|||
"h": 8
|
||||
},
|
||||
"frame": {
|
||||
"x": 1,
|
||||
"y": 21,
|
||||
"x": 0,
|
||||
"y": 16,
|
||||
"w": 20,
|
||||
"h": 8
|
||||
}
|
||||
|
@ -87,8 +87,8 @@
|
|||
"h": 8
|
||||
},
|
||||
"frame": {
|
||||
"x": 23,
|
||||
"y": 1,
|
||||
"x": 0,
|
||||
"y": 24,
|
||||
"w": 20,
|
||||
"h": 8
|
||||
}
|
||||
|
@ -108,8 +108,8 @@
|
|||
"h": 8
|
||||
},
|
||||
"frame": {
|
||||
"x": 23,
|
||||
"y": 11,
|
||||
"x": 0,
|
||||
"y": 32,
|
||||
"w": 20,
|
||||
"h": 8
|
||||
}
|
||||
|
@ -129,8 +129,29 @@
|
|||
"h": 8
|
||||
},
|
||||
"frame": {
|
||||
"x": 23,
|
||||
"y": 21,
|
||||
"x": 0,
|
||||
"y": 40,
|
||||
"w": 20,
|
||||
"h": 8
|
||||
}
|
||||
},
|
||||
{
|
||||
"filename": "toxic",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 20,
|
||||
"h": 8
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 20,
|
||||
"h": 8
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 48,
|
||||
"w": 20,
|
||||
"h": 8
|
||||
}
|
||||
|
@ -141,6 +162,6 @@
|
|||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:34eb38966145af4ef9cffbaaa8d07ea3:fba056f9a49345436b0820757c78f418:e6649238c018d3630e55681417c698ca$"
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:b1f59475db34388a7177fe541f95d9e8:47a06b96ac24cc4249538472b2604202:e6649238c018d3630e55681417c698ca$"
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 395 B After Width: | Height: | Size: 400 B |
Binary file not shown.
After Width: | Height: | Size: 174 B |
|
@ -35,12 +35,12 @@ export enum ChargeAnim {
|
|||
|
||||
export enum CommonAnim {
|
||||
HEALTH_UP = 2000,
|
||||
SLEEP,
|
||||
POISON,
|
||||
TOXIC,
|
||||
BURN,
|
||||
PARALYSIS,
|
||||
SLEEP,
|
||||
FROZEN,
|
||||
BURN,
|
||||
CONFUSION,
|
||||
ATTRACT,
|
||||
BIND,
|
||||
|
@ -209,7 +209,7 @@ abstract class AnimTimedEvent {
|
|||
this.resourceName = resourceName;
|
||||
}
|
||||
|
||||
abstract execute(scene: BattleScene, moveAnim: MoveAnim): void;
|
||||
abstract execute(scene: BattleScene, battleAnim: BattleAnim): integer;
|
||||
|
||||
abstract getEventType(): string;
|
||||
}
|
||||
|
@ -228,12 +228,13 @@ class AnimTimedSoundEvent extends AnimTimedEvent {
|
|||
this.pitch = 100;
|
||||
}
|
||||
|
||||
execute(scene: BattleScene, moveAnim: MoveAnim): void {
|
||||
execute(scene: BattleScene, battleAnim: BattleAnim): integer {
|
||||
const soundConfig = { rate: (this.pitch * 0.01), volume: (this.volume * 0.01) };
|
||||
if (this.resourceName)
|
||||
if (this.resourceName) {
|
||||
scene.sound.play(this.resourceName, soundConfig);
|
||||
else
|
||||
moveAnim.user.cry(soundConfig);
|
||||
return Math.ceil((scene.sound.get(this.resourceName).totalDuration * 1000) / 33.33);
|
||||
} else
|
||||
return Math.ceil(battleAnim.user.cry(soundConfig) / 33.33);
|
||||
}
|
||||
|
||||
getEventType(): string {
|
||||
|
@ -284,7 +285,7 @@ class AnimTimedUpdateBgEvent extends AnimTimedBgEvent {
|
|||
super(frameIndex, resourceName, source);
|
||||
}
|
||||
|
||||
execute(scene: BattleScene, moveAnim: MoveAnim): void {
|
||||
execute(scene: BattleScene, moveAnim: MoveAnim): integer {
|
||||
const tweenProps = {};
|
||||
if (this.bgX !== undefined)
|
||||
tweenProps['x'] = (this.bgX * 0.5) - 256;
|
||||
|
@ -299,6 +300,7 @@ class AnimTimedUpdateBgEvent extends AnimTimedBgEvent {
|
|||
useFrames: true
|
||||
}, tweenProps))
|
||||
}
|
||||
return this.duration * 2;
|
||||
}
|
||||
|
||||
getEventType(): string {
|
||||
|
@ -311,7 +313,7 @@ class AnimTimedAddBgEvent extends AnimTimedBgEvent {
|
|||
super(frameIndex, resourceName, source);
|
||||
}
|
||||
|
||||
execute(scene: BattleScene, moveAnim: MoveAnim): void {
|
||||
execute(scene: BattleScene, moveAnim: MoveAnim): integer {
|
||||
moveAnim.bgSprite = scene.add.tileSprite(this.bgX - 256, this.bgY - 284, 768, 576, this.resourceName);
|
||||
moveAnim.bgSprite.setOrigin(0, 0);
|
||||
moveAnim.bgSprite.setScale(1.25);
|
||||
|
@ -325,6 +327,8 @@ class AnimTimedAddBgEvent extends AnimTimedBgEvent {
|
|||
duration: this.duration * 2,
|
||||
useFrames: true
|
||||
});
|
||||
|
||||
return this.duration * 2;
|
||||
}
|
||||
|
||||
getEventType(): string {
|
||||
|
@ -336,7 +340,22 @@ export const moveAnims = new Map<Moves, Anim | [Anim, Anim]>();
|
|||
export const chargeAnims = new Map<ChargeAnim, Anim>();
|
||||
export const commonAnims = new Map<CommonAnim, Anim>();
|
||||
|
||||
export function initAnim(move: Moves): Promise<void> {
|
||||
export function initCommonAnims(): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
const commonAnimNames = Utils.getEnumKeys(CommonAnim);
|
||||
const commonAnimIds = Utils.getEnumValues(CommonAnim);
|
||||
const commonAnimFetches = [];
|
||||
for (let ca = 0; ca < commonAnimIds.length; ca++) {
|
||||
const commonAnimId = commonAnimIds[ca];
|
||||
commonAnimFetches.push(fetch(`./battle-anims/common-${commonAnimNames[ca].toLowerCase().replace(/\_/g, '-')}.json`)
|
||||
.then(response => response.json())
|
||||
.then(cas => commonAnims.set(commonAnimId, new Anim(cas))));
|
||||
}
|
||||
Promise.allSettled(commonAnimFetches).then(() => resolve());
|
||||
});
|
||||
}
|
||||
|
||||
export function initMoveAnim(move: Moves): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
if (moveAnims.has(move)) {
|
||||
if (moveAnims.get(move) !== null)
|
||||
|
@ -374,6 +393,12 @@ function populateMoveAnim(move: Moves, animSource: any) {
|
|||
moveAnims.set(move, [ moveAnims.get(move) as Anim, moveAnim ]);
|
||||
}
|
||||
|
||||
export function loadCommonAnimAssets(scene: BattleScene, startLoad?: boolean): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
loadAnimAssets(scene, Array.from(commonAnims.values()), startLoad).then(() => resolve());
|
||||
});
|
||||
}
|
||||
|
||||
export function loadMoveAnimAssets(scene: BattleScene, moveIds: Moves[], startLoad?: boolean): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
const moveAnimations = moveIds.map(m => {
|
||||
|
@ -382,17 +407,23 @@ export function loadMoveAnimAssets(scene: BattleScene, moveIds: Moves[], startLo
|
|||
return anims as Anim;
|
||||
return anims[0] as Anim;
|
||||
});
|
||||
loadAnimAssets(scene, moveAnimations, startLoad).then(() => resolve());
|
||||
});
|
||||
}
|
||||
|
||||
function loadAnimAssets(scene: BattleScene, anims: Anim[], startLoad?: boolean): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
const backgrounds = new Set<string>();
|
||||
const sounds = new Set<string>();
|
||||
for (let ma of moveAnimations) {
|
||||
const moveSounds = ma.getSoundResourceNames();
|
||||
for (let ms of moveSounds)
|
||||
sounds.add(ms);
|
||||
const moveBackgrounds = ma.getBackgroundResourceNames();
|
||||
for (let mbg of moveBackgrounds)
|
||||
backgrounds.add(mbg);
|
||||
if (ma.graphic)
|
||||
scene.loadSpritesheet(ma.graphic, 'battle_anims', 96);
|
||||
for (let a of anims) {
|
||||
const animSounds = a.getSoundResourceNames();
|
||||
for (let ms of animSounds)
|
||||
sounds.add(ms);
|
||||
const animBackgrounds = a.getBackgroundResourceNames();
|
||||
for (let abg of animBackgrounds)
|
||||
backgrounds.add(abg);
|
||||
if (a.graphic)
|
||||
scene.loadSpritesheet(a.graphic, 'battle_anims', 96);
|
||||
}
|
||||
for (let bg of backgrounds)
|
||||
scene.loadImage(bg, 'battle_anims');
|
||||
|
@ -404,25 +435,26 @@ export function loadMoveAnimAssets(scene: BattleScene, moveIds: Moves[], startLo
|
|||
});
|
||||
}
|
||||
|
||||
export class MoveAnim {
|
||||
public move: Moves;
|
||||
export abstract class BattleAnim {
|
||||
public user: Pokemon;
|
||||
public target: Pokemon;
|
||||
public moveSprites: Phaser.GameObjects.Sprite[];
|
||||
public sprites: Phaser.GameObjects.Sprite[];
|
||||
public bgSprite: Phaser.GameObjects.TileSprite;
|
||||
|
||||
constructor(move: Moves, user: Pokemon, target: Pokemon) {
|
||||
this.move = move;
|
||||
constructor(user: Pokemon, target: Pokemon) {
|
||||
this.user = user;
|
||||
this.target = target;
|
||||
this.moveSprites = [];
|
||||
this.sprites = [];
|
||||
}
|
||||
|
||||
abstract getAnim(): Anim;
|
||||
|
||||
abstract isOppAnim(): boolean;
|
||||
|
||||
abstract isReverseCoords(): boolean;
|
||||
|
||||
play(scene: BattleScene, callback?: Function) {
|
||||
const anim = moveAnims.get(this.move) instanceof Anim
|
||||
? moveAnims.get(this.move) as Anim
|
||||
: moveAnims.get(this.move)[this.user instanceof PlayerPokemon ? 0 : 1] as Anim;
|
||||
const isOppMove = Array.isArray(moveAnims.get(this.move)) && this.user instanceof EnemyPokemon;
|
||||
const anim = this.getAnim();
|
||||
|
||||
const userInitialX = this.user.x;
|
||||
const userInitialY = this.user.y;
|
||||
|
@ -431,11 +463,12 @@ export class MoveAnim {
|
|||
const targetInitialY = this.target.y;
|
||||
const targetHalfHeight = this.target.getSprite().displayHeight / 2;
|
||||
|
||||
const coordMultiplayer = this.user instanceof PlayerPokemon || isOppMove ? 1 : -1;
|
||||
|
||||
const coordMultiplier = this.isReverseCoords() ? -1 : 1;
|
||||
|
||||
let r = anim.frames.length;
|
||||
let f = 0;
|
||||
|
||||
const moveSprites: Phaser.GameObjects.Sprite[] = [];
|
||||
const sprites: Phaser.GameObjects.Sprite[] = [];
|
||||
|
||||
scene.tweens.addCounter({
|
||||
useFrames: true,
|
||||
|
@ -447,24 +480,25 @@ export class MoveAnim {
|
|||
for (let frame of spriteFrames) {
|
||||
switch (frame.target) {
|
||||
case AnimFrameTarget.USER:
|
||||
this.user.setPosition(userInitialX + frame.x * coordMultiplayer, userInitialY + frame.y * coordMultiplayer);
|
||||
this.user.setPosition(userInitialX + frame.x * coordMultiplier, userInitialY + frame.y * coordMultiplier);
|
||||
break;
|
||||
case AnimFrameTarget.TARGET:
|
||||
this.target.setPosition(targetInitialX + frame.x * coordMultiplayer, targetInitialY + frame.y * coordMultiplayer);
|
||||
this.target.setPosition(targetInitialX + frame.x * coordMultiplier, targetInitialY + frame.y * coordMultiplier);
|
||||
break;
|
||||
case AnimFrameTarget.GRAPHIC:
|
||||
if (g === moveSprites.length) {
|
||||
if (g === sprites.length) {
|
||||
const newSprite = scene.add.sprite(0, 0, anim.graphic, 1);
|
||||
scene.field.add(newSprite);
|
||||
moveSprites.push(newSprite);
|
||||
sprites.push(newSprite);
|
||||
}
|
||||
const moveSprite = moveSprites[g++];
|
||||
const moveSprite = sprites[g++];
|
||||
moveSprite.setFrame(frame.graphicFrame);
|
||||
const xProgress = Math.min(Math.max(frame.x, 0) / 128, 1);
|
||||
const yOffset = ((userHalfHeight * (1 - xProgress)) + (targetHalfHeight * xProgress)) * -1;
|
||||
moveSprite.setPosition((!isOppMove ? userInitialX : targetInitialX) + frame.x * coordMultiplayer, (!isOppMove ? userInitialY : targetInitialY) + yOffset + frame.y * coordMultiplayer);
|
||||
const isOppAnim = this.isOppAnim();
|
||||
moveSprite.setPosition((!isOppAnim ? userInitialX : targetInitialX) + frame.x * coordMultiplier, (!isOppAnim ? userInitialY : targetInitialY) + yOffset + frame.y * coordMultiplier);
|
||||
moveSprite.setAlpha(frame.opacity);
|
||||
moveSprite.setAngle(-frame.angle * coordMultiplayer);
|
||||
moveSprite.setAngle(-frame.angle * coordMultiplier);
|
||||
break;
|
||||
}
|
||||
if (frame.target !== AnimFrameTarget.GRAPHIC) {
|
||||
|
@ -472,7 +506,7 @@ export class MoveAnim {
|
|||
? this.user
|
||||
: this.target;
|
||||
pokemon.setAlpha(frame.opacity);
|
||||
pokemon.setAngle(-frame.angle * coordMultiplayer);
|
||||
pokemon.setAngle(-frame.angle * coordMultiplier);
|
||||
const zoomScaleX = frame.zoomX / 100;
|
||||
const zoomScaleY = frame.zoomY / 100;
|
||||
const zoomSprite = pokemon.getZoomSprite();
|
||||
|
@ -482,14 +516,15 @@ export class MoveAnim {
|
|||
}
|
||||
if (anim.frameTimedEvents.has(f)) {
|
||||
for (let event of anim.frameTimedEvents.get(f))
|
||||
event.execute(scene, this);
|
||||
r = Math.max((anim.frames.length - f) + event.execute(scene, this), r);
|
||||
}
|
||||
if (g < moveSprites.length) {
|
||||
const removedSprites = moveSprites.splice(g, moveSprites.length - g);
|
||||
if (g < sprites.length) {
|
||||
const removedSprites = sprites.splice(g, sprites.length - g);
|
||||
for (let rs of removedSprites)
|
||||
rs.destroy();
|
||||
}
|
||||
f++;
|
||||
r--;
|
||||
},
|
||||
onComplete: () => {
|
||||
this.user.setPosition(userInitialX, userInitialY);
|
||||
|
@ -498,15 +533,67 @@ export class MoveAnim {
|
|||
this.target.setPosition(targetInitialX, targetInitialY);
|
||||
this.target.setAlpha(1);
|
||||
this.target.setAngle(0);
|
||||
for (let ms of moveSprites)
|
||||
for (let ms of sprites)
|
||||
ms.destroy();
|
||||
if (callback)
|
||||
if (r && callback) {
|
||||
scene.tweens.addCounter({
|
||||
duration: r,
|
||||
useFrames: true,
|
||||
onComplete: () => callback()
|
||||
});
|
||||
} else if (callback)
|
||||
callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class CommonBattleAnim extends BattleAnim {
|
||||
public commonAnim: CommonAnim;
|
||||
|
||||
constructor(commonAnim: CommonAnim, user: Pokemon, target?: Pokemon) {
|
||||
super(user, target || user);
|
||||
|
||||
this.commonAnim = commonAnim;
|
||||
}
|
||||
|
||||
getAnim(): Anim {
|
||||
return commonAnims.get(this.commonAnim);
|
||||
}
|
||||
|
||||
isOppAnim(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
isReverseCoords(): boolean {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export class MoveAnim extends BattleAnim {
|
||||
public move: Moves;
|
||||
|
||||
constructor(move: Moves, user: Pokemon, target: Pokemon) {
|
||||
super(user, target);
|
||||
|
||||
this.move = move;
|
||||
}
|
||||
|
||||
getAnim(): Anim {
|
||||
return moveAnims.get(this.move) instanceof Anim
|
||||
? moveAnims.get(this.move) as Anim
|
||||
: moveAnims.get(this.move)[this.user instanceof PlayerPokemon ? 0 : 1] as Anim;
|
||||
}
|
||||
|
||||
isOppAnim(): boolean {
|
||||
return this.user instanceof EnemyPokemon && Array.isArray(moveAnims.get(this.move));
|
||||
}
|
||||
|
||||
isReverseCoords(): boolean {
|
||||
return this.user instanceof EnemyPokemon && !this.isOppAnim();
|
||||
}
|
||||
}
|
||||
|
||||
export function populateAnims() {
|
||||
return;
|
||||
const commonAnimNames = Utils.getEnumKeys(CommonAnim).map(k => k.toLowerCase());
|
||||
|
|
|
@ -3,10 +3,12 @@ import { getLevelTotalExp, getLevelRelExp } from './exp';
|
|||
import * as Utils from './utils';
|
||||
import { addTextObject, TextStyle } from './text';
|
||||
import { getGenderSymbol, getGenderColor } from './gender';
|
||||
import { StatusEffect } from './status-effect';
|
||||
|
||||
export default class BattleInfo extends Phaser.GameObjects.Container {
|
||||
private player: boolean;
|
||||
private lastName: string;
|
||||
private lastStatus: StatusEffect;
|
||||
private lastHp: integer;
|
||||
private lastMaxHp: integer;
|
||||
private lastHpFrame: string;
|
||||
|
@ -16,6 +18,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container {
|
|||
|
||||
private nameText: Phaser.GameObjects.Text;
|
||||
private genderText: Phaser.GameObjects.Text;
|
||||
private statusIndicator: Phaser.GameObjects.Sprite;
|
||||
private levelContainer: Phaser.GameObjects.Container;
|
||||
private hpBar: Phaser.GameObjects.Image;
|
||||
private levelNumbersContainer: Phaser.GameObjects.Container;
|
||||
|
@ -25,6 +28,8 @@ export default class BattleInfo extends Phaser.GameObjects.Container {
|
|||
constructor(scene: Phaser.Scene, x: number, y: number, player: boolean) {
|
||||
super(scene, x, y);
|
||||
this.player = player;
|
||||
this.lastName = null;
|
||||
this.lastStatus = StatusEffect.NONE;
|
||||
this.lastHp = -1;
|
||||
this.lastMaxHp = -1;
|
||||
this.lastHpFrame = null;
|
||||
|
@ -48,6 +53,12 @@ export default class BattleInfo extends Phaser.GameObjects.Container {
|
|||
this.genderText.setPositionRelative(this.nameText, 0, 2);
|
||||
this.add(this.genderText);
|
||||
|
||||
this.statusIndicator = this.scene.add.sprite(0, 0, 'statuses');
|
||||
this.statusIndicator.setVisible(false);
|
||||
this.statusIndicator.setOrigin(0, 0);
|
||||
this.statusIndicator.setPositionRelative(this.nameText, 0, 11.5);
|
||||
this.add(this.statusIndicator);
|
||||
|
||||
this.levelContainer = this.scene.add.container(player ? -41 : -50, player ? -10 : -5);
|
||||
this.add(this.levelContainer);
|
||||
|
||||
|
@ -121,6 +132,14 @@ export default class BattleInfo extends Phaser.GameObjects.Container {
|
|||
this.genderText.setPositionRelative(this.nameText, nameTextWidth, 0);
|
||||
}
|
||||
|
||||
if (this.lastStatus !== (pokemon.status?.effect || StatusEffect.NONE)) {
|
||||
this.lastStatus = pokemon.status?.effect || StatusEffect.NONE;
|
||||
|
||||
if (this.lastStatus !== StatusEffect.NONE)
|
||||
this.statusIndicator.setFrame(StatusEffect[this.lastStatus].toLowerCase());
|
||||
this.statusIndicator.setVisible(!!this.lastStatus);
|
||||
}
|
||||
|
||||
const updatePokemonHp = () => {
|
||||
const duration = !instant ? Utils.clampInt(Math.abs((this.lastHp) - pokemon.hp) * 5, 250, 5000) : 0;
|
||||
this.scene.tweens.add({
|
||||
|
|
|
@ -8,8 +8,8 @@ import { Stat } from "./pokemon-stat";
|
|||
import { ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, getModifierTypesForWave, ModifierType, PokemonModifierType, PokemonMoveModifierType, regenerateModifierPoolThresholds } from "./modifier";
|
||||
import PartyUiHandler, { PartyOption, PartyUiMode } from "./ui/party-ui-handler";
|
||||
import { doPokeballBounceAnim, getPokeballAtlasKey, getPokeballCatchMultiplier, getPokeballTintColor, PokeballType } from "./pokeball";
|
||||
import { MoveAnim, initAnim, loadMoveAnimAssets } from "./battle-anims";
|
||||
import { StatusEffect } from "./status-effect";
|
||||
import { CommonAnim, CommonBattleAnim, MoveAnim, initMoveAnim, loadMoveAnimAssets } from "./battle-anims";
|
||||
import { StatusEffect, getStatusEffectActivationText, getStatusEffectHealText, getStatusEffectObtainText, getStatusEffectOverlapText } from "./status-effect";
|
||||
import { SummaryUiMode } from "./ui/summary-ui-handler";
|
||||
import EvolutionSceneHandler from "./ui/evolution-scene-handler";
|
||||
import { EvolutionPhase } from "./evolution-phase";
|
||||
|
@ -351,19 +351,20 @@ export class CommandPhase extends BattlePhase {
|
|||
});
|
||||
}
|
||||
|
||||
handleCommand(command: Command, cursor: integer): boolean{
|
||||
handleCommand(command: Command, cursor: integer): boolean {
|
||||
const playerPokemon = this.scene.getPlayerPokemon();
|
||||
const enemyPokemon = this.scene.getEnemyPokemon();
|
||||
let success: boolean;
|
||||
let delayed: boolean;
|
||||
|
||||
const playerSpeed = playerPokemon.getBattleStat(Stat.SPD);
|
||||
const enemySpeed = enemyPokemon.getBattleStat(Stat.SPD);
|
||||
|
||||
const isDelayed = () => playerSpeed < enemySpeed || (playerSpeed === enemySpeed && Utils.randInt(2) === 1);
|
||||
|
||||
switch (command) {
|
||||
case Command.FIGHT:
|
||||
if (playerPokemon.trySelectMove(cursor)) {
|
||||
const playerPhase = new PlayerMovePhase(this.scene, playerPokemon, playerPokemon.moveset[cursor]);
|
||||
const playerSpeed = playerPokemon.getBattleStat(Stat.SPD);
|
||||
const enemySpeed = enemyPokemon.getBattleStat(Stat.SPD);
|
||||
delayed = playerSpeed < enemySpeed || (playerSpeed === enemySpeed && Utils.randInt(2) === 1)
|
||||
this.scene.pushPhase(playerPhase);
|
||||
success = true;
|
||||
}
|
||||
|
@ -382,10 +383,24 @@ export class CommandPhase extends BattlePhase {
|
|||
if (success) {
|
||||
const enemyMove = enemyPokemon.getNextMove();
|
||||
const enemyPhase = new EnemyMovePhase(this.scene, enemyPokemon, enemyMove);
|
||||
if (delayed)
|
||||
if (isDelayed())
|
||||
this.scene.unshiftPhase(enemyPhase);
|
||||
else
|
||||
this.scene.pushPhase(enemyPhase);
|
||||
|
||||
const statusEffectPhases: PostTurnStatusEffectPhase[] = [];
|
||||
if (playerPokemon.status && playerPokemon.status.isPostTurn())
|
||||
statusEffectPhases.push(new PostTurnStatusEffectPhase(this.scene, true));
|
||||
if (enemyPokemon.status && enemyPokemon.status.isPostTurn()) {
|
||||
const enemyStatusEffectPhase = new PostTurnStatusEffectPhase(this.scene, false);
|
||||
if (isDelayed())
|
||||
statusEffectPhases.unshift(enemyStatusEffectPhase);
|
||||
else
|
||||
statusEffectPhases.push(enemyStatusEffectPhase);
|
||||
}
|
||||
for (let sef of statusEffectPhases)
|
||||
this.scene.pushPhase(sef);
|
||||
|
||||
this.end();
|
||||
}
|
||||
|
||||
|
@ -428,12 +443,14 @@ export abstract class PartyMemberPokemonPhase extends PokemonPhase {
|
|||
abstract class MovePhase extends BattlePhase {
|
||||
protected pokemon: Pokemon;
|
||||
protected move: PokemonMove;
|
||||
protected cancelled: boolean;
|
||||
|
||||
constructor(scene: BattleScene, pokemon: Pokemon, move: PokemonMove) {
|
||||
super(scene);
|
||||
|
||||
this.pokemon = pokemon;
|
||||
this.move = move;
|
||||
this.cancelled = false;
|
||||
}
|
||||
|
||||
abstract getEffectPhase(): MoveEffectPhase;
|
||||
|
@ -445,17 +462,61 @@ abstract class MovePhase extends BattlePhase {
|
|||
start() {
|
||||
super.start();
|
||||
|
||||
const doMove = () => {
|
||||
if (this.cancelled) {
|
||||
this.end();
|
||||
return;
|
||||
}
|
||||
if (!this.move)
|
||||
console.log(this.pokemon.moveset);
|
||||
this.move.ppUsed++;
|
||||
this.scene.unshiftPhase(new MessagePhase(this.scene, `${this.pokemon.name} used\n${this.move.getName()}!`, 500));
|
||||
this.scene.unshiftPhase(this.getEffectPhase());
|
||||
this.end();
|
||||
};
|
||||
|
||||
if (!this.canMove()) {
|
||||
this.end();
|
||||
return;
|
||||
}
|
||||
if (!this.move)
|
||||
console.log(this.pokemon.moveset);
|
||||
this.scene.ui.showText(`${this.pokemon.name} used\n${this.move.getName()}!`, null, () => {
|
||||
this.move.ppUsed++;
|
||||
this.scene.unshiftPhase(this.getEffectPhase());
|
||||
this.end();
|
||||
}, 500);
|
||||
|
||||
if (this.pokemon.status && !this.pokemon.status.isPostTurn()) {
|
||||
this.pokemon.status.incrementTurn();
|
||||
let activated = false;
|
||||
let healed = false;
|
||||
switch (this.pokemon.status.effect) {
|
||||
case StatusEffect.PARALYSIS:
|
||||
if (Utils.randInt(4) === 0) {
|
||||
activated = true;
|
||||
this.cancelled = true;
|
||||
}
|
||||
break;
|
||||
case StatusEffect.SLEEP:
|
||||
healed = this.pokemon.status.turnCount === this.pokemon.status.cureTurn;
|
||||
activated = !healed;
|
||||
this.cancelled = activated;
|
||||
break;
|
||||
case StatusEffect.FREEZE:
|
||||
healed = Utils.randInt(5) === 0;
|
||||
activated = !healed;
|
||||
this.cancelled = activated;
|
||||
break;
|
||||
}
|
||||
if (activated) {
|
||||
this.scene.unshiftPhase(new MessagePhase(this.scene,
|
||||
`${this.pokemon instanceof PlayerPokemon ? '' : 'Foe '}${this.pokemon.name}${getStatusEffectActivationText(this.pokemon.status.effect)}`));
|
||||
new CommonBattleAnim(CommonAnim.POISON + (this.pokemon.status.effect - 1), this.pokemon).play(this.scene, () => doMove());
|
||||
} else {
|
||||
if (healed) {
|
||||
this.scene.unshiftPhase(new MessagePhase(this.scene,
|
||||
`${this.pokemon instanceof PlayerPokemon ? '' : 'Foe '}${this.pokemon.name}${getStatusEffectHealText(this.pokemon.status.effect)}`));
|
||||
this.pokemon.resetStatus();
|
||||
this.pokemon.updateInfo(true);
|
||||
}
|
||||
doMove();
|
||||
}
|
||||
} else
|
||||
doMove();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -498,7 +559,7 @@ abstract class MoveEffectPhase extends PokemonPhase {
|
|||
const hitCount = new Utils.IntegerHolder(1);
|
||||
applyMoveAttrs(MultiHitAttr, this.scene, user, target, this.move.getMove(), hitCount);
|
||||
user.turnData.hitCount = 0;
|
||||
user.turnData.hitsLeft = hitCount.value;
|
||||
user.turnData.hitsLeft = user.turnData.hitsTotal = hitCount.value;
|
||||
}
|
||||
|
||||
if (!this.hitCheck()) {
|
||||
|
@ -511,7 +572,8 @@ abstract class MoveEffectPhase extends PokemonPhase {
|
|||
new MoveAnim(this.move.getMove().id as Moves, user, target).play(this.scene, () => {
|
||||
this.getTargetPokemon().apply(this.getUserPokemon(), this.move, () => {
|
||||
++user.turnData.hitCount;
|
||||
applyMoveAttrs(MoveHitEffectAttr, this.scene, user, target, this.move.getMove());
|
||||
if (this.getTargetPokemon().hp)
|
||||
applyMoveAttrs(MoveHitEffectAttr, this.scene, user, target, this.move.getMove());
|
||||
this.end();
|
||||
});
|
||||
if (this.getUserPokemon().hp <= 0) {
|
||||
|
@ -529,7 +591,7 @@ abstract class MoveEffectPhase extends PokemonPhase {
|
|||
const user = this.getUserPokemon();
|
||||
if (--user.turnData.hitsLeft && this.getTargetPokemon().hp)
|
||||
this.scene.unshiftPhase(this.getNewHitPhase());
|
||||
else if (user.turnData.hitCount > 1)
|
||||
else if (user.turnData.hitsTotal > 1)
|
||||
this.scene.unshiftPhase(new MessagePhase(this.scene, `Hit ${user.turnData.hitCount} time(s)!`));
|
||||
|
||||
super.end();
|
||||
|
@ -683,14 +745,56 @@ export class ObtainStatusEffectPhase extends PokemonPhase {
|
|||
|
||||
constructor(scene: BattleScene, player: boolean, statusEffect: StatusEffect) {
|
||||
super(scene, player);
|
||||
|
||||
this.statusEffect = statusEffect;
|
||||
}
|
||||
|
||||
start() {
|
||||
const pokemon = this.getPokemon();
|
||||
if (pokemon.status === StatusEffect.NONE) {
|
||||
pokemon.status = this.statusEffect;
|
||||
// Show message and animation
|
||||
this.end();
|
||||
if (!pokemon.status) {
|
||||
if (pokemon.trySetStatus(this.statusEffect)) {
|
||||
pokemon.updateInfo(true);
|
||||
new CommonBattleAnim(CommonAnim.POISON + (this.statusEffect - 1), pokemon).play(this.scene, () => {
|
||||
this.scene.unshiftPhase(new MessagePhase(this.scene, `${this.player ? '' : 'Foe '}${pokemon.name}${getStatusEffectObtainText(this.statusEffect)}`));
|
||||
if (pokemon.status.isPostTurn())
|
||||
this.scene.pushPhase(new PostTurnStatusEffectPhase(this.scene, this.player));
|
||||
this.end();
|
||||
});
|
||||
return;
|
||||
}
|
||||
} else if (pokemon.status.effect === this.statusEffect)
|
||||
this.scene.unshiftPhase(new MessagePhase(this.scene, `${this.player ? '' : 'Foe '}${pokemon.name}${getStatusEffectOverlapText(this.statusEffect)}`));
|
||||
this.end();
|
||||
}
|
||||
}
|
||||
|
||||
export class PostTurnStatusEffectPhase extends PokemonPhase {
|
||||
constructor(scene: BattleScene, player: boolean) {
|
||||
super(scene, player);
|
||||
}
|
||||
|
||||
start() {
|
||||
const pokemon = this.getPokemon();
|
||||
if (pokemon.hp && pokemon.status && pokemon.status.isPostTurn()) {
|
||||
pokemon.status.incrementTurn();
|
||||
new CommonBattleAnim(CommonAnim.POISON + (pokemon.status.effect - 1), pokemon).play(this.scene, () => {
|
||||
this.scene.unshiftPhase(new MessagePhase(this.scene,
|
||||
`${pokemon instanceof PlayerPokemon ? '' : 'Foe '}${pokemon.name}${getStatusEffectActivationText(pokemon.status.effect)}`));
|
||||
switch (pokemon.status.effect) {
|
||||
case StatusEffect.POISON:
|
||||
case StatusEffect.BURN:
|
||||
pokemon.hp = Math.max(pokemon.hp - Math.max(pokemon.getMaxHp() >> 3, 1), 0);
|
||||
break;
|
||||
case StatusEffect.TOXIC:
|
||||
pokemon.hp = Math.max(pokemon.hp - Math.max(Math.floor((pokemon.getMaxHp() / 16) * pokemon.status.turnCount), 1), 0);
|
||||
break;
|
||||
}
|
||||
if (pokemon.hp <= 0) {
|
||||
this.scene.pushPhase(new FaintPhase(this.scene, this.player));
|
||||
(this.player ? this.scene.getEnemyPokemon() : this.scene.getPlayerPokemon()).resetBattleSummonData();
|
||||
}
|
||||
pokemon.updateInfo().then(() => this.end());
|
||||
});
|
||||
} else
|
||||
this.end();
|
||||
}
|
||||
|
@ -698,19 +802,21 @@ export class ObtainStatusEffectPhase extends PokemonPhase {
|
|||
|
||||
export class MessagePhase extends BattlePhase {
|
||||
private text: string;
|
||||
private callbackDelay: integer;
|
||||
private prompt: boolean;
|
||||
|
||||
constructor(scene: BattleScene, text: string, prompt?: boolean) {
|
||||
constructor(scene: BattleScene, text: string, callbackDelay?: integer, prompt?: boolean) {
|
||||
super(scene);
|
||||
|
||||
this.text = text;
|
||||
this.callbackDelay = callbackDelay;
|
||||
this.prompt = prompt;
|
||||
}
|
||||
|
||||
start() {
|
||||
super.start();
|
||||
|
||||
this.scene.ui.showText(this.text, null, () => this.end(), this.prompt ? 0 : 1500, this.prompt);
|
||||
this.scene.ui.showText(this.text, null, () => this.end(), this.callbackDelay || (this.prompt ? 0 : 1500), this.prompt);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -723,10 +829,10 @@ export class FaintPhase extends PokemonPhase {
|
|||
super.start();
|
||||
|
||||
if (this.player) {
|
||||
this.scene.unshiftPhase(new MessagePhase(this.scene, `${this.getPokemon().name} fainted!`, true));
|
||||
this.scene.unshiftPhase(new MessagePhase(this.scene, `${this.getPokemon().name} fainted!`, null, true));
|
||||
this.scene.unshiftPhase(new SwitchPhase(this.scene, true, false));
|
||||
} else {
|
||||
this.scene.unshiftPhase(new MessagePhase(this.scene, `Foe ${this.getPokemon().name} fainted!`, true));
|
||||
this.scene.unshiftPhase(new MessagePhase(this.scene, `Foe ${this.getPokemon().name} fainted!`, null, true));
|
||||
this.scene.unshiftPhase(new VictoryPhase(this.scene));
|
||||
}
|
||||
|
||||
|
@ -904,7 +1010,7 @@ export class LearnMovePhase extends PartyMemberPokemonPhase {
|
|||
|
||||
if (emptyMoveIndex > -1) {
|
||||
pokemon.moveset[emptyMoveIndex] = new PokemonMove(this.moveId, 0, 0);
|
||||
initAnim(this.moveId).then(() => {
|
||||
initMoveAnim(this.moveId).then(() => {
|
||||
loadMoveAnimAssets(this.scene, [ this.moveId ], true)
|
||||
.then(() => {
|
||||
this.scene.ui.setMode(messageMode).then(() => {
|
||||
|
|
|
@ -10,7 +10,7 @@ import { PokeballType } from './pokeball';
|
|||
import { Species } from './species';
|
||||
import { initAutoPlay } from './auto-play';
|
||||
import { Battle } from './battle';
|
||||
import { populateAnims } from './battle-anims';
|
||||
import { initCommonAnims, loadCommonAnimAssets, populateAnims } from './battle-anims';
|
||||
import { BattlePhase } from './battle-phase';
|
||||
|
||||
const enableAuto = true;
|
||||
|
@ -321,7 +321,7 @@ export default class BattleScene extends Phaser.Scene {
|
|||
|
||||
ui.setup();
|
||||
|
||||
Promise.all(loadPokemonAssets).then(() => {
|
||||
Promise.all([ Promise.all(loadPokemonAssets), initCommonAnims().then(() => loadCommonAnimAssets(this, true)) ]).then(() => {
|
||||
if (enableAuto)
|
||||
initAutoPlay.apply(this);
|
||||
|
||||
|
|
61
src/move.ts
61
src/move.ts
|
@ -2,8 +2,7 @@ import { MessagePhase, ObtainStatusEffectPhase, StatChangePhase } from "./battle
|
|||
import BattleScene from "./battle-scene";
|
||||
import { BattleStat } from "./battle-stat";
|
||||
import Pokemon, { PlayerPokemon } from "./pokemon";
|
||||
import { Stat } from "./pokemon-stat";
|
||||
import { StatusEffect } from "./status-effect";
|
||||
import { StatusEffect, getStatusEffectOverlapText } from "./status-effect";
|
||||
import { Type } from "./type";
|
||||
import * as Utils from "./utils";
|
||||
|
||||
|
@ -609,6 +608,10 @@ export enum Moves {
|
|||
FUSION_BOLT
|
||||
};
|
||||
|
||||
const enum MoveEffectText {
|
||||
BUT_IT_FAILED = 'But it failed!'
|
||||
}
|
||||
|
||||
type MoveAttrFunc = (scene: BattleScene, user: Pokemon, target: Pokemon, move: Move) => void;
|
||||
|
||||
export abstract class MoveAttr {
|
||||
|
@ -624,7 +627,7 @@ export class HighCritAttr extends MoveAttr {
|
|||
apply(scene: BattleScene, user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
const critChance = args[0] as Utils.IntegerHolder;
|
||||
critChance.value /= 2;
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -681,8 +684,10 @@ class StatusEffectAttr extends MoveHitEffectAttr {
|
|||
|
||||
apply(scene: BattleScene, user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
const statusCheck = move.chance < 0 || move.chance === 100 || Utils.randInt(100) < move.chance;
|
||||
if (statusCheck)
|
||||
scene.unshiftPhase(new ObtainStatusEffectPhase(scene, target instanceof PlayerPokemon, this.effect));
|
||||
if (statusCheck) {
|
||||
if (!target.status || (target.status.effect === this.effect && move.chance < 0))
|
||||
scene.unshiftPhase(new ObtainStatusEffectPhase(scene, target instanceof PlayerPokemon, this.effect));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -794,32 +799,32 @@ export const allMoves = [
|
|||
new Move(Moves.FURY_ATTACK, "Fury Attack", Type.NORMAL, MoveCategory.PHYSICAL, 15, 85, 20, -1, "Hits 2-5 times in one turn.", -1, 1, new MultiHitAttr()),
|
||||
new Move(Moves.HORN_DRILL, "Horn Drill", Type.NORMAL, MoveCategory.PHYSICAL, -1, 30, 5, -1, "One-Hit-KO, if it hits.", -1, 1, new OneHitKOAttr()),
|
||||
new Move(Moves.TACKLE, "Tackle", Type.NORMAL, MoveCategory.PHYSICAL, 40, 100, 35, -1, "", -1, 1),
|
||||
new Move(Moves.BODY_SLAM, "Body Slam", Type.NORMAL, MoveCategory.PHYSICAL, 85, 100, 15, 66, "May paralyze opponent.", 30, 1),
|
||||
new Move(Moves.BODY_SLAM, "Body Slam", Type.NORMAL, MoveCategory.PHYSICAL, 85, 100, 15, 66, "May paralyze opponent.", 30, 1, new StatusEffectAttr(StatusEffect.PARALYSIS)),
|
||||
new Move(Moves.WRAP, "Wrap", Type.NORMAL, MoveCategory.PHYSICAL, 15, 90, 20, -1, "Traps opponent, damaging them for 4-5 turns.", 100, 1),
|
||||
new Move(Moves.TAKE_DOWN, "Take Down", Type.NORMAL, MoveCategory.PHYSICAL, 90, 85, 20, 1, "User receives recoil damage.", -1, 1),
|
||||
new Move(Moves.THRASH, "Thrash", Type.NORMAL, MoveCategory.PHYSICAL, 120, 100, 10, -1, "User attacks for 2-3 turns but then becomes confused.", -1, 1),
|
||||
new Move(Moves.DOUBLE_EDGE, "Double-Edge", Type.NORMAL, MoveCategory.PHYSICAL, 120, 100, 15, -1, "User receives recoil damage.", -1, 1),
|
||||
new Move(Moves.TAIL_WHIP, "Tail Whip", Type.NORMAL, MoveCategory.STATUS, -1, 100, 30, -1, "Lowers opponent's Defense.", -1, 1, new StatChangeAttr(BattleStat.DEF, -1)),
|
||||
new Move(Moves.POISON_STING, "Poison Sting", Type.POISON, MoveCategory.PHYSICAL, 15, 100, 35, -1, "May poison the opponent.", 30, 1),
|
||||
new Move(Moves.TWINEEDLE, "Twineedle", Type.BUG, MoveCategory.PHYSICAL, 25, 100, 20, -1, "Hits twice in one turn. May poison opponent.", 20, 1, new MultiHitAttr(MultiHitType._2)),
|
||||
new Move(Moves.POISON_STING, "Poison Sting", Type.POISON, MoveCategory.PHYSICAL, 15, 100, 35, -1, "May poison the opponent.", 30, 1, new StatusEffectAttr(StatusEffect.POISON)),
|
||||
new Move(Moves.TWINEEDLE, "Twineedle", Type.BUG, MoveCategory.PHYSICAL, 25, 100, 20, -1, "Hits twice in one turn. May poison opponent.", 20, 1, new MultiHitAttr(MultiHitType._2), new StatusEffectAttr(StatusEffect.POISON)),
|
||||
new Move(Moves.PIN_MISSILE, "Pin Missile", Type.BUG, MoveCategory.PHYSICAL, 25, 95, 20, -1, "Hits 2-5 times in one turn.", -1, 1,new MultiHitAttr()),
|
||||
new Move(Moves.LEER, "Leer", Type.NORMAL, MoveCategory.STATUS, -1, 100, 30, -1, "Lowers opponent's Defense.", 100, 1, new StatChangeAttr(BattleStat.DEF, -1)),
|
||||
new Move(Moves.BITE, "Bite", Type.DARK, MoveCategory.PHYSICAL, 60, 100, 25, -1, "May cause flinching.", 30, 1, new FlinchAttr()),
|
||||
new Move(Moves.GROWL, "Growl", Type.NORMAL, MoveCategory.STATUS, -1, 100, 40, -1, "Lowers opponent's Attack.", -1, 1, new StatChangeAttr(BattleStat.ATK, -1)),
|
||||
new Move(Moves.ROAR, "Roar", Type.NORMAL, MoveCategory.STATUS, -1, -1, 20, -1, "In battles, the opponent switches. In the wild, the Pokémon runs.", -1, 1),
|
||||
new Move(Moves.SING, "Sing", Type.NORMAL, MoveCategory.STATUS, -1, 55, 15, -1, "Puts opponent to sleep.", -1, 1),
|
||||
new Move(Moves.SING, "Sing", Type.NORMAL, MoveCategory.STATUS, -1, 55, 15, -1, "Puts opponent to sleep.", -1, 1, new StatusEffectAttr(StatusEffect.SLEEP)),
|
||||
new Move(Moves.SUPERSONIC, "Supersonic", Type.NORMAL, MoveCategory.STATUS, -1, 55, 20, -1, "Confuses opponent.", -1, 1),
|
||||
new Move(Moves.SONIC_BOOM, "Sonic Boom", Type.NORMAL, MoveCategory.SPECIAL, -1, 90, 20, -1, "Always inflicts 20 HP.", -1, 1),
|
||||
new Move(Moves.DISABLE, "Disable", Type.NORMAL, MoveCategory.STATUS, -1, 100, 20, -1, "Opponent can't use its last attack for a few turns.", -1, 1),
|
||||
new Move(Moves.ACID, "Acid", Type.POISON, MoveCategory.SPECIAL, 40, 100, 30, -1, "May lower opponent's Special Defense.", 10, 1, new StatChangeAttr(BattleStat.SPDEF, -1)),
|
||||
new Move(Moves.EMBER, "Ember", Type.FIRE, MoveCategory.SPECIAL, 40, 100, 25, -1, "May burn opponent.", 10, 1),
|
||||
new Move(Moves.FLAMETHROWER, "Flamethrower", Type.FIRE, MoveCategory.SPECIAL, 90, 100, 15, 125, "May burn opponent.", 10, 1),
|
||||
new Move(Moves.EMBER, "Ember", Type.FIRE, MoveCategory.SPECIAL, 40, 100, 25, -1, "May burn opponent.", 10, 1, new StatusEffectAttr(StatusEffect.BURN)),
|
||||
new Move(Moves.FLAMETHROWER, "Flamethrower", Type.FIRE, MoveCategory.SPECIAL, 90, 100, 15, 125, "May burn opponent.", 10, 1, new StatusEffectAttr(StatusEffect.BURN)),
|
||||
new Move(Moves.MIST, "Mist", Type.ICE, MoveCategory.STATUS, -1, -1, 30, -1, "User's stats cannot be changed for a period of time.", -1, 1),
|
||||
new Move(Moves.WATER_GUN, "Water Gun", Type.WATER, MoveCategory.SPECIAL, 40, 100, 25, -1, "", -1, 1),
|
||||
new Move(Moves.HYDRO_PUMP, "Hydro Pump", Type.WATER, MoveCategory.SPECIAL, 110, 80, 5, 142, "", -1, 1),
|
||||
new Move(Moves.SURF, "Surf", Type.WATER, MoveCategory.SPECIAL, 90, 100, 15, 123, "Hits all adjacent Pokémon.", -1, 1),
|
||||
new Move(Moves.ICE_BEAM, "Ice Beam", Type.ICE, MoveCategory.SPECIAL, 90, 100, 10, 135, "May freeze opponent.", 10, 1),
|
||||
new Move(Moves.BLIZZARD, "Blizzard", Type.ICE, MoveCategory.SPECIAL, 110, 70, 5, 143, "May freeze opponent.", 10, 1),
|
||||
new Move(Moves.ICE_BEAM, "Ice Beam", Type.ICE, MoveCategory.SPECIAL, 90, 100, 10, 135, "May freeze opponent.", 10, 1, new StatusEffectAttr(StatusEffect.FREEZE)),
|
||||
new Move(Moves.BLIZZARD, "Blizzard", Type.ICE, MoveCategory.SPECIAL, 110, 70, 5, 143, "May freeze opponent.", 10, 1, new StatusEffectAttr(StatusEffect.FREEZE)),
|
||||
new Move(Moves.PSYBEAM, "Psybeam", Type.PSYCHIC, MoveCategory.SPECIAL, 65, 100, 20, 16, "May confuse opponent.", 10, 1),
|
||||
new Move(Moves.BUBBLE_BEAM, "Bubble Beam", Type.WATER, MoveCategory.SPECIAL, 65, 100, 20, -1, "May lower opponent's Speed.", 10, 1, new StatChangeAttr(BattleStat.SPD, -1)),
|
||||
new Move(Moves.AURORA_BEAM, "Aurora Beam", Type.ICE, MoveCategory.SPECIAL, 65, 100, 20, -1, "May lower opponent's Attack.", 10, 1, new StatChangeAttr(BattleStat.ATK, -1)),
|
||||
|
@ -838,9 +843,9 @@ export const allMoves = [
|
|||
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.SOLAR_BEAM, "Solar Beam", Type.GRASS, MoveCategory.SPECIAL, 120, 100, 10, 168, "Charges on first turn, attacks on second.", -1, 1),
|
||||
new Move(Moves.POISON_POWDER, "Poison Powder", Type.POISON, MoveCategory.STATUS, -1, 75, 35, -1, "Poisons opponent.", -1, 1),
|
||||
new Move(Moves.STUN_SPORE, "Stun Spore", Type.GRASS, MoveCategory.STATUS, -1, 75, 30, -1, "Paralyzes opponent.", -1, 1),
|
||||
new Move(Moves.SLEEP_POWDER, "Sleep Powder", Type.GRASS, MoveCategory.STATUS, -1, 75, 15, -1, "Puts opponent to sleep.", -1, 1),
|
||||
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.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.PETAL_DANCE, "Petal Dance", Type.GRASS, MoveCategory.SPECIAL, 120, 100, 10, -1, "User attacks for 2-3 turns but then becomes confused.", -1, 1),
|
||||
new Move(Moves.STRING_SHOT, "String Shot", Type.BUG, MoveCategory.STATUS, -1, 95, 40, -1, "Sharply lowers opponent's Speed.", -1, 1, new StatChangeAttr(BattleStat.SPD, -2)),
|
||||
new Move(Moves.DRAGON_RAGE, "Dragon Rage", Type.DRAGON, MoveCategory.SPECIAL, -1, 100, 10, -1, "Always inflicts 40 HP.", -1, 1),
|
||||
|
@ -944,7 +949,7 @@ export const allMoves = [
|
|||
new Move(Moves.COTTON_SPORE, "Cotton Spore", Type.GRASS, MoveCategory.STATUS, -1, 100, 40, -1, "Sharply lowers opponent's Speed.", -1, 2, new StatChangeAttr(BattleStat.SPD, -2)),
|
||||
new Move(Moves.REVERSAL, "Reversal", Type.FIGHTING, MoveCategory.PHYSICAL, -1, 100, 15, 134, "The lower the user's HP, the higher the power.", -1, 2),
|
||||
new Move(Moves.SPITE, "Spite", Type.GHOST, MoveCategory.STATUS, -1, 100, 10, -1, "The opponent's last move loses 2-5 PP.", -1, 2),
|
||||
new Move(Moves.POWDER_SNOW, "Powder Snow", Type.ICE, MoveCategory.SPECIAL, 40, 100, 25, -1, "May freeze opponent.", 10, 2),
|
||||
new Move(Moves.POWDER_SNOW, "Powder Snow", Type.ICE, MoveCategory.SPECIAL, 40, 100, 25, -1, "May freeze opponent.", 10, 2, new StatusEffectAttr(StatusEffect.FREEZE)),
|
||||
new Move(Moves.PROTECT, "Protect", Type.NORMAL, MoveCategory.STATUS, -1, -1, 10, 7, "Protects the user, but may fail if used consecutively.", -1, 2),
|
||||
new Move(Moves.MACH_PUNCH, "Mach Punch", Type.FIGHTING, MoveCategory.PHYSICAL, 40, 100, 30, -1, "User attacks first.", -1, 2),
|
||||
new Move(Moves.SCARY_FACE, "Scary Face", Type.NORMAL, MoveCategory.STATUS, -1, 100, 10, 6, "Sharply lowers opponent's Speed.", -1, 2, new StatChangeAttr(BattleStat.SPD, -2)),
|
||||
|
@ -1047,7 +1052,7 @@ export const allMoves = [
|
|||
new Move(Moves.RECYCLE, "Recycle", Type.NORMAL, MoveCategory.STATUS, -1, -1, 10, -1, "User's used hold item is restored.", -1, 3),
|
||||
new Move(Moves.REVENGE, "Revenge", Type.FIGHTING, MoveCategory.PHYSICAL, 60, 100, 10, -1, "Power increases if user was hit first.", -1, 3),
|
||||
new Move(Moves.BRICK_BREAK, "Brick Break", Type.FIGHTING, MoveCategory.PHYSICAL, 75, 100, 15, 58, "Breaks through Reflect and Light Screen barriers.", -1, 3),
|
||||
new Move(Moves.YAWN, "Yawn", Type.NORMAL, MoveCategory.STATUS, -1, -1, 10, -1, "Puts opponent to sleep in the next turn.", -1, 3),
|
||||
new Move(Moves.YAWN, "Yawn", Type.NORMAL, MoveCategory.STATUS, -1, -1, 10, -1, "Puts opponent to sleep in the next turn.", -1, 3), // TODO
|
||||
new Move(Moves.KNOCK_OFF, "Knock Off", Type.DARK, MoveCategory.PHYSICAL, 65, 100, 20, -1, "Removes opponent's held item for the rest of the battle.", -1, 3),
|
||||
new Move(Moves.ENDEAVOR, "Endeavor", Type.NORMAL, MoveCategory.PHYSICAL, -1, 100, 5, -1, "Reduces opponent's HP to same as user's.", -1, 3),
|
||||
new Move(Moves.ERUPTION, "Eruption", Type.FIRE, MoveCategory.SPECIAL, 150, 100, 5, -1, "Stronger when the user's HP is higher.", -1, 3),
|
||||
|
@ -1168,11 +1173,11 @@ export const allMoves = [
|
|||
new Move(Moves.HEART_SWAP, "Heart Swap", Type.PSYCHIC, MoveCategory.STATUS, -1, -1, 10, -1, "Stat changes are swapped with the opponent.", -1, 4),
|
||||
new Move(Moves.AQUA_RING, "Aqua Ring", Type.WATER, MoveCategory.STATUS, -1, -1, 20, -1, "Restores a little HP each turn.", -1, 4),
|
||||
new Move(Moves.MAGNET_RISE, "Magnet Rise", Type.ELECTRIC, MoveCategory.STATUS, -1, -1, 10, -1, "User becomes immune to Ground-type moves for 5 turns.", -1, 4),
|
||||
new Move(Moves.FLARE_BLITZ, "Flare Blitz", Type.FIRE, MoveCategory.PHYSICAL, 120, 100, 15, 165, "User receives recoil damage. May burn opponent.", 10, 4),
|
||||
new Move(Moves.FORCE_PALM, "Force Palm", Type.FIGHTING, MoveCategory.PHYSICAL, 60, 100, 10, -1, "May paralyze opponent.", 30, 4),
|
||||
new Move(Moves.FLARE_BLITZ, "Flare Blitz", Type.FIRE, MoveCategory.PHYSICAL, 120, 100, 15, 165, "User receives recoil damage. May burn opponent.", 10, 4, new StatusEffectAttr(StatusEffect.BURN)), // TODO
|
||||
new Move(Moves.FORCE_PALM, "Force Palm", Type.FIGHTING, MoveCategory.PHYSICAL, 60, 100, 10, -1, "May paralyze opponent.", 30, 4, new StatusEffectAttr(StatusEffect.PARALYSIS)),
|
||||
new Move(Moves.AURA_SPHERE, "Aura Sphere", Type.FIGHTING, MoveCategory.SPECIAL, 80, 999, 20, 112, "Ignores Accuracy and Evasiveness.", -1, 4),
|
||||
new Move(Moves.ROCK_POLISH, "Rock Polish", Type.ROCK, MoveCategory.STATUS, -1, -1, 20, -1, "Sharply raises user's Speed.", -1, 4, new StatChangeAttr(BattleStat.SPD, 2, true)),
|
||||
new Move(Moves.POISON_JAB, "Poison Jab", Type.POISON, MoveCategory.PHYSICAL, 80, 100, 20, 83, "May poison the opponent.", 30, 4),
|
||||
new Move(Moves.POISON_JAB, "Poison Jab", Type.POISON, MoveCategory.PHYSICAL, 80, 100, 20, 83, "May poison the opponent.", 30, 4, new StatusEffectAttr(StatusEffect.POISON)),
|
||||
new Move(Moves.DARK_PULSE, "Dark Pulse", Type.DARK, MoveCategory.SPECIAL, 80, 100, 15, 94, "May cause flinching.", 20, 4, new FlinchAttr()),
|
||||
new Move(Moves.NIGHT_SLASH, "Night Slash", Type.DARK, MoveCategory.PHYSICAL, 70, 100, 15, -1, "High critical hit ratio.", -1, 4),
|
||||
new Move(Moves.AQUA_TAIL, "Aqua Tail", Type.WATER, MoveCategory.PHYSICAL, 90, 90, 10, -1, "", -1, 4),
|
||||
|
@ -1209,8 +1214,8 @@ export const allMoves = [
|
|||
new Move(Moves.DEFOG, "Defog", Type.FLYING, MoveCategory.STATUS, -1, -1, 15, -1, "Lowers opponent's Evasiveness and clears fog.", -1, 4, new StatChangeAttr(BattleStat.EVA, -1)), // TODO
|
||||
new Move(Moves.TRICK_ROOM, "Trick Room", Type.PSYCHIC, MoveCategory.STATUS, -1, -1, 5, 161, "Slower Pokémon move first in the turn for 5 turns.", -1, 4),
|
||||
new Move(Moves.DRACO_METEOR, "Draco Meteor", Type.DRAGON, MoveCategory.SPECIAL, 130, 90, 5, 169, "Sharply lowers user's Special Attack.", 100, 4, new StatChangeAttr(BattleStat.SPATK, -2, true)),
|
||||
new Move(Moves.DISCHARGE, "Discharge", Type.ELECTRIC, MoveCategory.SPECIAL, 80, 100, 15, -1, "May paralyze opponent.", 30, 4),
|
||||
new Move(Moves.LAVA_PLUME, "Lava Plume", Type.FIRE, MoveCategory.SPECIAL, 80, 100, 15, -1, "May burn opponent.", 30, 4),
|
||||
new Move(Moves.DISCHARGE, "Discharge", Type.ELECTRIC, MoveCategory.SPECIAL, 80, 100, 15, -1, "May paralyze opponent.", 30, 4, new StatusEffectAttr(StatusEffect.PARALYSIS)),
|
||||
new Move(Moves.LAVA_PLUME, "Lava Plume", Type.FIRE, MoveCategory.SPECIAL, 80, 100, 15, -1, "May burn opponent.", 30, 4, new StatusEffectAttr(StatusEffect.BURN)),
|
||||
new Move(Moves.LEAF_STORM, "Leaf Storm", Type.GRASS, MoveCategory.SPECIAL, 130, 90, 5, 159, "Sharply lowers user's Special Attack.", 100, 4, new StatChangeAttr(BattleStat.SPATK, -2, true)),
|
||||
new Move(Moves.POWER_WHIP, "Power Whip", Type.GRASS, MoveCategory.PHYSICAL, 120, 85, 10, -1, "", -1, 4),
|
||||
new Move(Moves.ROCK_WRECKER, "Rock Wrecker", Type.ROCK, MoveCategory.PHYSICAL, 150, 90, 5, -1, "User must recharge next turn.", -1, 4),
|
||||
|
@ -1240,7 +1245,7 @@ export const allMoves = [
|
|||
new Move(Moves.LUNAR_DANCE, "Lunar Dance", Type.PSYCHIC, MoveCategory.STATUS, -1, -1, 10, -1, "The user faints but the next Pokémon released is fully healed.", -1, 4),
|
||||
new Move(Moves.CRUSH_GRIP, "Crush Grip", Type.NORMAL, MoveCategory.PHYSICAL, -1, 100, 5, -1, "More powerful when opponent has higher HP.", -1, 4),
|
||||
new Move(Moves.MAGMA_STORM, "Magma Storm", Type.FIRE, MoveCategory.SPECIAL, 100, 75, 5, -1, "Traps opponent, damaging them for 4-5 turns.", 100, 4),
|
||||
new Move(Moves.DARK_VOID, "Dark Void", Type.DARK, MoveCategory.STATUS, -1, 50, 10, -1, "Puts all adjacent opponents to sleep.", -1, 4),
|
||||
new Move(Moves.DARK_VOID, "Dark Void", Type.DARK, MoveCategory.STATUS, -1, 50, 10, -1, "Puts all adjacent opponents to sleep.", -1, 4, new StatusEffectAttr(StatusEffect.SLEEP)),
|
||||
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 StatChangeAttr([ BattleStat.ATK, BattleStat.DEF, BattleStat.SPATK, BattleStat.SPDEF, BattleStat.SPD ], 1, true)),
|
||||
|
@ -1283,7 +1288,7 @@ export const allMoves = [
|
|||
new Move(Moves.STORED_POWER, "Stored Power", Type.PSYCHIC, MoveCategory.SPECIAL, 20, 100, 10, 41, "Power increases when user's stats have been raised.", -1, 5),
|
||||
new Move(Moves.QUICK_GUARD, "Quick Guard", Type.FIGHTING, MoveCategory.STATUS, -1, -1, 15, -1, "Protects the user's team from high-priority moves.", -1, 5),
|
||||
new Move(Moves.ALLY_SWITCH, "Ally Switch", Type.PSYCHIC, MoveCategory.STATUS, -1, -1, 15, -1, "User switches with opposite teammate.", -1, 5),
|
||||
new Move(Moves.SCALD, "Scald", Type.WATER, MoveCategory.SPECIAL, 80, 100, 15, -1, "May burn opponent.", 30, 5),
|
||||
new Move(Moves.SCALD, "Scald", Type.WATER, MoveCategory.SPECIAL, 80, 100, 15, -1, "May burn opponent.", 30, 5, new StatusEffectAttr(StatusEffect.BURN)),
|
||||
new Move(Moves.SHELL_SMASH, "Shell Smash", Type.NORMAL, MoveCategory.STATUS, -1, -1, 15, -1, "Sharply raises user's Attack, Special Attack and Speed but lowers Defense and Special Defense.", -1, 5,
|
||||
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),
|
||||
|
@ -1330,14 +1335,14 @@ export const allMoves = [
|
|||
new Move(Moves.GEAR_GRIND, "Gear Grind", Type.STEEL, MoveCategory.PHYSICAL, 50, 85, 15, -1, "Hits twice in one turn.", -1, 5, new MultiHitAttr(MultiHitType._2)),
|
||||
new Move(Moves.SEARING_SHOT, "Searing Shot", Type.FIRE, MoveCategory.SPECIAL, 100, 100, 5, -1, "May burn opponent.", 30, 5, new StatusEffectAttr(StatusEffect.BURN)),
|
||||
new Move(Moves.TECHNO_BLAST, "Techno Blast", Type.NORMAL, MoveCategory.SPECIAL, 120, 100, 5, -1, "Type depends on the Drive being held.", -1, 5),
|
||||
new Move(Moves.RELIC_SONG, "Relic Song", Type.NORMAL, MoveCategory.SPECIAL, 75, 100, 10, -1, "May put the target to sleep.", 10, 5),
|
||||
new Move(Moves.RELIC_SONG, "Relic Song", Type.NORMAL, MoveCategory.SPECIAL, 75, 100, 10, -1, "May put the target to sleep.", 10, 5, new StatusEffectAttr(StatusEffect.SLEEP)),
|
||||
new Move(Moves.SECRET_SWORD, "Secret Sword", Type.FIGHTING, MoveCategory.SPECIAL, 85, 100, 10, -1, "Inflicts damage based on the target's Defense, not Special Defense.", -1, 5),
|
||||
new Move(Moves.GLACIATE, "Glaciate", Type.ICE, MoveCategory.SPECIAL, 65, 95, 10, -1, "Lowers opponent's Speed.", 100, 5, new StatChangeAttr(BattleStat.SPD, -1)),
|
||||
new Move(Moves.BOLT_STRIKE, "Bolt Strike", Type.ELECTRIC, MoveCategory.PHYSICAL, 130, 85, 5, -1, "May paralyze opponent.", 20, 5, new StatusEffectAttr(StatusEffect.PARALYSIS)),
|
||||
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.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 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 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.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.V_CREATE, "V-create", Type.FIRE, MoveCategory.PHYSICAL, 180, 95, 5, -1, "Lowers user's Defense, Special Defense and Speed.", 100, 5,
|
||||
|
|
|
@ -5,14 +5,14 @@ import { default as Move, allMoves, MoveCategory, Moves, StatChangeAttr, applyMo
|
|||
import { pokemonLevelMoves } from './pokemon-level-moves';
|
||||
import { default as PokemonSpecies, getPokemonSpecies } from './pokemon-species';
|
||||
import * as Utils from './utils';
|
||||
import { getTypeDamageMultiplier } from './type';
|
||||
import { Type, getTypeDamageMultiplier } from './type';
|
||||
import { getLevelTotalExp } from './exp';
|
||||
import { Stat } from './pokemon-stat';
|
||||
import { PokemonBaseStatModifier as PokemonBaseStatBoosterModifier, ShinyRateBoosterModifier } from './modifier';
|
||||
import { PokeballType } from './pokeball';
|
||||
import { Gender } from './gender';
|
||||
import { initAnim, loadMoveAnimAssets } from './battle-anims';
|
||||
import { StatusEffect } from './status-effect';
|
||||
import { initMoveAnim, loadMoveAnimAssets } from './battle-anims';
|
||||
import { Status, StatusEffect } from './status-effect';
|
||||
import { tmSpecies } from './tms';
|
||||
import { pokemonEvolutions, SpeciesEvolution, SpeciesEvolutionCondition } from './pokemon-evolutions';
|
||||
import { MessagePhase, StatChangePhase } from './battle-phases';
|
||||
|
@ -33,7 +33,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
public stats: integer[];
|
||||
public ivs: integer[];
|
||||
public moveset: PokemonMove[];
|
||||
public status: StatusEffect;
|
||||
public status: Status;
|
||||
public winCount: integer;
|
||||
|
||||
public summonData: PokemonSummonData;
|
||||
|
@ -109,8 +109,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
/*else
|
||||
this.shiny = Utils.randInt(16) === 0;*/
|
||||
|
||||
this.status = StatusEffect.NONE;
|
||||
|
||||
this.winCount = 0;
|
||||
}
|
||||
|
||||
|
@ -162,7 +160,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
loadAssets(): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
const moveIds = this.moveset.map(m => m.getMove().id);
|
||||
Promise.allSettled(moveIds.map(m => initAnim(m)))
|
||||
Promise.allSettled(moveIds.map(m => initMoveAnim(m)))
|
||||
.then(() => {
|
||||
loadMoveAnimAssets(this.scene as BattleScene, moveIds);
|
||||
(this.scene as BattleScene).loadAtlas(this.getSpriteKey(), 'pokemon', this.getSpriteAtlasPath());
|
||||
|
@ -258,7 +256,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
if (stat === Stat.HP)
|
||||
return this.stats[Stat.HP];
|
||||
const statLevel = this.summonData.battleStats[(stat + 1) as BattleStat];
|
||||
return this.stats[stat] * (Math.max(2, 2 + statLevel) / Math.max(2, 2 - statLevel));
|
||||
let ret = this.stats[stat] * (Math.max(2, 2 + statLevel) / Math.max(2, 2 - statLevel));
|
||||
if (this.status && this.status.effect === StatusEffect.PARALYSIS)
|
||||
ret >>= 2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
calculateStats(): void {
|
||||
|
@ -436,6 +437,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
const typeMultiplier = getTypeDamageMultiplier(move.type, this.species.type1) * (this.species.type2 > -1 ? getTypeDamageMultiplier(move.type, this.species.type2) : 1);
|
||||
const criticalMultiplier = isCritical ? 2 : 1;
|
||||
damage = Math.ceil(((((2 * source.level / 5 + 2) * move.power * sourceAtk / targetDef) / 50) + 2) * stabMultiplier * typeMultiplier * ((Utils.randInt(15) + 85) / 100)) * criticalMultiplier;
|
||||
if (isPhysical && source.status && source.status.effect === StatusEffect.BURN)
|
||||
damage = Math.floor(damage / 2);
|
||||
console.log('damage', damage, move.name, move.power, sourceAtk, targetDef);
|
||||
if (damage) {
|
||||
this.hp = Math.max(this.hp - damage, 0);
|
||||
|
@ -503,8 +506,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
callback();
|
||||
}
|
||||
|
||||
cry(soundConfig?: Phaser.Types.Sound.SoundConfig) {
|
||||
cry(soundConfig?: Phaser.Types.Sound.SoundConfig): integer {
|
||||
this.scene.sound.play(this.species.speciesId.toString(), soundConfig);
|
||||
return this.scene.sound.get(this.species.speciesId.toString()).totalDuration * 1000;
|
||||
}
|
||||
|
||||
faintCry(callback: Function) {
|
||||
|
@ -555,7 +559,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
}
|
||||
});
|
||||
// Failsafe
|
||||
this.scene.time.delayedCall(5000, () => {
|
||||
this.scene.time.delayedCall(3000, () => {
|
||||
if (!faintCryTimer || !this.scene)
|
||||
return;
|
||||
const crySound = this.scene.sound.get(key);
|
||||
|
@ -567,16 +571,42 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
});
|
||||
}
|
||||
|
||||
resetSummonData() {
|
||||
trySetStatus(effect: StatusEffect): boolean {
|
||||
if (this.status)
|
||||
return false;
|
||||
switch (effect) {
|
||||
case StatusEffect.POISON:
|
||||
case StatusEffect.TOXIC:
|
||||
if (this.species.isOfType(Type.POISON) || this.species.isOfType(Type.STEEL))
|
||||
return false;
|
||||
break;
|
||||
case StatusEffect.FREEZE:
|
||||
if (this.species.isOfType(Type.ICE))
|
||||
return false;
|
||||
break;
|
||||
case StatusEffect.BURN:
|
||||
if (this.species.isOfType(Type.FIRE))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
this.status = new Status(effect);
|
||||
return true;
|
||||
}
|
||||
|
||||
resetStatus(): void {
|
||||
this.status = undefined;
|
||||
}
|
||||
|
||||
resetSummonData(): void {
|
||||
this.summonData = new PokemonSummonData();
|
||||
this.resetBattleSummonData();
|
||||
}
|
||||
|
||||
resetBattleSummonData() {
|
||||
resetBattleSummonData(): void {
|
||||
this.battleSummonData = new PokemonBattleSummonData();
|
||||
}
|
||||
|
||||
resetTurnData() {
|
||||
resetTurnData(): void {
|
||||
this.turnData = new PokemonTurnData();
|
||||
}
|
||||
|
||||
|
@ -815,6 +845,7 @@ export class PokemonTurnData {
|
|||
public flinched: boolean;
|
||||
public hitCount: integer;
|
||||
public hitsLeft: integer;
|
||||
public hitsTotal: integer;
|
||||
}
|
||||
|
||||
export enum AiType {
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import * as Utils from "./utils";
|
||||
|
||||
export enum StatusEffect {
|
||||
NONE,
|
||||
POISON,
|
||||
|
@ -9,10 +11,95 @@ export enum StatusEffect {
|
|||
}
|
||||
|
||||
export class Status {
|
||||
public statusType: StatusEffect;
|
||||
public effect: StatusEffect;
|
||||
public turnCount: integer;
|
||||
public cureTurn: integer;
|
||||
|
||||
constructor(statusType: StatusEffect) {
|
||||
this.statusType = statusType;
|
||||
constructor(effect: StatusEffect) {
|
||||
this.effect = effect;
|
||||
this.turnCount = 0;
|
||||
if (effect === StatusEffect.SLEEP)
|
||||
this.cureTurn = Utils.randInt(3, 1);
|
||||
}
|
||||
|
||||
incrementTurn(): void {
|
||||
this.turnCount++;
|
||||
}
|
||||
|
||||
isPostTurn(): boolean {
|
||||
return this.effect === StatusEffect.POISON || this.effect === StatusEffect.TOXIC || this.effect === StatusEffect.BURN;
|
||||
}
|
||||
}
|
||||
|
||||
export function getStatusEffectObtainText(statusEffect: StatusEffect): string {
|
||||
switch (statusEffect) {
|
||||
case StatusEffect.POISON:
|
||||
return '\nwas poisoned!';
|
||||
case StatusEffect.TOXIC:
|
||||
return '\nwas badly poisoned!';
|
||||
case StatusEffect.PARALYSIS:
|
||||
return ' is paralyzed!\nIt may be unable to move!';
|
||||
case StatusEffect.SLEEP:
|
||||
return '\nfell asleep!';
|
||||
case StatusEffect.FREEZE:
|
||||
return '\nwas frozen solid!';
|
||||
case StatusEffect.BURN:
|
||||
return '\nwas burned!';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
export function getStatusEffectActivationText(statusEffect: StatusEffect): string {
|
||||
switch (statusEffect) {
|
||||
case StatusEffect.POISON:
|
||||
case StatusEffect.TOXIC:
|
||||
return ' is hurt\nby poison!';
|
||||
case StatusEffect.PARALYSIS:
|
||||
return ' is paralyzed!\nIt can\'t move!';
|
||||
case StatusEffect.SLEEP:
|
||||
return ' is fast asleep.';
|
||||
case StatusEffect.FREEZE:
|
||||
return ' is\nfrozen solid!';
|
||||
case StatusEffect.BURN:
|
||||
return ' is hurt\nby its burn!';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
export function getStatusEffectOverlapText(statusEffect: StatusEffect): string {
|
||||
switch (statusEffect) {
|
||||
case StatusEffect.POISON:
|
||||
case StatusEffect.TOXIC:
|
||||
return ' is\nalready poisoned!';
|
||||
case StatusEffect.PARALYSIS:
|
||||
return ' is\nalready paralyzed!';
|
||||
case StatusEffect.SLEEP:
|
||||
return ' is\nalready asleep!';
|
||||
case StatusEffect.FREEZE:
|
||||
return ' is\nalready frozen!';
|
||||
case StatusEffect.BURN:
|
||||
return ' is\nalready burned!';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
export function getStatusEffectHealText(statusEffect: StatusEffect) {
|
||||
switch (statusEffect) {
|
||||
case StatusEffect.POISON:
|
||||
case StatusEffect.TOXIC:
|
||||
return ' was\ncured of its poison!';
|
||||
case StatusEffect.PARALYSIS:
|
||||
return ' was\nhealed of paralysis!';
|
||||
case StatusEffect.SLEEP:
|
||||
return ' woke up!';
|
||||
case StatusEffect.FREEZE:
|
||||
return ' was\ndefrosted!';
|
||||
case StatusEffect.BURN:
|
||||
return ' is hurt\nby its burn!';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
Loading…
Reference in New Issue