Add TM modifiers

pull/1/head
Flashfyre 2023-04-08 00:21:44 -04:00
parent cf423c2d8c
commit a5186d378d
9 changed files with 9873 additions and 9738 deletions

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 B

View File

@ -684,14 +684,14 @@ export class SwitchPhase extends BattlePhase {
constructor(scene: BattleScene, isModal: boolean, doReturn: boolean) { constructor(scene: BattleScene, isModal: boolean, doReturn: boolean) {
super(scene); super(scene);
this.doReturn = doReturn;
this.isModal = isModal; this.isModal = isModal;
this.doReturn = doReturn;
} }
start() { start() {
super.start(); super.start();
this.scene.ui.setMode(Mode.PARTY, this.isModal ? PartyUiMode.SWITCH : PartyUiMode.FAINT_SWITCH, (slotIndex: integer) => { this.scene.ui.setMode(Mode.PARTY, this.isModal ? PartyUiMode.FAINT_SWITCH : PartyUiMode.SWITCH, (slotIndex: integer) => {
if (slotIndex && slotIndex < 6) if (slotIndex && slotIndex < 6)
this.scene.unshiftPhase(new SwitchSummonPhase(this.scene, slotIndex, this.doReturn)); this.scene.unshiftPhase(new SwitchSummonPhase(this.scene, slotIndex, this.doReturn));
this.scene.ui.setMode(Mode.MESSAGE).then(() => super.end()); this.scene.ui.setMode(Mode.MESSAGE).then(() => super.end());
@ -777,8 +777,9 @@ export class LearnMovePhase extends PartyMemberPokemonPhase {
const pokemon = this.getPokemon(); const pokemon = this.getPokemon();
const move = allMoves[this.moveId - 1]; const move = allMoves[this.moveId - 1];
console.log(move, this.moveId);
const existingMoveIndex = pokemon.moveset.findIndex(m => m.moveId === move.id); const existingMoveIndex = pokemon.moveset.findIndex(m => m?.moveId === move.id);
if (existingMoveIndex > -1) { if (existingMoveIndex > -1) {
this.end(); this.end();
@ -794,12 +795,14 @@ export class LearnMovePhase extends PartyMemberPokemonPhase {
initAnim(this.moveId).then(() => { initAnim(this.moveId).then(() => {
loadMoveAnimAssets(this.scene, [ this.moveId ], true) loadMoveAnimAssets(this.scene, [ this.moveId ], true)
.then(() => { .then(() => {
this.scene.ui.setMode(Mode.MESSAGE).then(() => {
this.scene.sound.play('level_up_fanfare'); this.scene.sound.play('level_up_fanfare');
this.scene.ui.showText(`${pokemon.name} learned\n${Utils.toPokemonUpperCase(move.name)}!`, null, () => this.end(), null, true); this.scene.ui.showText(`${pokemon.name} learned\n${Utils.toPokemonUpperCase(move.name)}!`, null, () => this.end(), null, true);
}); });
}); });
});
} else { } else {
this.scene.ui.setMode(Mode.MESSAGE); this.scene.ui.setMode(Mode.MESSAGE).then(() => {
this.scene.ui.showText(`${pokemon.name} wants to learn the\nmove ${move.name}.`, null, () => { this.scene.ui.showText(`${pokemon.name} wants to learn the\nmove ${move.name}.`, null, () => {
this.scene.ui.showText(`However, ${pokemon.name} already\nknows four moves.`, null, () => { this.scene.ui.showText(`However, ${pokemon.name} already\nknows four moves.`, null, () => {
this.scene.ui.showText(`Should a move be deleted and\nreplaced with ${move.name}?`, null, () => { this.scene.ui.showText(`Should a move be deleted and\nreplaced with ${move.name}?`, null, () => {
@ -841,6 +844,7 @@ export class LearnMovePhase extends PartyMemberPokemonPhase {
}); });
}, null, true); }, null, true);
}, null, true); }, null, true);
});
} }
} }
} }
@ -1006,10 +1010,11 @@ export class SelectModifierPhase extends BattlePhase {
start() { start() {
super.start(); super.start();
regenerateModifierPoolThresholds(this.scene.getParty()); const party = this.scene.getParty();
regenerateModifierPoolThresholds(party);
const modifierCount = new Utils.IntegerHolder(3); const modifierCount = new Utils.IntegerHolder(3);
this.scene.applyModifiers(ExtraModifierModifier, modifierCount); this.scene.applyModifiers(ExtraModifierModifier, modifierCount);
const types: Array<ModifierType> = getModifierTypesForWave(this.scene.currentBattle.waveIndex - 1, modifierCount.value); const types: Array<ModifierType> = getModifierTypesForWave(this.scene.currentBattle.waveIndex - 1, modifierCount.value, party);
this.scene.ui.setMode(Mode.MODIFIER_SELECT, types, (cursor: integer) => { this.scene.ui.setMode(Mode.MODIFIER_SELECT, types, (cursor: integer) => {
if (cursor < 0) { if (cursor < 0) {
@ -1024,7 +1029,7 @@ export class SelectModifierPhase extends BattlePhase {
this.scene.ui.setModeWithoutClear(Mode.PARTY, PartyUiMode.MODIFIER, (slotIndex: integer) => { this.scene.ui.setModeWithoutClear(Mode.PARTY, PartyUiMode.MODIFIER, (slotIndex: integer) => {
if (slotIndex < 6) { if (slotIndex < 6) {
this.scene.ui.setMode(Mode.MODIFIER_SELECT); this.scene.ui.setMode(Mode.MODIFIER_SELECT);
this.scene.addModifier(types[cursor].newModifier(this.scene.getParty()[slotIndex])).then(() => super.end()); this.scene.addModifier(types[cursor].newModifier(party[slotIndex])).then(() => super.end());
this.scene.ui.clearText(); this.scene.ui.clearText();
this.scene.ui.setMode(Mode.MESSAGE); this.scene.ui.setMode(Mode.MESSAGE);
} else } else

View File

@ -17,7 +17,6 @@ const expLevels = [
]; ];
export function getLevelTotalExp(level: integer, growthRate: integer) { export function getLevelTotalExp(level: integer, growthRate: integer) {
console.log(level, growthRate)
return expLevels[growthRate][level - 1]; return expLevels[growthRate][level - 1];
}; };

View File

@ -1,10 +1,13 @@
import { LevelUpPhase } from "./battle-phase"; import { LearnMovePhase, LevelUpPhase } from "./battle-phase";
import BattleScene from "./battle-scene"; import BattleScene from "./battle-scene";
import { getLevelTotalExp } from "./exp"; import { getLevelTotalExp } from "./exp";
import { allMoves, Moves } from "./move";
import { getPokeballName, PokeballType } from "./pokeball"; import { getPokeballName, PokeballType } from "./pokeball";
import Pokemon, { PlayerPokemon } from "./pokemon"; import Pokemon, { PlayerPokemon } from "./pokemon";
import { Stat, getStatName } from "./pokemon-stat"; import { Stat, getStatName } from "./pokemon-stat";
import { addTextObject, TextStyle } from "./text"; import { addTextObject, TextStyle } from "./text";
import { tmSpecies } from "./tms";
import { Type } from "./type";
import PartyUiHandler from "./ui/party-ui-handler"; import PartyUiHandler from "./ui/party-ui-handler";
import * as Utils from "./utils"; import * as Utils from "./utils";
@ -141,6 +144,7 @@ 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);
} }
@ -283,6 +287,21 @@ export class PokemonLevelIncrementModifier extends ConsumablePokemonModifier {
} }
} }
export class TmModifier extends ConsumablePokemonModifier {
constructor(type: TmModifierType, pokemonId: integer) {
super(type, pokemonId);
}
apply(args: any[]): boolean {
const pokemon = args[0] as PlayerPokemon;
const scene = pokemon.scene as BattleScene;
scene.unshiftPhase(new LearnMovePhase(scene, scene.getParty().indexOf(pokemon), (this.type as TmModifierType).moveId));
return true;
}
}
export class ExpBoosterModifier extends Modifier { export class ExpBoosterModifier extends Modifier {
private boostMultiplier: integer; private boostMultiplier: integer;
@ -387,7 +406,7 @@ export class ModifierType {
constructor(name: string, description: string, newModifierFunc: Function, iconImage?: string) { constructor(name: string, description: string, newModifierFunc: Function, iconImage?: string) {
this.name = name; this.name = name;
this.description = description; this.description = description;
this.iconImage = iconImage || name.replace(/[ \-]/g, '_').toLowerCase(); this.iconImage = iconImage || name?.replace(/[ \-]/g, '_')?.toLowerCase();
this.newModifierFunc = newModifierFunc; this.newModifierFunc = newModifierFunc;
} }
@ -498,6 +517,36 @@ export class ExpBoosterModifierType extends ModifierType {
} }
} }
export class TmModifierType extends PokemonModifierType {
public moveId: Moves;
constructor(moveId: Moves) {
super(`TM${Utils.padInt(Object.keys(tmSpecies).indexOf(moveId.toString()) + 1, 3)} - ${allMoves[moveId - 1].name}`, `Teach ${allMoves[moveId - 1].name} to a POKéMON`, (_type, args) => new TmModifier(this, (args[0] as PlayerPokemon).id),
(pokemon: PlayerPokemon) => {
if (pokemon.compatibleTms.indexOf(moveId) === -1 || pokemon.moveset.filter(m => m?.moveId === moveId).length)
return PartyUiHandler.NoEffectMessage;
return null;
}, `tm_${Type[allMoves[moveId - 1].type].toLowerCase()}`);
this.moveId = moveId;
}
}
class ModifierTypeGenerator extends ModifierType {
private genTypeFunc: Function;
constructor(genTypeFunc: Function) {
super(null, null, null, null);
this.genTypeFunc = genTypeFunc;
}
generateType(party: PlayerPokemon[]) {
const ret = this.genTypeFunc(party);
ret.setTier(this.tier);
return ret;
}
}
class WeightedModifierType { class WeightedModifierType {
public modifierType: ModifierType; public modifierType: ModifierType;
public weight: integer | Function; public weight: integer | Function;
@ -515,30 +564,35 @@ class WeightedModifierType {
const modifierPool = { const modifierPool = {
[ModifierTier.COMMON]: [ [ModifierTier.COMMON]: [
new WeightedModifierType(new AddPokeballModifierType(PokeballType.POKEBALL, 5, 'pb'), 2), new WeightedModifierType(new AddPokeballModifierType(PokeballType.POKEBALL, 5, 'pb'), 2),
new WeightedModifierType(new PokemonHpRestoreModifierType('POTION', 20), (party: Array<PlayerPokemon>) => { new WeightedModifierType(new PokemonHpRestoreModifierType('POTION', 20), (party: PlayerPokemon[]) => {
const thresholdPartyMemberCount = party.filter(p => p.getHpRatio() <= 0.9).length; const thresholdPartyMemberCount = party.filter(p => p.getHpRatio() <= 0.9).length;
console.log(thresholdPartyMemberCount, party.map(p => p.getHpRatio()));
return thresholdPartyMemberCount; return thresholdPartyMemberCount;
}), }),
new WeightedModifierType(new PokemonHpRestoreModifierType('SUPER POTION', 50), (party: Array<PlayerPokemon>) => { new WeightedModifierType(new PokemonHpRestoreModifierType('SUPER POTION', 50), (party: PlayerPokemon[]) => {
const thresholdPartyMemberCount = party.filter(p => p.getHpRatio() <= 0.75).length; const thresholdPartyMemberCount = party.filter(p => p.getHpRatio() <= 0.75).length;
return Math.ceil(thresholdPartyMemberCount / 3); return Math.ceil(thresholdPartyMemberCount / 3);
}), })
].map(m => { m.setTier(ModifierTier.COMMON); return m; }), ].map(m => { m.setTier(ModifierTier.COMMON); return m; }),
[ModifierTier.GREAT]: [ [ModifierTier.GREAT]: [
new WeightedModifierType(new AddPokeballModifierType(PokeballType.GREAT_BALL, 5, 'gb'), 3), new WeightedModifierType(new AddPokeballModifierType(PokeballType.GREAT_BALL, 5, 'gb'), 3),
new WeightedModifierType(new PokemonReviveModifierType('REVIVE', 50), (party: Array<PlayerPokemon>) => { new WeightedModifierType(new PokemonReviveModifierType('REVIVE', 50), (party: PlayerPokemon[]) => {
const faintedPartyMemberCount = party.filter(p => !p.hp).length; const faintedPartyMemberCount = party.filter(p => !p.hp).length;
return faintedPartyMemberCount * 3; return faintedPartyMemberCount * 3;
}), }),
new WeightedModifierType(new PokemonReviveModifierType('MAX REVIVE', 100), (party: Array<PlayerPokemon>) => { new WeightedModifierType(new PokemonReviveModifierType('MAX REVIVE', 100), (party: PlayerPokemon[]) => {
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: Array<PlayerPokemon>) => { new WeightedModifierType(new PokemonHpRestoreModifierType('HYPER POTION', 80), (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;
}), }),
new WeightedModifierType(new ModifierTypeGenerator((party: PlayerPokemon[]) => {
const partyMemberCompatibleTms = party.map(p => p.compatibleTms);
const uniqueCompatibleTms = partyMemberCompatibleTms.flat().filter((tm, i, array) => array.indexOf(tm) === i);
const randTmIndex = Utils.randInt(uniqueCompatibleTms.length);
return new TmModifierType(uniqueCompatibleTms[randTmIndex]);
}), 2),
new PokemonLevelIncrementModifierType('RARE CANDY'), new PokemonLevelIncrementModifierType('RARE CANDY'),
new PokemonBaseStatBoosterModifierType('HP-UP', Stat.HP), new PokemonBaseStatBoosterModifierType('HP-UP', Stat.HP),
new PokemonBaseStatBoosterModifierType('PROTEIN', Stat.ATK), new PokemonBaseStatBoosterModifierType('PROTEIN', Stat.ATK),
@ -549,11 +603,11 @@ const modifierPool = {
].map(m => { m.setTier(ModifierTier.GREAT); return m; }), ].map(m => { m.setTier(ModifierTier.GREAT); return m; }),
[ModifierTier.ULTRA]: [ [ModifierTier.ULTRA]: [
new AddPokeballModifierType(PokeballType.ULTRA_BALL, 5, 'ub'), new AddPokeballModifierType(PokeballType.ULTRA_BALL, 5, 'ub'),
new WeightedModifierType(new AllPokemonFullHpRestoreModifierType('MAX POTION'), (party: Array<PlayerPokemon>) => { new WeightedModifierType(new AllPokemonFullHpRestoreModifierType('MAX POTION'), (party: PlayerPokemon[]) => {
const thresholdPartyMemberCount = party.filter(p => p.getHpRatio() <= 0.5).length; const thresholdPartyMemberCount = party.filter(p => p.getHpRatio() <= 0.5).length;
return Math.ceil(thresholdPartyMemberCount / 3); return Math.ceil(thresholdPartyMemberCount / 3);
}), }),
new WeightedModifierType(new AllPokemonFullReviveModifierType('SACRED ASH'), (party: Array<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 ExpBoosterModifierType('LUCKY EGG', 25), new ExpBoosterModifierType('LUCKY EGG', 25),
@ -572,7 +626,7 @@ const modifierPool = {
let modifierPoolThresholds = {}; let modifierPoolThresholds = {};
let ignoredPoolIndexes = {}; let ignoredPoolIndexes = {};
export function regenerateModifierPoolThresholds(party: Array<PlayerPokemon>) { export function regenerateModifierPoolThresholds(party: PlayerPokemon[]) {
ignoredPoolIndexes = {}; ignoredPoolIndexes = {};
modifierPoolThresholds = Object.fromEntries(new Map(Object.keys(modifierPool).map(t => { modifierPoolThresholds = Object.fromEntries(new Map(Object.keys(modifierPool).map(t => {
ignoredPoolIndexes[t] = []; ignoredPoolIndexes[t] = [];
@ -600,16 +654,16 @@ export function regenerateModifierPoolThresholds(party: Array<PlayerPokemon>) {
console.log(modifierPoolThresholds) console.log(modifierPoolThresholds)
} }
export function getModifierTypesForWave(waveIndex: integer, count: integer): Array<ModifierType> { export function getModifierTypesForWave(waveIndex: integer, count: integer, party: PlayerPokemon[]): Array<ModifierType> {
if (waveIndex % 10 === 0) if (waveIndex % 10 === 0)
return modifierPool[ModifierTier.LUXURY]; return modifierPool[ModifierTier.LUXURY];
const ret = []; const ret = [];
for (let m = 0; m < count; m++) for (let m = 0; m < count; m++)
ret.push(getNewModifierType()); ret.push(getNewModifierType(party));
return ret; return ret;
} }
function getNewModifierType() { function getNewModifierType(party: PlayerPokemon[]) {
const tierValue = Utils.randInt(256); const tierValue = Utils.randInt(256);
const tier = tierValue >= 52 ? ModifierTier.COMMON : tierValue >= 8 ? ModifierTier.GREAT : tierValue >= 1 ? ModifierTier.ULTRA : ModifierTier.MASTER; const tier = tierValue >= 52 ? ModifierTier.COMMON : tierValue >= 8 ? ModifierTier.GREAT : tierValue >= 1 ? ModifierTier.ULTRA : ModifierTier.MASTER;
const thresholds = Object.keys(modifierPoolThresholds[tier]); const thresholds = Object.keys(modifierPoolThresholds[tier]);
@ -626,6 +680,8 @@ function getNewModifierType() {
console.log(index, ignoredPoolIndexes[tier].filter(i => i <= index).length, ignoredPoolIndexes[tier]) console.log(index, ignoredPoolIndexes[tier].filter(i => i <= index).length, ignoredPoolIndexes[tier])
let modifierType: ModifierType | WeightedModifierType = modifierPool[tier][index]; let modifierType: ModifierType | WeightedModifierType = modifierPool[tier][index];
if (modifierType instanceof WeightedModifierType) if (modifierType instanceof WeightedModifierType)
return (modifierType as WeightedModifierType).modifierType; modifierType = (modifierType as WeightedModifierType).modifierType;
if (modifierType instanceof ModifierTypeGenerator)
modifierType = (modifierType as ModifierTypeGenerator).generateType(party);
return modifierType; return modifierType;
} }

View File

@ -28,7 +28,7 @@ export default class Move {
constructor(id: Moves, name: string, type: Type, category: MoveCategory, power: integer, accuracy: integer, pp: integer, tm: integer, effect: string, chance: integer, generation: integer, ...attrs: MoveAttr[]) { constructor(id: Moves, name: string, type: Type, category: MoveCategory, power: integer, accuracy: integer, pp: integer, tm: integer, effect: string, chance: integer, generation: integer, ...attrs: MoveAttr[]) {
this.id = id; this.id = id;
this.name = name; this.name = name.toUpperCase();
this.type = type; this.type = type;
this.category = category; this.category = category;
this.power = power; this.power = power;

View File

@ -12,8 +12,9 @@ import { Stat } from './pokemon-stat';
import { PokemonBaseStatModifier as PokemonBaseStatBoosterModifier, ShinyRateBoosterModifier } from './modifier'; import { PokemonBaseStatModifier as PokemonBaseStatBoosterModifier, ShinyRateBoosterModifier } from './modifier';
import { PokeballType } from './pokeball'; import { PokeballType } from './pokeball';
import { Gender } from './gender'; import { Gender } from './gender';
import { Anim, initAnim, loadMoveAnimAssets, moveAnims } from './battle-anims'; import { initAnim, loadMoveAnimAssets } from './battle-anims';
import { StatusEffect } from './status-effect'; import { StatusEffect } from './status-effect';
import { tmSpecies } from './tms';
export default abstract class Pokemon extends Phaser.GameObjects.Container { export default abstract class Pokemon extends Phaser.GameObjects.Container {
public id: integer; public id: integer;
@ -254,7 +255,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
this.stats = [ 0, 0, 0, 0, 0, 0 ]; this.stats = [ 0, 0, 0, 0, 0, 0 ];
const baseStats = this.species.baseStats.slice(0); const baseStats = this.species.baseStats.slice(0);
console.log(this.id); console.log(this.id);
(this.scene as BattleScene).applyModifiers(PokemonBaseStatBoosterModifier, this.id, baseStats); (this.scene as BattleScene).applyModifiers(PokemonBaseStatBoosterModifier, this, baseStats);
const stats = Utils.getEnumValues(Stat); const stats = Utils.getEnumValues(Stat);
for (let s of stats) { for (let s of stats) {
const isHp = s === Stat.HP; const isHp = s === Stat.HP;
@ -573,17 +574,20 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
export class PlayerPokemon extends Pokemon { export class PlayerPokemon extends Pokemon {
public compatibleTms: Moves[];
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.generateIconAnim();
this.generateCompatibleTms();
} }
isPlayer() { isPlayer(): boolean {
return true; return true;
} }
generateIconAnim() { generateIconAnim(): void {
const frameNames = this.scene.anims.generateFrameNames(this.getIconAtlasKey(), { prefix: `${this.getIconId()}_`, zeroPad: 2, suffix: '.png', start: 1, end: 34 }); const frameNames = this.scene.anims.generateFrameNames(this.getIconAtlasKey(), { prefix: `${this.getIconId()}_`, zeroPad: 2, suffix: '.png', start: 1, end: 34 });
this.scene.anims.create({ this.scene.anims.create({
key: this.getIconKey(), key: this.getIconKey(),
@ -592,6 +596,26 @@ export class PlayerPokemon extends Pokemon {
repeat: -1 repeat: -1
}); });
} }
generateCompatibleTms(): void {
this.compatibleTms = [];
const tms = Object.keys(tmSpecies);
for (let tm of tms) {
const moveId = parseInt(tm) as Moves;
for (let p of tmSpecies[tm]) {
if (Array.isArray(p)) {
if (p[0] === this.species.speciesId) {
this.compatibleTms.push(moveId);
break;
}
} else if (p === this.species.speciesId) {
this.compatibleTms.push(moveId);
break;
}
}
}
}
} }
export class EnemyPokemon extends Pokemon { export class EnemyPokemon extends Pokemon {

18644
src/tms.ts

File diff suppressed because it is too large Load Diff