Move modifier types to separate file
parent
7529ac938e
commit
638750f75b
|
@ -1,6 +1,6 @@
|
||||||
import { SelectModifierPhase } from "./battle-phases";
|
import { SelectModifierPhase } from "./battle-phases";
|
||||||
import BattleScene, { Button } from "./battle-scene";
|
import BattleScene, { Button } from "./battle-scene";
|
||||||
import { ModifierTier, ModifierType, PokemonBaseStatBoosterModifierType, PokemonHpRestoreModifierType, PokemonReviveModifierType } from "./modifier";
|
import { ModifierTier, ModifierType, PokemonBaseStatBoosterModifierType, PokemonHpRestoreModifierType, PokemonReviveModifierType } from "./modifier-type";
|
||||||
import Pokemon, { AiType, EnemyPokemon, PlayerPokemon, PokemonMove } from "./pokemon";
|
import Pokemon, { AiType, EnemyPokemon, PlayerPokemon, PokemonMove } from "./pokemon";
|
||||||
import { Species } from "./species";
|
import { Species } from "./species";
|
||||||
import { getTypeDamageMultiplier } from "./type";
|
import { getTypeDamageMultiplier } from "./type";
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { allMoves, applyMoveAttrs, MissEffectAttr, MoveCategory, MoveHitEffectAt
|
||||||
import { Mode } from './ui/ui';
|
import { Mode } from './ui/ui';
|
||||||
import { Command } from "./ui/command-ui-handler";
|
import { Command } from "./ui/command-ui-handler";
|
||||||
import { Stat } from "./pokemon-stat";
|
import { Stat } from "./pokemon-stat";
|
||||||
import { ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, getModifierTypesForWave, ModifierType, PokemonModifierType, PokemonMoveModifierType, regenerateModifierPoolThresholds } from "./modifier";
|
import { ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier } from "./modifier";
|
||||||
import PartyUiHandler, { PartyOption, PartyUiMode } from "./ui/party-ui-handler";
|
import PartyUiHandler, { PartyOption, PartyUiMode } from "./ui/party-ui-handler";
|
||||||
import { doPokeballBounceAnim, getPokeballAtlasKey, getPokeballCatchMultiplier, getPokeballTintColor, PokeballType } from "./pokeball";
|
import { doPokeballBounceAnim, getPokeballAtlasKey, getPokeballCatchMultiplier, getPokeballTintColor, PokeballType } from "./pokeball";
|
||||||
import { CommonAnim, CommonBattleAnim, MoveAnim, initMoveAnim, loadMoveAnimAssets } from "./battle-anims";
|
import { CommonAnim, CommonBattleAnim, MoveAnim, initMoveAnim, loadMoveAnimAssets } from "./battle-anims";
|
||||||
|
@ -16,6 +16,7 @@ import { EvolutionPhase } from "./evolution-phase";
|
||||||
import { BattlePhase } from "./battle-phase";
|
import { BattlePhase } from "./battle-phase";
|
||||||
import { BattleStat, getBattleStatLevelChangeDescription, getBattleStatName } from "./battle-stat";
|
import { BattleStat, getBattleStatLevelChangeDescription, getBattleStatName } from "./battle-stat";
|
||||||
import { Biome, biomeLinks } from "./biome";
|
import { Biome, biomeLinks } from "./biome";
|
||||||
|
import { ModifierType, PokemonModifierType, PokemonMoveModifierType, getModifierTypesForWave, regenerateModifierPoolThresholds } from "./modifier-type";
|
||||||
|
|
||||||
export class SelectStarterPhase extends BattlePhase {
|
export class SelectStarterPhase extends BattlePhase {
|
||||||
constructor(scene: BattleScene) {
|
constructor(scene: BattleScene) {
|
||||||
|
|
|
@ -0,0 +1,358 @@
|
||||||
|
import * as Modifiers from './modifier';
|
||||||
|
import { Moves, allMoves } from './move';
|
||||||
|
import { PokeballType, getPokeballName } from './pokeball';
|
||||||
|
import { PlayerPokemon, PokemonMove } from './pokemon';
|
||||||
|
import { Stat, getStatName } from './pokemon-stat';
|
||||||
|
import { tmSpecies } from './tms';
|
||||||
|
import { Type } from './type';
|
||||||
|
import PartyUiHandler, { PokemonMoveSelectFilter, PokemonSelectFilter } from './ui/party-ui-handler';
|
||||||
|
import * as Utils from './utils';
|
||||||
|
|
||||||
|
type Modifier = Modifiers.Modifier;
|
||||||
|
|
||||||
|
export enum ModifierTier {
|
||||||
|
COMMON,
|
||||||
|
GREAT,
|
||||||
|
ULTRA,
|
||||||
|
MASTER,
|
||||||
|
LUXURY
|
||||||
|
};
|
||||||
|
|
||||||
|
type NewModifierFunc = (type: ModifierType, args: any[]) => Modifier;
|
||||||
|
|
||||||
|
export class ModifierType {
|
||||||
|
public name: string;
|
||||||
|
public description: string;
|
||||||
|
public iconImage: string;
|
||||||
|
public tier: ModifierTier;
|
||||||
|
private newModifierFunc: NewModifierFunc;
|
||||||
|
|
||||||
|
constructor(name: string, description: string, newModifierFunc: NewModifierFunc, iconImage?: string) {
|
||||||
|
this.name = name;
|
||||||
|
this.description = description;
|
||||||
|
this.iconImage = iconImage || name?.replace(/[ \-]/g, '_')?.toLowerCase();
|
||||||
|
this.newModifierFunc = newModifierFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
setTier(tier: ModifierTier) {
|
||||||
|
this.tier = tier;
|
||||||
|
}
|
||||||
|
|
||||||
|
newModifier(...args: any[]) {
|
||||||
|
return this.newModifierFunc(this, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AddPokeballModifierType extends ModifierType {
|
||||||
|
constructor(pokeballType: PokeballType, count: integer, iconImage?: string) {
|
||||||
|
super(`${count}x ${getPokeballName(pokeballType)}`, `Receive ${getPokeballName(pokeballType)} x${count}`, (_type, _args) => new Modifiers.AddPokeballModifier(this, pokeballType, count), iconImage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export abstract class PokemonModifierType extends ModifierType {
|
||||||
|
public selectFilter: PokemonSelectFilter;
|
||||||
|
|
||||||
|
constructor(name: string, description: string, newModifierFunc: NewModifierFunc, selectFilter?: PokemonSelectFilter, iconImage?: string) {
|
||||||
|
super(name, description, newModifierFunc, iconImage);
|
||||||
|
|
||||||
|
this.selectFilter = selectFilter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PokemonHpRestoreModifierType extends PokemonModifierType {
|
||||||
|
protected restorePoints: integer;
|
||||||
|
protected percent: boolean;
|
||||||
|
|
||||||
|
constructor(name: string, restorePoints: integer, percent?: boolean, newModifierFunc?: NewModifierFunc, selectFilter?: PokemonSelectFilter, iconImage?: string) {
|
||||||
|
super(name, `Restore ${restorePoints}${percent ? '%' : ''} HP for one POKéMON`,
|
||||||
|
newModifierFunc || ((_type, args) => new Modifiers.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.restorePoints = restorePoints;
|
||||||
|
this.percent = !!percent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PokemonReviveModifierType extends PokemonHpRestoreModifierType {
|
||||||
|
constructor(name: string, restorePercent: integer, iconImage?: string) {
|
||||||
|
super(name, restorePercent, true, (_type, args) => new Modifiers.PokemonHpRestoreModifier(this, (args[0] as PlayerPokemon).id, this.restorePoints, true, true),
|
||||||
|
((pokemon: PlayerPokemon) => {
|
||||||
|
if (pokemon.hp)
|
||||||
|
return PartyUiHandler.NoEffectMessage;
|
||||||
|
return null;
|
||||||
|
}), iconImage);
|
||||||
|
|
||||||
|
this.description = `Revive one POKéMON and restore ${restorePercent}% HP`;
|
||||||
|
this.selectFilter = (pokemon: PlayerPokemon) => {
|
||||||
|
if (pokemon.hp)
|
||||||
|
return PartyUiHandler.NoEffectMessage;
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export abstract class PokemonMoveModifierType extends PokemonModifierType {
|
||||||
|
public moveSelectFilter: PokemonMoveSelectFilter;
|
||||||
|
|
||||||
|
constructor(name: string, description: string, newModifierFunc: NewModifierFunc, selectFilter?: PokemonSelectFilter, moveSelectFilter?: PokemonMoveSelectFilter, iconImage?: string) {
|
||||||
|
super(name, description, newModifierFunc, selectFilter, iconImage);
|
||||||
|
|
||||||
|
this.moveSelectFilter = moveSelectFilter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PokemonPpRestoreModifierType extends PokemonMoveModifierType {
|
||||||
|
protected restorePoints: integer;
|
||||||
|
|
||||||
|
constructor(name: string, restorePoints: integer, iconImage?: string) {
|
||||||
|
super(name, `Restore ${restorePoints > -1 ? restorePoints : 'all'} PP for one POKéMON move`, (_type, args) => new Modifiers.PokemonPpRestoreModifier(this, (args[0] as PlayerPokemon).id, (args[1] as integer), this.restorePoints),
|
||||||
|
(_pokemon: PlayerPokemon) => {
|
||||||
|
return null;
|
||||||
|
}, (pokemonMove: PokemonMove) => {
|
||||||
|
if (!pokemonMove.ppUsed)
|
||||||
|
return PartyUiHandler.NoEffectMessage;
|
||||||
|
return null;
|
||||||
|
}, iconImage);
|
||||||
|
|
||||||
|
this.restorePoints = this.restorePoints;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PokemonAllMovePpRestoreModifierType extends PokemonModifierType {
|
||||||
|
protected restorePoints: integer;
|
||||||
|
|
||||||
|
constructor(name: string, restorePoints: integer, iconImage?: string) {
|
||||||
|
super(name, `Restore ${restorePoints > -1 ? restorePoints : 'all'} PP for all of one POKéMON's moves`, (_type, args) => new Modifiers.PokemonAllMovePpRestoreModifier(this, (args[0] as PlayerPokemon).id, this.restorePoints),
|
||||||
|
(pokemon: PlayerPokemon) => {
|
||||||
|
if (!pokemon.moveset.filter(m => m.ppUsed).length)
|
||||||
|
return PartyUiHandler.NoEffectMessage;
|
||||||
|
return null;
|
||||||
|
}, iconImage);
|
||||||
|
|
||||||
|
this.restorePoints = this.restorePoints;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PokemonLevelIncrementModifierType extends PokemonModifierType {
|
||||||
|
constructor(name: string, iconImage?: string) {
|
||||||
|
super(name, `Increase a POKéMON\'s level by 1`, (_type, args) => new Modifiers.PokemonLevelIncrementModifier(this, (args[0] as PlayerPokemon).id),
|
||||||
|
(_pokemon: PlayerPokemon) => null, iconImage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PokemonBaseStatBoosterModifierType extends PokemonModifierType {
|
||||||
|
private stat: Stat;
|
||||||
|
|
||||||
|
constructor(name: string, stat: Stat, _iconImage?: string) {
|
||||||
|
super(name, `Increases one POKéMON's base ${getStatName(stat)} by 20%` , (_type, args) => new Modifiers.PokemonBaseStatModifier(this, (args[0] as PlayerPokemon).id, this.stat));
|
||||||
|
|
||||||
|
this.stat = stat;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AllPokemonFullHpRestoreModifierType extends ModifierType {
|
||||||
|
constructor(name: string, description?: string, newModifierFunc?: NewModifierFunc, iconImage?: string) {
|
||||||
|
super(name, description || `Restore 100% HP for all POKéMON`, newModifierFunc || ((_type, _args) => new Modifiers.PokemonHpRestoreModifier(this, -1, 100, false)), iconImage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AllPokemonFullReviveModifierType extends AllPokemonFullHpRestoreModifierType {
|
||||||
|
constructor(name: string, iconImage?: string) {
|
||||||
|
super(name, `Revives all fainted POKéMON, restoring 100% HP`, (_type, _args) => new Modifiers.PokemonHpRestoreModifier(this, -1, 100, true), iconImage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ExpBoosterModifierType extends ModifierType {
|
||||||
|
constructor(name: string, boostPercent: integer, iconImage?: string) {
|
||||||
|
super(name, `Increases gain of EXP. Points by ${boostPercent}%`, () => new Modifiers.ExpBoosterModifier(this, boostPercent), iconImage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 Modifiers.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;
|
||||||
|
|
||||||
|
constructor(modifierType: ModifierType, weight: integer | Function) {
|
||||||
|
this.modifierType = modifierType;
|
||||||
|
this.weight = weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
setTier(tier: ModifierTier) {
|
||||||
|
this.modifierType.setTier(tier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const modifierPool = {
|
||||||
|
[ModifierTier.COMMON]: [
|
||||||
|
new WeightedModifierType(new AddPokeballModifierType(PokeballType.POKEBALL, 5, 'pb'), 2),
|
||||||
|
new WeightedModifierType(new PokemonHpRestoreModifierType('POTION', 20), (party: PlayerPokemon[]) => {
|
||||||
|
const thresholdPartyMemberCount = party.filter(p => p.getInverseHp() >= 10 || p.getHpRatio() <= 0.875).length;
|
||||||
|
return thresholdPartyMemberCount;
|
||||||
|
}),
|
||||||
|
new WeightedModifierType(new PokemonHpRestoreModifierType('SUPER POTION', 50), (party: PlayerPokemon[]) => {
|
||||||
|
const thresholdPartyMemberCount = party.filter(p => p.getInverseHp() >= 25 || p.getHpRatio() <= 0.75).length;
|
||||||
|
return Math.ceil(thresholdPartyMemberCount / 3);
|
||||||
|
}),
|
||||||
|
new WeightedModifierType(new PokemonPpRestoreModifierType('ETHER', 10), (party: PlayerPokemon[]) => {
|
||||||
|
const thresholdPartyMemberCount = party.filter(p => p.moveset.filter(m => m.ppUsed >= 5)).length;
|
||||||
|
return thresholdPartyMemberCount;
|
||||||
|
}),
|
||||||
|
new WeightedModifierType(new PokemonPpRestoreModifierType('MAX ETHER', -1), (party: PlayerPokemon[]) => {
|
||||||
|
const thresholdPartyMemberCount = party.filter(p => p.moveset.filter(m => m.ppUsed > 10)).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: PlayerPokemon[]) => {
|
||||||
|
const faintedPartyMemberCount = party.filter(p => !p.hp).length;
|
||||||
|
return faintedPartyMemberCount * 3;
|
||||||
|
}),
|
||||||
|
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', 200), (party: PlayerPokemon[]) => {
|
||||||
|
const thresholdPartyMemberCount = party.filter(p => p.getInverseHp() >= 100 || p.getHpRatio() <= 0.625).length;
|
||||||
|
return thresholdPartyMemberCount;
|
||||||
|
}),
|
||||||
|
new WeightedModifierType(new PokemonHpRestoreModifierType('MAX POTION', 100, true), (party: PlayerPokemon[]) => {
|
||||||
|
const thresholdPartyMemberCount = party.filter(p => p.getInverseHp() >= 150 || p.getHpRatio() <= 0.5).length;
|
||||||
|
return Math.ceil(thresholdPartyMemberCount / 3);
|
||||||
|
}),
|
||||||
|
new WeightedModifierType(new PokemonAllMovePpRestoreModifierType('ELIXIR', 10), (party: PlayerPokemon[]) => {
|
||||||
|
const thresholdPartyMemberCount = party.filter(p => p.moveset.filter(m => m.ppUsed >= 5)).length;
|
||||||
|
return thresholdPartyMemberCount;
|
||||||
|
}),
|
||||||
|
new WeightedModifierType(new PokemonAllMovePpRestoreModifierType('MAX ELIXIR', -1), (party: PlayerPokemon[]) => {
|
||||||
|
const thresholdPartyMemberCount = party.filter(p => p.moveset.filter(m => m.ppUsed > 10)).length;
|
||||||
|
return Math.ceil(thresholdPartyMemberCount / 3);
|
||||||
|
}),
|
||||||
|
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),
|
||||||
|
new PokemonBaseStatBoosterModifierType('IRON', Stat.DEF),
|
||||||
|
new PokemonBaseStatBoosterModifierType('CALCIUM', Stat.SPATK),
|
||||||
|
new PokemonBaseStatBoosterModifierType('ZINC', Stat.SPDEF),
|
||||||
|
new PokemonBaseStatBoosterModifierType('CARBOS', Stat.SPD)
|
||||||
|
].map(m => { m.setTier(ModifierTier.GREAT); return m; }),
|
||||||
|
[ModifierTier.ULTRA]: [
|
||||||
|
new AddPokeballModifierType(PokeballType.ULTRA_BALL, 5, 'ub'),
|
||||||
|
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 Modifiers.PartyShareModifier(type), 'oval_charm'),
|
||||||
|
new ModifierType('HEALING CHARM', 'Doubles the effectiveness of HP restoring items (excludes revives)', (type, _args) => new Modifiers.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 Modifiers.ExpShareModifier(type), 'exp_share')
|
||||||
|
].map(m => { m.setTier(ModifierTier.ULTRA); return m; }),
|
||||||
|
[ModifierTier.MASTER]: [
|
||||||
|
new AddPokeballModifierType(PokeballType.MASTER_BALL, 1, 'mb'),
|
||||||
|
new WeightedModifierType(new ModifierType('SHINY CHARM', 'Dramatically increases the chance of a wild POKéMON being shiny', (type, _args) => new Modifiers.ShinyRateBoosterModifier(type)), 2)
|
||||||
|
].map(m => { m.setTier(ModifierTier.MASTER); return m; }),
|
||||||
|
[ModifierTier.LUXURY]: [
|
||||||
|
new ExpBoosterModifierType('GOLDEN EGG', 100),
|
||||||
|
new ModifierType(`GOLDEN ${getPokeballName(PokeballType.POKEBALL)}`, 'Adds 1 extra ITEM option at the end of every battle', (type, _args) => new Modifiers.ExtraModifierModifier(type), 'pb_gold')
|
||||||
|
].map(m => { m.setTier(ModifierTier.LUXURY); return m; }),
|
||||||
|
};
|
||||||
|
|
||||||
|
let modifierPoolThresholds = {};
|
||||||
|
let ignoredPoolIndexes = {};
|
||||||
|
|
||||||
|
export function regenerateModifierPoolThresholds(party: PlayerPokemon[]) {
|
||||||
|
ignoredPoolIndexes = {};
|
||||||
|
modifierPoolThresholds = Object.fromEntries(new Map(Object.keys(modifierPool).map(t => {
|
||||||
|
ignoredPoolIndexes[t] = [];
|
||||||
|
const thresholds = new Map();
|
||||||
|
let i = 0;
|
||||||
|
modifierPool[t].reduce((total: integer, modifierType: ModifierType | WeightedModifierType) => {
|
||||||
|
if (modifierType instanceof WeightedModifierType) {
|
||||||
|
const weightedModifierType = modifierType as WeightedModifierType;
|
||||||
|
const weight = weightedModifierType.weight instanceof Function
|
||||||
|
? (weightedModifierType.weight as Function)(party)
|
||||||
|
: weightedModifierType.weight as integer;
|
||||||
|
if (weight)
|
||||||
|
total += weight;
|
||||||
|
else {
|
||||||
|
ignoredPoolIndexes[t].push(i++);
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
total++;
|
||||||
|
thresholds.set(total, i++);
|
||||||
|
return total;
|
||||||
|
}, 0);
|
||||||
|
return [ t, Object.fromEntries(thresholds) ]
|
||||||
|
})));
|
||||||
|
console.log(modifierPoolThresholds)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getModifierTypesForWave(waveIndex: integer, count: integer, party: PlayerPokemon[]): ModifierType[] {
|
||||||
|
if (waveIndex % 10 === 0)
|
||||||
|
return modifierPool[ModifierTier.LUXURY];
|
||||||
|
return new Array(count).fill(0).map(() => getNewModifierType(party));
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNewModifierType(party: PlayerPokemon[]): ModifierType {
|
||||||
|
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]);
|
||||||
|
const totalWeight = parseInt(thresholds[thresholds.length - 1]);
|
||||||
|
const value = Utils.randInt(totalWeight);
|
||||||
|
let index: integer;
|
||||||
|
for (let t of thresholds) {
|
||||||
|
let threshold = parseInt(t);
|
||||||
|
if (value < threshold) {
|
||||||
|
index = modifierPoolThresholds[tier][threshold];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(index, ignoredPoolIndexes[tier].filter(i => i <= index).length, ignoredPoolIndexes[tier])
|
||||||
|
let modifierType: ModifierType | WeightedModifierType = modifierPool[tier][index];
|
||||||
|
if (modifierType instanceof WeightedModifierType)
|
||||||
|
modifierType = (modifierType as WeightedModifierType).modifierType;
|
||||||
|
if (modifierType instanceof ModifierTypeGenerator)
|
||||||
|
modifierType = (modifierType as ModifierTypeGenerator).generateType(party);
|
||||||
|
return modifierType as ModifierType;
|
||||||
|
}
|
370
src/modifier.ts
370
src/modifier.ts
|
@ -1,16 +1,15 @@
|
||||||
|
import * as ModifierTypes from './modifier-type';
|
||||||
import { LearnMovePhase, LevelUpPhase } from "./battle-phases";
|
import { LearnMovePhase, LevelUpPhase } from "./battle-phases";
|
||||||
import BattleScene from "./battle-scene";
|
import BattleScene from "./battle-scene";
|
||||||
import { getLevelTotalExp } from "./exp";
|
import { getLevelTotalExp } from "./exp";
|
||||||
import { allMoves, Moves } from "./move";
|
import { PokeballType } from "./pokeball";
|
||||||
import { getPokeballName, PokeballType } from "./pokeball";
|
import Pokemon, { PlayerPokemon } from "./pokemon";
|
||||||
import Pokemon, { PlayerPokemon, PokemonMove } from "./pokemon";
|
import { Stat } 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, { PokemonMoveSelectFilter, PokemonSelectFilter } from "./ui/party-ui-handler";
|
|
||||||
import * as Utils from "./utils";
|
import * as Utils from "./utils";
|
||||||
|
|
||||||
|
type ModifierType = ModifierTypes.ModifierType;
|
||||||
|
|
||||||
export class ModifierBar extends Phaser.GameObjects.Container {
|
export class ModifierBar extends Phaser.GameObjects.Container {
|
||||||
constructor(scene: BattleScene) {
|
constructor(scene: BattleScene) {
|
||||||
super(scene, 1, 2);
|
super(scene, 1, 2);
|
||||||
|
@ -158,7 +157,7 @@ export abstract class ConsumableModifier extends Modifier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AddPokeballModifier extends ConsumableModifier {
|
export class AddPokeballModifier extends ConsumableModifier {
|
||||||
private pokeballType: PokeballType;
|
private pokeballType: PokeballType;
|
||||||
private count: integer;
|
private count: integer;
|
||||||
|
|
||||||
|
@ -211,7 +210,7 @@ export abstract class PokemonHeldItemModifier extends PersistentModifier {
|
||||||
export class PokemonBaseStatModifier extends PokemonHeldItemModifier {
|
export class PokemonBaseStatModifier extends PokemonHeldItemModifier {
|
||||||
protected stat: Stat;
|
protected stat: Stat;
|
||||||
|
|
||||||
constructor(type: PokemonBaseStatBoosterModifierType, pokemonId: integer, stat: Stat) {
|
constructor(type: ModifierTypes.PokemonBaseStatBoosterModifierType, pokemonId: integer, stat: Stat) {
|
||||||
super(type, pokemonId);
|
super(type, pokemonId);
|
||||||
this.stat = stat;
|
this.stat = stat;
|
||||||
}
|
}
|
||||||
|
@ -225,7 +224,7 @@ export class PokemonBaseStatModifier extends PokemonHeldItemModifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
clone(): PersistentModifier {
|
clone(): PersistentModifier {
|
||||||
return new PokemonBaseStatModifier(this.type as PokemonBaseStatBoosterModifierType, this.pokemonId, this.stat);
|
return new PokemonBaseStatModifier(this.type as ModifierTypes.PokemonBaseStatBoosterModifierType, this.pokemonId, this.stat);
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldApply(args: any[]): boolean {
|
shouldApply(args: any[]): boolean {
|
||||||
|
@ -373,7 +372,7 @@ export class PokemonLevelIncrementModifier extends ConsumablePokemonModifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TmModifier extends ConsumablePokemonModifier {
|
export class TmModifier extends ConsumablePokemonModifier {
|
||||||
constructor(type: TmModifierType, pokemonId: integer) {
|
constructor(type: ModifierTypes.TmModifierType, pokemonId: integer) {
|
||||||
super(type, pokemonId);
|
super(type, pokemonId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -381,7 +380,7 @@ export class TmModifier extends ConsumablePokemonModifier {
|
||||||
const pokemon = args[0] as PlayerPokemon;
|
const pokemon = args[0] as PlayerPokemon;
|
||||||
|
|
||||||
const scene = pokemon.scene as BattleScene;
|
const scene = pokemon.scene as BattleScene;
|
||||||
scene.unshiftPhase(new LearnMovePhase(scene, scene.getParty().indexOf(pokemon), (this.type as TmModifierType).moveId));
|
scene.unshiftPhase(new LearnMovePhase(scene, scene.getParty().indexOf(pokemon), (this.type as ModifierTypes.TmModifierType).moveId));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -543,351 +542,4 @@ export class ExtraModifierModifier extends PersistentModifier {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
export enum ModifierTier {
|
|
||||||
COMMON,
|
|
||||||
GREAT,
|
|
||||||
ULTRA,
|
|
||||||
MASTER,
|
|
||||||
LUXURY
|
|
||||||
};
|
|
||||||
|
|
||||||
type NewModifierFunc = (type: ModifierType, args: any[]) => Modifier;
|
|
||||||
|
|
||||||
export class ModifierType {
|
|
||||||
public name: string;
|
|
||||||
public description: string;
|
|
||||||
public iconImage: string;
|
|
||||||
public tier: ModifierTier;
|
|
||||||
private newModifierFunc: NewModifierFunc;
|
|
||||||
|
|
||||||
constructor(name: string, description: string, newModifierFunc: NewModifierFunc, iconImage?: string) {
|
|
||||||
this.name = name;
|
|
||||||
this.description = description;
|
|
||||||
this.iconImage = iconImage || name?.replace(/[ \-]/g, '_')?.toLowerCase();
|
|
||||||
this.newModifierFunc = newModifierFunc;
|
|
||||||
}
|
|
||||||
|
|
||||||
setTier(tier: ModifierTier) {
|
|
||||||
this.tier = tier;
|
|
||||||
}
|
|
||||||
|
|
||||||
newModifier(...args: any[]) {
|
|
||||||
return this.newModifierFunc(this, args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class AddPokeballModifierType extends ModifierType {
|
|
||||||
constructor(pokeballType: PokeballType, count: integer, iconImage?: string) {
|
|
||||||
super(`${count}x ${getPokeballName(pokeballType)}`, `Receive ${getPokeballName(pokeballType)} x${count}`, (_type, _args) => new AddPokeballModifier(this, pokeballType, count), iconImage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export abstract class PokemonModifierType extends ModifierType {
|
|
||||||
public selectFilter: PokemonSelectFilter;
|
|
||||||
|
|
||||||
constructor(name: string, description: string, newModifierFunc: NewModifierFunc, selectFilter?: PokemonSelectFilter, iconImage?: string) {
|
|
||||||
super(name, description, newModifierFunc, iconImage);
|
|
||||||
|
|
||||||
this.selectFilter = selectFilter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class PokemonHpRestoreModifierType extends PokemonModifierType {
|
|
||||||
protected restorePoints: integer;
|
|
||||||
protected percent: boolean;
|
|
||||||
|
|
||||||
constructor(name: string, restorePoints: integer, percent?: boolean, newModifierFunc?: NewModifierFunc, selectFilter?: PokemonSelectFilter, 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.restorePoints = restorePoints;
|
|
||||||
this.percent = !!percent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class PokemonReviveModifierType extends PokemonHpRestoreModifierType {
|
|
||||||
constructor(name: string, restorePercent: integer, iconImage?: string) {
|
|
||||||
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;
|
|
||||||
return null;
|
|
||||||
}), iconImage);
|
|
||||||
|
|
||||||
this.description = `Revive one POKéMON and restore ${restorePercent}% HP`;
|
|
||||||
this.selectFilter = (pokemon: PlayerPokemon) => {
|
|
||||||
if (pokemon.hp)
|
|
||||||
return PartyUiHandler.NoEffectMessage;
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export abstract class PokemonMoveModifierType extends PokemonModifierType {
|
|
||||||
public moveSelectFilter: PokemonMoveSelectFilter;
|
|
||||||
|
|
||||||
constructor(name: string, description: string, newModifierFunc: NewModifierFunc, selectFilter?: PokemonSelectFilter, moveSelectFilter?: PokemonMoveSelectFilter, iconImage?: string) {
|
|
||||||
super(name, description, newModifierFunc, selectFilter, iconImage);
|
|
||||||
|
|
||||||
this.moveSelectFilter = moveSelectFilter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class PokemonPpRestoreModifierType extends PokemonMoveModifierType {
|
|
||||||
protected restorePoints: integer;
|
|
||||||
|
|
||||||
constructor(name: string, restorePoints: integer, iconImage?: string) {
|
|
||||||
super(name, `Restore ${restorePoints > -1 ? restorePoints : 'all'} PP for one POKéMON move`, (_type, args) => new PokemonPpRestoreModifier(this, (args[0] as PlayerPokemon).id, (args[1] as integer), this.restorePoints),
|
|
||||||
(_pokemon: PlayerPokemon) => {
|
|
||||||
return null;
|
|
||||||
}, (pokemonMove: PokemonMove) => {
|
|
||||||
if (!pokemonMove.ppUsed)
|
|
||||||
return PartyUiHandler.NoEffectMessage;
|
|
||||||
return null;
|
|
||||||
}, iconImage);
|
|
||||||
|
|
||||||
this.restorePoints = this.restorePoints;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class PokemonAllMovePpRestoreModifierType extends PokemonModifierType {
|
|
||||||
protected restorePoints: integer;
|
|
||||||
|
|
||||||
constructor(name: string, restorePoints: integer, iconImage?: string) {
|
|
||||||
super(name, `Restore ${restorePoints > -1 ? restorePoints : 'all'} PP for all of one POKéMON's moves`, (_type, args) => new PokemonAllMovePpRestoreModifier(this, (args[0] as PlayerPokemon).id, this.restorePoints),
|
|
||||||
(pokemon: PlayerPokemon) => {
|
|
||||||
if (!pokemon.moveset.filter(m => m.ppUsed).length)
|
|
||||||
return PartyUiHandler.NoEffectMessage;
|
|
||||||
return null;
|
|
||||||
}, iconImage);
|
|
||||||
|
|
||||||
this.restorePoints = this.restorePoints;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class PokemonLevelIncrementModifierType extends PokemonModifierType {
|
|
||||||
constructor(name: string, iconImage?: string) {
|
|
||||||
super(name, `Increase a POKéMON\'s level by 1`, (_type, args) => new PokemonLevelIncrementModifier(this, (args[0] as PlayerPokemon).id),
|
|
||||||
(_pokemon: PlayerPokemon) => null, iconImage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class PokemonBaseStatBoosterModifierType extends PokemonModifierType {
|
|
||||||
private stat: Stat;
|
|
||||||
|
|
||||||
constructor(name: string, stat: Stat, _iconImage?: string) {
|
|
||||||
super(name, `Increases one POKéMON's base ${getStatName(stat)} by 20%` , (_type, args) => new PokemonBaseStatModifier(this, (args[0] as PlayerPokemon).id, this.stat));
|
|
||||||
|
|
||||||
this.stat = stat;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class AllPokemonFullHpRestoreModifierType extends ModifierType {
|
|
||||||
constructor(name: string, description?: string, newModifierFunc?: NewModifierFunc, iconImage?: string) {
|
|
||||||
super(name, description || `Restore 100% HP for all POKéMON`, newModifierFunc || ((_type, _args) => new PokemonHpRestoreModifier(this, -1, 100, false)), iconImage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class AllPokemonFullReviveModifierType extends AllPokemonFullHpRestoreModifierType {
|
|
||||||
constructor(name: string, iconImage?: string) {
|
|
||||||
super(name, `Revives all fainted POKéMON, restoring 100% HP`, (_type, _args) => new PokemonHpRestoreModifier(this, -1, 100, true), iconImage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ExpBoosterModifierType extends ModifierType {
|
|
||||||
constructor(name: string, boostPercent: integer, iconImage?: string) {
|
|
||||||
super(name, `Increases gain of EXP. Points by ${boostPercent}%`, () => new ExpBoosterModifier(this, boostPercent), iconImage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
constructor(modifierType: ModifierType, weight: integer | Function) {
|
|
||||||
this.modifierType = modifierType;
|
|
||||||
this.weight = weight;
|
|
||||||
}
|
|
||||||
|
|
||||||
setTier(tier: ModifierTier) {
|
|
||||||
this.modifierType.setTier(tier);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const modifierPool = {
|
|
||||||
[ModifierTier.COMMON]: [
|
|
||||||
new WeightedModifierType(new AddPokeballModifierType(PokeballType.POKEBALL, 5, 'pb'), 2),
|
|
||||||
new WeightedModifierType(new PokemonHpRestoreModifierType('POTION', 20), (party: PlayerPokemon[]) => {
|
|
||||||
const thresholdPartyMemberCount = party.filter(p => p.getInverseHp() >= 10 || p.getHpRatio() <= 0.875).length;
|
|
||||||
return thresholdPartyMemberCount;
|
|
||||||
}),
|
|
||||||
new WeightedModifierType(new PokemonHpRestoreModifierType('SUPER POTION', 50), (party: PlayerPokemon[]) => {
|
|
||||||
const thresholdPartyMemberCount = party.filter(p => p.getInverseHp() >= 25 || p.getHpRatio() <= 0.75).length;
|
|
||||||
return Math.ceil(thresholdPartyMemberCount / 3);
|
|
||||||
}),
|
|
||||||
new WeightedModifierType(new PokemonPpRestoreModifierType('ETHER', 10), (party: PlayerPokemon[]) => {
|
|
||||||
const thresholdPartyMemberCount = party.filter(p => p.moveset.filter(m => m.ppUsed >= 5)).length;
|
|
||||||
return thresholdPartyMemberCount;
|
|
||||||
}),
|
|
||||||
new WeightedModifierType(new PokemonPpRestoreModifierType('MAX ETHER', -1), (party: PlayerPokemon[]) => {
|
|
||||||
const thresholdPartyMemberCount = party.filter(p => p.moveset.filter(m => m.ppUsed > 10)).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: PlayerPokemon[]) => {
|
|
||||||
const faintedPartyMemberCount = party.filter(p => !p.hp).length;
|
|
||||||
return faintedPartyMemberCount * 3;
|
|
||||||
}),
|
|
||||||
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', 200), (party: PlayerPokemon[]) => {
|
|
||||||
const thresholdPartyMemberCount = party.filter(p => p.getInverseHp() >= 100 || p.getHpRatio() <= 0.625).length;
|
|
||||||
return thresholdPartyMemberCount;
|
|
||||||
}),
|
|
||||||
new WeightedModifierType(new PokemonHpRestoreModifierType('MAX POTION', 100, true), (party: PlayerPokemon[]) => {
|
|
||||||
const thresholdPartyMemberCount = party.filter(p => p.getInverseHp() >= 150 || p.getHpRatio() <= 0.5).length;
|
|
||||||
return Math.ceil(thresholdPartyMemberCount / 3);
|
|
||||||
}),
|
|
||||||
new WeightedModifierType(new PokemonAllMovePpRestoreModifierType('ELIXIR', 10), (party: PlayerPokemon[]) => {
|
|
||||||
const thresholdPartyMemberCount = party.filter(p => p.moveset.filter(m => m.ppUsed >= 5)).length;
|
|
||||||
return thresholdPartyMemberCount;
|
|
||||||
}),
|
|
||||||
new WeightedModifierType(new PokemonAllMovePpRestoreModifierType('MAX ELIXIR', -1), (party: PlayerPokemon[]) => {
|
|
||||||
const thresholdPartyMemberCount = party.filter(p => p.moveset.filter(m => m.ppUsed > 10)).length;
|
|
||||||
return Math.ceil(thresholdPartyMemberCount / 3);
|
|
||||||
}),
|
|
||||||
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),
|
|
||||||
new PokemonBaseStatBoosterModifierType('IRON', Stat.DEF),
|
|
||||||
new PokemonBaseStatBoosterModifierType('CALCIUM', Stat.SPATK),
|
|
||||||
new PokemonBaseStatBoosterModifierType('ZINC', Stat.SPDEF),
|
|
||||||
new PokemonBaseStatBoosterModifierType('CARBOS', Stat.SPD)
|
|
||||||
].map(m => { m.setTier(ModifierTier.GREAT); return m; }),
|
|
||||||
[ModifierTier.ULTRA]: [
|
|
||||||
new AddPokeballModifierType(PokeballType.ULTRA_BALL, 5, 'ub'),
|
|
||||||
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; }),
|
|
||||||
[ModifierTier.MASTER]: [
|
|
||||||
new AddPokeballModifierType(PokeballType.MASTER_BALL, 1, 'mb'),
|
|
||||||
new WeightedModifierType(new ModifierType('SHINY CHARM', 'Dramatically increases the chance of a wild POKéMON being shiny', (type, _args) => new ShinyRateBoosterModifier(type)), 2)
|
|
||||||
].map(m => { m.setTier(ModifierTier.MASTER); return m; }),
|
|
||||||
[ModifierTier.LUXURY]: [
|
|
||||||
new ExpBoosterModifierType('GOLDEN EGG', 100),
|
|
||||||
new ModifierType(`GOLDEN ${getPokeballName(PokeballType.POKEBALL)}`, 'Adds 1 extra ITEM option at the end of every battle', (type, _args) => new ExtraModifierModifier(type), 'pb_gold')
|
|
||||||
].map(m => { m.setTier(ModifierTier.LUXURY); return m; }),
|
|
||||||
};
|
|
||||||
|
|
||||||
let modifierPoolThresholds = {};
|
|
||||||
let ignoredPoolIndexes = {};
|
|
||||||
|
|
||||||
export function regenerateModifierPoolThresholds(party: PlayerPokemon[]) {
|
|
||||||
ignoredPoolIndexes = {};
|
|
||||||
modifierPoolThresholds = Object.fromEntries(new Map(Object.keys(modifierPool).map(t => {
|
|
||||||
ignoredPoolIndexes[t] = [];
|
|
||||||
const thresholds = new Map();
|
|
||||||
let i = 0;
|
|
||||||
modifierPool[t].reduce((total: integer, modifierType: ModifierType | WeightedModifierType) => {
|
|
||||||
if (modifierType instanceof WeightedModifierType) {
|
|
||||||
const weightedModifierType = modifierType as WeightedModifierType;
|
|
||||||
const weight = weightedModifierType.weight instanceof Function
|
|
||||||
? (weightedModifierType.weight as Function)(party)
|
|
||||||
: weightedModifierType.weight as integer;
|
|
||||||
if (weight)
|
|
||||||
total += weight;
|
|
||||||
else {
|
|
||||||
ignoredPoolIndexes[t].push(i++);
|
|
||||||
return total;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
total++;
|
|
||||||
thresholds.set(total, i++);
|
|
||||||
return total;
|
|
||||||
}, 0);
|
|
||||||
return [ t, Object.fromEntries(thresholds) ]
|
|
||||||
})));
|
|
||||||
console.log(modifierPoolThresholds)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getModifierTypesForWave(waveIndex: integer, count: integer, party: PlayerPokemon[]): ModifierType[] {
|
|
||||||
if (waveIndex % 10 === 0)
|
|
||||||
return modifierPool[ModifierTier.LUXURY];
|
|
||||||
return new Array(count).fill(0).map(() => getNewModifierType(party));
|
|
||||||
}
|
|
||||||
|
|
||||||
function getNewModifierType(party: PlayerPokemon[]): ModifierType {
|
|
||||||
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]);
|
|
||||||
const totalWeight = parseInt(thresholds[thresholds.length - 1]);
|
|
||||||
const value = Utils.randInt(totalWeight);
|
|
||||||
let index: integer;
|
|
||||||
for (let t of thresholds) {
|
|
||||||
let threshold = parseInt(t);
|
|
||||||
if (value < threshold) {
|
|
||||||
index = modifierPoolThresholds[tier][threshold];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
console.log(index, ignoredPoolIndexes[tier].filter(i => i <= index).length, ignoredPoolIndexes[tier])
|
|
||||||
let modifierType: ModifierType | WeightedModifierType = modifierPool[tier][index];
|
|
||||||
if (modifierType instanceof WeightedModifierType)
|
|
||||||
modifierType = (modifierType as WeightedModifierType).modifierType;
|
|
||||||
if (modifierType instanceof ModifierTypeGenerator)
|
|
||||||
modifierType = (modifierType as ModifierTypeGenerator).generateType(party);
|
|
||||||
return modifierType as ModifierType;
|
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
import BattleScene, { Button } from "../battle-scene";
|
import BattleScene, { Button } from "../battle-scene";
|
||||||
import { ModifierTier, ModifierType } from "../modifier";
|
import { ModifierTier, ModifierType } from "../modifier-type";
|
||||||
import { getPokeballAtlasKey, PokeballType } from "../pokeball";
|
import { getPokeballAtlasKey, PokeballType } from "../pokeball";
|
||||||
import { addTextObject, TextStyle } from "../text";
|
import { addTextObject, TextStyle } from "../text";
|
||||||
import AwaitableUiHandler from "./awaitable-ui-handler";
|
import AwaitableUiHandler from "./awaitable-ui-handler";
|
||||||
|
|
Loading…
Reference in New Issue