Refactor modifiers
This commit is contained in:
parent
4ec91695f7
commit
15105231ba
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 28 KiB |
Binary file not shown.
After Width: | Height: | Size: 347 B |
Binary file not shown.
After Width: | Height: | Size: 245 B |
|
@ -101,10 +101,10 @@ export default class BattleInfo extends Phaser.GameObjects.Container {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateInfo(pokemon: Pokemon, callback?: Function) {
|
updateInfo(pokemon: Pokemon): Promise<void> {
|
||||||
|
return new Promise(resolve => {
|
||||||
if (!this.scene) {
|
if (!this.scene) {
|
||||||
if (callback)
|
resolve();
|
||||||
callback();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,10 +129,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onComplete: () => {
|
onComplete: () => {
|
||||||
if (callback) {
|
resolve();
|
||||||
callback();
|
|
||||||
callback = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (!this.player)
|
if (!this.player)
|
||||||
|
@ -141,22 +138,24 @@ export default class BattleInfo extends Phaser.GameObjects.Container {
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.player && this.lastExp !== pokemon.exp) {
|
if (this.player && this.lastExp !== pokemon.exp) {
|
||||||
const originalCallback = callback;
|
const originalResolve = resolve;
|
||||||
callback = () => this.updatePokemonExp(pokemon, originalCallback);
|
resolve = () => this.updatePokemonExp(pokemon).then(() => originalResolve());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.lastHp !== pokemon.hp || this.lastMaxHp !== pokemon.getMaxHp())
|
if (this.lastHp !== pokemon.hp || this.lastMaxHp !== pokemon.getMaxHp()) {
|
||||||
updatePokemonHp();
|
updatePokemonHp();
|
||||||
else if (!this.player && this.lastLevel !== pokemon.level) {
|
return;
|
||||||
|
} else if (!this.player && this.lastLevel !== pokemon.level) {
|
||||||
this.setLevel(pokemon.level);
|
this.setLevel(pokemon.level);
|
||||||
this.lastLevel = pokemon.level;
|
this.lastLevel = pokemon.level;
|
||||||
if (callback)
|
|
||||||
callback();
|
|
||||||
} else if (callback)
|
|
||||||
callback();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePokemonExp(battler: Pokemon, callback?: Function) {
|
resolve();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
updatePokemonExp(battler: Pokemon): Promise<void> {
|
||||||
|
return new Promise(resolve => {
|
||||||
const levelUp = this.lastLevel < battler.level;
|
const levelUp = this.lastLevel < battler.level;
|
||||||
const relLevelExp = getLevelRelExp(this.lastLevel + 1, battler.species.growthRate);
|
const relLevelExp = getLevelRelExp(this.lastLevel + 1, battler.species.growthRate);
|
||||||
const levelExp = levelUp ? relLevelExp : battler.levelExp;
|
const levelExp = levelUp ? relLevelExp : battler.levelExp;
|
||||||
|
@ -192,19 +191,17 @@ export default class BattleInfo extends Phaser.GameObjects.Container {
|
||||||
this.setLevel(this.lastLevel);
|
this.setLevel(this.lastLevel);
|
||||||
this.scene.time.delayedCall(500, () => {
|
this.scene.time.delayedCall(500, () => {
|
||||||
this.expBar.setScale(0, 1);
|
this.expBar.setScale(0, 1);
|
||||||
this.updateInfo(battler, callback);
|
this.updateInfo(battler).then(() => resolve());
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
this.lastExp = battler.exp;
|
this.lastExp = battler.exp;
|
||||||
this.lastLevelExp = battler.levelExp;
|
this.lastLevelExp = battler.levelExp;
|
||||||
}
|
}
|
||||||
if (callback) {
|
resolve();
|
||||||
callback();
|
|
||||||
callback = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
setLevel(level: integer) {
|
setLevel(level: integer) {
|
||||||
|
|
|
@ -29,6 +29,18 @@ export class BattlePhase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class SelectStarterPhase extends BattlePhase {
|
||||||
|
constructor(scene: BattleScene) {
|
||||||
|
super(scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
super.start();
|
||||||
|
|
||||||
|
this.scene.ui.setMode(Mode.STARTER_SELECT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class EncounterPhase extends BattlePhase {
|
export class EncounterPhase extends BattlePhase {
|
||||||
constructor(scene: BattleScene) {
|
constructor(scene: BattleScene) {
|
||||||
super(scene);
|
super(scene);
|
||||||
|
@ -722,7 +734,7 @@ export class ExpPhase extends PartyMemberPokemonPhase {
|
||||||
newLevel = pokemon.level;
|
newLevel = pokemon.level;
|
||||||
if (newLevel > lastLevel)
|
if (newLevel > lastLevel)
|
||||||
this.scene.unshiftPhase(new LevelUpPhase(this.scene, this.partyMemberIndex, newLevel));
|
this.scene.unshiftPhase(new LevelUpPhase(this.scene, this.partyMemberIndex, newLevel));
|
||||||
pokemon.updateInfo(() => this.end());
|
pokemon.updateInfo().then(() => this.end());
|
||||||
}, null, true);
|
}, null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1016,7 +1028,7 @@ export class SelectModifierPhase extends BattlePhase {
|
||||||
this.scene.applyModifiers(ExtraModifierModifier, modifierCount);
|
this.scene.applyModifiers(ExtraModifierModifier, modifierCount);
|
||||||
const types: Array<ModifierType> = getModifierTypesForWave(this.scene.currentBattle.waveIndex - 1, modifierCount.value, party);
|
const types: Array<ModifierType> = getModifierTypesForWave(this.scene.currentBattle.waveIndex - 1, modifierCount.value, party);
|
||||||
|
|
||||||
this.scene.ui.setMode(Mode.MODIFIER_SELECT, types, (cursor: integer) => {
|
const modifierSelectCallback = (cursor: integer) => {
|
||||||
if (cursor < 0) {
|
if (cursor < 0) {
|
||||||
this.scene.ui.setMode(Mode.MESSAGE);
|
this.scene.ui.setMode(Mode.MESSAGE);
|
||||||
super.end();
|
super.end();
|
||||||
|
@ -1033,14 +1045,15 @@ export class SelectModifierPhase extends BattlePhase {
|
||||||
this.scene.ui.clearText();
|
this.scene.ui.clearText();
|
||||||
this.scene.ui.setMode(Mode.MESSAGE);
|
this.scene.ui.setMode(Mode.MESSAGE);
|
||||||
} else
|
} else
|
||||||
this.scene.ui.setMode(Mode.MODIFIER_SELECT);
|
this.scene.ui.setMode(Mode.MODIFIER_SELECT, types, modifierSelectCallback);
|
||||||
}, pokemonModifierType.selectFilter);
|
}, pokemonModifierType.selectFilter);
|
||||||
} else {
|
} else {
|
||||||
this.scene.addModifier(types[cursor].newModifier()).then(() => super.end());
|
this.scene.addModifier(types[cursor].newModifier()).then(() => super.end());
|
||||||
this.scene.ui.clearText();
|
this.scene.ui.clearText();
|
||||||
this.scene.ui.setMode(Mode.MESSAGE);
|
this.scene.ui.setMode(Mode.MESSAGE);
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
this.scene.ui.setMode(Mode.MODIFIER_SELECT, types, modifierSelectCallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
import Phaser from 'phaser';
|
import Phaser from 'phaser';
|
||||||
import { Biome, BiomeArena } from './biome';
|
import { Biome, BiomeArena } from './biome';
|
||||||
import UI from './ui/ui';
|
import UI from './ui/ui';
|
||||||
import { BattlePhase, EncounterPhase, SummonPhase, CommandPhase, NextEncounterPhase, SwitchBiomePhase, NewBiomeEncounterPhase, LearnMovePhase } from './battle-phase';
|
import { BattlePhase, EncounterPhase, SummonPhase, CommandPhase, NextEncounterPhase, SwitchBiomePhase, NewBiomeEncounterPhase } from './battle-phase';
|
||||||
import { PlayerPokemon, EnemyPokemon } from './pokemon';
|
import { PlayerPokemon, EnemyPokemon } from './pokemon';
|
||||||
import PokemonSpecies, { allSpecies, getPokemonSpecies } from './pokemon-species';
|
import PokemonSpecies, { allSpecies, getPokemonSpecies } from './pokemon-species';
|
||||||
import * as Utils from './utils';
|
import * as Utils from './utils';
|
||||||
import { Modifier, ModifierBar, ConsumablePokemonModifier, ConsumableModifier, PokemonModifier} from './modifier';
|
import { Modifier, ModifierBar, ConsumablePokemonModifier, ConsumableModifier, PartyShareModifier, PokemonHpRestoreModifier, HealingBoosterModifier, PersistentModifier, PokemonBaseStatBoosterModifierType, PokemonBaseStatModifier } from './modifier';
|
||||||
import { PokeballType } from './pokeball';
|
import { PokeballType } from './pokeball';
|
||||||
import { Species } from './species';
|
import { Species } from './species';
|
||||||
import { initAutoPlay } from './auto-play';
|
import { initAutoPlay } from './auto-play';
|
||||||
import { Battle } from './battle';
|
import { Battle } from './battle';
|
||||||
import { populateAnims } from './battle-anims';
|
import { populateAnims } from './battle-anims';
|
||||||
|
import { Stat } from './pokemon-stat';
|
||||||
|
|
||||||
const enableAuto = true;
|
const enableAuto = true;
|
||||||
|
|
||||||
|
@ -36,7 +37,7 @@ export default class BattleScene extends Phaser.Scene {
|
||||||
public pokeballCounts = Object.fromEntries(Utils.getEnumValues(PokeballType).filter(p => p <= PokeballType.MASTER_BALL).map(t => [ t, 0 ]));
|
public pokeballCounts = Object.fromEntries(Utils.getEnumValues(PokeballType).filter(p => p <= PokeballType.MASTER_BALL).map(t => [ t, 0 ]));
|
||||||
private party: PlayerPokemon[];
|
private party: PlayerPokemon[];
|
||||||
private modifierBar: ModifierBar;
|
private modifierBar: ModifierBar;
|
||||||
private modifiers: Modifier[];
|
private modifiers: PersistentModifier[];
|
||||||
public uiContainer: Phaser.GameObjects.Container;
|
public uiContainer: Phaser.GameObjects.Container;
|
||||||
public ui: UI;
|
public ui: UI;
|
||||||
|
|
||||||
|
@ -301,6 +302,10 @@ export default class BattleScene extends Phaser.Scene {
|
||||||
this.plusKey = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.PLUS);
|
this.plusKey = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.PLUS);
|
||||||
this.minusKey = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.MINUS);
|
this.minusKey = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.MINUS);
|
||||||
|
|
||||||
|
for (let a = 0; a < 3; a++) {
|
||||||
|
this.addModifier(new PokemonBaseStatModifier(new PokemonBaseStatBoosterModifierType('HP-UP', Stat.HP), this.getParty()[0].id, Stat.HP));
|
||||||
|
}
|
||||||
|
|
||||||
Promise.all(loadPokemonAssets).then(() => {
|
Promise.all(loadPokemonAssets).then(() => {
|
||||||
if (enableAuto)
|
if (enableAuto)
|
||||||
initAutoPlay.apply(this);
|
initAutoPlay.apply(this);
|
||||||
|
@ -341,6 +346,7 @@ export default class BattleScene extends Phaser.Scene {
|
||||||
this.unshiftPhase(new NewBiomeEncounterPhase(this));
|
this.unshiftPhase(new NewBiomeEncounterPhase(this));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
//this.pushPhase(new SelectStarterPhase(this));
|
||||||
this.pushPhase(new EncounterPhase(this));
|
this.pushPhase(new EncounterPhase(this));
|
||||||
this.pushPhase(new SummonPhase(this));
|
this.pushPhase(new SummonPhase(this));
|
||||||
}
|
}
|
||||||
|
@ -443,44 +449,72 @@ export default class BattleScene extends Phaser.Scene {
|
||||||
this.phaseQueue.push(new CommandPhase(this));
|
this.phaseQueue.push(new CommandPhase(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
addModifier(modifier: Modifier): Promise<void> {
|
addModifier(modifier: Modifier, virtual?: boolean): Promise<void> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
if (modifier.add(this.modifierBar, this.modifiers))
|
if (modifier instanceof PersistentModifier) {
|
||||||
|
if ((modifier as PersistentModifier).add(this.modifiers, !!virtual) && !virtual)
|
||||||
this.sound.play('restore');
|
this.sound.play('restore');
|
||||||
|
|
||||||
if (modifier instanceof ConsumableModifier) {
|
if (!virtual)
|
||||||
const args = [ this ];
|
this.updateModifiers().then(() => resolve());
|
||||||
if (modifier.shouldApply(args))
|
} else if (modifier instanceof ConsumableModifier) {
|
||||||
modifier.apply(args);
|
this.sound.play('restore');
|
||||||
resolve();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let pokemonToUpdate = 0;
|
if (modifier instanceof ConsumablePokemonModifier) {
|
||||||
|
|
||||||
if (modifier instanceof PokemonModifier) {
|
|
||||||
for (let p in this.party) {
|
for (let p in this.party) {
|
||||||
const pokemon = this.party[p];
|
const pokemon = this.party[p];
|
||||||
|
|
||||||
if (modifier instanceof ConsumablePokemonModifier) {
|
const args: any[] = [ pokemon ];
|
||||||
const args = [ pokemon ];
|
if (modifier instanceof PokemonHpRestoreModifier) {
|
||||||
|
const hpRestoreMultiplier = new Utils.IntegerHolder(1);
|
||||||
|
this.applyModifiers(HealingBoosterModifier, hpRestoreMultiplier);
|
||||||
|
args.push(hpRestoreMultiplier.value);
|
||||||
|
}
|
||||||
if (modifier.shouldApply(args))
|
if (modifier.shouldApply(args))
|
||||||
modifier.apply(args);
|
modifier.apply(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
pokemonToUpdate++;
|
Promise.allSettled(this.party.map(p => p.updateInfo())).then(() => resolve());
|
||||||
|
} else {
|
||||||
|
const args = [ this ];
|
||||||
|
if (modifier.shouldApply(args))
|
||||||
|
modifier.apply(args);
|
||||||
|
|
||||||
pokemon.calculateStats();
|
|
||||||
pokemon.updateInfo(() => {
|
|
||||||
if (!(--pokemonToUpdate))
|
|
||||||
resolve();
|
resolve();
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updatePartyForModifiers(): Promise<void> {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
Promise.allSettled(this.party.map(p => {
|
||||||
|
p.calculateStats();
|
||||||
|
return p.updateInfo();
|
||||||
|
})).then(() => resolve());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pokemonToUpdate)
|
updateModifiers(): Promise<void> {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
for (let modifier of this.modifiers) {
|
||||||
|
if (modifier instanceof PersistentModifier)
|
||||||
|
(modifier as PersistentModifier).virtualStackCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.applyModifiers(PartyShareModifier, this, this.modifiers);
|
||||||
|
|
||||||
|
const modifiers = this.modifiers.slice(0);
|
||||||
|
for (let modifier of modifiers) {
|
||||||
|
if (!modifier.getStackCount())
|
||||||
|
this.modifiers.splice(this.modifiers.indexOf(modifier), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updatePartyForModifiers().then(() => {
|
||||||
|
this.modifierBar.updateModifiers(this.modifiers);
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getModifier(modifierType: { new(...args: any[]): Modifier }): Modifier {
|
getModifier(modifierType: { new(...args: any[]): Modifier }): Modifier {
|
||||||
|
|
298
src/modifier.ts
298
src/modifier.ts
|
@ -18,20 +18,14 @@ export class ModifierBar extends Phaser.GameObjects.Container {
|
||||||
this.setScale(0.5);
|
this.setScale(0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
addModifier(modifier: Modifier) {
|
updateModifiers(modifiers: PersistentModifier[]) {
|
||||||
|
this.removeAll(true);
|
||||||
|
|
||||||
|
for (let modifier of modifiers) {
|
||||||
const icon = modifier.getIcon(this.scene as BattleScene);
|
const icon = modifier.getIcon(this.scene as BattleScene);
|
||||||
this.add(icon);
|
this.add(icon);
|
||||||
this.setModifierIconPosition(icon);
|
this.setModifierIconPosition(icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateModifier(modifier: Modifier, modifiers: Modifier[]) {
|
|
||||||
const index = modifiers.indexOf(modifier);
|
|
||||||
if (index > -1) {
|
|
||||||
this.getAt(index).destroy();
|
|
||||||
const newIcon = modifier.getIcon(this.scene as BattleScene);
|
|
||||||
this.addAt(newIcon, index);
|
|
||||||
this.setModifierIconPosition(newIcon);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setModifierIconPosition(icon: Phaser.GameObjects.Container) {
|
setModifierIconPosition(icon: Phaser.GameObjects.Container) {
|
||||||
|
@ -44,19 +38,13 @@ export class ModifierBar extends Phaser.GameObjects.Container {
|
||||||
|
|
||||||
export abstract class Modifier {
|
export abstract class Modifier {
|
||||||
public type: ModifierType;
|
public type: ModifierType;
|
||||||
public stackCount: integer;
|
|
||||||
|
|
||||||
constructor(type: ModifierType) {
|
constructor(type: ModifierType) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.stackCount = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
add(modifierBar: ModifierBar, modifiers: Modifier[]): boolean {
|
match(_modifier: Modifier): boolean {
|
||||||
modifiers.push(this);
|
return false;
|
||||||
|
|
||||||
modifierBar.addModifier(this);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldApply(_args: any[]): boolean {
|
shouldApply(_args: any[]): boolean {
|
||||||
|
@ -64,10 +52,47 @@ export abstract class Modifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract apply(args: any[]): boolean;
|
abstract apply(args: any[]): boolean;
|
||||||
|
}
|
||||||
|
|
||||||
incrementStack(): void {
|
export abstract class PersistentModifier extends Modifier {
|
||||||
if (this.stackCount < this.getMaxStackCount())
|
public stackCount: integer;
|
||||||
|
public virtualStackCount: integer;
|
||||||
|
|
||||||
|
constructor(type: ModifierType) {
|
||||||
|
super(type);
|
||||||
|
this.stackCount = 1;
|
||||||
|
this.virtualStackCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
add(modifiers: PersistentModifier[], virtual: boolean): boolean {
|
||||||
|
for (let modifier of modifiers) {
|
||||||
|
if (this.match(modifier)) {
|
||||||
|
modifier.incrementStack(virtual);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virtual) {
|
||||||
|
this.virtualStackCount += this.stackCount;
|
||||||
|
this.stackCount = 0;
|
||||||
|
}
|
||||||
|
modifiers.push(this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract clone(): PersistentModifier;
|
||||||
|
|
||||||
|
incrementStack(virtual: boolean): void {
|
||||||
|
if (this.getStackCount() < this.getMaxStackCount()) {
|
||||||
|
if (!virtual)
|
||||||
this.stackCount++;
|
this.stackCount++;
|
||||||
|
else
|
||||||
|
this.virtualStackCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getStackCount(): integer {
|
||||||
|
return this.stackCount + this.virtualStackCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
getMaxStackCount(): integer {
|
getMaxStackCount(): integer {
|
||||||
|
@ -86,16 +111,34 @@ export abstract class Modifier {
|
||||||
if (stackText)
|
if (stackText)
|
||||||
container.add(stackText);
|
container.add(stackText);
|
||||||
|
|
||||||
|
const virtualStackText = this.getIconStackText(scene, true);
|
||||||
|
if (virtualStackText)
|
||||||
|
container.add(virtualStackText);
|
||||||
|
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
|
|
||||||
getIconStackText(scene: BattleScene): Phaser.GameObjects.Text {
|
getIconStackText(scene: BattleScene, virtual?: boolean): Phaser.GameObjects.Text {
|
||||||
if (this.stackCount <= 1)
|
if (this.getMaxStackCount() === 1 || (virtual && !this.virtualStackCount))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
const text = addTextObject(scene, 16, 12, this.stackCount.toString(), TextStyle.PARTY, { fontSize: '66px', color: this.stackCount < this.getMaxStackCount() ? '#f8f8f8' : '#e64a18' });
|
const isStackMax = this.getStackCount() >= this.getMaxStackCount();
|
||||||
|
const maxColor = '#f89890';
|
||||||
|
const maxStrokeColor = '#984038';
|
||||||
|
|
||||||
|
if (virtual) {
|
||||||
|
const virtualText = addTextObject(scene, 1 * 11 + 16, 12, `+${this.virtualStackCount.toString()}`, TextStyle.PARTY, { fontSize: '66px', color: !isStackMax ? '#40c8f8' : maxColor });
|
||||||
|
virtualText.setShadow(0, 0, null);
|
||||||
|
virtualText.setStroke(!isStackMax ? '#006090' : maxStrokeColor, 16)
|
||||||
|
virtualText.setOrigin(1, 0);
|
||||||
|
|
||||||
|
return virtualText;
|
||||||
|
}
|
||||||
|
|
||||||
|
const text = addTextObject(scene, 8, 12, this.stackCount.toString(), TextStyle.PARTY, { fontSize: '66px', color: !isStackMax ? '#f8f8f8' : maxColor });
|
||||||
|
text.setShadow(0, 0, null);
|
||||||
text.setStroke('#424242', 16)
|
text.setStroke('#424242', 16)
|
||||||
text.setOrigin(1, 0);
|
text.setOrigin(0, 0);
|
||||||
|
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
@ -106,7 +149,7 @@ export abstract class ConsumableModifier extends Modifier {
|
||||||
super(type);
|
super(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
add(_modifierBar: ModifierBar, _modifiers: Modifier[]): boolean {
|
add(_modifiers: Modifier[]): boolean {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,7 +177,7 @@ class AddPokeballModifier extends ConsumableModifier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export abstract class PokemonModifier extends Modifier {
|
export abstract class PokemonHeldItemModifier extends PersistentModifier {
|
||||||
public pokemonId: integer;
|
public pokemonId: integer;
|
||||||
|
|
||||||
constructor(type: ModifierType, pokemonId: integer) {
|
constructor(type: ModifierType, pokemonId: integer) {
|
||||||
|
@ -144,7 +187,6 @@ export abstract class PokemonModifier extends Modifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldApply(args: any[]): boolean {
|
shouldApply(args: any[]): boolean {
|
||||||
console.log(args[0]);
|
|
||||||
return super.shouldApply(args) && args.length && args[0] instanceof Pokemon && (this.pokemonId === -1 || (args[0] as Pokemon).id === this.pokemonId);
|
return super.shouldApply(args) && args.length && args[0] instanceof Pokemon && (this.pokemonId === -1 || (args[0] as Pokemon).id === this.pokemonId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,8 +194,8 @@ export abstract class PokemonModifier extends Modifier {
|
||||||
const container = scene.add.container(0, 0);
|
const container = scene.add.container(0, 0);
|
||||||
|
|
||||||
const pokemon = this.getPokemon(scene);
|
const pokemon = this.getPokemon(scene);
|
||||||
const pokemonIcon = scene.add.sprite(0, 8, pokemon.getIconAtlasKey());
|
const pokemonIcon = scene.add.sprite(0, 8, pokemon.species.getIconAtlasKey());
|
||||||
pokemonIcon.play(pokemon.getIconKey()).stop();
|
pokemonIcon.play(pokemon.species.getIconKey()).stop();
|
||||||
pokemonIcon.setOrigin(0, 0.5);
|
pokemonIcon.setOrigin(0, 0.5);
|
||||||
|
|
||||||
container.add(pokemonIcon);
|
container.add(pokemonIcon);
|
||||||
|
@ -166,7 +208,7 @@ export abstract class PokemonModifier extends Modifier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PokemonBaseStatModifier extends PokemonModifier {
|
export class PokemonBaseStatModifier extends PokemonHeldItemModifier {
|
||||||
protected stat: Stat;
|
protected stat: Stat;
|
||||||
|
|
||||||
constructor(type: PokemonBaseStatBoosterModifierType, pokemonId: integer, stat: Stat) {
|
constructor(type: PokemonBaseStatBoosterModifierType, pokemonId: integer, stat: Stat) {
|
||||||
|
@ -174,19 +216,16 @@ export class PokemonBaseStatModifier extends PokemonModifier {
|
||||||
this.stat = stat;
|
this.stat = stat;
|
||||||
}
|
}
|
||||||
|
|
||||||
add(modifierBar: ModifierBar, modifiers: Modifier[]): boolean {
|
match(modifier: Modifier): boolean {
|
||||||
for (let modifier of modifiers) {
|
|
||||||
if (modifier instanceof PokemonBaseStatModifier) {
|
if (modifier instanceof PokemonBaseStatModifier) {
|
||||||
const pokemonStatModifier = modifier as PokemonBaseStatModifier;
|
const pokemonStatModifier = modifier as PokemonBaseStatModifier;
|
||||||
if (pokemonStatModifier.pokemonId === this.pokemonId && pokemonStatModifier.stat === this.stat) {
|
return pokemonStatModifier.pokemonId === this.pokemonId && pokemonStatModifier.stat === this.stat;
|
||||||
pokemonStatModifier.incrementStack();
|
|
||||||
modifierBar.updateModifier(pokemonStatModifier, modifiers);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.add(modifierBar, modifiers);
|
clone(): PersistentModifier {
|
||||||
|
return new PokemonBaseStatModifier(this.type as PokemonBaseStatBoosterModifierType, this.pokemonId, this.stat);
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldApply(args: any[]): boolean {
|
shouldApply(args: any[]): boolean {
|
||||||
|
@ -194,7 +233,7 @@ export class PokemonBaseStatModifier extends PokemonModifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(args: any[]): boolean {
|
apply(args: any[]): boolean {
|
||||||
args[1][this.stat] = Math.min(Math.floor(args[1][this.stat] * (1 + this.stackCount * 0.2)), 999999);
|
args[1][this.stat] = Math.min(Math.floor(args[1][this.stat] * (1 + this.getStackCount() * 0.2)), 999999);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -202,7 +241,7 @@ export class PokemonBaseStatModifier extends PokemonModifier {
|
||||||
getIcon(scene: BattleScene): Phaser.GameObjects.Container {
|
getIcon(scene: BattleScene): Phaser.GameObjects.Container {
|
||||||
const container = super.getIcon(scene);
|
const container = super.getIcon(scene);
|
||||||
|
|
||||||
const item = scene.add.sprite(16, 16, 'items');
|
const item = scene.add.sprite(16, this.virtualStackCount ? 8 : 16, 'items');
|
||||||
item.setScale(0.5);
|
item.setScale(0.5);
|
||||||
item.setOrigin(0, 0.5);
|
item.setOrigin(0, 0.5);
|
||||||
item.setTexture('items', this.type.iconImage);
|
item.setTexture('items', this.type.iconImage);
|
||||||
|
@ -212,35 +251,57 @@ export class PokemonBaseStatModifier extends PokemonModifier {
|
||||||
if (stackText)
|
if (stackText)
|
||||||
container.add(stackText);
|
container.add(stackText);
|
||||||
|
|
||||||
|
const virtualStackText = this.getIconStackText(scene, true);
|
||||||
|
if (virtualStackText)
|
||||||
|
container.add(virtualStackText);
|
||||||
|
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export abstract class ConsumablePokemonModifier extends PokemonModifier {
|
export abstract class ConsumablePokemonModifier extends ConsumableModifier {
|
||||||
|
public pokemonId: integer;
|
||||||
|
|
||||||
constructor(type: ModifierType, pokemonId: integer) {
|
constructor(type: ModifierType, pokemonId: integer) {
|
||||||
super(type, pokemonId);
|
super(type);
|
||||||
|
|
||||||
|
this.pokemonId = pokemonId;
|
||||||
}
|
}
|
||||||
|
|
||||||
add(_modifierBar: ModifierBar, _modifiers: Modifier[]): boolean {
|
shouldApply(args: any[]): boolean {
|
||||||
return true;
|
return args.length && args[0] instanceof Pokemon && (this.pokemonId === -1 || (args[0] as Pokemon).id === this.pokemonId);
|
||||||
|
}
|
||||||
|
|
||||||
|
getPokemon(scene: BattleScene) {
|
||||||
|
return scene.getParty().find(p => p.id === this.pokemonId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PokemonHpRestoreModifier extends ConsumablePokemonModifier {
|
export class PokemonHpRestoreModifier extends ConsumablePokemonModifier {
|
||||||
private restorePercent: integer;
|
private restorePoints: integer;
|
||||||
|
private percent: boolean;
|
||||||
private fainted: boolean;
|
private fainted: boolean;
|
||||||
|
|
||||||
constructor(type: ModifierType, pokemonId: integer, restorePercent: integer, fainted?: boolean) {
|
constructor(type: ModifierType, pokemonId: integer, restorePoints: integer, percent: boolean, fainted?: boolean) {
|
||||||
super(type, pokemonId);
|
super(type, pokemonId);
|
||||||
|
|
||||||
this.restorePercent = restorePercent;
|
this.restorePoints = restorePoints;
|
||||||
|
this.percent = percent;
|
||||||
this.fainted = !!fainted;
|
this.fainted = !!fainted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shouldApply(args: any[]): boolean {
|
||||||
|
return super.shouldApply(args) && (this.fainted || (args.length > 1 && typeof(args[1]) === 'number'));
|
||||||
|
}
|
||||||
|
|
||||||
apply(args: any[]): boolean {
|
apply(args: any[]): boolean {
|
||||||
const pokemon = args[0] as Pokemon;
|
const pokemon = args[0] as Pokemon;
|
||||||
if (!pokemon.hp === this.fainted)
|
if (!pokemon.hp === this.fainted) {
|
||||||
pokemon.hp = Math.min(pokemon.hp + Math.max((this.restorePercent * 0.01) * pokemon.getMaxHp(), this.restorePercent), pokemon.getMaxHp());
|
let restorePoints = this.restorePoints;
|
||||||
|
if (!this.fainted)
|
||||||
|
restorePoints = Math.floor(restorePoints * (args[1] as number));
|
||||||
|
pokemon.hp = Math.min(pokemon.hp + (this.percent ? (restorePoints * 0.01) * pokemon.getMaxHp() : restorePoints), pokemon.getMaxHp());
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -302,7 +363,79 @@ export class TmModifier extends ConsumablePokemonModifier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ExpBoosterModifier extends Modifier {
|
export class PartyShareModifier extends PersistentModifier {
|
||||||
|
constructor(type: ModifierType) {
|
||||||
|
super(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
match(modifier: Modifier) {
|
||||||
|
return modifier instanceof PartyShareModifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
clone(): PartyShareModifier {
|
||||||
|
return new PartyShareModifier(this.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
shouldApply(args: any[]): boolean {
|
||||||
|
return super.shouldApply(args) && args.length === 2 && args[0] instanceof BattleScene && args[1] instanceof Array<Modifier>;
|
||||||
|
}
|
||||||
|
|
||||||
|
apply(args: any[]): boolean {
|
||||||
|
const scene = args[0] as BattleScene;
|
||||||
|
const modifiers = args[1] as Modifier[];
|
||||||
|
const party = scene.getParty();
|
||||||
|
for (let modifier of modifiers) {
|
||||||
|
if (modifier instanceof PokemonHeldItemModifier) {
|
||||||
|
const heldItemModifier = modifier as PokemonHeldItemModifier;
|
||||||
|
const extraStacks = Math.floor(modifier.stackCount / Math.max(party.length - (this.getStackCount() - 1), 1));
|
||||||
|
for (let s = 0; s < extraStacks; s++) {
|
||||||
|
for (let p of party) {
|
||||||
|
if (p.id === heldItemModifier.pokemonId)
|
||||||
|
continue;
|
||||||
|
const newHeldItemModifier = heldItemModifier.clone() as PokemonHeldItemModifier;
|
||||||
|
newHeldItemModifier.pokemonId = p.id;
|
||||||
|
scene.addModifier(newHeldItemModifier, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
getMaxStackCount(): number {
|
||||||
|
return 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class HealingBoosterModifier extends PersistentModifier {
|
||||||
|
private multiplier: number;
|
||||||
|
|
||||||
|
constructor(type: ModifierType, multiplier: number) {
|
||||||
|
super(type);
|
||||||
|
|
||||||
|
this.multiplier = multiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
match(modifier: Modifier): boolean {
|
||||||
|
return modifier instanceof HealingBoosterModifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
clone(): HealingBoosterModifier {
|
||||||
|
return new HealingBoosterModifier(this.type, this.multiplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
apply(args: any[]): boolean {
|
||||||
|
const healingMultiplier = args[0] as Utils.IntegerHolder;
|
||||||
|
for (let s = 0; s < this.getStackCount(); s++)
|
||||||
|
healingMultiplier.value *= this.multiplier;
|
||||||
|
healingMultiplier.value = Math.floor(healingMultiplier.value);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ExpBoosterModifier extends PersistentModifier {
|
||||||
private boostMultiplier: integer;
|
private boostMultiplier: integer;
|
||||||
|
|
||||||
constructor(type: ModifierType, boostPercent: integer) {
|
constructor(type: ModifierType, boostPercent: integer) {
|
||||||
|
@ -311,29 +444,26 @@ export class ExpBoosterModifier extends Modifier {
|
||||||
this.boostMultiplier = boostPercent * 0.01;
|
this.boostMultiplier = boostPercent * 0.01;
|
||||||
}
|
}
|
||||||
|
|
||||||
add(modifierBar: ModifierBar, modifiers: Modifier[]): boolean {
|
match(modifier: Modifier): boolean {
|
||||||
for (let modifier of modifiers) {
|
|
||||||
if (modifier instanceof ExpBoosterModifier) {
|
if (modifier instanceof ExpBoosterModifier) {
|
||||||
const expModifier = modifier as ExpBoosterModifier;
|
const expModifier = modifier as ExpBoosterModifier;
|
||||||
if (expModifier.boostMultiplier === this.boostMultiplier) {
|
return expModifier.boostMultiplier === this.boostMultiplier;
|
||||||
expModifier.incrementStack();
|
|
||||||
modifierBar.updateModifier(expModifier, modifiers);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.add(modifierBar, modifiers);
|
clone(): ExpBoosterModifier {
|
||||||
|
return new ExpBoosterModifier(this.type, this.boostMultiplier * 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(args: any[]): boolean {
|
apply(args: any[]): boolean {
|
||||||
(args[0] as Utils.NumberHolder).value = Math.floor((args[0] as Utils.NumberHolder).value * (1 + (this.stackCount * (this.boostMultiplier))));
|
(args[0] as Utils.NumberHolder).value = Math.floor((args[0] as Utils.NumberHolder).value * (1 + (this.getStackCount() * this.boostMultiplier)));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ExpShareModifier extends Modifier {
|
export class ExpShareModifier extends PersistentModifier {
|
||||||
constructor(type: ModifierType) {
|
constructor(type: ModifierType) {
|
||||||
super(type);
|
super(type);
|
||||||
}
|
}
|
||||||
|
@ -342,31 +472,30 @@ export class ExpShareModifier extends Modifier {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clone(): ExpShareModifier {
|
||||||
|
return new ExpShareModifier(this.type);
|
||||||
|
}
|
||||||
|
|
||||||
getMaxStackCount(): integer {
|
getMaxStackCount(): integer {
|
||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ShinyRateBoosterModifier extends Modifier {
|
export class ShinyRateBoosterModifier extends PersistentModifier {
|
||||||
constructor(type: ModifierType) {
|
constructor(type: ModifierType) {
|
||||||
super(type);
|
super(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
add(modifierBar: ModifierBar, modifiers: Modifier[]): boolean {
|
match(modifier: Modifier): boolean {
|
||||||
for (let modifier of modifiers) {
|
return modifier instanceof ShinyRateBoosterModifier;
|
||||||
if (modifier instanceof ShinyRateBoosterModifier) {
|
|
||||||
const shinyRateModifier = modifier as ShinyRateBoosterModifier;
|
|
||||||
shinyRateModifier.incrementStack();
|
|
||||||
modifierBar.updateModifier(shinyRateModifier, modifiers);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.add(modifierBar, modifiers);
|
clone(): ShinyRateBoosterModifier {
|
||||||
|
return new ShinyRateBoosterModifier(this.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(args: any[]): boolean {
|
apply(args: any[]): boolean {
|
||||||
(args[0] as Utils.IntegerHolder).value = Math.pow((args[0] as Utils.IntegerHolder).value * 0.5, this.stackCount + 1);
|
(args[0] as Utils.IntegerHolder).value = Math.pow((args[0] as Utils.IntegerHolder).value * 0.5, this.getStackCount() + 1);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -376,13 +505,17 @@ export class ShinyRateBoosterModifier extends Modifier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ExtraModifierModifier extends Modifier {
|
export class ExtraModifierModifier extends PersistentModifier {
|
||||||
constructor(type: ModifierType) {
|
constructor(type: ModifierType) {
|
||||||
super(type);
|
super(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clone(): ExtraModifierModifier {
|
||||||
|
return new ExtraModifierModifier(this.type);
|
||||||
|
}
|
||||||
|
|
||||||
apply(args: any[]): boolean {
|
apply(args: any[]): boolean {
|
||||||
(args[0] as Utils.IntegerHolder).value += this.stackCount;
|
(args[0] as Utils.IntegerHolder).value += this.getStackCount();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -436,24 +569,26 @@ export abstract class PokemonModifierType extends ModifierType {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PokemonHpRestoreModifierType extends PokemonModifierType {
|
export class PokemonHpRestoreModifierType extends PokemonModifierType {
|
||||||
protected restorePercent: integer;
|
protected restorePoints: integer;
|
||||||
|
protected percent: boolean;
|
||||||
|
|
||||||
constructor(name: string, restorePercent: integer, newModifierFunc?: Function, selectFilter?: Function, iconImage?: string) {
|
constructor(name: string, restorePoints: integer, percent?: boolean, newModifierFunc?: Function, selectFilter?: Function, iconImage?: string) {
|
||||||
super(name, `Restore ${restorePercent} HP or ${restorePercent}% HP for one POKéMON, whichever is higher`,
|
super(name, `Restore ${restorePoints}${percent ? '%' : ''} HP for one POKéMON`,
|
||||||
newModifierFunc || ((_type, args) => new PokemonHpRestoreModifier(this, (args[0] as PlayerPokemon).id, this.restorePercent, false)),
|
newModifierFunc || ((_type, args) => new PokemonHpRestoreModifier(this, (args[0] as PlayerPokemon).id, this.restorePoints, this.percent, false)),
|
||||||
selectFilter || ((pokemon: PlayerPokemon) => {
|
selectFilter || ((pokemon: PlayerPokemon) => {
|
||||||
if (!pokemon.hp || pokemon.hp >= pokemon.getMaxHp())
|
if (!pokemon.hp || pokemon.hp >= pokemon.getMaxHp())
|
||||||
return PartyUiHandler.NoEffectMessage;
|
return PartyUiHandler.NoEffectMessage;
|
||||||
return null;
|
return null;
|
||||||
}), iconImage);
|
}), iconImage);
|
||||||
|
|
||||||
this.restorePercent = restorePercent;
|
this.restorePoints = restorePoints;
|
||||||
|
this.percent = !!percent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PokemonReviveModifierType extends PokemonHpRestoreModifierType {
|
export class PokemonReviveModifierType extends PokemonHpRestoreModifierType {
|
||||||
constructor(name: string, restorePercent: integer, iconImage?: string) {
|
constructor(name: string, restorePercent: integer, iconImage?: string) {
|
||||||
super(name, restorePercent, (_type, args) => new PokemonHpRestoreModifier(this, (args[0] as PlayerPokemon).id, this.restorePercent, true),
|
super(name, restorePercent, true, (_type, args) => new PokemonHpRestoreModifier(this, (args[0] as PlayerPokemon).id, this.restorePoints, true, true),
|
||||||
((pokemon: PlayerPokemon) => {
|
((pokemon: PlayerPokemon) => {
|
||||||
if (pokemon.hp)
|
if (pokemon.hp)
|
||||||
return PartyUiHandler.NoEffectMessage;
|
return PartyUiHandler.NoEffectMessage;
|
||||||
|
@ -583,7 +718,7 @@ const modifierPool = {
|
||||||
const faintedPartyMemberCount = party.filter(p => !p.hp).length;
|
const faintedPartyMemberCount = party.filter(p => !p.hp).length;
|
||||||
return faintedPartyMemberCount;
|
return faintedPartyMemberCount;
|
||||||
}),
|
}),
|
||||||
new WeightedModifierType(new PokemonHpRestoreModifierType('HYPER POTION', 80), (party: PlayerPokemon[]) => {
|
new WeightedModifierType(new PokemonHpRestoreModifierType('HYPER POTION', 200), (party: PlayerPokemon[]) => {
|
||||||
const thresholdPartyMemberCount = party.filter(p => p.getHpRatio() <= 0.6).length;
|
const thresholdPartyMemberCount = party.filter(p => p.getHpRatio() <= 0.6).length;
|
||||||
return thresholdPartyMemberCount;
|
return thresholdPartyMemberCount;
|
||||||
}),
|
}),
|
||||||
|
@ -610,6 +745,9 @@ const modifierPool = {
|
||||||
new WeightedModifierType(new AllPokemonFullReviveModifierType('SACRED ASH'), (party: PlayerPokemon[]) => {
|
new WeightedModifierType(new AllPokemonFullReviveModifierType('SACRED ASH'), (party: PlayerPokemon[]) => {
|
||||||
return party.filter(p => !p.hp).length >= Math.ceil(party.length / 2) ? 1 : 0;
|
return party.filter(p => !p.hp).length >= Math.ceil(party.length / 2) ? 1 : 0;
|
||||||
}),
|
}),
|
||||||
|
new ModifierType('OVAL CHARM', 'For every X (no. of party members) items in a POKéMON\'s held item stack, give one to each other party member',
|
||||||
|
(type, _args) => new PartyShareModifier(type), 'oval_charm'),
|
||||||
|
new ModifierType('HEALING CHARM', 'Doubles the effectiveness of HP restoring items (excludes revives)', (type, _args) => new HealingBoosterModifier(type, 2), 'healing_charm'),
|
||||||
new ExpBoosterModifierType('LUCKY EGG', 25),
|
new ExpBoosterModifierType('LUCKY EGG', 25),
|
||||||
new ModifierType('EXP. SHARE', 'All POKéMON in your party gain an additional 10% of a battle\'s EXP. Points', (type, _args) => new ExpShareModifier(type), 'exp_share')
|
new ModifierType('EXP. SHARE', 'All POKéMON in your party gain an additional 10% of a battle\'s EXP. Points', (type, _args) => new ExpShareModifier(type), 'exp_share')
|
||||||
].map(m => { m.setTier(ModifierTier.ULTRA); return m; }),
|
].map(m => { m.setTier(ModifierTier.ULTRA); return m; }),
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import BattleScene from './battle-scene';
|
||||||
import { GrowthRate } from './exp';
|
import { GrowthRate } from './exp';
|
||||||
import { pokemonEvolutions } from './pokemon-evolutions';
|
import { pokemonEvolutions } from './pokemon-evolutions';
|
||||||
import { Species } from './species';
|
import { Species } from './species';
|
||||||
|
@ -160,7 +161,6 @@ export default class PokemonSpecies {
|
||||||
const subPrevolutionLevels = getPokemonSpecies(speciesId).getPrevolutionLevels();
|
const subPrevolutionLevels = getPokemonSpecies(speciesId).getPrevolutionLevels();
|
||||||
for (let spl of subPrevolutionLevels)
|
for (let spl of subPrevolutionLevels)
|
||||||
prevolutionLevels.push(spl);
|
prevolutionLevels.push(spl);
|
||||||
console.log(Species[speciesId])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -168,6 +168,72 @@ export default class PokemonSpecies {
|
||||||
|
|
||||||
return prevolutionLevels;
|
return prevolutionLevels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getIconAtlasKey(): string {
|
||||||
|
return `pokemon_icons_${this.generation}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
getIconId(): string {
|
||||||
|
let ret = `${Utils.padInt(this.speciesId, 3)}`;
|
||||||
|
|
||||||
|
switch (this.speciesId) {
|
||||||
|
case Species.UNOWN:
|
||||||
|
ret += 'a';
|
||||||
|
break;
|
||||||
|
case Species.BURMY:
|
||||||
|
case Species.WORMADAM:
|
||||||
|
ret += 'plant';
|
||||||
|
break;
|
||||||
|
case Species.SHELLOS:
|
||||||
|
case Species.GASTRODON:
|
||||||
|
ret += 'east';
|
||||||
|
break;
|
||||||
|
case Species.GIRATINA:
|
||||||
|
ret += 'altered';
|
||||||
|
break;
|
||||||
|
case Species.SHAYMIN:
|
||||||
|
ret += 'land';
|
||||||
|
break;
|
||||||
|
case Species.BASCULIN:
|
||||||
|
ret += 'redstriped';
|
||||||
|
break;
|
||||||
|
case Species.DEERLING:
|
||||||
|
case Species.SAWSBUCK:
|
||||||
|
ret += 'spring';
|
||||||
|
break;
|
||||||
|
case Species.FRILLISH:
|
||||||
|
case Species.JELLICENT:
|
||||||
|
ret += 'm';
|
||||||
|
break;
|
||||||
|
case Species.TORNADUS:
|
||||||
|
case Species.THUNDURUS:
|
||||||
|
case Species.LANDORUS:
|
||||||
|
ret += 'incarnate';
|
||||||
|
break;
|
||||||
|
case Species.KELDEO:
|
||||||
|
ret += 'ordinary';
|
||||||
|
break;
|
||||||
|
case Species.MELOETTA:
|
||||||
|
ret += 'aria';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
getIconKey(): string {
|
||||||
|
return `pkmn_icon__${this.getIconId()}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
generateIconAnim(scene: BattleScene): void {
|
||||||
|
const frameNames = scene.anims.generateFrameNames(this.getIconAtlasKey(), { prefix: `${this.getIconId()}_`, zeroPad: 2, suffix: '.png', start: 1, end: 34 });
|
||||||
|
scene.anims.create({
|
||||||
|
key: this.getIconKey(),
|
||||||
|
frames: frameNames,
|
||||||
|
frameRate: 128,
|
||||||
|
repeat: -1
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PokemonForm extends PokemonSpecies {
|
class PokemonForm extends PokemonSpecies {
|
||||||
|
@ -718,7 +784,7 @@ export const allSpecies = [
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
[ Species.ARCEUS, "Arceus", 4, 0, 0, 1, "Alpha Pokémon", Type.NORMAL, -1, 3.2, 320, "Multitype", null, null, 720, 120, 120, 120, 120, 120, 120, 3, 0, 324, GrowthRate.SLOW, "Undiscovered", null, null, 120, 0 ],
|
[ Species.ARCEUS, "Arceus", 4, 0, 0, 1, "Alpha Pokémon", Type.NORMAL, -1, 3.2, 320, "Multitype", null, null, 720, 120, 120, 120, 120, 120, 120, 3, 0, 324, GrowthRate.SLOW, "Undiscovered", null, null, 120, 0 ],
|
||||||
[ Species.VICTINI, "Victini", 5, 0, 0, 1, "Victory Pokémon", Type.PSYCHIC, Type.FIRE, 0.4, 4, "Victory Star", null, null, 600, 100, 100, 100, 100, 100, 100, 3, 100, 270, GrowthRate.SLOW, "Undiscovered", null, null, 120, 0 ],
|
[ Species.VICTINI, "Victini", 4, 0, 0, 1, "Victory Pokémon", Type.PSYCHIC, Type.FIRE, 0.4, 4, "Victory Star", null, null, 600, 100, 100, 100, 100, 100, 100, 3, 100, 270, GrowthRate.SLOW, "Undiscovered", null, null, 120, 0 ],
|
||||||
[ Species.SNIVY, "Snivy", 5, 0, 0, 0, "Grass Snake Pokémon", Type.GRASS, -1, 0.6, 8.1, "Overgrow", null, "Contrary", 308, 45, 45, 55, 45, 55, 63, 45, 70, 62, GrowthRate.MEDIUM_SLOW, "Field", "Grass", 87.5, 20, 0 ],
|
[ Species.SNIVY, "Snivy", 5, 0, 0, 0, "Grass Snake Pokémon", Type.GRASS, -1, 0.6, 8.1, "Overgrow", null, "Contrary", 308, 45, 45, 55, 45, 55, 63, 45, 70, 62, GrowthRate.MEDIUM_SLOW, "Field", "Grass", 87.5, 20, 0 ],
|
||||||
[ Species.SERVINE, "Servine", 5, 0, 0, 0, "Grass Snake Pokémon", Type.GRASS, -1, 0.8, 16, "Overgrow", null, "Contrary", 413, 60, 60, 75, 60, 75, 83, 45, 70, 145, GrowthRate.MEDIUM_SLOW, "Field", "Grass", 87.5, 20, 0 ],
|
[ Species.SERVINE, "Servine", 5, 0, 0, 0, "Grass Snake Pokémon", Type.GRASS, -1, 0.8, 16, "Overgrow", null, "Contrary", 413, 60, 60, 75, 60, 75, 83, 45, 70, 145, GrowthRate.MEDIUM_SLOW, "Field", "Grass", 87.5, 20, 0 ],
|
||||||
[ Species.SERPERIOR, "Serperior", 5, 0, 0, 0, "Regal Pokémon", Type.GRASS, -1, 3.3, 63, "Overgrow", null, "Contrary", 528, 75, 75, 95, 75, 95, 113, 45, 70, 238, GrowthRate.MEDIUM_SLOW, "Field", "Grass", 87.5, 20, 0 ],
|
[ Species.SERPERIOR, "Serperior", 5, 0, 0, 0, "Regal Pokémon", Type.GRASS, -1, 3.3, 63, "Overgrow", null, "Contrary", 528, 75, 75, 95, 75, 95, 113, 45, 70, 238, GrowthRate.MEDIUM_SLOW, "Field", "Grass", 87.5, 20, 0 ],
|
||||||
|
|
|
@ -220,12 +220,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
return `pkmn__${this.getBattleSpriteId()}`;
|
return `pkmn__${this.getBattleSpriteId()}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
getIconAtlasKey(): string {
|
|
||||||
return `pokemon_icons_${this.species.generation}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
getIconId(): string {
|
getIconId(): string {
|
||||||
return `${Utils.padInt(this.species.speciesId, 3)}`;
|
// TODO: Add form special cases
|
||||||
|
return this.species.getIconId();
|
||||||
}
|
}
|
||||||
|
|
||||||
getIconKey(): string {
|
getIconKey(): string {
|
||||||
|
@ -355,8 +352,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateInfo(callback?: Function) {
|
updateInfo(): Promise<void> {
|
||||||
this.battleInfo.updateInfo(this, callback);
|
return this.battleInfo.updateInfo(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
addExp(exp: integer) {
|
addExp(exp: integer) {
|
||||||
|
@ -434,7 +431,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
callback: () => {
|
callback: () => {
|
||||||
this.getSprite().setVisible(flashTimer.repeatCount % 2 === 0);
|
this.getSprite().setVisible(flashTimer.repeatCount % 2 === 0);
|
||||||
if (!flashTimer.repeatCount) {
|
if (!flashTimer.repeatCount) {
|
||||||
this.battleInfo.updateInfo(this, () => {
|
this.battleInfo.updateInfo(this).then(() => {
|
||||||
if (callback)
|
if (callback)
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
|
@ -442,7 +439,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.battleInfo.updateInfo(this, () => {
|
this.battleInfo.updateInfo(this).then(() => {
|
||||||
if (callback)
|
if (callback)
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
|
@ -579,7 +576,7 @@ export class PlayerPokemon extends Pokemon {
|
||||||
constructor(scene: BattleScene, species: PokemonSpecies, level: integer, dataSource?: Pokemon) {
|
constructor(scene: BattleScene, species: PokemonSpecies, level: integer, dataSource?: Pokemon) {
|
||||||
super(scene, 106, 148, species, level, dataSource);
|
super(scene, 106, 148, species, level, dataSource);
|
||||||
|
|
||||||
this.generateIconAnim();
|
this.species.generateIconAnim(scene);
|
||||||
this.generateCompatibleTms();
|
this.generateCompatibleTms();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -587,16 +584,6 @@ export class PlayerPokemon extends Pokemon {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
generateIconAnim(): void {
|
|
||||||
const frameNames = this.scene.anims.generateFrameNames(this.getIconAtlasKey(), { prefix: `${this.getIconId()}_`, zeroPad: 2, suffix: '.png', start: 1, end: 34 });
|
|
||||||
this.scene.anims.create({
|
|
||||||
key: this.getIconKey(),
|
|
||||||
frames: frameNames,
|
|
||||||
frameRate: 128,
|
|
||||||
repeat: -1
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
generateCompatibleTms(): void {
|
generateCompatibleTms(): void {
|
||||||
this.compatibleTms = [];
|
this.compatibleTms = [];
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,15 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
show(args: any[]) {
|
show(args: any[]) {
|
||||||
if (this.active || args.length !== 2 || !(args[0] instanceof Array) || !args[0].length || !(args[1] instanceof Function))
|
if (this.active) {
|
||||||
|
if (args.length === 2) {
|
||||||
|
this.awaitingActionInput = true;
|
||||||
|
this.onActionInput = args[1];
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.length !== 2 || !(args[0] instanceof Array) || !args[0].length || !(args[1] instanceof Function))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
super.show(args);
|
super.show(args);
|
||||||
|
@ -92,6 +100,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
|
||||||
success = true;
|
success = true;
|
||||||
if (this.onActionInput) {
|
if (this.onActionInput) {
|
||||||
const originalOnActionInput = this.onActionInput;
|
const originalOnActionInput = this.onActionInput;
|
||||||
|
this.awaitingActionInput = false;
|
||||||
this.onActionInput = null;
|
this.onActionInput = null;
|
||||||
originalOnActionInput(this.cursor);
|
originalOnActionInput(this.cursor);
|
||||||
}
|
}
|
||||||
|
@ -99,6 +108,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
|
||||||
success = true;
|
success = true;
|
||||||
if (this.onActionInput) {
|
if (this.onActionInput) {
|
||||||
const originalOnActionInput = this.onActionInput;
|
const originalOnActionInput = this.onActionInput;
|
||||||
|
this.awaitingActionInput = false;
|
||||||
this.onActionInput = null;
|
this.onActionInput = null;
|
||||||
originalOnActionInput(-1);
|
originalOnActionInput(-1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,6 +158,8 @@ export default class PartyUiHandler extends MessageUiHandler {
|
||||||
selectCallback(this.cursor);
|
selectCallback(this.cursor);
|
||||||
} else if (this.cursor)
|
} else if (this.cursor)
|
||||||
(this.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.POKEMON, this.cursor);
|
(this.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.POKEMON, this.cursor);
|
||||||
|
if (this.partyUiMode !== PartyUiMode.MODIFIER)
|
||||||
|
ui.playSelect();
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
this.clearOptions();
|
this.clearOptions();
|
||||||
|
@ -396,9 +398,9 @@ class PartySlot extends Phaser.GameObjects.Container {
|
||||||
|
|
||||||
this.add(slotPb);
|
this.add(slotPb);
|
||||||
|
|
||||||
const pokemonIcon = this.scene.add.sprite(slotPb.x, slotPb.y, this.pokemon.getIconAtlasKey());
|
const pokemonIcon = this.scene.add.sprite(slotPb.x, slotPb.y, this.pokemon.species.getIconAtlasKey());
|
||||||
console.log(pokemonIcon)
|
console.log(pokemonIcon)
|
||||||
pokemonIcon.play(this.pokemon.getIconKey());
|
pokemonIcon.play(this.pokemon.species.getIconKey());
|
||||||
this.slotPokemonIcon = pokemonIcon;
|
this.slotPokemonIcon = pokemonIcon;
|
||||||
|
|
||||||
this.add(pokemonIcon);
|
this.add(pokemonIcon);
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
import BattleScene from "../battle-scene";
|
||||||
|
import { allSpecies } from "../pokemon-species";
|
||||||
|
import { Mode } from "./ui";
|
||||||
|
import UiHandler from "./uiHandler";
|
||||||
|
|
||||||
|
export default class StarterSelectUiHandler extends UiHandler {
|
||||||
|
private starterSelectContainer: Phaser.GameObjects.Container;
|
||||||
|
|
||||||
|
constructor(scene: BattleScene) {
|
||||||
|
super(scene, Mode.STARTER_SELECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
const ui = this.getUi();
|
||||||
|
|
||||||
|
this.starterSelectContainer = this.scene.add.container(0, -this.scene.game.canvas.height / 6);
|
||||||
|
this.starterSelectContainer.setVisible(false);
|
||||||
|
ui.add(this.starterSelectContainer);
|
||||||
|
|
||||||
|
let s = 0;
|
||||||
|
|
||||||
|
for (let species of allSpecies) {
|
||||||
|
if (species.getSpeciesForLevel(1) !== species.speciesId || species.generation >= 6)
|
||||||
|
continue;
|
||||||
|
species.generateIconAnim(this.scene);
|
||||||
|
const x = (s % 24) * 13;
|
||||||
|
const y = Math.floor(s / 24) * 13;
|
||||||
|
const icon = this.scene.add.sprite(x, y, species.getIconAtlasKey());
|
||||||
|
icon.setScale(0.5);
|
||||||
|
icon.setOrigin(0, 0);
|
||||||
|
icon.play(species.getIconKey()).stop();
|
||||||
|
this.starterSelectContainer.add(icon);
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
show(args: any[]) {
|
||||||
|
super.show(args);
|
||||||
|
|
||||||
|
this.starterSelectContainer.setVisible(true);
|
||||||
|
this.setCursor(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
processInput(keyCode: integer) {
|
||||||
|
const ui = this.getUi();
|
||||||
|
const keyCodes = Phaser.Input.Keyboard.KeyCodes;
|
||||||
|
|
||||||
|
let success = false;
|
||||||
|
|
||||||
|
if (keyCode === keyCodes.Z) {
|
||||||
|
} else if (keyCode === keyCodes.X) {
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
ui.playSelect();
|
||||||
|
}
|
||||||
|
|
||||||
|
setCursor(cursor: integer): boolean {
|
||||||
|
let changed: boolean = this.cursor !== cursor;
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
const forward = this.cursor < cursor;
|
||||||
|
this.cursor = cursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
clear() {
|
||||||
|
super.clear();
|
||||||
|
this.cursor = -1;
|
||||||
|
this.starterSelectContainer.setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
10
src/ui/ui.ts
10
src/ui/ui.ts
|
@ -9,6 +9,7 @@ import ConfirmUiHandler from './confirm-ui-handler';
|
||||||
import ModifierSelectUiHandler from './modifier-select-ui-handler';
|
import ModifierSelectUiHandler from './modifier-select-ui-handler';
|
||||||
import BallUiHandler from './ball-ui-handler';
|
import BallUiHandler from './ball-ui-handler';
|
||||||
import SummaryUiHandler from './summary-ui-handler';
|
import SummaryUiHandler from './summary-ui-handler';
|
||||||
|
import StarterSelectUiHandler from './starter-select-ui-handler';
|
||||||
|
|
||||||
export enum Mode {
|
export enum Mode {
|
||||||
MESSAGE = 0,
|
MESSAGE = 0,
|
||||||
|
@ -18,12 +19,14 @@ export enum Mode {
|
||||||
CONFIRM,
|
CONFIRM,
|
||||||
MODIFIER_SELECT,
|
MODIFIER_SELECT,
|
||||||
PARTY,
|
PARTY,
|
||||||
SUMMARY
|
SUMMARY,
|
||||||
|
STARTER_SELECT,
|
||||||
};
|
};
|
||||||
|
|
||||||
const transitionModes = [
|
const transitionModes = [
|
||||||
Mode.PARTY,
|
Mode.PARTY,
|
||||||
Mode.SUMMARY
|
Mode.SUMMARY,
|
||||||
|
Mode.STARTER_SELECT,
|
||||||
];
|
];
|
||||||
|
|
||||||
export default class UI extends Phaser.GameObjects.Container {
|
export default class UI extends Phaser.GameObjects.Container {
|
||||||
|
@ -45,7 +48,8 @@ export default class UI extends Phaser.GameObjects.Container {
|
||||||
new ConfirmUiHandler(scene),
|
new ConfirmUiHandler(scene),
|
||||||
new ModifierSelectUiHandler(scene),
|
new ModifierSelectUiHandler(scene),
|
||||||
new PartyUiHandler(scene),
|
new PartyUiHandler(scene),
|
||||||
new SummaryUiHandler(scene)
|
new SummaryUiHandler(scene),
|
||||||
|
new StarterSelectUiHandler(scene)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue