Refactor modifiers
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,24 +101,77 @@ export default class BattleInfo extends Phaser.GameObjects.Container {
|
|||
}
|
||||
}
|
||||
|
||||
updateInfo(pokemon: Pokemon, callback?: Function) {
|
||||
if (!this.scene) {
|
||||
if (callback)
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
updateInfo(pokemon: Pokemon): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
if (!this.scene) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
const updatePokemonHp = () => {
|
||||
const duration = Utils.clampInt(Math.abs((this.lastHp) - pokemon.hp) * 5, 250, 5000);
|
||||
const updatePokemonHp = () => {
|
||||
const duration = Utils.clampInt(Math.abs((this.lastHp) - pokemon.hp) * 5, 250, 5000);
|
||||
this.scene.tweens.add({
|
||||
targets: this.hpBar,
|
||||
ease: 'Sine.easeOut',
|
||||
scaleX: pokemon.getHpRatio(),
|
||||
duration: duration,
|
||||
onUpdate: () => {
|
||||
if (this.player && this.lastHp !== pokemon.hp) {
|
||||
const tweenHp = Math.ceil(this.hpBar.scaleX * pokemon.getMaxHp());
|
||||
this.setHpNumbers(tweenHp, pokemon.getMaxHp())
|
||||
this.lastHp = tweenHp;
|
||||
}
|
||||
|
||||
const hpFrame = this.hpBar.scaleX > 0.5 ? 'high' : this.hpBar.scaleX > 0.25 ? 'medium' : 'low';
|
||||
if (hpFrame !== this.lastHpFrame) {
|
||||
this.hpBar.setFrame(hpFrame);
|
||||
this.lastHpFrame = hpFrame;
|
||||
}
|
||||
},
|
||||
onComplete: () => {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
if (!this.player)
|
||||
this.lastHp = pokemon.hp;
|
||||
this.lastMaxHp = pokemon.getMaxHp();
|
||||
};
|
||||
|
||||
if (this.player && this.lastExp !== pokemon.exp) {
|
||||
const originalResolve = resolve;
|
||||
resolve = () => this.updatePokemonExp(pokemon).then(() => originalResolve());
|
||||
}
|
||||
|
||||
if (this.lastHp !== pokemon.hp || this.lastMaxHp !== pokemon.getMaxHp()) {
|
||||
updatePokemonHp();
|
||||
return;
|
||||
} else if (!this.player && this.lastLevel !== pokemon.level) {
|
||||
this.setLevel(pokemon.level);
|
||||
this.lastLevel = pokemon.level;
|
||||
}
|
||||
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
updatePokemonExp(battler: Pokemon): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
const levelUp = this.lastLevel < battler.level;
|
||||
const relLevelExp = getLevelRelExp(this.lastLevel + 1, battler.species.growthRate);
|
||||
const levelExp = levelUp ? relLevelExp : battler.levelExp;
|
||||
let ratio = levelExp / relLevelExp;
|
||||
let duration = this.visible ? ((levelExp - this.lastLevelExp) / relLevelExp) * 1650 : 0;
|
||||
if (duration)
|
||||
this.scene.sound.play('exp');
|
||||
this.scene.tweens.add({
|
||||
targets: this.hpBar,
|
||||
ease: 'Sine.easeOut',
|
||||
scaleX: pokemon.getHpRatio(),
|
||||
targets: this.expBar,
|
||||
ease: 'Sine.easeIn',
|
||||
scaleX: ratio,
|
||||
duration: duration,
|
||||
onUpdate: () => {
|
||||
if (this.player && this.lastHp !== pokemon.hp) {
|
||||
const tweenHp = Math.ceil(this.hpBar.scaleX * pokemon.getMaxHp());
|
||||
this.setHpNumbers(tweenHp, pokemon.getMaxHp())
|
||||
if (this.player && this.lastHp !== battler.hp) {
|
||||
const tweenHp = Math.ceil(this.hpBar.scaleX * battler.getMaxHp());
|
||||
this.setHpNumbers(tweenHp, battler.getMaxHp());
|
||||
this.lastHp = tweenHp;
|
||||
}
|
||||
|
||||
|
@ -129,81 +182,25 @@ export default class BattleInfo extends Phaser.GameObjects.Container {
|
|||
}
|
||||
},
|
||||
onComplete: () => {
|
||||
if (callback) {
|
||||
callback();
|
||||
callback = null;
|
||||
if (duration)
|
||||
this.scene.sound.stopByKey('exp');
|
||||
if (ratio === 1) {
|
||||
this.lastLevelExp = 0;
|
||||
this.lastLevel++;
|
||||
this.scene.sound.play('level_up');
|
||||
this.setLevel(this.lastLevel);
|
||||
this.scene.time.delayedCall(500, () => {
|
||||
this.expBar.setScale(0, 1);
|
||||
this.updateInfo(battler).then(() => resolve());
|
||||
});
|
||||
return;
|
||||
} else {
|
||||
this.lastExp = battler.exp;
|
||||
this.lastLevelExp = battler.levelExp;
|
||||
}
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
if (!this.player)
|
||||
this.lastHp = pokemon.hp;
|
||||
this.lastMaxHp = pokemon.getMaxHp();
|
||||
};
|
||||
|
||||
if (this.player && this.lastExp !== pokemon.exp) {
|
||||
const originalCallback = callback;
|
||||
callback = () => this.updatePokemonExp(pokemon, originalCallback);
|
||||
}
|
||||
|
||||
if (this.lastHp !== pokemon.hp || this.lastMaxHp !== pokemon.getMaxHp())
|
||||
updatePokemonHp();
|
||||
else if (!this.player && this.lastLevel !== pokemon.level) {
|
||||
this.setLevel(pokemon.level);
|
||||
this.lastLevel = pokemon.level;
|
||||
if (callback)
|
||||
callback();
|
||||
} else if (callback)
|
||||
callback();
|
||||
}
|
||||
|
||||
updatePokemonExp(battler: Pokemon, callback?: Function) {
|
||||
const levelUp = this.lastLevel < battler.level;
|
||||
const relLevelExp = getLevelRelExp(this.lastLevel + 1, battler.species.growthRate);
|
||||
const levelExp = levelUp ? relLevelExp : battler.levelExp;
|
||||
let ratio = levelExp / relLevelExp;
|
||||
let duration = this.visible ? ((levelExp - this.lastLevelExp) / relLevelExp) * 1650 : 0;
|
||||
if (duration)
|
||||
this.scene.sound.play('exp');
|
||||
this.scene.tweens.add({
|
||||
targets: this.expBar,
|
||||
ease: 'Sine.easeIn',
|
||||
scaleX: ratio,
|
||||
duration: duration,
|
||||
onUpdate: () => {
|
||||
if (this.player && this.lastHp !== battler.hp) {
|
||||
const tweenHp = Math.ceil(this.hpBar.scaleX * battler.getMaxHp());
|
||||
this.setHpNumbers(tweenHp, battler.getMaxHp());
|
||||
this.lastHp = tweenHp;
|
||||
}
|
||||
|
||||
const hpFrame = this.hpBar.scaleX > 0.5 ? 'high' : this.hpBar.scaleX > 0.25 ? 'medium' : 'low';
|
||||
if (hpFrame !== this.lastHpFrame) {
|
||||
this.hpBar.setFrame(hpFrame);
|
||||
this.lastHpFrame = hpFrame;
|
||||
}
|
||||
},
|
||||
onComplete: () => {
|
||||
if (duration)
|
||||
this.scene.sound.stopByKey('exp');
|
||||
if (ratio === 1) {
|
||||
this.lastLevelExp = 0;
|
||||
this.lastLevel++;
|
||||
this.scene.sound.play('level_up');
|
||||
this.setLevel(this.lastLevel);
|
||||
this.scene.time.delayedCall(500, () => {
|
||||
this.expBar.setScale(0, 1);
|
||||
this.updateInfo(battler, callback);
|
||||
});
|
||||
return;
|
||||
} else {
|
||||
this.lastExp = battler.exp;
|
||||
this.lastLevelExp = battler.levelExp;
|
||||
}
|
||||
if (callback) {
|
||||
callback();
|
||||
callback = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
constructor(scene: BattleScene) {
|
||||
super(scene);
|
||||
|
@ -722,7 +734,7 @@ export class ExpPhase extends PartyMemberPokemonPhase {
|
|||
newLevel = pokemon.level;
|
||||
if (newLevel > lastLevel)
|
||||
this.scene.unshiftPhase(new LevelUpPhase(this.scene, this.partyMemberIndex, newLevel));
|
||||
pokemon.updateInfo(() => this.end());
|
||||
pokemon.updateInfo().then(() => this.end());
|
||||
}, null, true);
|
||||
}
|
||||
|
||||
|
@ -1016,7 +1028,7 @@ export class SelectModifierPhase extends BattlePhase {
|
|||
this.scene.applyModifiers(ExtraModifierModifier, modifierCount);
|
||||
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) {
|
||||
this.scene.ui.setMode(Mode.MESSAGE);
|
||||
super.end();
|
||||
|
@ -1033,14 +1045,15 @@ export class SelectModifierPhase extends BattlePhase {
|
|||
this.scene.ui.clearText();
|
||||
this.scene.ui.setMode(Mode.MESSAGE);
|
||||
} else
|
||||
this.scene.ui.setMode(Mode.MODIFIER_SELECT);
|
||||
this.scene.ui.setMode(Mode.MODIFIER_SELECT, types, modifierSelectCallback);
|
||||
}, pokemonModifierType.selectFilter);
|
||||
} else {
|
||||
this.scene.addModifier(types[cursor].newModifier()).then(() => super.end());
|
||||
this.scene.ui.clearText();
|
||||
this.scene.ui.setMode(Mode.MESSAGE);
|
||||
}
|
||||
});
|
||||
};
|
||||
this.scene.ui.setMode(Mode.MODIFIER_SELECT, types, modifierSelectCallback);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
import Phaser from 'phaser';
|
||||
import { Biome, BiomeArena } from './biome';
|
||||
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 PokemonSpecies, { allSpecies, getPokemonSpecies } from './pokemon-species';
|
||||
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 { Species } from './species';
|
||||
import { initAutoPlay } from './auto-play';
|
||||
import { Battle } from './battle';
|
||||
import { populateAnims } from './battle-anims';
|
||||
import { Stat } from './pokemon-stat';
|
||||
|
||||
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 ]));
|
||||
private party: PlayerPokemon[];
|
||||
private modifierBar: ModifierBar;
|
||||
private modifiers: Modifier[];
|
||||
private modifiers: PersistentModifier[];
|
||||
public uiContainer: Phaser.GameObjects.Container;
|
||||
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.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(() => {
|
||||
if (enableAuto)
|
||||
initAutoPlay.apply(this);
|
||||
|
@ -341,6 +346,7 @@ export default class BattleScene extends Phaser.Scene {
|
|||
this.unshiftPhase(new NewBiomeEncounterPhase(this));
|
||||
}
|
||||
} else {
|
||||
//this.pushPhase(new SelectStarterPhase(this));
|
||||
this.pushPhase(new EncounterPhase(this));
|
||||
this.pushPhase(new SummonPhase(this));
|
||||
}
|
||||
|
@ -443,43 +449,71 @@ export default class BattleScene extends Phaser.Scene {
|
|||
this.phaseQueue.push(new CommandPhase(this));
|
||||
}
|
||||
|
||||
addModifier(modifier: Modifier): Promise<void> {
|
||||
addModifier(modifier: Modifier, virtual?: boolean): Promise<void> {
|
||||
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');
|
||||
|
||||
if (!virtual)
|
||||
this.updateModifiers().then(() => resolve());
|
||||
} else if (modifier instanceof ConsumableModifier) {
|
||||
this.sound.play('restore');
|
||||
|
||||
if (modifier instanceof ConsumableModifier) {
|
||||
const args = [ this ];
|
||||
if (modifier.shouldApply(args))
|
||||
modifier.apply(args);
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
if (modifier instanceof ConsumablePokemonModifier) {
|
||||
for (let p in this.party) {
|
||||
const pokemon = this.party[p];
|
||||
|
||||
let pokemonToUpdate = 0;
|
||||
|
||||
if (modifier instanceof PokemonModifier) {
|
||||
for (let p in this.party) {
|
||||
const pokemon = this.party[p];
|
||||
|
||||
if (modifier instanceof ConsumablePokemonModifier) {
|
||||
const args = [ pokemon ];
|
||||
const args: any[] = [ pokemon ];
|
||||
if (modifier instanceof PokemonHpRestoreModifier) {
|
||||
const hpRestoreMultiplier = new Utils.IntegerHolder(1);
|
||||
this.applyModifiers(HealingBoosterModifier, hpRestoreMultiplier);
|
||||
args.push(hpRestoreMultiplier.value);
|
||||
}
|
||||
if (modifier.shouldApply(args))
|
||||
modifier.apply(args);
|
||||
}
|
||||
|
||||
pokemonToUpdate++;
|
||||
|
||||
pokemon.calculateStats();
|
||||
pokemon.updateInfo(() => {
|
||||
if (!(--pokemonToUpdate))
|
||||
resolve();
|
||||
});
|
||||
|
||||
Promise.allSettled(this.party.map(p => p.updateInfo())).then(() => resolve());
|
||||
} else {
|
||||
const args = [ this ];
|
||||
if (modifier.shouldApply(args))
|
||||
modifier.apply(args);
|
||||
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (!pokemonToUpdate)
|
||||
updatePartyForModifiers(): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
Promise.allSettled(this.party.map(p => {
|
||||
p.calculateStats();
|
||||
return p.updateInfo();
|
||||
})).then(() => resolve());
|
||||
});
|
||||
}
|
||||
|
||||
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();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
318
src/modifier.ts
318
src/modifier.ts
|
@ -18,19 +18,13 @@ export class ModifierBar extends Phaser.GameObjects.Container {
|
|||
this.setScale(0.5);
|
||||
}
|
||||
|
||||
addModifier(modifier: Modifier) {
|
||||
const icon = modifier.getIcon(this.scene as BattleScene);
|
||||
this.add(icon);
|
||||
this.setModifierIconPosition(icon);
|
||||
}
|
||||
updateModifiers(modifiers: PersistentModifier[]) {
|
||||
this.removeAll(true);
|
||||
|
||||
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);
|
||||
for (let modifier of modifiers) {
|
||||
const icon = modifier.getIcon(this.scene as BattleScene);
|
||||
this.add(icon);
|
||||
this.setModifierIconPosition(icon);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,19 +38,13 @@ export class ModifierBar extends Phaser.GameObjects.Container {
|
|||
|
||||
export abstract class Modifier {
|
||||
public type: ModifierType;
|
||||
public stackCount: integer;
|
||||
|
||||
constructor(type: ModifierType) {
|
||||
this.type = type;
|
||||
this.stackCount = 1;
|
||||
}
|
||||
|
||||
add(modifierBar: ModifierBar, modifiers: Modifier[]): boolean {
|
||||
modifiers.push(this);
|
||||
|
||||
modifierBar.addModifier(this);
|
||||
|
||||
return true;
|
||||
match(_modifier: Modifier): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
shouldApply(_args: any[]): boolean {
|
||||
|
@ -64,10 +52,47 @@ export abstract class Modifier {
|
|||
}
|
||||
|
||||
abstract apply(args: any[]): boolean;
|
||||
}
|
||||
|
||||
incrementStack(): void {
|
||||
if (this.stackCount < this.getMaxStackCount())
|
||||
this.stackCount++;
|
||||
export abstract class PersistentModifier extends Modifier {
|
||||
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++;
|
||||
else
|
||||
this.virtualStackCount++;
|
||||
}
|
||||
}
|
||||
|
||||
getStackCount(): integer {
|
||||
return this.stackCount + this.virtualStackCount;
|
||||
}
|
||||
|
||||
getMaxStackCount(): integer {
|
||||
|
@ -86,16 +111,34 @@ export abstract class Modifier {
|
|||
if (stackText)
|
||||
container.add(stackText);
|
||||
|
||||
const virtualStackText = this.getIconStackText(scene, true);
|
||||
if (virtualStackText)
|
||||
container.add(virtualStackText);
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
getIconStackText(scene: BattleScene): Phaser.GameObjects.Text {
|
||||
if (this.stackCount <= 1)
|
||||
getIconStackText(scene: BattleScene, virtual?: boolean): Phaser.GameObjects.Text {
|
||||
if (this.getMaxStackCount() === 1 || (virtual && !this.virtualStackCount))
|
||||
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.setOrigin(1, 0);
|
||||
text.setOrigin(0, 0);
|
||||
|
||||
return text;
|
||||
}
|
||||
|
@ -106,7 +149,7 @@ export abstract class ConsumableModifier extends Modifier {
|
|||
super(type);
|
||||
}
|
||||
|
||||
add(_modifierBar: ModifierBar, _modifiers: Modifier[]): boolean {
|
||||
add(_modifiers: Modifier[]): boolean {
|
||||
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;
|
||||
|
||||
constructor(type: ModifierType, pokemonId: integer) {
|
||||
|
@ -144,7 +187,6 @@ export abstract class PokemonModifier extends Modifier {
|
|||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -152,8 +194,8 @@ export abstract class PokemonModifier extends Modifier {
|
|||
const container = scene.add.container(0, 0);
|
||||
|
||||
const pokemon = this.getPokemon(scene);
|
||||
const pokemonIcon = scene.add.sprite(0, 8, pokemon.getIconAtlasKey());
|
||||
pokemonIcon.play(pokemon.getIconKey()).stop();
|
||||
const pokemonIcon = scene.add.sprite(0, 8, pokemon.species.getIconAtlasKey());
|
||||
pokemonIcon.play(pokemon.species.getIconKey()).stop();
|
||||
pokemonIcon.setOrigin(0, 0.5);
|
||||
|
||||
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;
|
||||
|
||||
constructor(type: PokemonBaseStatBoosterModifierType, pokemonId: integer, stat: Stat) {
|
||||
|
@ -174,19 +216,16 @@ export class PokemonBaseStatModifier extends PokemonModifier {
|
|||
this.stat = stat;
|
||||
}
|
||||
|
||||
add(modifierBar: ModifierBar, modifiers: Modifier[]): boolean {
|
||||
for (let modifier of modifiers) {
|
||||
if (modifier instanceof PokemonBaseStatModifier) {
|
||||
const pokemonStatModifier = modifier as PokemonBaseStatModifier;
|
||||
if (pokemonStatModifier.pokemonId === this.pokemonId && pokemonStatModifier.stat === this.stat) {
|
||||
pokemonStatModifier.incrementStack();
|
||||
modifierBar.updateModifier(pokemonStatModifier, modifiers);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
match(modifier: Modifier): boolean {
|
||||
if (modifier instanceof PokemonBaseStatModifier) {
|
||||
const pokemonStatModifier = modifier as PokemonBaseStatModifier;
|
||||
return pokemonStatModifier.pokemonId === this.pokemonId && pokemonStatModifier.stat === this.stat;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return super.add(modifierBar, modifiers);
|
||||
clone(): PersistentModifier {
|
||||
return new PokemonBaseStatModifier(this.type as PokemonBaseStatBoosterModifierType, this.pokemonId, this.stat);
|
||||
}
|
||||
|
||||
shouldApply(args: any[]): boolean {
|
||||
|
@ -194,7 +233,7 @@ export class PokemonBaseStatModifier extends PokemonModifier {
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -202,7 +241,7 @@ export class PokemonBaseStatModifier extends PokemonModifier {
|
|||
getIcon(scene: BattleScene): Phaser.GameObjects.Container {
|
||||
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.setOrigin(0, 0.5);
|
||||
item.setTexture('items', this.type.iconImage);
|
||||
|
@ -212,35 +251,57 @@ export class PokemonBaseStatModifier extends PokemonModifier {
|
|||
if (stackText)
|
||||
container.add(stackText);
|
||||
|
||||
const virtualStackText = this.getIconStackText(scene, true);
|
||||
if (virtualStackText)
|
||||
container.add(virtualStackText);
|
||||
|
||||
return container;
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class ConsumablePokemonModifier extends PokemonModifier {
|
||||
export abstract class ConsumablePokemonModifier extends ConsumableModifier {
|
||||
public pokemonId: integer;
|
||||
|
||||
constructor(type: ModifierType, pokemonId: integer) {
|
||||
super(type, pokemonId);
|
||||
super(type);
|
||||
|
||||
this.pokemonId = pokemonId;
|
||||
}
|
||||
|
||||
add(_modifierBar: ModifierBar, _modifiers: Modifier[]): boolean {
|
||||
return true;
|
||||
shouldApply(args: any[]): boolean {
|
||||
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 {
|
||||
private restorePercent: integer;
|
||||
private restorePoints: integer;
|
||||
private percent: 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);
|
||||
|
||||
this.restorePercent = restorePercent;
|
||||
this.restorePoints = restorePoints;
|
||||
this.percent = percent;
|
||||
this.fainted = !!fainted;
|
||||
}
|
||||
|
||||
shouldApply(args: any[]): boolean {
|
||||
return super.shouldApply(args) && (this.fainted || (args.length > 1 && typeof(args[1]) === 'number'));
|
||||
}
|
||||
|
||||
apply(args: any[]): boolean {
|
||||
const pokemon = args[0] as Pokemon;
|
||||
if (!pokemon.hp === this.fainted)
|
||||
pokemon.hp = Math.min(pokemon.hp + Math.max((this.restorePercent * 0.01) * pokemon.getMaxHp(), this.restorePercent), pokemon.getMaxHp());
|
||||
if (!pokemon.hp === this.fainted) {
|
||||
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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
constructor(type: ModifierType, boostPercent: integer) {
|
||||
|
@ -311,29 +444,26 @@ export class ExpBoosterModifier extends Modifier {
|
|||
this.boostMultiplier = boostPercent * 0.01;
|
||||
}
|
||||
|
||||
add(modifierBar: ModifierBar, modifiers: Modifier[]): boolean {
|
||||
for (let modifier of modifiers) {
|
||||
if (modifier instanceof ExpBoosterModifier) {
|
||||
const expModifier = modifier as ExpBoosterModifier;
|
||||
if (expModifier.boostMultiplier === this.boostMultiplier) {
|
||||
expModifier.incrementStack();
|
||||
modifierBar.updateModifier(expModifier, modifiers);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
match(modifier: Modifier): boolean {
|
||||
if (modifier instanceof ExpBoosterModifier) {
|
||||
const expModifier = modifier as ExpBoosterModifier;
|
||||
return expModifier.boostMultiplier === this.boostMultiplier;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return super.add(modifierBar, modifiers);
|
||||
clone(): ExpBoosterModifier {
|
||||
return new ExpBoosterModifier(this.type, this.boostMultiplier * 100);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
export class ExpShareModifier extends Modifier {
|
||||
export class ExpShareModifier extends PersistentModifier {
|
||||
constructor(type: ModifierType) {
|
||||
super(type);
|
||||
}
|
||||
|
@ -342,31 +472,30 @@ export class ExpShareModifier extends Modifier {
|
|||
return true;
|
||||
}
|
||||
|
||||
clone(): ExpShareModifier {
|
||||
return new ExpShareModifier(this.type);
|
||||
}
|
||||
|
||||
getMaxStackCount(): integer {
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
|
||||
export class ShinyRateBoosterModifier extends Modifier {
|
||||
export class ShinyRateBoosterModifier extends PersistentModifier {
|
||||
constructor(type: ModifierType) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
add(modifierBar: ModifierBar, modifiers: Modifier[]): boolean {
|
||||
for (let modifier of modifiers) {
|
||||
if (modifier instanceof ShinyRateBoosterModifier) {
|
||||
const shinyRateModifier = modifier as ShinyRateBoosterModifier;
|
||||
shinyRateModifier.incrementStack();
|
||||
modifierBar.updateModifier(shinyRateModifier, modifiers);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
match(modifier: Modifier): boolean {
|
||||
return modifier instanceof ShinyRateBoosterModifier;
|
||||
}
|
||||
|
||||
return super.add(modifierBar, modifiers);
|
||||
clone(): ShinyRateBoosterModifier {
|
||||
return new ShinyRateBoosterModifier(this.type);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -376,13 +505,17 @@ export class ShinyRateBoosterModifier extends Modifier {
|
|||
}
|
||||
}
|
||||
|
||||
export class ExtraModifierModifier extends Modifier {
|
||||
export class ExtraModifierModifier extends PersistentModifier {
|
||||
constructor(type: ModifierType) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
clone(): ExtraModifierModifier {
|
||||
return new ExtraModifierModifier(this.type);
|
||||
}
|
||||
|
||||
apply(args: any[]): boolean {
|
||||
(args[0] as Utils.IntegerHolder).value += this.stackCount;
|
||||
(args[0] as Utils.IntegerHolder).value += this.getStackCount();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -436,24 +569,26 @@ export abstract class PokemonModifierType extends ModifierType {
|
|||
}
|
||||
|
||||
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) {
|
||||
super(name, `Restore ${restorePercent} HP or ${restorePercent}% HP for one POKéMON, whichever is higher`,
|
||||
newModifierFunc || ((_type, args) => new PokemonHpRestoreModifier(this, (args[0] as PlayerPokemon).id, this.restorePercent, false)),
|
||||
constructor(name: string, restorePoints: integer, percent?: boolean, newModifierFunc?: Function, selectFilter?: Function, iconImage?: string) {
|
||||
super(name, `Restore ${restorePoints}${percent ? '%' : ''} HP for one POKéMON`,
|
||||
newModifierFunc || ((_type, args) => new PokemonHpRestoreModifier(this, (args[0] as PlayerPokemon).id, this.restorePoints, this.percent, false)),
|
||||
selectFilter || ((pokemon: PlayerPokemon) => {
|
||||
if (!pokemon.hp || pokemon.hp >= pokemon.getMaxHp())
|
||||
return PartyUiHandler.NoEffectMessage;
|
||||
return null;
|
||||
}), iconImage);
|
||||
|
||||
this.restorePercent = restorePercent;
|
||||
this.restorePoints = restorePoints;
|
||||
this.percent = !!percent;
|
||||
}
|
||||
}
|
||||
|
||||
export class PokemonReviveModifierType extends PokemonHpRestoreModifierType {
|
||||
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) => {
|
||||
if (pokemon.hp)
|
||||
return PartyUiHandler.NoEffectMessage;
|
||||
|
@ -583,7 +718,7 @@ const modifierPool = {
|
|||
const faintedPartyMemberCount = party.filter(p => !p.hp).length;
|
||||
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;
|
||||
return thresholdPartyMemberCount;
|
||||
}),
|
||||
|
@ -610,6 +745,9 @@ const modifierPool = {
|
|||
new WeightedModifierType(new AllPokemonFullReviveModifierType('SACRED ASH'), (party: PlayerPokemon[]) => {
|
||||
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 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; }),
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import BattleScene from './battle-scene';
|
||||
import { GrowthRate } from './exp';
|
||||
import { pokemonEvolutions } from './pokemon-evolutions';
|
||||
import { Species } from './species';
|
||||
|
@ -160,7 +161,6 @@ export default class PokemonSpecies {
|
|||
const subPrevolutionLevels = getPokemonSpecies(speciesId).getPrevolutionLevels();
|
||||
for (let spl of subPrevolutionLevels)
|
||||
prevolutionLevels.push(spl);
|
||||
console.log(Species[speciesId])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -168,6 +168,72 @@ export default class PokemonSpecies {
|
|||
|
||||
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 {
|
||||
|
@ -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.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.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 ],
|
||||
|
|
|
@ -220,12 +220,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
return `pkmn__${this.getBattleSpriteId()}`;
|
||||
}
|
||||
|
||||
getIconAtlasKey(): string {
|
||||
return `pokemon_icons_${this.species.generation}`;
|
||||
}
|
||||
|
||||
getIconId(): string {
|
||||
return `${Utils.padInt(this.species.speciesId, 3)}`;
|
||||
// TODO: Add form special cases
|
||||
return this.species.getIconId();
|
||||
}
|
||||
|
||||
getIconKey(): string {
|
||||
|
@ -355,8 +352,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
}
|
||||
}
|
||||
|
||||
updateInfo(callback?: Function) {
|
||||
this.battleInfo.updateInfo(this, callback);
|
||||
updateInfo(): Promise<void> {
|
||||
return this.battleInfo.updateInfo(this);
|
||||
}
|
||||
|
||||
addExp(exp: integer) {
|
||||
|
@ -434,7 +431,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
callback: () => {
|
||||
this.getSprite().setVisible(flashTimer.repeatCount % 2 === 0);
|
||||
if (!flashTimer.repeatCount) {
|
||||
this.battleInfo.updateInfo(this, () => {
|
||||
this.battleInfo.updateInfo(this).then(() => {
|
||||
if (callback)
|
||||
callback();
|
||||
});
|
||||
|
@ -442,7 +439,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
}
|
||||
});
|
||||
} else {
|
||||
this.battleInfo.updateInfo(this, () => {
|
||||
this.battleInfo.updateInfo(this).then(() => {
|
||||
if (callback)
|
||||
callback();
|
||||
});
|
||||
|
@ -579,7 +576,7 @@ export class PlayerPokemon extends Pokemon {
|
|||
constructor(scene: BattleScene, species: PokemonSpecies, level: integer, dataSource?: Pokemon) {
|
||||
super(scene, 106, 148, species, level, dataSource);
|
||||
|
||||
this.generateIconAnim();
|
||||
this.species.generateIconAnim(scene);
|
||||
this.generateCompatibleTms();
|
||||
}
|
||||
|
||||
|
@ -587,16 +584,6 @@ export class PlayerPokemon extends Pokemon {
|
|||
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 {
|
||||
this.compatibleTms = [];
|
||||
|
||||
|
|
|
@ -33,7 +33,15 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
|
|||
}
|
||||
|
||||
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;
|
||||
|
||||
super.show(args);
|
||||
|
@ -92,6 +100,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
|
|||
success = true;
|
||||
if (this.onActionInput) {
|
||||
const originalOnActionInput = this.onActionInput;
|
||||
this.awaitingActionInput = false;
|
||||
this.onActionInput = null;
|
||||
originalOnActionInput(this.cursor);
|
||||
}
|
||||
|
@ -99,6 +108,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
|
|||
success = true;
|
||||
if (this.onActionInput) {
|
||||
const originalOnActionInput = this.onActionInput;
|
||||
this.awaitingActionInput = false;
|
||||
this.onActionInput = null;
|
||||
originalOnActionInput(-1);
|
||||
}
|
||||
|
|
|
@ -158,6 +158,8 @@ export default class PartyUiHandler extends MessageUiHandler {
|
|||
selectCallback(this.cursor);
|
||||
} else if (this.cursor)
|
||||
(this.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.POKEMON, this.cursor);
|
||||
if (this.partyUiMode !== PartyUiMode.MODIFIER)
|
||||
ui.playSelect();
|
||||
return;
|
||||
} else {
|
||||
this.clearOptions();
|
||||
|
@ -396,9 +398,9 @@ class PartySlot extends Phaser.GameObjects.Container {
|
|||
|
||||
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)
|
||||
pokemonIcon.play(this.pokemon.getIconKey());
|
||||
pokemonIcon.play(this.pokemon.species.getIconKey());
|
||||
this.slotPokemonIcon = 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 BallUiHandler from './ball-ui-handler';
|
||||
import SummaryUiHandler from './summary-ui-handler';
|
||||
import StarterSelectUiHandler from './starter-select-ui-handler';
|
||||
|
||||
export enum Mode {
|
||||
MESSAGE = 0,
|
||||
|
@ -18,12 +19,14 @@ export enum Mode {
|
|||
CONFIRM,
|
||||
MODIFIER_SELECT,
|
||||
PARTY,
|
||||
SUMMARY
|
||||
SUMMARY,
|
||||
STARTER_SELECT,
|
||||
};
|
||||
|
||||
const transitionModes = [
|
||||
Mode.PARTY,
|
||||
Mode.SUMMARY
|
||||
Mode.SUMMARY,
|
||||
Mode.STARTER_SELECT,
|
||||
];
|
||||
|
||||
export default class UI extends Phaser.GameObjects.Container {
|
||||
|
@ -45,7 +48,8 @@ export default class UI extends Phaser.GameObjects.Container {
|
|||
new ConfirmUiHandler(scene),
|
||||
new ModifierSelectUiHandler(scene),
|
||||
new PartyUiHandler(scene),
|
||||
new SummaryUiHandler(scene)
|
||||
new SummaryUiHandler(scene),
|
||||
new StarterSelectUiHandler(scene)
|
||||
];
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue