Add evolution items and new modifiers

pull/1/head
Flashfyre 2023-04-14 18:21:33 -04:00
parent 927f17b71f
commit b11e391e7a
32 changed files with 1949 additions and 1246 deletions

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 571 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 272 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 347 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 B

View File

@ -5,7 +5,7 @@ import { EncounterPhase, SummonPhase, CommandPhase, NextEncounterPhase, SwitchBi
import { PlayerPokemon, EnemyPokemon } from './pokemon'; import { PlayerPokemon, EnemyPokemon } from './pokemon';
import PokemonSpecies, { allSpecies, getPokemonSpecies } from './pokemon-species'; import PokemonSpecies, { allSpecies, getPokemonSpecies } from './pokemon-species';
import * as Utils from './utils'; import * as Utils from './utils';
import { Modifier, ModifierBar, ConsumablePokemonModifier, ConsumableModifier, PartyShareModifier, PokemonHpRestoreModifier, HealingBoosterModifier, PersistentModifier, PokemonHeldItemModifier, ConsumablePokemonMoveModifier } from './modifier'; import { Modifier, ModifierBar, ConsumablePokemonModifier, ConsumableModifier, PartyShareModifier, PokemonHpRestoreModifier, HealingBoosterModifier, PersistentModifier, PokemonHeldItemModifier, ConsumablePokemonMoveModifier, ModifierPredicate } from './modifier';
import { PokeballType } from './pokeball'; import { PokeballType } from './pokeball';
import { Species } from './species'; import { Species } from './species';
import { initAutoPlay } from './auto-play'; import { initAutoPlay } from './auto-play';
@ -279,7 +279,7 @@ export default class BattleScene extends Phaser.Scene {
let loadPokemonAssets = []; let loadPokemonAssets = [];
const isRandom = this.isButtonPressed(Button.RANDOM); // For testing purposes const isRandom = this.isButtonPressed(Button.RANDOM); // For testing purposes
this.quickStart = isRandom || this.isButtonPressed(Button.QUICK_START); this.quickStart = this.quickStart || isRandom || this.isButtonPressed(Button.QUICK_START);
if (isRandom) { if (isRandom) {
const biomes = Utils.getEnumValues(Biome); const biomes = Utils.getEnumValues(Biome);
@ -617,6 +617,10 @@ export default class BattleScene extends Phaser.Scene {
return this.modifiers.find(m => m instanceof modifierType); return this.modifiers.find(m => m instanceof modifierType);
} }
findModifier(modifierFilter: ModifierPredicate): Modifier {
return this.modifiers.find(m => (modifierFilter as ModifierPredicate)(m));
}
applyModifiers(modifierType: { new(...args: any[]): Modifier }, ...args: any[]): void { applyModifiers(modifierType: { new(...args: any[]): Modifier }, ...args: any[]): void {
const modifiers = this.modifiers.filter(m => m instanceof modifierType && m.shouldApply(args)); const modifiers = this.modifiers.filter(m => m instanceof modifierType && m.shouldApply(args));
for (let modifier of modifiers) { for (let modifier of modifiers) {

View File

@ -187,6 +187,22 @@ export class BiomeArena {
return Biome[this.biomeType].toLowerCase(); return Biome[this.biomeType].toLowerCase();
} }
isDaytime() {
switch (this.biomeType) {
case Biome.PLAINS:
case Biome.GRASS:
case Biome.SEA:
case Biome.BEACH:
case Biome.LAKE:
case Biome.MOUNTAIN:
case Biome.LAND:
case Biome.DESERT:
case Biome.MEADOW:
case Biome.DOJO:
return true;
}
}
preloadBgm(): void { preloadBgm(): void {
this.scene.loadBgm(this.bgm); this.scene.loadBgm(this.bgm);
} }

View File

@ -15,7 +15,7 @@ const config: Phaser.Types.Core.GameConfig = {
scene: [ BattleScene ] scene: [ BattleScene ]
}; };
const setPositionRelative = function(guideObject: any, x: number, y: number) { const setPositionRelative = function (guideObject: any, x: number, y: number) {
if (guideObject && guideObject.hasOwnProperty('width') && guideObject.hasOwnProperty('height')) { if (guideObject && guideObject.hasOwnProperty('width') && guideObject.hasOwnProperty('height')) {
const offsetX = guideObject.width * (-0.5 + (0.5 - guideObject.originX)); const offsetX = guideObject.width * (-0.5 + (0.5 - guideObject.originX));
const offsetY = guideObject.height * (-0.5 + (0.5 - guideObject.originY)); const offsetY = guideObject.height * (-0.5 + (0.5 - guideObject.originY));

View File

@ -1,7 +1,8 @@
import * as Modifiers from './modifier'; import * as Modifiers from './modifier';
import { Moves, allMoves } from './move'; import { AttackMove, Moves, allMoves } from './move';
import { PokeballType, getPokeballName } from './pokeball'; import { PokeballType, getPokeballName } from './pokeball';
import { PlayerPokemon, PokemonMove } from './pokemon'; import { PlayerPokemon, PokemonMove } from './pokemon';
import { EvolutionItem, pokemonEvolutions } from './pokemon-evolutions';
import { Stat, getStatName } from './pokemon-stat'; import { Stat, getStatName } from './pokemon-stat';
import { tmSpecies } from './tms'; import { tmSpecies } from './tms';
import { Type } from './type'; import { Type } from './type';
@ -137,6 +138,61 @@ export class PokemonAllMovePpRestoreModifierType extends PokemonModifierType {
} }
} }
function getAttackTypeBoosterItemName(type: Type) {
switch (type) {
case Type.NORMAL:
return 'Silk Scarf';
case Type.FIGHTING:
return 'Black Belt';
case Type.FLYING:
return 'Sharp Beak';
case Type.POISON:
return 'Poison Barb';
case Type.GROUND:
return 'Soft Sand';
case Type.ROCK:
return 'Hard Stone';
case Type.BUG:
return 'Silver Powder';
case Type.GHOST:
return 'Spell Tag';
case Type.STEEL:
return 'Metal Coat';
case Type.FIRE:
return 'Charcoal';
case Type.WATER:
return 'Mystic Water';
case Type.GRASS:
return 'Miracle Seed';
case Type.ELECTRIC:
return 'Magnet';
case Type.PSYCHIC:
return 'Twisted Spoon';
case Type.ICE:
return 'Never-Melt Ice'
case Type.DRAGON:
return 'Dragon Fang';
case Type.DARK:
return 'Black Glasses';
case Type.FAIRY:
return 'Clefairy Doll';
}
}
export class AttackTypeBoosterModifierType extends PokemonModifierType {
public moveType: Type;
public boostPercent: integer;
constructor(moveType: Type, boostPercent: integer) {
super(getAttackTypeBoosterItemName(moveType), `Inceases the power of a POKéMON's ${Type[moveType]}-type moves by 20%`,
(_type, args) => new Modifiers.AttackTypeBoosterModifier(this, (args[0] as PlayerPokemon).id, moveType, boostPercent),
null, `${getAttackTypeBoosterItemName(moveType).replace(/[ \-]/g, '_').toLowerCase()}`);
this.moveType = moveType;
this.boostPercent = boostPercent;
}
}
export class PokemonLevelIncrementModifierType extends PokemonModifierType { export class PokemonLevelIncrementModifierType extends PokemonModifierType {
constructor(name: string, iconImage?: string) { 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), super(name, `Increase a POKéMON\'s level by 1`, (_type, args) => new Modifiers.PokemonLevelIncrementModifier(this, (args[0] as PlayerPokemon).id),
@ -187,6 +243,50 @@ export class TmModifierType extends PokemonModifierType {
} }
} }
function getEvolutionItemName(evolutionItem: EvolutionItem) {
switch (evolutionItem) {
case EvolutionItem.LINKING_CORD:
return 'Linking Cord';
case EvolutionItem.SUN_STONE:
return 'Sun Stone';
case EvolutionItem.MOON_STONE:
return 'Moon Stone';
case EvolutionItem.LEAF_STONE:
return 'Leaf Stone';
case EvolutionItem.FIRE_STONE:
return 'Fire Stone';
case EvolutionItem.WATER_STONE:
return 'Water Stone';
case EvolutionItem.THUNDER_STONE:
return 'Thunder Stone';
case EvolutionItem.ICE_STONE:
return 'Ice Stone';
case EvolutionItem.DUSK_STONE:
return 'Dusk Stone';
case EvolutionItem.DAWN_STONE:
return 'Dawn Stone';
case EvolutionItem.SHINY_STONE:
return 'Shiny Stone';
}
}
export class EvolutionItemModifierType extends PokemonModifierType {
public evolutionItem: EvolutionItem;
constructor(evolutionItem: EvolutionItem) {
super(getEvolutionItemName(evolutionItem), `Causes certain POKéMON to evolve`, (_type, args) => new Modifiers.EvolutionItemModifier(this, (args[0] as PlayerPokemon).id),
(pokemon: PlayerPokemon) => {
if (pokemonEvolutions.hasOwnProperty(pokemon.species.speciesId) && pokemonEvolutions[pokemon.species.speciesId].filter(e => e.item === this.evolutionItem
&& (!e.condition || e.condition.predicate(pokemon))).length)
return null;
return PartyUiHandler.NoEffectMessage;
}, getEvolutionItemName(evolutionItem).replace(/[ \-]/g, '_').toLowerCase());
this.evolutionItem = evolutionItem;
}
}
class ModifierTypeGenerator extends ModifierType { class ModifierTypeGenerator extends ModifierType {
private genTypeFunc: Function; private genTypeFunc: Function;
@ -197,11 +297,69 @@ class ModifierTypeGenerator extends ModifierType {
generateType(party: PlayerPokemon[]) { generateType(party: PlayerPokemon[]) {
const ret = this.genTypeFunc(party); const ret = this.genTypeFunc(party);
ret.setTier(this.tier); if (ret) {
console.log(ret);
ret.setTier(this.tier);
}
return ret; return ret;
} }
} }
class AttackTypeBoosterModifierTypeGenerator extends ModifierTypeGenerator {
constructor() {
super((party: PlayerPokemon[]) => {
const attackMoveTypes = party.map(p => p.moveset.map(m => m.getMove()).filter(m => m instanceof AttackMove).map(m => m.type)).flat();
const attackMoveTypeWeights = new Map<Type, integer>();
let totalWeight = 0;
for (let t of attackMoveTypes) {
if (attackMoveTypeWeights.has(t)) {
if (attackMoveTypeWeights.get(t) < 3)
attackMoveTypeWeights.set(t, attackMoveTypeWeights.get(t) + 1);
else
continue;
} else
attackMoveTypeWeights.set(t, 1);
totalWeight++;
}
if (!totalWeight)
return null;
let type: Type;
const randInt = Utils.randInt(totalWeight);
let weight = 0;
for (let t of attackMoveTypeWeights.keys()) {
const typeWeight = attackMoveTypeWeights.get(t);
if (randInt <= weight + typeWeight) {
type = t;
break;
}
weight += typeWeight;
}
return new AttackTypeBoosterModifierType(type, 20);
});
}
}
class EvolutionItemModifierTypeGenerator extends ModifierTypeGenerator {
constructor() {
super((party: PlayerPokemon[]) => {
const evolutionItemPool = party.filter(p => pokemonEvolutions.hasOwnProperty(p.species.speciesId)).map(p => {
const evolutions = pokemonEvolutions[p.species.speciesId]
return evolutions.filter(e => e.item !== EvolutionItem.NONE && (!e.condition || e.condition.predicate(p)));
}).flat().flatMap(e => e.item);
if (!evolutionItemPool.length)
return null;
return new EvolutionItemModifierType(evolutionItemPool[Utils.randInt(evolutionItemPool.length)]);
});
}
}
class WeightedModifierType { class WeightedModifierType {
public modifierType: ModifierType; public modifierType: ModifierType;
public weight: integer | Function; public weight: integer | Function;
@ -237,56 +395,58 @@ const modifierPool = {
}) })
].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'), 12),
new WeightedModifierType(new PokemonReviveModifierType('REVIVE', 50), (party: 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 * 6;
}), }),
new WeightedModifierType(new PokemonReviveModifierType('MAX REVIVE', 100), (party: 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 * 2;
}),
new WeightedModifierType(new AllPokemonFullReviveModifierType('SACRED ASH'), (party: PlayerPokemon[]) => {
return party.filter(p => !p.hp).length >= Math.ceil(party.length / 2) ? 1 : 0;
}), }),
new WeightedModifierType(new PokemonHpRestoreModifierType('HYPER POTION', 200), (party: PlayerPokemon[]) => { new WeightedModifierType(new PokemonHpRestoreModifierType('HYPER POTION', 200), (party: PlayerPokemon[]) => {
const thresholdPartyMemberCount = party.filter(p => p.getInverseHp() >= 100 || p.getHpRatio() <= 0.625).length; const thresholdPartyMemberCount = party.filter(p => p.getInverseHp() >= 100 || p.getHpRatio() <= 0.625).length;
return thresholdPartyMemberCount; return thresholdPartyMemberCount * 2;
}), }),
new WeightedModifierType(new PokemonHpRestoreModifierType('MAX POTION', 100, true), (party: PlayerPokemon[]) => { new WeightedModifierType(new PokemonHpRestoreModifierType('MAX POTION', 100, true), (party: PlayerPokemon[]) => {
const thresholdPartyMemberCount = party.filter(p => p.getInverseHp() >= 150 || p.getHpRatio() <= 0.5).length; const thresholdPartyMemberCount = party.filter(p => p.getInverseHp() >= 150 || p.getHpRatio() <= 0.5).length;
return Math.ceil(thresholdPartyMemberCount / 3); return Math.ceil(thresholdPartyMemberCount / 1.5);
}), }),
new WeightedModifierType(new PokemonAllMovePpRestoreModifierType('ELIXIR', 10), (party: PlayerPokemon[]) => { new WeightedModifierType(new PokemonAllMovePpRestoreModifierType('ELIXIR', 10), (party: PlayerPokemon[]) => {
const thresholdPartyMemberCount = party.filter(p => p.moveset.filter(m => m.ppUsed >= 5).length).length; const thresholdPartyMemberCount = party.filter(p => p.moveset.filter(m => m.ppUsed >= 5).length).length;
return thresholdPartyMemberCount; return thresholdPartyMemberCount * 2;
}), }),
new WeightedModifierType(new PokemonAllMovePpRestoreModifierType('MAX ELIXIR', -1), (party: PlayerPokemon[]) => { new WeightedModifierType(new PokemonAllMovePpRestoreModifierType('MAX ELIXIR', -1), (party: PlayerPokemon[]) => {
const thresholdPartyMemberCount = party.filter(p => p.moveset.filter(m => m.ppUsed > 10).length).length; const thresholdPartyMemberCount = party.filter(p => p.moveset.filter(m => m.ppUsed > 10).length).length;
return Math.ceil(thresholdPartyMemberCount / 3); return Math.ceil(thresholdPartyMemberCount / 1.5);
}), }),
new WeightedModifierType(new ModifierTypeGenerator((party: PlayerPokemon[]) => { new WeightedModifierType(new ModifierTypeGenerator((party: PlayerPokemon[]) => {
const partyMemberCompatibleTms = party.map(p => p.compatibleTms); const partyMemberCompatibleTms = party.map(p => p.compatibleTms);
const uniqueCompatibleTms = partyMemberCompatibleTms.flat().filter((tm, i, array) => array.indexOf(tm) === i); const uniqueCompatibleTms = partyMemberCompatibleTms.flat().filter((tm, i, array) => array.indexOf(tm) === i);
const randTmIndex = Utils.randInt(uniqueCompatibleTms.length); const randTmIndex = Utils.randInt(uniqueCompatibleTms.length);
return new TmModifierType(uniqueCompatibleTms[randTmIndex]); return new TmModifierType(uniqueCompatibleTms[randTmIndex]);
}), 2), }), 4),
new PokemonLevelIncrementModifierType('RARE CANDY'), new WeightedModifierType(new PokemonLevelIncrementModifierType('RARE CANDY'), 4),
new PokemonBaseStatBoosterModifierType('HP-UP', Stat.HP), new WeightedModifierType(new PokemonBaseStatBoosterModifierType('HP-UP', Stat.HP), 1),
new PokemonBaseStatBoosterModifierType('PROTEIN', Stat.ATK), new WeightedModifierType(new PokemonBaseStatBoosterModifierType('PROTEIN', Stat.ATK), 1),
new PokemonBaseStatBoosterModifierType('IRON', Stat.DEF), new WeightedModifierType(new PokemonBaseStatBoosterModifierType('IRON', Stat.DEF), 1),
new PokemonBaseStatBoosterModifierType('CALCIUM', Stat.SPATK), new WeightedModifierType(new PokemonBaseStatBoosterModifierType('CALCIUM', Stat.SPATK), 1),
new PokemonBaseStatBoosterModifierType('ZINC', Stat.SPDEF), new WeightedModifierType(new PokemonBaseStatBoosterModifierType('ZINC', Stat.SPDEF), 1),
new PokemonBaseStatBoosterModifierType('CARBOS', Stat.SPD) new WeightedModifierType(new PokemonBaseStatBoosterModifierType('CARBOS', Stat.SPD), 1)
].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 WeightedModifierType(new AddPokeballModifierType(PokeballType.ULTRA_BALL, 5, 'ub'), 8),
new WeightedModifierType(new AllPokemonFullReviveModifierType('SACRED ASH'), (party: PlayerPokemon[]) => { new WeightedModifierType(new EvolutionItemModifierTypeGenerator(), 5),
return party.filter(p => !p.hp).length >= Math.ceil(party.length / 2) ? 1 : 0; new WeightedModifierType(new AttackTypeBoosterModifierTypeGenerator(), 3),
}),
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', 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'), (type, _args) => new Modifiers.PartyShareModifier(type), 'oval_charm'),
new ModifierType('HEALING CHARM', 'Doubles the effectiveness of HP restoring moves and items (excludes revives)', (type, _args) => new Modifiers.HealingBoosterModifier(type, 2), 'healing_charm'), new ModifierType('HEALING CHARM', 'Doubles the effectiveness of HP restoring moves and items (excludes revives)', (type, _args) => new Modifiers.HealingBoosterModifier(type, 2), 'healing_charm'),
new WeightedModifierType(new PokemonModifierType('SHELL BELL', 'Heals 1/8 of a POKéMON\'s damage dealt', (type, args) => new Modifiers.HitHealModifier(type, (args[0] as PlayerPokemon).id)), 8), new WeightedModifierType(new PokemonModifierType('SHELL BELL', 'Heals 1/8 of a POKéMON\'s dealt damage', (type, args) => new Modifiers.HitHealModifier(type, (args[0] as PlayerPokemon).id)), 8),
new ExpBoosterModifierType('LUCKY EGG', 25), new WeightedModifierType(new ExpBoosterModifierType('LUCKY EGG', 25), 4),
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') new WeightedModifierType(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'), 3)
].map(m => { m.setTier(ModifierTier.ULTRA); return m; }), ].map(m => { m.setTier(ModifierTier.ULTRA); return m; }),
[ModifierTier.MASTER]: [ [ModifierTier.MASTER]: [
new AddPokeballModifierType(PokeballType.MASTER_BALL, 1, 'mb'), new AddPokeballModifierType(PokeballType.MASTER_BALL, 1, 'mb'),
@ -335,10 +495,12 @@ export function getModifierTypeOptionsForWave(waveIndex: integer, count: integer
return new Array(count).fill(0).map(() => getNewModifierTypeOption(party)); return new Array(count).fill(0).map(() => getNewModifierTypeOption(party));
} }
function getNewModifierTypeOption(party: PlayerPokemon[]): ModifierTypeOption { function getNewModifierTypeOption(party: PlayerPokemon[], tier?: ModifierTier, upgrade?: boolean): ModifierTypeOption {
const tierValue = Utils.randInt(256); const tierValue = Utils.randInt(256);
const upgrade = Utils.randInt(32) === 0; if (tier === undefined) {
const tier: ModifierTier = (tierValue >= 52 ? ModifierTier.COMMON : tierValue >= 8 ? ModifierTier.GREAT : tierValue >= 1 ? ModifierTier.ULTRA : ModifierTier.MASTER) + (upgrade ? 1 : 0); tier = (tierValue >= 52 ? ModifierTier.COMMON : tierValue >= 8 ? ModifierTier.GREAT : tierValue >= 1 ? ModifierTier.ULTRA : ModifierTier.MASTER) + (upgrade ? 1 : 0);
upgrade = Utils.randInt(32) === 0;
}
const thresholds = Object.keys(modifierPoolThresholds[tier]); const thresholds = Object.keys(modifierPoolThresholds[tier]);
const totalWeight = parseInt(thresholds[thresholds.length - 1]); const totalWeight = parseInt(thresholds[thresholds.length - 1]);
const value = Utils.randInt(totalWeight); const value = Utils.randInt(totalWeight);
@ -354,8 +516,14 @@ function getNewModifierTypeOption(party: PlayerPokemon[]): ModifierTypeOption {
let modifierType: ModifierType | WeightedModifierType = modifierPool[tier][index]; let modifierType: ModifierType | WeightedModifierType = modifierPool[tier][index];
if (modifierType instanceof WeightedModifierType) if (modifierType instanceof WeightedModifierType)
modifierType = (modifierType as WeightedModifierType).modifierType; modifierType = (modifierType as WeightedModifierType).modifierType;
if (modifierType instanceof ModifierTypeGenerator) if (modifierType instanceof ModifierTypeGenerator) {
modifierType = (modifierType as ModifierTypeGenerator).generateType(party); modifierType = (modifierType as ModifierTypeGenerator).generateType(party);
if (modifierType === null) {
console.log(ModifierTier[tier], upgrade);
return getNewModifierTypeOption(party, tier, upgrade);
}
}
console.log(modifierType);
return new ModifierTypeOption(modifierType as ModifierType, upgrade); return new ModifierTypeOption(modifierType as ModifierType, upgrade);
} }

View File

@ -1,5 +1,5 @@
import * as ModifierTypes from './modifier-type'; import * as ModifierTypes from './modifier-type';
import { CommonAnimPhase, LearnMovePhase, LevelUpPhase, MessagePhase, PokemonHealPhase } from "./battle-phases"; import { LearnMovePhase, LevelUpPhase, MessagePhase, PokemonHealPhase } from "./battle-phases";
import BattleScene from "./battle-scene"; import BattleScene from "./battle-scene";
import { getLevelTotalExp } from "./exp"; import { getLevelTotalExp } from "./exp";
import { PokeballType } from "./pokeball"; import { PokeballType } from "./pokeball";
@ -7,9 +7,12 @@ import Pokemon, { PlayerPokemon } from "./pokemon";
import { Stat } from "./pokemon-stat"; import { Stat } from "./pokemon-stat";
import { addTextObject, TextStyle } from "./text"; import { addTextObject, TextStyle } from "./text";
import * as Utils from "./utils"; import * as Utils from "./utils";
import { CommonAnim } from './battle-anims'; import { Type } from './type';
import { EvolutionPhase } from './evolution-phase';
import { pokemonEvolutions } from './pokemon-evolutions';
type ModifierType = ModifierTypes.ModifierType; type ModifierType = ModifierTypes.ModifierType;
export type ModifierPredicate = (modifier: Modifier) => boolean;
export class ModifierBar extends Phaser.GameObjects.Container { export class ModifierBar extends Phaser.GameObjects.Container {
constructor(scene: BattleScene) { constructor(scene: BattleScene) {
@ -253,6 +256,36 @@ export class PokemonBaseStatModifier extends PokemonHeldItemModifier {
} }
} }
export class AttackTypeBoosterModifier extends PokemonHeldItemModifier {
private moveType: Type;
private boostMultiplier: number;
constructor(type: ModifierType, pokemonId: integer, moveType: Type, boostPercent: integer) {
super(type, pokemonId);
this.moveType = moveType;
this.boostMultiplier = boostPercent * 0.01;
}
match(modifier: Modifier) {
return modifier instanceof AttackTypeBoosterModifier;
}
clone() {
return new AttackTypeBoosterModifier(this.type, this.pokemonId, this.moveType, this.boostMultiplier * 100);
}
shouldApply(args: any[]): boolean {
return super.shouldApply(args) && args.length === 2 && args[1] instanceof Utils.NumberHolder;
}
apply(args: any[]): boolean {
(args[1] as Utils.NumberHolder).value = Math.floor((args[1] as Utils.NumberHolder).value * (1 + (this.getStackCount() * this.boostMultiplier)));
return true;
}
}
export class HitHealModifier extends PokemonHeldItemModifier { export class HitHealModifier extends PokemonHeldItemModifier {
constructor(type: ModifierType, pokemonId: integer) { constructor(type: ModifierType, pokemonId: integer) {
super(type, pokemonId); super(type, pokemonId);
@ -270,7 +303,7 @@ export class HitHealModifier extends PokemonHeldItemModifier {
const pokemon = args[0] as PlayerPokemon; const pokemon = args[0] as PlayerPokemon;
if (pokemon.turnData.damageDealt && pokemon.getHpRatio() < 1) { if (pokemon.turnData.damageDealt && pokemon.getHpRatio() < 1) {
const scene = pokemon.scene as BattleScene; const scene = pokemon.scene;
const hpRestoreMultiplier = new Utils.IntegerHolder(1); const hpRestoreMultiplier = new Utils.IntegerHolder(1);
scene.applyModifiers(HealingBoosterModifier, hpRestoreMultiplier); scene.applyModifiers(HealingBoosterModifier, hpRestoreMultiplier);
@ -388,8 +421,7 @@ export class PokemonLevelIncrementModifier extends ConsumablePokemonModifier {
pokemon.exp = getLevelTotalExp(pokemon.level, pokemon.species.growthRate); pokemon.exp = getLevelTotalExp(pokemon.level, pokemon.species.growthRate);
pokemon.levelExp = 0; pokemon.levelExp = 0;
const scene = pokemon.scene as BattleScene; pokemon.scene.unshiftPhase(new LevelUpPhase(pokemon.scene, pokemon.scene.getParty().indexOf(pokemon), pokemon.level - 1, pokemon.level));
scene.unshiftPhase(new LevelUpPhase(scene, scene.getParty().indexOf(pokemon), pokemon.level - 1, pokemon.level));
return true; return true;
} }
@ -403,13 +435,32 @@ export class TmModifier extends ConsumablePokemonModifier {
apply(args: any[]): boolean { apply(args: any[]): boolean {
const pokemon = args[0] as PlayerPokemon; const pokemon = args[0] as PlayerPokemon;
const scene = pokemon.scene as BattleScene; pokemon.scene.unshiftPhase(new LearnMovePhase(pokemon.scene, pokemon.scene.getParty().indexOf(pokemon), (this.type as ModifierTypes.TmModifierType).moveId));
scene.unshiftPhase(new LearnMovePhase(scene, scene.getParty().indexOf(pokemon), (this.type as ModifierTypes.TmModifierType).moveId));
return true; return true;
} }
} }
export class EvolutionItemModifier extends ConsumablePokemonModifier {
constructor(type: ModifierTypes.EvolutionItemModifierType, pokemonId: integer) {
super(type, pokemonId);
}
apply(args: any[]): boolean {
const pokemon = args[0] as PlayerPokemon;
const matchingEvolution = pokemonEvolutions[pokemon.species.speciesId].find(e => e.item === (this.type as ModifierTypes.EvolutionItemModifierType).evolutionItem
&& (!e.condition || e.condition.predicate(pokemon)));
if (matchingEvolution) {
pokemon.scene.unshiftPhase(new EvolutionPhase(pokemon.scene, pokemon.scene.getParty().indexOf(pokemon), matchingEvolution, pokemon.level - 1));
return true;
}
return false;
}
}
export class PartyShareModifier extends PersistentModifier { export class PartyShareModifier extends PersistentModifier {
constructor(type: ModifierType) { constructor(type: ModifierType) {
super(type); super(type);

View File

@ -1,6 +1,13 @@
import { Biome } from "./biome";
import { AttackTypeBoosterModifier } from "./modifier";
import { AttackTypeBoosterModifierType } from "./modifier-type";
import { Moves } from "./move";
import { PokeballType } from "./pokeball";
import Pokemon from "./pokemon"; import Pokemon from "./pokemon";
import { Stat } from "./pokemon-stat"; import { Stat } from "./pokemon-stat";
import { Species } from "./species"; import { Species } from "./species";
import { Type } from "./type";
import * as Utils from "./utils";
export enum SpeciesWildEvolutionDelay { export enum SpeciesWildEvolutionDelay {
NONE, NONE,
@ -10,17 +17,32 @@ export enum SpeciesWildEvolutionDelay {
VERY_LONG VERY_LONG
} }
export enum EvolutionItem {
NONE,
LINKING_CORD,
SUN_STONE,
MOON_STONE,
LEAF_STONE,
FIRE_STONE,
WATER_STONE,
THUNDER_STONE,
ICE_STONE,
DUSK_STONE,
DAWN_STONE,
SHINY_STONE
}
export class SpeciesEvolution { export class SpeciesEvolution {
public speciesId: Species; public speciesId: Species;
public level: integer; public level: integer;
public item: string; public item: EvolutionItem;
public condition: SpeciesEvolutionCondition | string; public condition: SpeciesEvolutionCondition;
public wildDelay: SpeciesWildEvolutionDelay; public wildDelay: SpeciesWildEvolutionDelay;
constructor(speciesId: Species, level: integer, item: string, condition: SpeciesEvolutionCondition | string, wildDelay?: SpeciesWildEvolutionDelay) { constructor(speciesId: Species, level: integer, item: EvolutionItem, condition: SpeciesEvolutionCondition, wildDelay?: SpeciesWildEvolutionDelay) {
this.speciesId = speciesId; this.speciesId = speciesId;
this.level = level; this.level = level;
this.item = item; this.item = item || EvolutionItem.NONE;
this.condition = condition; this.condition = condition;
this.wildDelay = wildDelay || SpeciesWildEvolutionDelay.NONE; this.wildDelay = wildDelay || SpeciesWildEvolutionDelay.NONE;
} }
@ -142,7 +164,7 @@ export const pokemonEvolutions: PokemonEvolutions = {
], ],
[Species.SLOWPOKE]: [ [Species.SLOWPOKE]: [
new SpeciesEvolution(Species.SLOWBRO, 37, null, null), new SpeciesEvolution(Species.SLOWBRO, 37, null, null),
new SpeciesEvolution(Species.SLOWKING, 1, "Link Cable", new SpeciesEvolutionCondition((p: Pokemon) => true /* King's rock*/), SpeciesWildEvolutionDelay.VERY_LONG) new SpeciesEvolution(Species.SLOWKING, 1, EvolutionItem.LINKING_CORD, new SpeciesEvolutionCondition((p: Pokemon) => true /* King's rock*/), SpeciesWildEvolutionDelay.VERY_LONG)
], ],
[Species.MAGNEMITE]: [ [Species.MAGNEMITE]: [
new SpeciesEvolution(Species.MAGNETON, 30, null, null) new SpeciesEvolution(Species.MAGNETON, 30, null, null)
@ -324,8 +346,8 @@ export const pokemonEvolutions: PokemonEvolutions = {
new SpeciesEvolution(Species.LINOONE, 20, null, null) new SpeciesEvolution(Species.LINOONE, 20, null, null)
], ],
[Species.WURMPLE]: [ [Species.WURMPLE]: [
new SpeciesEvolution(Species.SILCOON, 7, null, 'random based on personality'), new SpeciesEvolution(Species.SILCOON, 7, null, new SpeciesEvolutionCondition((p: Pokemon) => Utils.randInt(2) === 0, true)), // TODO: Improve these conditions
new SpeciesEvolution(Species.CASCOON, 7, null, 'random based on personality') new SpeciesEvolution(Species.CASCOON, 7, null, new SpeciesEvolutionCondition((p: Pokemon) => Utils.randInt(2) === 0, true))
], ],
[Species.SILCOON]: [ [Species.SILCOON]: [
new SpeciesEvolution(Species.BEAUTIFLY, 10, null, null) new SpeciesEvolution(Species.BEAUTIFLY, 10, null, null)
@ -350,7 +372,7 @@ export const pokemonEvolutions: PokemonEvolutions = {
], ],
[Species.KIRLIA]: [ [Species.KIRLIA]: [
new SpeciesEvolution(Species.GARDEVOIR, 30, null, new SpeciesEvolutionCondition((p: Pokemon) => !p.gender, true)), new SpeciesEvolution(Species.GARDEVOIR, 30, null, new SpeciesEvolutionCondition((p: Pokemon) => !p.gender, true)),
new SpeciesEvolution(Species.GALLADE, 1, "Dawn Stone", new SpeciesEvolutionCondition((p: Pokemon) => p.gender, true), SpeciesWildEvolutionDelay.LONG) new SpeciesEvolution(Species.GALLADE, 1, EvolutionItem.DAWN_STONE, new SpeciesEvolutionCondition((p: Pokemon) => p.gender, true), SpeciesWildEvolutionDelay.LONG)
], ],
[Species.SURSKIT]: [ [Species.SURSKIT]: [
new SpeciesEvolution(Species.MASQUERAIN, 22, null, null) new SpeciesEvolution(Species.MASQUERAIN, 22, null, null)
@ -366,7 +388,7 @@ export const pokemonEvolutions: PokemonEvolutions = {
], ],
[Species.NINCADA]: [ [Species.NINCADA]: [
new SpeciesEvolution(Species.NINJASK, 20, null, null), new SpeciesEvolution(Species.NINJASK, 20, null, null),
new SpeciesEvolution(Species.SHEDINJA, 20, null, 'empty spot in party, Pokéball in bag') new SpeciesEvolution(Species.SHEDINJA, 20, null, new SpeciesEvolutionCondition((p: Pokemon) => p.scene.getParty().length < 6 && p.scene.pokeballCounts[PokeballType.POKEBALL], true))
], ],
[Species.WHISMUR]: [ [Species.WHISMUR]: [
new SpeciesEvolution(Species.LOUDRED, 20, null, null) new SpeciesEvolution(Species.LOUDRED, 20, null, null)
@ -439,7 +461,7 @@ export const pokemonEvolutions: PokemonEvolutions = {
], ],
[Species.SNORUNT]: [ [Species.SNORUNT]: [
new SpeciesEvolution(Species.GLALIE, 42, null, null), new SpeciesEvolution(Species.GLALIE, 42, null, null),
new SpeciesEvolution(Species.FROSLASS, 1, "Dawn Stone", new SpeciesEvolutionCondition((p: Pokemon) => !p.gender, true), SpeciesWildEvolutionDelay.VERY_LONG) new SpeciesEvolution(Species.FROSLASS, 1, EvolutionItem.DAWN_STONE, new SpeciesEvolutionCondition((p: Pokemon) => !p.gender, true), SpeciesWildEvolutionDelay.VERY_LONG)
], ],
[Species.SPHEAL]: [ [Species.SPHEAL]: [
new SpeciesEvolution(Species.SEALEO, 32, null, null) new SpeciesEvolution(Species.SEALEO, 32, null, null)
@ -503,9 +525,9 @@ export const pokemonEvolutions: PokemonEvolutions = {
], ],
[Species.BURMY]: [ [Species.BURMY]: [
new SpeciesEvolution(Species.MOTHIM, 20, null, new SpeciesEvolutionCondition((p: Pokemon) => p.gender, true)), new SpeciesEvolution(Species.MOTHIM, 20, null, new SpeciesEvolutionCondition((p: Pokemon) => p.gender, true)),
new SpeciesEvolution(Species.WORMADAM, 20, null, new SpeciesEvolutionCondition((p: Pokemon) => !p.gender/* && grass*/, true)), new SpeciesEvolution(Species.WORMADAM, 20, null, new SpeciesEvolutionCondition((p: Pokemon) => !p.gender && p.scene.arena.biomeType === Biome.FOREST, true)),
new SpeciesEvolution(Species.WORMADAM, 20, null, new SpeciesEvolutionCondition((p: Pokemon) => !p.gender/* && cave*/, true)), new SpeciesEvolution(Species.WORMADAM, 20, null, new SpeciesEvolutionCondition((p: Pokemon) => !p.gender && p.scene.arena.biomeType === Biome.CAVE, true)),
new SpeciesEvolution(Species.WORMADAM, 20, null, new SpeciesEvolutionCondition((p: Pokemon) => !p.gender/* && building*/, true)) new SpeciesEvolution(Species.WORMADAM, 20, null, new SpeciesEvolutionCondition((p: Pokemon) => !p.gender && p.scene.arena.biomeType === Biome.CITY, true))
], ],
[Species.COMBEE]: [ [Species.COMBEE]: [
new SpeciesEvolution(Species.VESPIQUEN, 21, null, new SpeciesEvolutionCondition((p: Pokemon) => !p.gender, true)) new SpeciesEvolution(Species.VESPIQUEN, 21, null, new SpeciesEvolutionCondition((p: Pokemon) => !p.gender, true))
@ -730,199 +752,203 @@ export const pokemonEvolutions: PokemonEvolutions = {
new SpeciesEvolution(Species.VOLCARONA, 59, null, null) new SpeciesEvolution(Species.VOLCARONA, 59, null, null)
], ],
[Species.PIKACHU]: [ [Species.PIKACHU]: [
new SpeciesEvolution(Species.RAICHU, 1, "Thunder Stone", null, SpeciesWildEvolutionDelay.LONG) new SpeciesEvolution(Species.RAICHU, 1, EvolutionItem.THUNDER_STONE, null, SpeciesWildEvolutionDelay.LONG)
], ],
[Species.NIDORINA]: [ [Species.NIDORINA]: [
new SpeciesEvolution(Species.NIDOQUEEN, 1, "Moon Stone", null, SpeciesWildEvolutionDelay.LONG) new SpeciesEvolution(Species.NIDOQUEEN, 1, EvolutionItem.MOON_STONE, null, SpeciesWildEvolutionDelay.LONG)
], ],
[Species.NIDORINO]: [ [Species.NIDORINO]: [
new SpeciesEvolution(Species.NIDOKING, 1, "Moon Stone", null, SpeciesWildEvolutionDelay.LONG) new SpeciesEvolution(Species.NIDOKING, 1, EvolutionItem.MOON_STONE, null, SpeciesWildEvolutionDelay.LONG)
], ],
[Species.CLEFAIRY]: [ [Species.CLEFAIRY]: [
new SpeciesEvolution(Species.CLEFABLE, 1, "Moon Stone", null, SpeciesWildEvolutionDelay.LONG) new SpeciesEvolution(Species.CLEFABLE, 1, EvolutionItem.MOON_STONE, null, SpeciesWildEvolutionDelay.LONG)
], ],
[Species.VULPIX]: [ [Species.VULPIX]: [
new SpeciesEvolution(Species.NINETALES, 1, "Fire Stone", null, SpeciesWildEvolutionDelay.LONG) new SpeciesEvolution(Species.NINETALES, 1, EvolutionItem.FIRE_STONE, null, SpeciesWildEvolutionDelay.LONG)
], ],
[Species.JIGGLYPUFF]: [ [Species.JIGGLYPUFF]: [
new SpeciesEvolution(Species.WIGGLYTUFF, 1, "Moon Stone", null, SpeciesWildEvolutionDelay.LONG) new SpeciesEvolution(Species.WIGGLYTUFF, 1, EvolutionItem.MOON_STONE, null, SpeciesWildEvolutionDelay.LONG)
], ],
[Species.GLOOM]: [ [Species.GLOOM]: [
new SpeciesEvolution(Species.VILEPLUME, 1, "Leaf Stone", null, SpeciesWildEvolutionDelay.LONG), new SpeciesEvolution(Species.VILEPLUME, 1, EvolutionItem.LEAF_STONE, null, SpeciesWildEvolutionDelay.LONG),
new SpeciesEvolution(Species.BELLOSSOM, 1, "Sun Stone", null, SpeciesWildEvolutionDelay.LONG) new SpeciesEvolution(Species.BELLOSSOM, 1, EvolutionItem.SUN_STONE, null, SpeciesWildEvolutionDelay.LONG)
], ],
[Species.GROWLITHE]: [ [Species.GROWLITHE]: [
new SpeciesEvolution(Species.ARCANINE, 1, "Fire Stone", null, SpeciesWildEvolutionDelay.LONG) new SpeciesEvolution(Species.ARCANINE, 1, EvolutionItem.FIRE_STONE, null, SpeciesWildEvolutionDelay.LONG)
], ],
[Species.POLIWHIRL]: [ [Species.POLIWHIRL]: [
new SpeciesEvolution(Species.POLIWRATH, 1, "Water Stone", null, SpeciesWildEvolutionDelay.LONG), new SpeciesEvolution(Species.POLIWRATH, 1, EvolutionItem.WATER_STONE, null, SpeciesWildEvolutionDelay.LONG),
new SpeciesEvolution(Species.POLITOED, 1, "Link Cable", new SpeciesEvolutionCondition((p: Pokemon) => true /* King's rock*/), SpeciesWildEvolutionDelay.VERY_LONG) new SpeciesEvolution(Species.POLITOED, 1, EvolutionItem.LINKING_CORD, new SpeciesEvolutionCondition((p: Pokemon) => true /* King's rock*/), SpeciesWildEvolutionDelay.VERY_LONG)
], ],
[Species.WEEPINBELL]: [ [Species.WEEPINBELL]: [
new SpeciesEvolution(Species.VICTREEBEL, 1, "Leaf Stone", null, SpeciesWildEvolutionDelay.LONG) new SpeciesEvolution(Species.VICTREEBEL, 1, EvolutionItem.LEAF_STONE, null, SpeciesWildEvolutionDelay.LONG)
], ],
[Species.MAGNETON]: [ [Species.MAGNETON]: [
new SpeciesEvolution(Species.MAGNEZONE, 1, "Thunder Stone", null, SpeciesWildEvolutionDelay.VERY_LONG) new SpeciesEvolution(Species.MAGNEZONE, 1, EvolutionItem.THUNDER_STONE, null, SpeciesWildEvolutionDelay.LONG)
], ],
[Species.SHELLDER]: [ [Species.SHELLDER]: [
new SpeciesEvolution(Species.CLOYSTER, 1, "Water Stone", null, SpeciesWildEvolutionDelay.MEDIUM) new SpeciesEvolution(Species.CLOYSTER, 1, EvolutionItem.WATER_STONE, null, SpeciesWildEvolutionDelay.MEDIUM)
], ],
[Species.EXEGGCUTE]: [ [Species.EXEGGCUTE]: [
new SpeciesEvolution(Species.EXEGGUTOR, 1, "Leaf Stone", null, SpeciesWildEvolutionDelay.LONG) new SpeciesEvolution(Species.EXEGGUTOR, 1, EvolutionItem.LEAF_STONE, null, SpeciesWildEvolutionDelay.LONG)
], ],
[Species.TANGELA]: [ [Species.TANGELA]: [
new SpeciesEvolution(Species.TANGROWTH, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => true /* Ancient power learned*/), SpeciesWildEvolutionDelay.LONG) new SpeciesEvolution(Species.TANGROWTH, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => p.moveset.filter(m => m.moveId === Moves.ANCIENT_POWER).length), SpeciesWildEvolutionDelay.LONG)
], ],
[Species.LICKITUNG]: [ [Species.LICKITUNG]: [
new SpeciesEvolution(Species.LICKILICKY, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => true /* Rollout learned*/), SpeciesWildEvolutionDelay.LONG) new SpeciesEvolution(Species.LICKILICKY, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => p.moveset.filter(m => m.moveId === Moves.ROLLOUT).length), SpeciesWildEvolutionDelay.LONG)
], ],
[Species.STARYU]: [ [Species.STARYU]: [
new SpeciesEvolution(Species.STARMIE, 1, "Water Stone", null, SpeciesWildEvolutionDelay.MEDIUM) new SpeciesEvolution(Species.STARMIE, 1, EvolutionItem.WATER_STONE, null, SpeciesWildEvolutionDelay.MEDIUM)
], ],
[Species.EEVEE]: [ [Species.EEVEE]: [
new SpeciesEvolution(Species.ESPEON, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => p.winCount >= 10 /* daytime */), SpeciesWildEvolutionDelay.MEDIUM), new SpeciesEvolution(Species.ESPEON, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => p.winCount >= 10 && p.scene.arena.isDaytime()), SpeciesWildEvolutionDelay.MEDIUM),
new SpeciesEvolution(Species.UMBREON, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => p.winCount >= 10 /* nighttime */), SpeciesWildEvolutionDelay.MEDIUM), new SpeciesEvolution(Species.UMBREON, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => p.winCount >= 10 && !p.scene.arena.isDaytime()), SpeciesWildEvolutionDelay.MEDIUM),
new SpeciesEvolution(Species.VAPOREON, 1, "Water Stone", null, SpeciesWildEvolutionDelay.MEDIUM), new SpeciesEvolution(Species.VAPOREON, 1, EvolutionItem.WATER_STONE, null, SpeciesWildEvolutionDelay.MEDIUM),
new SpeciesEvolution(Species.JOLTEON, 1, "Thunder Stone", null, SpeciesWildEvolutionDelay.MEDIUM), new SpeciesEvolution(Species.JOLTEON, 1, EvolutionItem.THUNDER_STONE, null, SpeciesWildEvolutionDelay.MEDIUM),
new SpeciesEvolution(Species.FLAREON, 1, "Fire Stone", null, SpeciesWildEvolutionDelay.MEDIUM), new SpeciesEvolution(Species.FLAREON, 1, EvolutionItem.FIRE_STONE, null, SpeciesWildEvolutionDelay.MEDIUM),
new SpeciesEvolution(Species.LEAFEON, 1, "Leaf Stone", null, SpeciesWildEvolutionDelay.MEDIUM), new SpeciesEvolution(Species.LEAFEON, 1, EvolutionItem.LEAF_STONE, null, SpeciesWildEvolutionDelay.MEDIUM),
new SpeciesEvolution(Species.GLACEON, 1, "Ice Stone", null, SpeciesWildEvolutionDelay.MEDIUM) new SpeciesEvolution(Species.GLACEON, 1, EvolutionItem.ICE_STONE, null, SpeciesWildEvolutionDelay.MEDIUM)
], ],
[Species.TOGETIC]: [ [Species.TOGETIC]: [
new SpeciesEvolution(Species.TOGEKISS, 1, "Shiny Stone", null, SpeciesWildEvolutionDelay.VERY_LONG) new SpeciesEvolution(Species.TOGEKISS, 1, EvolutionItem.SHINY_STONE, null, SpeciesWildEvolutionDelay.VERY_LONG)
], ],
[Species.AIPOM]: [ [Species.AIPOM]: [
new SpeciesEvolution(Species.AMBIPOM, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => true /* Double hit learned*/), SpeciesWildEvolutionDelay.LONG) new SpeciesEvolution(Species.AMBIPOM, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => p.moveset.filter(m => m.moveId === Moves.DOUBLE_HIT).length), SpeciesWildEvolutionDelay.LONG)
], ],
[Species.SUNKERN]: [ [Species.SUNKERN]: [
new SpeciesEvolution(Species.SUNFLORA, 1, "Sun Stone", null, SpeciesWildEvolutionDelay.MEDIUM) new SpeciesEvolution(Species.SUNFLORA, 1, EvolutionItem.SUN_STONE, null, SpeciesWildEvolutionDelay.MEDIUM)
], ],
[Species.YANMA]: [ [Species.YANMA]: [
new SpeciesEvolution(Species.YANMEGA, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => true /* Rollout learned*/), SpeciesWildEvolutionDelay.LONG) new SpeciesEvolution(Species.YANMEGA, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => p.moveset.filter(m => m.moveId === Moves.ROLLOUT).length), SpeciesWildEvolutionDelay.LONG)
], ],
[Species.MURKROW]: [ [Species.MURKROW]: [
new SpeciesEvolution(Species.HONCHKROW, 1, "Dusk Stone", null, SpeciesWildEvolutionDelay.VERY_LONG) new SpeciesEvolution(Species.HONCHKROW, 1, EvolutionItem.DUSK_STONE, null, SpeciesWildEvolutionDelay.VERY_LONG)
], ],
[Species.MISDREAVUS]: [ [Species.MISDREAVUS]: [
new SpeciesEvolution(Species.MISMAGIUS, 1, "Dusk Stone", null, SpeciesWildEvolutionDelay.VERY_LONG) new SpeciesEvolution(Species.MISMAGIUS, 1, EvolutionItem.DUSK_STONE, null, SpeciesWildEvolutionDelay.VERY_LONG)
], ],
[Species.GLIGAR]: [ [Species.GLIGAR]: [
new SpeciesEvolution(Species.GLISCOR, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => true /* Razor fang at night*/), SpeciesWildEvolutionDelay.LONG) new SpeciesEvolution(Species.GLISCOR, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => !p.scene.arena.isDaytime() /* Razor fang at night*/), SpeciesWildEvolutionDelay.LONG)
], ],
[Species.SNEASEL]: [ [Species.SNEASEL]: [
new SpeciesEvolution(Species.WEAVILE, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => true /* Razor claw at night*/), SpeciesWildEvolutionDelay.LONG) new SpeciesEvolution(Species.WEAVILE, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => !p.scene.arena.isDaytime() /* Razor claw at night*/), SpeciesWildEvolutionDelay.LONG)
], ],
[Species.PILOSWINE]: [ [Species.PILOSWINE]: [
new SpeciesEvolution(Species.MAMOSWINE, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => true /* Ancient power learned*/), SpeciesWildEvolutionDelay.VERY_LONG) new SpeciesEvolution(Species.MAMOSWINE, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => p.moveset.filter(m => m.moveId === Moves.ANCIENT_POWER).length), SpeciesWildEvolutionDelay.VERY_LONG)
], ],
[Species.LOMBRE]: [ [Species.LOMBRE]: [
new SpeciesEvolution(Species.LUDICOLO, 1, "Water Stone", null, SpeciesWildEvolutionDelay.LONG) new SpeciesEvolution(Species.LUDICOLO, 1, EvolutionItem.WATER_STONE, null, SpeciesWildEvolutionDelay.LONG)
], ],
[Species.NUZLEAF]: [ [Species.NUZLEAF]: [
new SpeciesEvolution(Species.SHIFTRY, 1, "Leaf Stone", null, SpeciesWildEvolutionDelay.LONG) new SpeciesEvolution(Species.SHIFTRY, 1, EvolutionItem.LEAF_STONE, null, SpeciesWildEvolutionDelay.LONG)
], ],
[Species.NOSEPASS]: [ [Species.NOSEPASS]: [
new SpeciesEvolution(Species.PROBOPASS, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => true /* Magnetic field??*/), SpeciesWildEvolutionDelay.LONG) new SpeciesEvolution(Species.PROBOPASS, 1, EvolutionItem.THUNDER_STONE, null, SpeciesWildEvolutionDelay.LONG)
], ],
[Species.SKITTY]: [ [Species.SKITTY]: [
new SpeciesEvolution(Species.DELCATTY, 1, "Moon Stone", null, SpeciesWildEvolutionDelay.MEDIUM) new SpeciesEvolution(Species.DELCATTY, 1, EvolutionItem.MOON_STONE, null, SpeciesWildEvolutionDelay.MEDIUM)
], ],
[Species.ROSELIA]: [ [Species.ROSELIA]: [
new SpeciesEvolution(Species.ROSERADE, 1, "Shiny Stone", null, SpeciesWildEvolutionDelay.VERY_LONG) new SpeciesEvolution(Species.ROSERADE, 1, EvolutionItem.SHINY_STONE, null, SpeciesWildEvolutionDelay.VERY_LONG)
], ],
[Species.BONSLY]: [ [Species.BONSLY]: [
new SpeciesEvolution(Species.SUDOWOODO, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => true /* Mimic learned */), SpeciesWildEvolutionDelay.MEDIUM) new SpeciesEvolution(Species.SUDOWOODO, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => p.moveset.filter(m => m.moveId === Moves.MIMIC).length), SpeciesWildEvolutionDelay.MEDIUM)
], ],
[Species.MIME_JR]: [ [Species.MIME_JR]: [
new SpeciesEvolution(Species.MR_MIME, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => true /* Mimic learned */), SpeciesWildEvolutionDelay.MEDIUM) new SpeciesEvolution(Species.MR_MIME, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => p.moveset.filter(m => m.moveId === Moves.MIMIC).length), SpeciesWildEvolutionDelay.MEDIUM)
], ],
[Species.MANTYKE]: [ [Species.MANTYKE]: [
new SpeciesEvolution(Species.MANTINE, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => true /* Remoraid in party */), SpeciesWildEvolutionDelay.MEDIUM) new SpeciesEvolution(Species.MANTINE, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => p.scene.getParty().find(p => p.species.speciesId === Species.REMORAID)), SpeciesWildEvolutionDelay.MEDIUM)
], ],
[Species.PANSAGE]: [ [Species.PANSAGE]: [
new SpeciesEvolution(Species.SIMISAGE, 1, "Leaf Stone", null, SpeciesWildEvolutionDelay.MEDIUM) new SpeciesEvolution(Species.SIMISAGE, 1, EvolutionItem.LEAF_STONE, null, SpeciesWildEvolutionDelay.MEDIUM)
], ],
[Species.PANSEAR]: [ [Species.PANSEAR]: [
new SpeciesEvolution(Species.SIMISEAR, 1, "Fire Stone", null, SpeciesWildEvolutionDelay.MEDIUM) new SpeciesEvolution(Species.SIMISEAR, 1, EvolutionItem.FIRE_STONE, null, SpeciesWildEvolutionDelay.MEDIUM)
], ],
[Species.PANPOUR]: [ [Species.PANPOUR]: [
new SpeciesEvolution(Species.SIMIPOUR, 1, "Water Stone", null, SpeciesWildEvolutionDelay.MEDIUM) new SpeciesEvolution(Species.SIMIPOUR, 1, EvolutionItem.WATER_STONE, null, SpeciesWildEvolutionDelay.MEDIUM)
], ],
[Species.MUNNA]: [ [Species.MUNNA]: [
new SpeciesEvolution(Species.MUSHARNA, 1, "Moon Stone", null, SpeciesWildEvolutionDelay.LONG) new SpeciesEvolution(Species.MUSHARNA, 1, EvolutionItem.MOON_STONE, null, SpeciesWildEvolutionDelay.LONG)
], ],
[Species.COTTONEE]: [ [Species.COTTONEE]: [
new SpeciesEvolution(Species.WHIMSICOTT, 1, "Sun Stone", null, SpeciesWildEvolutionDelay.MEDIUM) new SpeciesEvolution(Species.WHIMSICOTT, 1, EvolutionItem.SUN_STONE, null, SpeciesWildEvolutionDelay.MEDIUM)
], ],
[Species.PETILIL]: [ [Species.PETILIL]: [
new SpeciesEvolution(Species.LILLIGANT, 1, "Sun Stone", null, SpeciesWildEvolutionDelay.MEDIUM) new SpeciesEvolution(Species.LILLIGANT, 1, EvolutionItem.SUN_STONE, null, SpeciesWildEvolutionDelay.MEDIUM)
], ],
[Species.MINCCINO]: [ [Species.MINCCINO]: [
new SpeciesEvolution(Species.CINCCINO, 1, "Shiny Stone", null, SpeciesWildEvolutionDelay.SHORT) new SpeciesEvolution(Species.CINCCINO, 1, EvolutionItem.SHINY_STONE, null, SpeciesWildEvolutionDelay.SHORT)
], ],
[Species.EELEKTRIK]: [ [Species.EELEKTRIK]: [
new SpeciesEvolution(Species.EELEKTROSS, 1, "Thunder Stone", null, SpeciesWildEvolutionDelay.VERY_LONG) new SpeciesEvolution(Species.EELEKTROSS, 1, EvolutionItem.THUNDER_STONE, null, SpeciesWildEvolutionDelay.VERY_LONG)
], ],
[Species.LAMPENT]: [ [Species.LAMPENT]: [
new SpeciesEvolution(Species.CHANDELURE, 1, "Dusk Stone", null, SpeciesWildEvolutionDelay.VERY_LONG) new SpeciesEvolution(Species.CHANDELURE, 1, EvolutionItem.DUSK_STONE, null, SpeciesWildEvolutionDelay.VERY_LONG)
], ],
[Species.KADABRA]: [ [Species.KADABRA]: [
new SpeciesEvolution(Species.ALAKAZAM, 1, "Link Cable", null, SpeciesWildEvolutionDelay.VERY_LONG) new SpeciesEvolution(Species.ALAKAZAM, 1, EvolutionItem.LINKING_CORD, null, SpeciesWildEvolutionDelay.VERY_LONG)
], ],
[Species.MACHOKE]: [ [Species.MACHOKE]: [
new SpeciesEvolution(Species.MACHAMP, 1, "Link Cable", null, SpeciesWildEvolutionDelay.VERY_LONG) new SpeciesEvolution(Species.MACHAMP, 1, EvolutionItem.LINKING_CORD, null, SpeciesWildEvolutionDelay.VERY_LONG)
], ],
[Species.GRAVELER]: [ [Species.GRAVELER]: [
new SpeciesEvolution(Species.GOLEM, 1, "Link Cable", null, SpeciesWildEvolutionDelay.VERY_LONG) new SpeciesEvolution(Species.GOLEM, 1, EvolutionItem.LINKING_CORD, null, SpeciesWildEvolutionDelay.VERY_LONG)
], ],
[Species.HAUNTER]: [ [Species.HAUNTER]: [
new SpeciesEvolution(Species.GENGAR, 1, "Link Cable", new SpeciesEvolutionCondition((p: Pokemon) => true), SpeciesWildEvolutionDelay.VERY_LONG) new SpeciesEvolution(Species.GENGAR, 1, EvolutionItem.LINKING_CORD, null, SpeciesWildEvolutionDelay.VERY_LONG)
], ],
[Species.ONIX]: [ [Species.ONIX]: [
new SpeciesEvolution(Species.STEELIX, 1, "Link Cable", new SpeciesEvolutionCondition((p: Pokemon) => true /* Metal coat*/ ), SpeciesWildEvolutionDelay.VERY_LONG) new SpeciesEvolution(Species.STEELIX, 1, EvolutionItem.LINKING_CORD, new SpeciesEvolutionCondition(
(p: Pokemon) => p.scene.findModifier(m => m instanceof AttackTypeBoosterModifier && (m.type as AttackTypeBoosterModifierType).moveType === Type.STEEL)),
SpeciesWildEvolutionDelay.VERY_LONG)
], ],
[Species.RHYDON]: [ [Species.RHYDON]: [
new SpeciesEvolution(Species.RHYPERIOR, 1, "Link Cable", new SpeciesEvolutionCondition((p: Pokemon) => true /* Protector */), SpeciesWildEvolutionDelay.VERY_LONG) new SpeciesEvolution(Species.RHYPERIOR, 1, EvolutionItem.LINKING_CORD, new SpeciesEvolutionCondition((p: Pokemon) => true /* Protector */), SpeciesWildEvolutionDelay.VERY_LONG)
], ],
[Species.SEADRA]: [ [Species.SEADRA]: [
new SpeciesEvolution(Species.KINGDRA, 1, "Link Cable", new SpeciesEvolutionCondition((p: Pokemon) => true /* Dragon scale*/), SpeciesWildEvolutionDelay.VERY_LONG) new SpeciesEvolution(Species.KINGDRA, 1, EvolutionItem.LINKING_CORD, new SpeciesEvolutionCondition((p: Pokemon) => true /* Dragon scale*/), SpeciesWildEvolutionDelay.VERY_LONG)
], ],
[Species.SCYTHER]: [ [Species.SCYTHER]: [
new SpeciesEvolution(Species.SCIZOR, 1, "Link Cable", new SpeciesEvolutionCondition((p: Pokemon) => true /* Metal coat*/), SpeciesWildEvolutionDelay.VERY_LONG) new SpeciesEvolution(Species.SCIZOR, 1, EvolutionItem.LINKING_CORD, new SpeciesEvolutionCondition(
(p: Pokemon) => p.scene.findModifier(m => m instanceof AttackTypeBoosterModifier && (m.type as AttackTypeBoosterModifierType).moveType === Type.STEEL) ),
SpeciesWildEvolutionDelay.VERY_LONG)
], ],
[Species.ELECTABUZZ]: [ [Species.ELECTABUZZ]: [
new SpeciesEvolution(Species.ELECTIVIRE, 1, "Link Cable", new SpeciesEvolutionCondition((p: Pokemon) => true /* Electirizer*/), SpeciesWildEvolutionDelay.VERY_LONG) new SpeciesEvolution(Species.ELECTIVIRE, 1, EvolutionItem.LINKING_CORD, new SpeciesEvolutionCondition((p: Pokemon) => true /* Electirizer*/), SpeciesWildEvolutionDelay.VERY_LONG)
], ],
[Species.MAGMAR]: [ [Species.MAGMAR]: [
new SpeciesEvolution(Species.MAGMORTAR, 1, "Link Cable", new SpeciesEvolutionCondition((p: Pokemon) => true /* Magmarizer*/), SpeciesWildEvolutionDelay.VERY_LONG) new SpeciesEvolution(Species.MAGMORTAR, 1, EvolutionItem.LINKING_CORD, new SpeciesEvolutionCondition((p: Pokemon) => true /* Magmarizer*/), SpeciesWildEvolutionDelay.VERY_LONG)
], ],
[Species.PORYGON]: [ [Species.PORYGON]: [
new SpeciesEvolution(Species.PORYGON2, 1, "Link Cable", new SpeciesEvolutionCondition((p: Pokemon) => true /*Upgrade*/), SpeciesWildEvolutionDelay.MEDIUM) new SpeciesEvolution(Species.PORYGON2, 1, EvolutionItem.LINKING_CORD, new SpeciesEvolutionCondition((p: Pokemon) => true /*Upgrade*/), SpeciesWildEvolutionDelay.MEDIUM)
], ],
[Species.PORYGON2]: [ [Species.PORYGON2]: [
new SpeciesEvolution(Species.PORYGON_Z, 1, "Link Cable", new SpeciesEvolutionCondition((p: Pokemon) => true /* Dubious disc*/), SpeciesWildEvolutionDelay.VERY_LONG) new SpeciesEvolution(Species.PORYGON_Z, 1, EvolutionItem.LINKING_CORD, new SpeciesEvolutionCondition((p: Pokemon) => true /* Dubious disc*/), SpeciesWildEvolutionDelay.VERY_LONG)
], ],
[Species.FEEBAS]: [ [Species.FEEBAS]: [
new SpeciesEvolution(Species.MILOTIC, 1, "Link Cable", new SpeciesEvolutionCondition((p: Pokemon) => true /* Prism scale*/), SpeciesWildEvolutionDelay.VERY_LONG) new SpeciesEvolution(Species.MILOTIC, 1, EvolutionItem.LINKING_CORD, new SpeciesEvolutionCondition((p: Pokemon) => true /* Prism scale*/), SpeciesWildEvolutionDelay.VERY_LONG)
], ],
[Species.DUSCLOPS]: [ [Species.DUSCLOPS]: [
new SpeciesEvolution(Species.DUSKNOIR, 1, "Link Cable", new SpeciesEvolutionCondition((p: Pokemon) => true /* Reaper cloth*/), SpeciesWildEvolutionDelay.VERY_LONG) new SpeciesEvolution(Species.DUSKNOIR, 1, EvolutionItem.LINKING_CORD, new SpeciesEvolutionCondition((p: Pokemon) => true /* Reaper cloth*/), SpeciesWildEvolutionDelay.VERY_LONG)
], ],
[Species.CLAMPERL]: [ [Species.CLAMPERL]: [
new SpeciesEvolution(Species.HUNTAIL, 1, "Link Cable", new SpeciesEvolutionCondition((p: Pokemon) => true /* Deep sea tooth*/), SpeciesWildEvolutionDelay.MEDIUM), new SpeciesEvolution(Species.HUNTAIL, 1, EvolutionItem.LINKING_CORD, new SpeciesEvolutionCondition((p: Pokemon) => true /* Deep sea tooth*/), SpeciesWildEvolutionDelay.MEDIUM),
new SpeciesEvolution(Species.GOREBYSS, 1, "Link Cable", new SpeciesEvolutionCondition((p: Pokemon) => true /* Deep sea scale*/), SpeciesWildEvolutionDelay.MEDIUM) new SpeciesEvolution(Species.GOREBYSS, 1, EvolutionItem.LINKING_CORD, new SpeciesEvolutionCondition((p: Pokemon) => true /* Deep sea scale*/), SpeciesWildEvolutionDelay.MEDIUM)
], ],
[Species.BOLDORE]: [ [Species.BOLDORE]: [
new SpeciesEvolution(Species.GIGALITH, 1, "Link Cable", null, SpeciesWildEvolutionDelay.VERY_LONG) new SpeciesEvolution(Species.GIGALITH, 1, EvolutionItem.LINKING_CORD, null, SpeciesWildEvolutionDelay.VERY_LONG)
], ],
[Species.GURDURR]: [ [Species.GURDURR]: [
new SpeciesEvolution(Species.CONKELDURR, 1, "Link Cable", null, SpeciesWildEvolutionDelay.VERY_LONG) new SpeciesEvolution(Species.CONKELDURR, 1, EvolutionItem.LINKING_CORD, null, SpeciesWildEvolutionDelay.VERY_LONG)
], ],
[Species.KARRABLAST]: [ [Species.KARRABLAST]: [
new SpeciesEvolution(Species.ESCAVALIER, 1, "Link Cable", new SpeciesEvolutionCondition((p: Pokemon) => true /* Trade with shelmet??*/), SpeciesWildEvolutionDelay.LONG) new SpeciesEvolution(Species.ESCAVALIER, 1, EvolutionItem.LINKING_CORD, new SpeciesEvolutionCondition((p: Pokemon) => p.scene.getParty().find(p => p.species.speciesId === Species.SHELMET)), SpeciesWildEvolutionDelay.LONG)
], ],
[Species.SHELMET]: [ [Species.SHELMET]: [
new SpeciesEvolution(Species.ACCELGOR, 1, "Link Cable", new SpeciesEvolutionCondition((p: Pokemon) => true /* Trade with karrablast??*/), SpeciesWildEvolutionDelay.LONG) new SpeciesEvolution(Species.ACCELGOR, 1, EvolutionItem.LINKING_CORD, new SpeciesEvolutionCondition((p: Pokemon) => p.scene.getParty().find(p => p.species.speciesId === Species.KARRABLAST)), SpeciesWildEvolutionDelay.LONG)
], ],
[Species.PICHU]: [ [Species.PICHU]: [
new SpeciesEvolution(Species.PIKACHU, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => p.winCount >= 10), SpeciesWildEvolutionDelay.SHORT) new SpeciesEvolution(Species.PIKACHU, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => p.winCount >= 10), SpeciesWildEvolutionDelay.SHORT)
@ -949,16 +975,16 @@ export const pokemonEvolutions: PokemonEvolutions = {
new SpeciesEvolution(Species.MARILL, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => p.winCount >= 10), SpeciesWildEvolutionDelay.SHORT) new SpeciesEvolution(Species.MARILL, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => p.winCount >= 10), SpeciesWildEvolutionDelay.SHORT)
], ],
[Species.BUDEW]: [ [Species.BUDEW]: [
new SpeciesEvolution(Species.ROSELIA, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => p.winCount > 10 /* daytime */), SpeciesWildEvolutionDelay.SHORT) new SpeciesEvolution(Species.ROSELIA, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => p.winCount > 10 && p.scene.arena.isDaytime()), SpeciesWildEvolutionDelay.SHORT)
], ],
[Species.CHINGLING]: [ [Species.CHINGLING]: [
new SpeciesEvolution(Species.CHIMECHO, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => p.winCount >= 10 /* nighttime */), SpeciesWildEvolutionDelay.MEDIUM) new SpeciesEvolution(Species.CHIMECHO, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => p.winCount >= 10 && !p.scene.arena.isDaytime()), SpeciesWildEvolutionDelay.MEDIUM)
], ],
[Species.BUNEARY]: [ [Species.BUNEARY]: [
new SpeciesEvolution(Species.LOPUNNY, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => p.winCount >= 10), SpeciesWildEvolutionDelay.MEDIUM) new SpeciesEvolution(Species.LOPUNNY, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => p.winCount >= 10), SpeciesWildEvolutionDelay.MEDIUM)
], ],
[Species.RIOLU]: [ [Species.RIOLU]: [
new SpeciesEvolution(Species.LUCARIO, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => p.winCount >= 10 /* daytime */), SpeciesWildEvolutionDelay.MEDIUM) new SpeciesEvolution(Species.LUCARIO, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => p.winCount >= 10 && p.scene.arena.isDaytime()), SpeciesWildEvolutionDelay.MEDIUM)
], ],
[Species.WOOBAT]: [ [Species.WOOBAT]: [
new SpeciesEvolution(Species.SWOOBAT, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => p.winCount >= 10), SpeciesWildEvolutionDelay.MEDIUM) new SpeciesEvolution(Species.SWOOBAT, 1, null, new SpeciesEvolutionCondition((p: Pokemon) => p.winCount >= 10), SpeciesWildEvolutionDelay.MEDIUM)

View File

@ -8,7 +8,7 @@ import * as Utils from './utils';
import { Type, getTypeDamageMultiplier } from './type'; import { Type, getTypeDamageMultiplier } from './type';
import { getLevelTotalExp } from './exp'; import { getLevelTotalExp } from './exp';
import { Stat } from './pokemon-stat'; import { Stat } from './pokemon-stat';
import { PokemonBaseStatModifier as PokemonBaseStatBoosterModifier, ShinyRateBoosterModifier } from './modifier'; import { AttackTypeBoosterModifier, PokemonBaseStatModifier as PokemonBaseStatBoosterModifier, ShinyRateBoosterModifier } from './modifier';
import { PokeballType } from './pokeball'; import { PokeballType } from './pokeball';
import { Gender } from './gender'; import { Gender } from './gender';
import { initMoveAnim, loadMoveAnimAssets } from './battle-anims'; import { initMoveAnim, loadMoveAnimAssets } from './battle-anims';
@ -18,6 +18,7 @@ import { pokemonEvolutions, SpeciesEvolution, SpeciesEvolutionCondition } from '
import { MessagePhase } from './battle-phases'; import { MessagePhase } from './battle-phases';
import { BattleStat } from './battle-stat'; import { BattleStat } from './battle-stat';
import { BattleTag, BattleTagLapseType, BattleTagType } from './battle-tag'; import { BattleTag, BattleTagLapseType, BattleTagType } from './battle-tag';
import { Species } from './species';
export default abstract class Pokemon extends Phaser.GameObjects.Container { export default abstract class Pokemon extends Phaser.GameObjects.Container {
public id: integer; public id: integer;
@ -95,11 +96,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const rand1 = Utils.binToDec(Utils.decToBin(this.id).substring(0, 16)); const rand1 = Utils.binToDec(Utils.decToBin(this.id).substring(0, 16));
const rand2 = Utils.binToDec(Utils.decToBin(this.id).substring(16, 32)); const rand2 = Utils.binToDec(Utils.decToBin(this.id).substring(16, 32));
const E = (this.scene as BattleScene).trainerId ^ (this.scene as BattleScene).secretId; const E = this.scene.trainerId ^ this.scene.secretId;
const F = rand1 ^ rand2; const F = rand1 ^ rand2;
let shinyThreshold = new Utils.IntegerHolder(32); let shinyThreshold = new Utils.IntegerHolder(32);
(this.scene as BattleScene).applyModifiers(ShinyRateBoosterModifier, shinyThreshold); this.scene.applyModifiers(ShinyRateBoosterModifier, shinyThreshold);
console.log(shinyThreshold.value); console.log(shinyThreshold.value);
this.shiny = (E ^ F) < shinyThreshold.value; this.shiny = (E ^ F) < shinyThreshold.value;
@ -113,11 +114,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
this.winCount = 0; this.winCount = 0;
} }
//this.setPipeline((this.scene as BattleScene).spritePipeline); //this.setPipeline(this.scene).spritePipeline);
this.calculateStats(); this.calculateStats();
(scene as BattleScene).fieldUI.addAt(this.battleInfo, 0); scene.fieldUI.addAt(this.battleInfo, 0);
this.battleInfo.initInfo(this); this.battleInfo.initInfo(this);
@ -163,10 +164,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const moveIds = this.moveset.map(m => m.getMove().id); const moveIds = this.moveset.map(m => m.getMove().id);
Promise.allSettled(moveIds.map(m => initMoveAnim(m))) Promise.allSettled(moveIds.map(m => initMoveAnim(m)))
.then(() => { .then(() => {
loadMoveAnimAssets(this.scene as BattleScene, moveIds); loadMoveAnimAssets(this.scene, moveIds);
this.species.loadAssets(this.scene as BattleScene, this.gender === Gender.FEMALE); this.species.loadAssets(this.scene, this.gender === Gender.FEMALE);
if (this.isPlayer()) if (this.isPlayer())
(this.scene as BattleScene).loadAtlas(this.getBattleSpriteKey(), 'pokemon', this.getBattleSpriteAtlasPath()); this.scene.loadAtlas(this.getBattleSpriteKey(), 'pokemon', this.getBattleSpriteAtlasPath());
this.scene.load.once(Phaser.Loader.Events.COMPLETE, () => { this.scene.load.once(Phaser.Loader.Events.COMPLETE, () => {
if (this.isPlayer()) { if (this.isPlayer()) {
const originalWarn = console.warn; const originalWarn = console.warn;
@ -260,7 +261,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, baseStats); this.scene.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;
@ -412,7 +413,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
apply(source: Pokemon, battlerMove: PokemonMove): Promise<MoveResult> { apply(source: Pokemon, battlerMove: PokemonMove): Promise<MoveResult> {
return new Promise(resolve => { return new Promise(resolve => {
const battleScene = this.scene as BattleScene;
let result: MoveResult = MoveResult.STATUS; let result: MoveResult = MoveResult.STATUS;
let success = false; let success = false;
const move = battlerMove.getMove(); const move = battlerMove.getMove();
@ -422,15 +422,17 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
case MoveCategory.PHYSICAL: case MoveCategory.PHYSICAL:
case MoveCategory.SPECIAL: case MoveCategory.SPECIAL:
const isPhysical = moveCategory === MoveCategory.PHYSICAL; const isPhysical = moveCategory === MoveCategory.PHYSICAL;
const power = new Utils.NumberHolder(move.power);
this.scene.applyModifiers(AttackTypeBoosterModifier, source, power);
const critChance = new Utils.IntegerHolder(16); const critChance = new Utils.IntegerHolder(16);
applyMoveAttrs(HighCritAttr, this.scene as BattleScene, source, this, move, critChance); applyMoveAttrs(HighCritAttr, this.scene, source, this, move, critChance);
const isCritical = Utils.randInt(critChance.value) === 0; const isCritical = Utils.randInt(critChance.value) === 0;
const sourceAtk = source.getBattleStat(isPhysical ? Stat.ATK : Stat.SPATK); const sourceAtk = source.getBattleStat(isPhysical ? Stat.ATK : Stat.SPATK);
const targetDef = this.getBattleStat(isPhysical ? Stat.DEF : Stat.SPDEF); const targetDef = this.getBattleStat(isPhysical ? Stat.DEF : Stat.SPDEF);
const stabMultiplier = source.species.type1 === move.type || (source.species.type2 > -1 && source.species.type2 === move.type) ? 1.5 : 1; const stabMultiplier = source.species.type1 === move.type || (source.species.type2 > -1 && source.species.type2 === move.type) ? 1.5 : 1;
const typeMultiplier = getTypeDamageMultiplier(move.type, this.species.type1) * (this.species.type2 > -1 ? getTypeDamageMultiplier(move.type, this.species.type2) : 1); const typeMultiplier = getTypeDamageMultiplier(move.type, this.species.type1) * (this.species.type2 > -1 ? getTypeDamageMultiplier(move.type, this.species.type2) : 1);
const criticalMultiplier = isCritical ? 2 : 1; const criticalMultiplier = isCritical ? 2 : 1;
damage = Math.ceil(((((2 * source.level / 5 + 2) * move.power * sourceAtk / targetDef) / 50) + 2) * stabMultiplier * typeMultiplier * ((Utils.randInt(15) + 85) / 100)) * criticalMultiplier; damage = Math.ceil(((((2 * source.level / 5 + 2) * power.value * sourceAtk / targetDef) / 50) + 2) * stabMultiplier * typeMultiplier * ((Utils.randInt(15) + 85) / 100)) * criticalMultiplier;
if (isPhysical && source.status && source.status.effect === StatusEffect.BURN) if (isPhysical && source.status && source.status.effect === StatusEffect.BURN)
damage = Math.floor(damage / 2); damage = Math.floor(damage / 2);
move.getAttrs(HitsTagAttr).map(hta => hta as HitsTagAttr).filter(hta => hta.doubleDamage).forEach(hta => { move.getAttrs(HitsTagAttr).map(hta => hta as HitsTagAttr).filter(hta => hta.doubleDamage).forEach(hta => {
@ -444,7 +446,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
this.hp = Math.max(this.hp - damage, 0); this.hp = Math.max(this.hp - damage, 0);
source.turnData.damageDealt += damage; source.turnData.damageDealt += damage;
if (isCritical) if (isCritical)
battleScene.unshiftPhase(new MessagePhase(battleScene, 'A critical hit!')); this.scene.unshiftPhase(new MessagePhase(this.scene, 'A critical hit!'));
} }
if (typeMultiplier >= 2) if (typeMultiplier >= 2)
result = MoveResult.SUPER_EFFECTIVE; result = MoveResult.SUPER_EFFECTIVE;
@ -462,16 +464,16 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
break; break;
case MoveResult.SUPER_EFFECTIVE: case MoveResult.SUPER_EFFECTIVE:
this.scene.sound.play('hit_strong'); this.scene.sound.play('hit_strong');
battleScene.unshiftPhase(new MessagePhase(battleScene, 'It\'s super effective!')); this.scene.unshiftPhase(new MessagePhase(this.scene, 'It\'s super effective!'));
success = true; success = true;
break; break;
case MoveResult.NOT_VERY_EFFECTIVE: case MoveResult.NOT_VERY_EFFECTIVE:
this.scene.sound.play('hit_weak'); this.scene.sound.play('hit_weak');
battleScene.unshiftPhase(new MessagePhase(battleScene, 'It\'s not very effective!')) this.scene.unshiftPhase(new MessagePhase(this.scene, 'It\'s not very effective!'))
success = true; success = true;
break; break;
case MoveResult.NO_EFFECT: case MoveResult.NO_EFFECT:
battleScene.unshiftPhase(new MessagePhase(battleScene, `It doesn\'t affect ${this.name}!`)) this.scene.unshiftPhase(new MessagePhase(this.scene, `It doesn\'t affect ${this.name}!`))
success = true; success = true;
break; break;
} }
@ -546,7 +548,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
cry(soundConfig?: Phaser.Types.Sound.SoundConfig): integer { cry(soundConfig?: Phaser.Types.Sound.SoundConfig): integer {
return this.species.cry(this.scene as BattleScene, soundConfig); return this.species.cry(this.scene, soundConfig);
} }
faintCry(callback: Function) { faintCry(callback: Function) {
@ -724,6 +726,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
} }
export default interface Pokemon {
scene: BattleScene
}
export class PlayerPokemon extends Pokemon { export class PlayerPokemon extends Pokemon {
public compatibleTms: Moves[]; public compatibleTms: Moves[];
@ -760,9 +766,10 @@ export class PlayerPokemon extends Pokemon {
evolve(evolution: SpeciesEvolution): Promise<void> { evolve(evolution: SpeciesEvolution): Promise<void> {
return new Promise(resolve => { return new Promise(resolve => {
this.handleSpecialEvolutions(evolution);
this.species = getPokemonSpecies(evolution.speciesId); this.species = getPokemonSpecies(evolution.speciesId);
this.name = this.species.name.toUpperCase(); this.name = this.species.name.toUpperCase();
this.species.generateIconAnim(this.scene as BattleScene); this.species.generateIconAnim(this.scene);
this.compatibleTms.splice(0, this.compatibleTms.length); this.compatibleTms.splice(0, this.compatibleTms.length);
this.generateCompatibleTms(); this.generateCompatibleTms();
this.loadAssets().then(() => { this.loadAssets().then(() => {
@ -771,6 +778,17 @@ export class PlayerPokemon extends Pokemon {
}); });
}); });
} }
private handleSpecialEvolutions(evolution: SpeciesEvolution) {
if (this.species.speciesId === Species.NINCADA && evolution.speciesId === Species.NINJASK) {
const newEvolution = pokemonEvolutions[this.species.speciesId][1];
if (newEvolution.condition.predicate(this)) {
const newPokemon = new PlayerPokemon(this.scene, this.species, this.level);
this.scene.getParty().push(newPokemon);
newPokemon.evolve(newEvolution);
}
}
}
} }
export class EnemyPokemon extends Pokemon { export class EnemyPokemon extends Pokemon {
@ -798,7 +816,7 @@ export class EnemyPokemon extends Pokemon {
return movePool[Utils.randInt(movePool.length)]; return movePool[Utils.randInt(movePool.length)];
case AiType.SMART_RANDOM: case AiType.SMART_RANDOM:
case AiType.SMART: case AiType.SMART:
const target = (this.scene as BattleScene).getPlayerPokemon(); const target = this.scene.getPlayerPokemon();
const moveScores = movePool.map(() => 0); const moveScores = movePool.map(() => 0);
for (let m in movePool) { for (let m in movePool) {
const pokemonMove = movePool[m]; const pokemonMove = movePool[m];
@ -868,11 +886,11 @@ export class EnemyPokemon extends Pokemon {
} }
addToParty() { addToParty() {
const party = (this.scene as BattleScene).getParty(); const party = this.scene.getParty();
let ret: PlayerPokemon = null; let ret: PlayerPokemon = null;
if (party.length < 6) { if (party.length < 6) {
const newPokemon = new PlayerPokemon(this.scene as BattleScene, this.species, this.level, this); const newPokemon = new PlayerPokemon(this.scene, this.species, this.level, this);
party.push(newPokemon); party.push(newPokemon);
ret = newPokemon; ret = newPokemon;
} }

View File

@ -43,7 +43,7 @@ export default class CommandUiHandler extends UiHandler {
const messageHandler = this.getUi().getMessageHandler(); const messageHandler = this.getUi().getMessageHandler();
messageHandler.bg.setTexture('bg_command'); messageHandler.bg.setTexture('bg_command');
messageHandler.message.setWordWrapWidth(1110); messageHandler.message.setWordWrapWidth(1110);
messageHandler.showText(`What will\n${(this.scene as BattleScene).getPlayerPokemon().name} do?`, 0); messageHandler.showText(`What will\n${this.scene.getPlayerPokemon().name} do?`, 0);
this.setCursor(this.cursor); this.setCursor(this.cursor);
} }

View File

@ -49,7 +49,7 @@ export default class FightUiHandler extends UiHandler {
if (button === Button.CANCEL || button === Button.ACTION) { if (button === Button.CANCEL || button === Button.ACTION) {
if (button === Button.ACTION) { if (button === Button.ACTION) {
if (((this.scene as BattleScene).getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, this.cursor)) if ((this.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, this.cursor))
success = true; success = true;
else else
ui.playError(); ui.playError();
@ -91,7 +91,7 @@ export default class FightUiHandler extends UiHandler {
ui.add(this.cursorObj); ui.add(this.cursorObj);
} }
const moveset = (this.scene as BattleScene).getPlayerPokemon().moveset; const moveset = this.scene.getPlayerPokemon().moveset;
const hasMove = cursor < moveset.length; const hasMove = cursor < moveset.length;
@ -114,7 +114,7 @@ export default class FightUiHandler extends UiHandler {
} }
displayMoves() { displayMoves() {
const moveset = (this.scene as BattleScene).getPlayerPokemon().moveset; const moveset = this.scene.getPlayerPokemon().moveset;
for (let m = 0; m < 4; m++) { for (let m = 0; m < 4; m++) {
const moveText = addTextObject(this.scene, m % 2 === 0 ? 0 : 100, m < 2 ? 0 : 16, '-', TextStyle.WINDOW); const moveText = addTextObject(this.scene, m % 2 === 0 ? 0 : 100, m < 2 ? 0 : 16, '-', TextStyle.WINDOW);
if (m < moveset.length) if (m < moveset.length)

View File

@ -280,7 +280,7 @@ export default class PartyUiHandler extends MessageUiHandler {
} }
populatePartySlots() { populatePartySlots() {
const party = (this.scene as BattleScene).getParty(); const party = this.scene.getParty();
if (this.cursor < 6 && this.cursor >= party.length) if (this.cursor < 6 && this.cursor >= party.length)
this.cursor = party.length - 1; this.cursor = party.length - 1;
@ -289,7 +289,7 @@ export default class PartyUiHandler extends MessageUiHandler {
for (let p in party) { for (let p in party) {
const slotIndex = parseInt(p); const slotIndex = parseInt(p);
const partySlot = new PartySlot(this.scene as BattleScene, slotIndex, party[p]); const partySlot = new PartySlot(this.scene, slotIndex, party[p]);
this.scene.add.existing(partySlot); this.scene.add.existing(partySlot);
this.partySlotsContainer.add(partySlot); this.partySlotsContainer.add(partySlot);
this.partySlots.push(partySlot); this.partySlots.push(partySlot);