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) {
super(scene);
this.doReturn = doReturn;
this.isModal = isModal;
this.doReturn = doReturn;
}
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)
this.scene.unshiftPhase(new SwitchSummonPhase(this.scene, slotIndex, this.doReturn));
this.scene.ui.setMode(Mode.MESSAGE).then(() => super.end());
@ -777,8 +777,9 @@ export class LearnMovePhase extends PartyMemberPokemonPhase {
const pokemon = this.getPokemon();
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) {
this.end();
@ -794,53 +795,56 @@ export class LearnMovePhase extends PartyMemberPokemonPhase {
initAnim(this.moveId).then(() => {
loadMoveAnimAssets(this.scene, [ this.moveId ], true)
.then(() => {
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.setMode(Mode.MESSAGE).then(() => {
this.scene.sound.play('level_up_fanfare');
this.scene.ui.showText(`${pokemon.name} learned\n${Utils.toPokemonUpperCase(move.name)}!`, null, () => this.end(), null, true);
});
});
});
} else {
this.scene.ui.setMode(Mode.MESSAGE);
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(`Should a move be deleted and\nreplaced with ${move.name}?`, null, () => {
const noHandler = () => {
this.scene.ui.setMode(Mode.MESSAGE).then(() => {
this.scene.ui.showText(`Stop trying to teach\n${move.name}?`, null, () => {
this.scene.ui.setMode(Mode.CONFIRM, () => {
this.scene.ui.setMode(Mode.MESSAGE);
this.scene.ui.showText(`${pokemon.name} did not learn the\nmove ${move.name}.`, null, () => this.end(), null, true);
}, () => {
this.scene.unshiftPhase(new LearnMovePhase(this.scene, this.partyMemberIndex, this.moveId));
this.end();
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(`However, ${pokemon.name} already\nknows four moves.`, null, () => {
this.scene.ui.showText(`Should a move be deleted and\nreplaced with ${move.name}?`, null, () => {
const noHandler = () => {
this.scene.ui.setMode(Mode.MESSAGE).then(() => {
this.scene.ui.showText(`Stop trying to teach\n${move.name}?`, null, () => {
this.scene.ui.setMode(Mode.CONFIRM, () => {
this.scene.ui.setMode(Mode.MESSAGE);
this.scene.ui.showText(`${pokemon.name} did not learn the\nmove ${move.name}.`, null, () => this.end(), null, true);
}, () => {
this.scene.unshiftPhase(new LearnMovePhase(this.scene, this.partyMemberIndex, this.moveId));
this.end();
});
});
});
});
};
this.scene.ui.setMode(Mode.CONFIRM, () => {
this.scene.ui.setMode(Mode.MESSAGE);
this.scene.ui.showText('Which move should be forgotten?', null, () => {
this.scene.ui.setMode(Mode.SUMMARY, this.getPokemon(), SummaryUiMode.LEARN_MOVE, move, (moveIndex: integer) => {
if (moveIndex === 4) {
noHandler();
return;
}
this.scene.ui.setMode(Mode.MESSAGE).then(() => {
this.scene.ui.showText('1, 2, and… … … Poof!', null, () => {
this.scene.ui.showText(`${pokemon.name} forgot how to\nuse ${pokemon.moveset[moveIndex].getName()}.`, null, () => {
this.scene.ui.showText('And…', null, () => {
pokemon.moveset[moveIndex] = null;
this.scene.unshiftPhase(new LearnMovePhase(this.scene, this.partyMemberIndex, this.moveId));
this.end();
};
this.scene.ui.setMode(Mode.CONFIRM, () => {
this.scene.ui.setMode(Mode.MESSAGE);
this.scene.ui.showText('Which move should be forgotten?', null, () => {
this.scene.ui.setMode(Mode.SUMMARY, this.getPokemon(), SummaryUiMode.LEARN_MOVE, move, (moveIndex: integer) => {
if (moveIndex === 4) {
noHandler();
return;
}
this.scene.ui.setMode(Mode.MESSAGE).then(() => {
this.scene.ui.showText('1, 2, and… … … Poof!', null, () => {
this.scene.ui.showText(`${pokemon.name} forgot how to\nuse ${pokemon.moveset[moveIndex].getName()}.`, null, () => {
this.scene.ui.showText('And…', null, () => {
pokemon.moveset[moveIndex] = null;
this.scene.unshiftPhase(new LearnMovePhase(this.scene, this.partyMemberIndex, this.moveId));
this.end();
}, null, true);
}, null, true);
}, null, true);
}, null, true);
});
});
});
}, null, true);
}, noHandler);
});
}, null, true);
}, noHandler);
});
}, null, true);
}, null, true);
}, null, true);
});
}
}
}
@ -1006,10 +1010,11 @@ export class SelectModifierPhase extends BattlePhase {
start() {
super.start();
regenerateModifierPoolThresholds(this.scene.getParty());
const party = this.scene.getParty();
regenerateModifierPoolThresholds(party);
const modifierCount = new Utils.IntegerHolder(3);
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) => {
if (cursor < 0) {
@ -1024,7 +1029,7 @@ export class SelectModifierPhase extends BattlePhase {
this.scene.ui.setModeWithoutClear(Mode.PARTY, PartyUiMode.MODIFIER, (slotIndex: integer) => {
if (slotIndex < 6) {
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.setMode(Mode.MESSAGE);
} else

View File

@ -17,7 +17,6 @@ const expLevels = [
];
export function getLevelTotalExp(level: integer, growthRate: integer) {
console.log(level, growthRate)
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 { getLevelTotalExp } from "./exp";
import { allMoves, Moves } from "./move";
import { getPokeballName, PokeballType } from "./pokeball";
import Pokemon, { PlayerPokemon } from "./pokemon";
import { Stat, getStatName } from "./pokemon-stat";
import { addTextObject, TextStyle } from "./text";
import { tmSpecies } from "./tms";
import { Type } from "./type";
import PartyUiHandler from "./ui/party-ui-handler";
import * as Utils from "./utils";
@ -141,6 +144,7 @@ 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);
}
@ -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 {
private boostMultiplier: integer;
@ -387,7 +406,7 @@ export class ModifierType {
constructor(name: string, description: string, newModifierFunc: Function, iconImage?: string) {
this.name = name;
this.description = description;
this.iconImage = iconImage || name.replace(/[ \-]/g, '_').toLowerCase();
this.iconImage = iconImage || name?.replace(/[ \-]/g, '_')?.toLowerCase();
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 {
public modifierType: ModifierType;
public weight: integer | Function;
@ -515,30 +564,35 @@ class WeightedModifierType {
const modifierPool = {
[ModifierTier.COMMON]: [
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;
console.log(thresholdPartyMemberCount, party.map(p => p.getHpRatio()));
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;
return Math.ceil(thresholdPartyMemberCount / 3);
}),
})
].map(m => { m.setTier(ModifierTier.COMMON); return m; }),
[ModifierTier.GREAT]: [
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;
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;
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;
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 PokemonBaseStatBoosterModifierType('HP-UP', Stat.HP),
new PokemonBaseStatBoosterModifierType('PROTEIN', Stat.ATK),
@ -549,11 +603,11 @@ const modifierPool = {
].map(m => { m.setTier(ModifierTier.GREAT); return m; }),
[ModifierTier.ULTRA]: [
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;
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;
}),
new ExpBoosterModifierType('LUCKY EGG', 25),
@ -572,7 +626,7 @@ const modifierPool = {
let modifierPoolThresholds = {};
let ignoredPoolIndexes = {};
export function regenerateModifierPoolThresholds(party: Array<PlayerPokemon>) {
export function regenerateModifierPoolThresholds(party: PlayerPokemon[]) {
ignoredPoolIndexes = {};
modifierPoolThresholds = Object.fromEntries(new Map(Object.keys(modifierPool).map(t => {
ignoredPoolIndexes[t] = [];
@ -600,16 +654,16 @@ export function regenerateModifierPoolThresholds(party: Array<PlayerPokemon>) {
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)
return modifierPool[ModifierTier.LUXURY];
const ret = [];
for (let m = 0; m < count; m++)
ret.push(getNewModifierType());
ret.push(getNewModifierType(party));
return ret;
}
function getNewModifierType() {
function getNewModifierType(party: PlayerPokemon[]) {
const tierValue = Utils.randInt(256);
const tier = tierValue >= 52 ? ModifierTier.COMMON : tierValue >= 8 ? ModifierTier.GREAT : tierValue >= 1 ? ModifierTier.ULTRA : ModifierTier.MASTER;
const thresholds = Object.keys(modifierPoolThresholds[tier]);
@ -626,6 +680,8 @@ function getNewModifierType() {
console.log(index, ignoredPoolIndexes[tier].filter(i => i <= index).length, ignoredPoolIndexes[tier])
let modifierType: ModifierType | WeightedModifierType = modifierPool[tier][index];
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;
}

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[]) {
this.id = id;
this.name = name;
this.name = name.toUpperCase();
this.type = type;
this.category = category;
this.power = power;

View File

@ -12,8 +12,9 @@ import { Stat } from './pokemon-stat';
import { PokemonBaseStatModifier as PokemonBaseStatBoosterModifier, ShinyRateBoosterModifier } from './modifier';
import { PokeballType } from './pokeball';
import { Gender } from './gender';
import { Anim, initAnim, loadMoveAnimAssets, moveAnims } from './battle-anims';
import { initAnim, loadMoveAnimAssets } from './battle-anims';
import { StatusEffect } from './status-effect';
import { tmSpecies } from './tms';
export default abstract class Pokemon extends Phaser.GameObjects.Container {
public id: integer;
@ -254,7 +255,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
this.stats = [ 0, 0, 0, 0, 0, 0 ];
const baseStats = this.species.baseStats.slice(0);
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);
for (let s of stats) {
const isHp = s === Stat.HP;
@ -573,17 +574,20 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
}
export class PlayerPokemon extends Pokemon {
public compatibleTms: Moves[];
constructor(scene: BattleScene, species: PokemonSpecies, level: integer, dataSource?: Pokemon) {
super(scene, 106, 148, species, level, dataSource);
this.generateIconAnim();
this.generateCompatibleTms();
}
isPlayer() {
isPlayer(): boolean {
return true;
}
generateIconAnim() {
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(),
@ -592,6 +596,26 @@ export class PlayerPokemon extends Pokemon {
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 {

18648
src/tms.ts

File diff suppressed because it is too large Load Diff