Implement trainer battles and various changes

Implement trainer battles; add dialogue functionality; add random session seed for predictable random results; remove capitalization from text; add full party heal after every 10 waves
This commit is contained in:
Flashfyre committed 2023-10-18 18:01:15 -04:00
1 parent 75bd40863e
commit 83c70889fc
50 files changed
+1500 -399

No files matched your search

+114 -114
View File
@@ -1,13 +1,13 @@
import Pokemon, { HitResult, MoveResult, PokemonMove } from "../pokemon";
import Pokemon, { HitResult, PokemonMove } from "../pokemon";
import { Type } from "./type";
import * as Utils from "../utils";
import { BattleStat, getBattleStatName } from "./battle-stat";
import { DamagePhase, PokemonHealPhase, ShowAbilityPhase, StatChangePhase } from "../battle-phases";
import { getPokemonMessage } from "../messages";
import { Weather, WeatherType } from "./weather";
import { BattlerTag, BattlerTagType, TrappedTag } from "./battler-tag";
import { BattlerTag, BattlerTagType } from "./battler-tag";
import { StatusEffect, getStatusEffectDescriptor } from "./status-effect";
import { MoveFlags, Moves, RecoilAttr, allMoves } from "./move";
import { MoveFlags, Moves, RecoilAttr } from "./move";
import { ArenaTagType } from "./arena-tag";
export class Ability {
@@ -20,7 +20,7 @@ export class Ability {
constructor(id: Abilities, name: string, description: string, generation: integer) {
this.id = id;
this.name = name.toUpperCase();
this.name = name;
this.description = description;
this.generation = generation;
this.attrs = [];
@@ -265,7 +265,7 @@ export class PostDefendTypeChangeAbAttr extends PostDefendAbAttr {
}
getTriggerMessage(pokemon: Pokemon, ...args: any[]): string {
return getPokemonMessage(pokemon, `'s ${pokemon.getAbility().name}\nmade it the ${Type[pokemon.getTypes()[0]]} type!`);
return getPokemonMessage(pokemon, `'s ${pokemon.getAbility().name}\nmade it the ${Utils.toReadableString(Type[pokemon.getTypes()[0]])} type!`);
}
}
@@ -1196,142 +1196,142 @@ export function initAbilities() {
.attr(SuppressWeatherEffectAbAttr, true),
new Ability(Abilities.ARENA_TRAP, "Arena Trap", "Prevents the foe from fleeing.", 3)
.attr(ArenaTrapAbAttr),
new Ability(Abilities.BATTLE_ARMOR, "Battle Armor", "The POKéMON is protected against critical hits.", 3)
new Ability(Abilities.BATTLE_ARMOR, "Battle Armor", "The Pokémon is protected against critical hits.", 3)
.attr(BlockCritAbAttr),
new Ability(Abilities.BLAZE, "Blaze", "Powers up FIRE-type moves in a pinch.", 3)
new Ability(Abilities.BLAZE, "Blaze", "Powers up Fire-type moves in a pinch.", 3)
.attr(LowHpMoveTypePowerBoostAbAttr, Type.FIRE),
new Ability(Abilities.CHLOROPHYLL, "Chlorophyll", "Boosts the POKéMON's SPEED in sunshine.", 3)
new Ability(Abilities.CHLOROPHYLL, "Chlorophyll", "Boosts the Pokémon's Speed in sunshine.", 3)
.attr(BattleStatMultiplierAbAttr, BattleStat.SPD, 2)
.condition(getWeatherCondition(WeatherType.SUNNY, WeatherType.HARSH_SUN)), // TODO: Show ability bar on weather change and summon
new Ability(Abilities.CLEAR_BODY, "Clear Body", "Prevents other POKéMON from lowering its stats.", 3)
new Ability(Abilities.CLEAR_BODY, "Clear Body", "Prevents other Pokémon from lowering its stats.", 3)
.attr(ProtectStatAbAttr),
new Ability(Abilities.CLOUD_NINE, "Cloud Nine", "Eliminates the effects of non-severe weather.", 3)
.attr(SuppressWeatherEffectAbAttr),
new Ability(Abilities.COLOR_CHANGE, "Color Change", "Changes the POKéMON's type to the foe's move.", 3)
new Ability(Abilities.COLOR_CHANGE, "Color Change", "Changes the Pokémon's type to the foe's move.", 3)
.attr(PostDefendTypeChangeAbAttr),
new Ability(Abilities.COMPOUND_EYES, "Compound Eyes", "The POKéMON's accuracy is boosted.", 3)
new Ability(Abilities.COMPOUND_EYES, "Compound Eyes", "The Pokémon's Accuracy is boosted.", 3)
.attr(BattleStatMultiplierAbAttr, BattleStat.ACC, 1.3),
new Ability(Abilities.CUTE_CHARM, "Cute Charm", "Contact with the POKéMON may cause infatuation.", 3)
new Ability(Abilities.CUTE_CHARM, "Cute Charm", "Contact with the Pokémon may cause infatuation.", 3)
.attr(PostDefendContactApplyTagChanceAbAttr, 30, BattlerTagType.INFATUATED),
new Ability(Abilities.DAMP, "Damp (N)", "Prevents the use of self-destructing moves.", 3),
new Ability(Abilities.DRIZZLE, "Drizzle", "The POKéMON makes it rain when it enters a battle.", 3)
new Ability(Abilities.DRIZZLE, "Drizzle", "The Pokémon makes it rain when it enters a battle.", 3)
.attr(PostSummonWeatherChangeAbAttr, WeatherType.RAIN),
new Ability(Abilities.DROUGHT, "Drought", "Turns the sunlight harsh when the POKéMON enters a battle.", 3)
new Ability(Abilities.DROUGHT, "Drought", "Turns the sunlight harsh when the Pokémon enters a battle.", 3)
.attr(PostSummonWeatherChangeAbAttr, WeatherType.SUNNY),
new Ability(Abilities.EARLY_BIRD, "Early Bird (N)", "The POKéMON awakens quickly from sleep.", 3),
new Ability(Abilities.EARLY_BIRD, "Early Bird (N)", "The Pokémon awakens quickly from sleep.", 3),
new Ability(Abilities.EFFECT_SPORE, "Effect Spore", "Contact may poison or cause paralysis or sleep.", 3)
.attr(PostDefendContactApplyStatusEffectAbAttr, 10, StatusEffect.POISON, StatusEffect.PARALYSIS, StatusEffect.SLEEP),
new Ability(Abilities.FLAME_BODY, "Flame Body", "Contact with the POKéMON may burn the attacker.", 3)
new Ability(Abilities.FLAME_BODY, "Flame Body", "Contact with the Pokémon may burn the attacker.", 3)
.attr(PostDefendContactApplyStatusEffectAbAttr, 30, StatusEffect.BURN),
new Ability(Abilities.FLASH_FIRE, "Flash Fire", "It powers up FIRE-type moves if it's hit by one.", 3)
new Ability(Abilities.FLASH_FIRE, "Flash Fire", "It powers up Fire-type moves if it's hit by one.", 3)
.attr(TypeImmunityAddBattlerTagAbAttr, Type.FIRE, BattlerTagType.FIRE_BOOST, 1, (pokemon: Pokemon) => !pokemon.status || pokemon.status.effect !== StatusEffect.FREEZE),
new Ability(Abilities.FORECAST, "Forecast (N)", "Castform transforms with the weather.", 3),
new Ability(Abilities.GUTS, "Guts (N)", "Boosts ATTACK if there is a status problem.", 3),
new Ability(Abilities.HUGE_POWER, "Huge Power", "Raises the POKéMON's ATTACK stat.", 3)
new Ability(Abilities.GUTS, "Guts (N)", "Boosts Attack if there is a status problem.", 3),
new Ability(Abilities.HUGE_POWER, "Huge Power", "Raises the Pokémon's Attack stat.", 3)
.attr(PostSummonStatChangeAbAttr, BattleStat.ATK, 1, true),
new Ability(Abilities.HUSTLE, "Hustle (N)", "Boosts the ATTACK stat, but lowers accuracy.", 3),
new Ability(Abilities.HYPER_CUTTER, "Hyper Cutter", "Prevents other POKéMON from lowering ATTACK stat.", 3)
new Ability(Abilities.HUSTLE, "Hustle (N)", "Boosts the Attack stat, but lowers Accuracy.", 3),
new Ability(Abilities.HYPER_CUTTER, "Hyper Cutter", "Prevents other Pokémon from lowering Attack stat.", 3)
.attr(ProtectStatAbAttr, BattleStat.ATK),
new Ability(Abilities.ILLUMINATE, "Illuminate", "Raises the likelihood of an encounter being a double battle.", 3)
.attr(DoubleBattleChanceAbAttr),
new Ability(Abilities.IMMUNITY, "Immunity", "Prevents the POKéMON from getting poisoned.", 3)
new Ability(Abilities.IMMUNITY, "Immunity", "Prevents the Pokémon from getting poisoned.", 3)
.attr(StatusEffectImmunityAbAttr, StatusEffect.POISON),
new Ability(Abilities.INNER_FOCUS, "Inner Focus", "The POKéMON is protected from flinching.", 3)
new Ability(Abilities.INNER_FOCUS, "Inner Focus", "The Pokémon is protected from flinching.", 3)
.attr(BattlerTagImmunityAbAttr, BattlerTagType.FLINCHED),
new Ability(Abilities.INSOMNIA, "Insomnia", "Prevents the POKéMON from falling asleep.", 3)
new Ability(Abilities.INSOMNIA, "Insomnia", "Prevents the Pokémon from falling asleep.", 3)
.attr(StatusEffectImmunityAbAttr, StatusEffect.SLEEP)
.attr(BattlerTagImmunityAbAttr, BattlerTagType.DROWSY),
new Ability(Abilities.INTIMIDATE, "Intimidate", "Lowers the foe's ATTACK stat.", 3)
new Ability(Abilities.INTIMIDATE, "Intimidate", "Lowers the foe's Attack stat.", 3)
.attr(PostSummonStatChangeAbAttr, BattleStat.ATK, -1),
new Ability(Abilities.KEEN_EYE, "Keen Eye", "Prevents other POKéMON from lowering accuracy.", 3)
new Ability(Abilities.KEEN_EYE, "Keen Eye", "Prevents other Pokémon from lowering Accuracy.", 3)
.attr(ProtectStatAbAttr, BattleStat.ACC),
new Ability(Abilities.LEVITATE, "Levitate", "Gives immunity to GROUND-type moves.", 3)
new Ability(Abilities.LEVITATE, "Levitate", "Gives immunity to Ground-type moves.", 3)
.attr(TypeImmunityAbAttr, Type.GROUND, (pokemon: Pokemon) => !pokemon.getTag(BattlerTagType.IGNORE_FLYING) && !pokemon.scene.arena.getTag(ArenaTagType.GRAVITY)),
new Ability(Abilities.LIGHTNING_ROD, "Lightning Rod", "Draws in all ELECTRIC-type moves to up SP. ATK.", 3)
new Ability(Abilities.LIGHTNING_ROD, "Lightning Rod", "Draws in all Electric-type moves to up Sp. Atk.", 3)
.attr(TypeImmunityStatChangeAbAttr, Type.ELECTRIC, BattleStat.SPATK, 1),
new Ability(Abilities.LIMBER, "Limber", "The POKéMON is protected from paralysis.", 3)
new Ability(Abilities.LIMBER, "Limber", "The Pokémon is protected from paralysis.", 3)
.attr(StatusEffectImmunityAbAttr, StatusEffect.PARALYSIS),
new Ability(Abilities.LIQUID_OOZE, "Liquid Ooze (N)", "Damages attackers using any draining move.", 3),
new Ability(Abilities.MAGMA_ARMOR, "Magma Armor", "Prevents the POKéMON from becoming frozen.", 3)
new Ability(Abilities.MAGMA_ARMOR, "Magma Armor", "Prevents the Pokémon from becoming frozen.", 3)
.attr(StatusEffectImmunityAbAttr, StatusEffect.FREEZE),
new Ability(Abilities.MAGNET_PULL, "Magnet Pull", "Prevents STEEL-type POKéMON from escaping.", 3)
new Ability(Abilities.MAGNET_PULL, "Magnet Pull", "Prevents Steel-type Pokémon from escaping.", 3)
/*.attr(ArenaTrapAbAttr)
.condition((pokemon: Pokemon) => pokemon.getOpponent()?.isOfType(Type.STEEL))*/, // TODO: Rework
new Ability(Abilities.MARVEL_SCALE, "Marvel Scale (N)", "Ups DEFENSE if there is a status problem.", 3),
new Ability(Abilities.MINUS, "Minus (N)", "Ups SP. ATK if another POKéMON has PLUS or MINUS.", 3),
new Ability(Abilities.MARVEL_SCALE, "Marvel Scale (N)", "Ups Defense if there is a status problem.", 3),
new Ability(Abilities.MINUS, "Minus (N)", "Ups Sp. Atk if another Pokémon has Plus or Minus.", 3),
new Ability(Abilities.NATURAL_CURE, "Natural Cure (N)", "All status problems heal when it switches out.", 3),
new Ability(Abilities.OBLIVIOUS, "Oblivious", "Prevents it from becoming infatuated.", 3)
.attr(BattlerTagImmunityAbAttr, BattlerTagType.INFATUATED),
new Ability(Abilities.OVERGROW, "Overgrow", "Powers up GRASS-type moves in a pinch.", 3)
new Ability(Abilities.OVERGROW, "Overgrow", "Powers up Grass-type moves in a pinch.", 3)
.attr(LowHpMoveTypePowerBoostAbAttr, Type.GRASS),
new Ability(Abilities.OWN_TEMPO, "Own Tempo", "Prevents the POKéMON from becoming confused.", 3)
new Ability(Abilities.OWN_TEMPO, "Own Tempo", "Prevents the Pokémon from becoming confused.", 3)
.attr(BattlerTagImmunityAbAttr, BattlerTagType.CONFUSED),
new Ability(Abilities.PICKUP, "Pickup (N)", "The POKéMON may pick up items.", 3),
new Ability(Abilities.PLUS, "Plus (N)", "Ups SP. ATK if another POKéMON has PLUS or MINUS.", 3),
new Ability(Abilities.POISON_POINT, "Poison Point", "Contact with the POKéMON may poison the attacker.", 3)
new Ability(Abilities.PICKUP, "Pickup (N)", "The Pokémon may pick up items.", 3),
new Ability(Abilities.PLUS, "Plus (N)", "Ups Sp. Atk if another Pokémon has PLUS or MINUS.", 3),
new Ability(Abilities.POISON_POINT, "Poison Point", "Contact with the Pokémon may poison the attacker.", 3)
.attr(PostDefendContactApplyStatusEffectAbAttr, StatusEffect.POISON),
new Ability(Abilities.PRESSURE, "Pressure (N)", "The POKéMON raises the foe's PP usage.", 3),
new Ability(Abilities.PURE_POWER, "Pure Power", "Raises the POKéMON's ATTACK stat.", 3)
new Ability(Abilities.PRESSURE, "Pressure (N)", "The Pokémon raises the foe's PP usage.", 3),
new Ability(Abilities.PURE_POWER, "Pure Power", "Raises the Pokémon's Attack stat.", 3)
.attr(PostSummonStatChangeAbAttr, BattleStat.ATK, 1, true),
new Ability(Abilities.RAIN_DISH, "Rain Dish", "The POKéMON gradually regains HP in rain.", 3)
new Ability(Abilities.RAIN_DISH, "Rain Dish", "The Pokémon gradually regains HP in rain.", 3)
.attr(PostWeatherLapseHealAbAttr, 1, WeatherType.RAIN, WeatherType.HEAVY_RAIN),
new Ability(Abilities.ROCK_HEAD, "Rock Head", "Protects the POKéMON from recoil damage.", 3)
new Ability(Abilities.ROCK_HEAD, "Rock Head", "Protects the Pokémon from recoil damage.", 3)
.attr(BlockRecoilDamageAttr),
new Ability(Abilities.ROUGH_SKIN, "Rough Skin (N)", "Inflicts damage to the attacker on contact.", 3),
new Ability(Abilities.RUN_AWAY, "Run Away (N)", "Enables a sure getaway from wild POKéMON.", 3),
new Ability(Abilities.SAND_STREAM, "Sand Stream", "The POKéMON summons a sandstorm in battle.", 3)
new Ability(Abilities.RUN_AWAY, "Run Away (N)", "Enables a sure getaway from wild Pokémon.", 3),
new Ability(Abilities.SAND_STREAM, "Sand Stream", "The Pokémon summons a sandstorm in battle.", 3)
.attr(PostSummonWeatherChangeAbAttr, WeatherType.SANDSTORM),
new Ability(Abilities.SAND_VEIL, "Sand Veil", "Boosts the POKéMON's evasion in a sandstorm.", 3)
new Ability(Abilities.SAND_VEIL, "Sand Veil", "Boosts the Pokémon's Evasiveness in a sandstorm.", 3)
.attr(BattleStatMultiplierAbAttr, BattleStat.EVA, 1.2)
.attr(BlockWeatherDamageAttr, WeatherType.SANDSTORM)
.condition(getWeatherCondition(WeatherType.SANDSTORM)),
new Ability(Abilities.SERENE_GRACE, "Serene Grace (N)", "Boosts the likelihood of added effects appearing.", 3),
new Ability(Abilities.SHADOW_TAG, "Shadow Tag", "Prevents the foe from escaping.", 3)
.attr(ArenaTrapAbAttr),
new Ability(Abilities.SHED_SKIN, "Shed Skin (N)", "The POKéMON may heal its own status problems.", 3),
new Ability(Abilities.SHELL_ARMOR, "Shell Armor", "The POKéMON is protected against critical hits.", 3)
new Ability(Abilities.SHED_SKIN, "Shed Skin (N)", "The Pokémon may heal its own status problems.", 3),
new Ability(Abilities.SHELL_ARMOR, "Shell Armor", "The Pokémon is protected against critical hits.", 3)
.attr(BlockCritAbAttr),
new Ability(Abilities.SHIELD_DUST, "Shield Dust (N)", "Blocks the added effects of attacks taken.", 3),
new Ability(Abilities.SOUNDPROOF, "Soundproof (N)", "Gives immunity to sound-based moves.", 3),
new Ability(Abilities.SPEED_BOOST, "Speed Boost", "Its SPEED stat is gradually boosted.", 3)
new Ability(Abilities.SPEED_BOOST, "Speed Boost", "Its Speed stat is gradually boosted.", 3)
.attr(PostTurnSpeedBoostAbAttr),
new Ability(Abilities.STATIC, "Static", "Contact with the POKéMON may cause paralysis.", 3)
new Ability(Abilities.STATIC, "Static", "Contact with the Pokémon may cause paralysis.", 3)
.attr(PostDefendContactApplyStatusEffectAbAttr, StatusEffect.PARALYSIS),
new Ability(Abilities.STENCH, "Stench (N)", "The stench may cause the target to flinch.", 3),
new Ability(Abilities.STICKY_HOLD, "Sticky Hold", "Protects the POKéMON from item theft.", 3)
new Ability(Abilities.STICKY_HOLD, "Sticky Hold", "Protects the Pokémon from item theft.", 3)
.attr(BlockItemTheftAbAttr),
new Ability(Abilities.STURDY, "Sturdy (N)", "It cannot be knocked out with one hit.", 3),
new Ability(Abilities.SUCTION_CUPS, "Suction Cups (N)", "Negates all moves that force switching out.", 3),
new Ability(Abilities.SWARM, "Swarm", "Powers up BUG-type moves in a pinch.", 3)
new Ability(Abilities.SWARM, "Swarm", "Powers up Bug-type moves in a pinch.", 3)
.attr(LowHpMoveTypePowerBoostAbAttr, Type.BUG),
new Ability(Abilities.SWIFT_SWIM, "Swift Swim", "Boosts the POKéMON's SPEED in rain.", 3)
new Ability(Abilities.SWIFT_SWIM, "Swift Swim", "Boosts the Pokémon's Speed in rain.", 3)
.attr(BattleStatMultiplierAbAttr, BattleStat.SPD, 2)
.condition(getWeatherCondition(WeatherType.RAIN, WeatherType.HEAVY_RAIN)), // TODO: Show ability bar on weather change and summon
new Ability(Abilities.SYNCHRONIZE, "Synchronize (N)", "Passes a burn, poison, or paralysis to the foe.", 3),
new Ability(Abilities.THICK_FAT, "Thick Fat", "Ups resistance to Fire- and ICE-type moves.", 3)
new Ability(Abilities.THICK_FAT, "Thick Fat", "Ups resistance to Fire-type and Ice-type moves.", 3)
.attr(ReceivedTypeDamageMultiplierAbAttr, Type.FIRE, 0.5)
.attr(ReceivedTypeDamageMultiplierAbAttr, Type.ICE, 0.5),
new Ability(Abilities.TORRENT, "Torrent", "Powers up WATER-type moves in a pinch.", 3)
new Ability(Abilities.TORRENT, "Torrent", "Powers up Water-type moves in a pinch.", 3)
.attr(LowHpMoveTypePowerBoostAbAttr, Type.WATER),
new Ability(Abilities.TRACE, "Trace (N)", "The POKéMON copies a foe's Ability.", 3),
new Ability(Abilities.TRUANT, "Truant", "POKéMON can't attack on consecutive turns.", 3)
new Ability(Abilities.TRACE, "Trace (N)", "The Pokémon copies a foe's Ability.", 3),
new Ability(Abilities.TRUANT, "Truant", "Pokémon can't attack on consecutive turns.", 3)
.attr(PostSummonAddBattlerTagAbAttr, BattlerTagType.TRUANT, 1),
new Ability(Abilities.VITAL_SPIRIT, "Vital Spirit", "Prevents the POKéMON from falling asleep.", 3)
new Ability(Abilities.VITAL_SPIRIT, "Vital Spirit", "Prevents the Pokémon from falling asleep.", 3)
.attr(StatusEffectImmunityAbAttr, StatusEffect.SLEEP)
.attr(BattlerTagImmunityAbAttr, BattlerTagType.DROWSY),
new Ability(Abilities.VOLT_ABSORB, "Volt Absorb", "Restores HP if hit by an ELECTRIC-type move.", 3)
new Ability(Abilities.VOLT_ABSORB, "Volt Absorb", "Restores HP if hit by an Electric-type move.", 3)
.attr(TypeImmunityHealAbAttr, Type.ELECTRIC),
new Ability(Abilities.WATER_ABSORB, "Water Absorb", "Restores HP if hit by a WATER-type move.", 3)
new Ability(Abilities.WATER_ABSORB, "Water Absorb", "Restores HP if hit by a Water-type move.", 3)
.attr(TypeImmunityHealAbAttr, Type.WATER),
new Ability(Abilities.WATER_VEIL, "Water Veil", "Prevents the POKéMON from getting a burn.", 3)
new Ability(Abilities.WATER_VEIL, "Water Veil", "Prevents the Pokémon from getting a burn.", 3)
.attr(StatusEffectImmunityAbAttr, StatusEffect.BURN),
new Ability(Abilities.WHITE_SMOKE, "White Smoke", "Prevents other POKéMON from lowering its stats.", 3)
new Ability(Abilities.WHITE_SMOKE, "White Smoke", "Prevents other Pokémon from lowering its stats.", 3)
.attr(ProtectStatAbAttr),
new Ability(Abilities.WONDER_GUARD, "Wonder Guard", "Only super effective moves will hit.", 3)
.attr(NonSuperEffectiveImmunityAbAttr),
new Ability(Abilities.ADAPTABILITY, "Adaptability (N)", "Powers up moves of the same type.", 4),
new Ability(Abilities.AFTERMATH, "Aftermath (N)", "Damages the attacker landing the finishing hit.", 4),
new Ability(Abilities.ANGER_POINT, "Anger Point (N)", "Maxes ATTACK after taking a critical hit.", 4),
new Ability(Abilities.ANGER_POINT, "Anger Point (N)", "Maxes Attack after taking a critical hit.", 4),
new Ability(Abilities.ANTICIPATION, "Anticipation (N)", "Senses a foe's dangerous moves.", 4),
new Ability(Abilities.BAD_DREAMS, "Bad Dreams (N)", "Reduces a sleeping foe's HP.", 4),
new Ability(Abilities.DOWNLOAD, "Download (N)", "Adjusts power according to a foe's defenses.", 4),
@@ -1341,105 +1341,105 @@ export function initAbilities() {
.attr(ReceivedTypeDamageMultiplierAbAttr, Type.FIRE, 1.25)
.attr(TypeImmunityHealAbAttr, Type.WATER),
new Ability(Abilities.FILTER, "Filter (N)", "Reduces damage from super-effective attacks.", 4),
new Ability(Abilities.FLOWER_GIFT, "Flower Gift (N)", "Powers up party POKéMON when it is sunny.", 4),
new Ability(Abilities.FLOWER_GIFT, "Flower Gift (N)", "Powers up party Pokémon when it is sunny.", 4),
new Ability(Abilities.FOREWARN, "Forewarn (N)", "Determines what moves a foe has.", 4),
new Ability(Abilities.FRISK, "Frisk (N)", "The POKéMON can check a foe's held item.", 4),
new Ability(Abilities.FRISK, "Frisk (N)", "The Pokémon can check a foe's held item.", 4),
new Ability(Abilities.GLUTTONY, "Gluttony (N)", "Encourages the early use of a held Berry.", 4),
new Ability(Abilities.HEATPROOF, "Heatproof", "Weakens the power of FIRE-type moves.", 4)
new Ability(Abilities.HEATPROOF, "Heatproof", "Weakens the power of Fire-type moves.", 4)
.attr(ReceivedTypeDamageMultiplierAbAttr, Type.FIRE, 0.5),
new Ability(Abilities.HONEY_GATHER, "Honey Gather (N)", "The POKéMON may gather Honey from somewhere.", 4),
new Ability(Abilities.HONEY_GATHER, "Honey Gather (N)", "The Pokémon may gather Honey from somewhere.", 4),
new Ability(Abilities.HYDRATION, "Hydration (N)", "Heals status problems if it is raining.", 4),
new Ability(Abilities.ICE_BODY, "Ice Body", "The POKéMON gradually regains HP in a hailstorm.", 4)
new Ability(Abilities.ICE_BODY, "Ice Body", "The Pokémon gradually regains HP in a hailstorm.", 4)
.attr(PostWeatherLapseHealAbAttr, 1, WeatherType.HAIL),
new Ability(Abilities.IRON_FIST, "Iron Fist (N)", "Boosts the power of punching moves.", 4),
new Ability(Abilities.KLUTZ, "Klutz (N)", "The POKéMON can't use any held items.", 4),
new Ability(Abilities.KLUTZ, "Klutz (N)", "The Pokémon can't use any held items.", 4),
new Ability(Abilities.LEAF_GUARD, "Leaf Guard", "Prevents problems with status in sunny weather.", 4)
.attr(StatusEffectImmunityAbAttr)
.condition(getWeatherCondition(WeatherType.SUNNY, WeatherType.HARSH_SUN)),
new Ability(Abilities.MAGIC_GUARD, "Magic Guard (N)", "Protects the POKéMON from indirect damage.", 4),
new Ability(Abilities.MAGIC_GUARD, "Magic Guard (N)", "Protects the Pokémon from indirect damage.", 4),
new Ability(Abilities.MOLD_BREAKER, "Mold Breaker (N)", "Moves can be used regardless of Abilities.", 4),
new Ability(Abilities.MOTOR_DRIVE, "Motor Drive", "Raises SPEED if hit by an ELECTRIC-type move.", 4)
new Ability(Abilities.MOTOR_DRIVE, "Motor Drive", "Raises Speed if hit by an Electric-type move.", 4)
.attr(TypeImmunityStatChangeAbAttr, Type.ELECTRIC, BattleStat.SPD, 1),
new Ability(Abilities.MULTITYPE, "Multitype (N)", "Changes type to match the held Plate.", 4),
new Ability(Abilities.NO_GUARD, "No Guard (N)", "Ensures attacks by or against the POKéMON land.", 4),
new Ability(Abilities.NORMALIZE, "Normalize (N)", "All the POKéMON's moves become the NORMAL type.", 4),
new Ability(Abilities.POISON_HEAL, "Poison Heal (N)", "Restores HP if the POKéMON is poisoned.", 4),
new Ability(Abilities.QUICK_FEET, "Quick Feet (N)", "Boosts SPEED if there is a status problem.", 4),
new Ability(Abilities.NO_GUARD, "No Guard (N)", "Ensures attacks by or against the Pokémon land.", 4),
new Ability(Abilities.NORMALIZE, "Normalize (N)", "All the Pokémon's moves become Normal-type.", 4),
new Ability(Abilities.POISON_HEAL, "Poison Heal (N)", "Restores HP if the Pokémon is poisoned.", 4),
new Ability(Abilities.QUICK_FEET, "Quick Feet (N)", "Boosts Speed if there is a status problem.", 4),
new Ability(Abilities.RECKLESS, "Reckless", "Powers up moves that have recoil damage.", 4)
.attr(RecoilMovePowerBoostAbAttr),
new Ability(Abilities.RIVALRY, "Rivalry (N)", "Deals more damage to a POKéMON of same gender.", 4),
new Ability(Abilities.SCRAPPY, "Scrappy (N)", "Enables moves to hit GHOST-type POKéMON.", 4),
new Ability(Abilities.RIVALRY, "Rivalry (N)", "Deals more damage to a Pokémon of same gender.", 4),
new Ability(Abilities.SCRAPPY, "Scrappy (N)", "Enables moves to hit Ghost-type Pokémon.", 4),
new Ability(Abilities.SIMPLE, "Simple (N)", "Doubles all stat changes.", 4),
new Ability(Abilities.SKILL_LINK, "Skill Link (N)", "Increases the frequency of multi-strike moves.", 4),
new Ability(Abilities.SLOW_START, "Slow Start (N)", "Temporarily halves ATTACK and SPEED.", 4),
new Ability(Abilities.SLOW_START, "Slow Start (N)", "Temporarily halves Attack and Speed.", 4),
new Ability(Abilities.SNIPER, "Sniper (N)", "Powers up moves if they become critical hits.", 4),
new Ability(Abilities.SNOW_CLOAK, "Snow Cloak", "Raises evasion in a hailstorm.", 4)
new Ability(Abilities.SNOW_CLOAK, "Snow Cloak", "Raises Evasiveness in a hailstorm.", 4)
.attr(BattleStatMultiplierAbAttr, BattleStat.EVA, 1.2)
.attr(BlockWeatherDamageAttr, WeatherType.HAIL),
new Ability(Abilities.SNOW_WARNING, "Snow Warning", "The POKéMON summons a hailstorm in battle.", 4)
new Ability(Abilities.SNOW_WARNING, "Snow Warning", "The Pokémon summons a hailstorm in battle.", 4)
.attr(PostSummonWeatherChangeAbAttr, WeatherType.HAIL),
new Ability(Abilities.SOLAR_POWER, "Solar Power (N)", "In sunshine, SP. ATK is boosted but HP decreases.", 4),
new Ability(Abilities.SOLAR_POWER, "Solar Power (N)", "In sunshine, Sp. Atk is boosted but HP decreases.", 4),
new Ability(Abilities.SOLID_ROCK, "Solid Rock (N)", "Reduces damage from super-effective attacks.", 4),
new Ability(Abilities.STALL, "Stall (N)", "The POKéMON moves after all other POKéMON do.", 4),
new Ability(Abilities.STEADFAST, "Steadfast (N)", "Raises SPEED each time the POKéMON flinches.", 4),
new Ability(Abilities.STORM_DRAIN, "Storm Drain", "Draws in all WATER-type moves to up SP. ATK.", 4)
new Ability(Abilities.STALL, "Stall (N)", "The Pokémon moves after all other Pokémon do.", 4),
new Ability(Abilities.STEADFAST, "Steadfast (N)", "Raises Speed each time the Pokémon flinches.", 4),
new Ability(Abilities.STORM_DRAIN, "Storm Drain", "Draws in all Water-type moves to up Sp. Atk.", 4)
.attr(TypeImmunityStatChangeAbAttr, Type.WATER, BattleStat.SPATK, 1),
new Ability(Abilities.SUPER_LUCK, "Super Luck (N)", "Heightens the critical-hit ratios of moves.", 4),
new Ability(Abilities.TANGLED_FEET, "Tangled Feet (N)", "Raises evasion if the POKéMON is confused.", 4),
new Ability(Abilities.TECHNICIAN, "Technician (N)", "Powers up the POKéMON's weaker moves.", 4),
new Ability(Abilities.TANGLED_FEET, "Tangled Feet (N)", "Raises Evasiveness if the Pokémon is confused.", 4),
new Ability(Abilities.TECHNICIAN, "Technician (N)", "Powers up the Pokémon's weaker moves.", 4),
new Ability(Abilities.TINTED_LENS, "Tinted Lens (N)", "Powers up \"not very effective\" moves.", 4),
new Ability(Abilities.UNAWARE, "Unaware (N)", "Ignores any stat changes in the POKéMON.", 4),
new Ability(Abilities.UNBURDEN, "Unburden (N)", "Raises SPEED if a held item is used.", 4),
new Ability(Abilities.ANALYTIC, "Analytic (N)", "Boosts move power when the POKéMON moves last.", 5),
new Ability(Abilities.BIG_PECKS, "Big Pecks", "Protects the POKéMON from DEFENSE-lowering attacks.", 5)
new Ability(Abilities.UNAWARE, "Unaware (N)", "Ignores any stat changes in the Pokémon.", 4),
new Ability(Abilities.UNBURDEN, "Unburden (N)", "Raises Speed if a held item is used.", 4),
new Ability(Abilities.ANALYTIC, "Analytic (N)", "Boosts move power when the Pokémon moves last.", 5),
new Ability(Abilities.BIG_PECKS, "Big Pecks", "Protects the Pokémon from Defense-lowering attacks.", 5)
.attr(ProtectStatAbAttr, BattleStat.DEF),
new Ability(Abilities.CONTRARY, "Contrary (N)", "Makes stat changes have an opposite effect.", 5),
new Ability(Abilities.CURSED_BODY, "Cursed Body (N)", "May disable a move used on the POKéMON.", 5),
new Ability(Abilities.CURSED_BODY, "Cursed Body (N)", "May disable a move used on the Pokémon.", 5),
new Ability(Abilities.DEFEATIST, "Defeatist (N)", "Lowers stats when HP drops below half.", 5),
new Ability(Abilities.DEFIANT, "Defiant (N)", "Sharply raises ATTACK when the POKéMON's stats are lowered.", 5),
new Ability(Abilities.DEFIANT, "Defiant (N)", "Sharply raises Attack when the Pokémon's stats are lowered.", 5),
new Ability(Abilities.FLARE_BOOST, "Flare Boost (N)", "Powers up special attacks when burned.", 5),
new Ability(Abilities.FRIEND_GUARD, "Friend Guard (N)", "Reduces damage done to allies.", 5),
new Ability(Abilities.HARVEST, "Harvest (N)", "May create another Berry after one is used.", 5),
new Ability(Abilities.HEALER, "Healer (N)", "May heal an ally's status conditions.", 5),
new Ability(Abilities.HEAVY_METAL, "Heavy Metal (N)", "Doubles the POKéMON's weight.", 5),
new Ability(Abilities.ILLUSION, "Illusion (N)", "Enters battle disguised as the last POKéMON in the party.", 5),
new Ability(Abilities.IMPOSTER, "Imposter (N)", "It transforms itself into the POKéMON it is facing.", 5),
new Ability(Abilities.HEAVY_METAL, "Heavy Metal (N)", "Doubles the Pokémon's weight.", 5),
new Ability(Abilities.ILLUSION, "Illusion (N)", "Enters battle disguised as the last Pokémon in the party.", 5),
new Ability(Abilities.IMPOSTER, "Imposter (N)", "It transforms itself into the Pokémon it is facing.", 5),
new Ability(Abilities.INFILTRATOR, "Infiltrator (N)", "Passes through the foe's barrier and strikes.", 5),
new Ability(Abilities.IRON_BARBS, "Iron Barbs (N)", "Inflicts damage to the POKéMON on contact.", 5),
new Ability(Abilities.JUSTIFIED, "Justified (N)", "Raises ATTACK when hit by a DARK-type move.", 5),
new Ability(Abilities.LIGHT_METAL, "Light Metal (N)", "Halves the POKéMON's weight.", 5),
new Ability(Abilities.IRON_BARBS, "Iron Barbs (N)", "Inflicts damage to the Pokémon on contact.", 5),
new Ability(Abilities.JUSTIFIED, "Justified (N)", "Raises Attack when hit by a Dark-type move.", 5),
new Ability(Abilities.LIGHT_METAL, "Light Metal (N)", "Halves the Pokémon's weight.", 5),
new Ability(Abilities.MAGIC_BOUNCE, "Magic Bounce (N)", "Reflects status- changing moves.", 5),
new Ability(Abilities.MOODY, "Moody (N)", "Raises one stat and lowers another.", 5),
new Ability(Abilities.MOXIE, "Moxie (N)", "Boosts ATTACK after knocking out any POKéMON.", 5),
new Ability(Abilities.MOXIE, "Moxie (N)", "Boosts Attack after knocking out any Pokémon.", 5),
new Ability(Abilities.MULTISCALE, "Multiscale (N)", "Reduces damage when HP is full.", 5),
new Ability(Abilities.MUMMY, "Mummy (N)", "Contact with this POKéMON spreads this Ability.", 5),
new Ability(Abilities.OVERCOAT, "Overcoat", "Protects the POKéMON from weather damage.", 5)
new Ability(Abilities.MUMMY, "Mummy (N)", "Contact with this Pokémon spreads this Ability.", 5),
new Ability(Abilities.OVERCOAT, "Overcoat", "Protects the Pokémon from weather damage.", 5)
.attr(BlockWeatherDamageAttr),
new Ability(Abilities.PICKPOCKET, "Pickpocket (N)", "Once per battle, steals an item when hit by another POKéMON.", 5),
new Ability(Abilities.POISON_TOUCH, "Poison Touch", "May poison targets when a POKéMON makes contact.", 5)
new Ability(Abilities.PICKPOCKET, "Pickpocket (N)", "Once per battle, steals an item when hit by another Pokémon.", 5),
new Ability(Abilities.POISON_TOUCH, "Poison Touch", "May poison targets when a Pokémon makes contact.", 5)
.attr(PostDefendContactApplyStatusEffectAbAttr, 30, StatusEffect.POISON),
new Ability(Abilities.PRANKSTER, "Prankster (N)", "Gives priority to a status move.", 5),
new Ability(Abilities.RATTLED, "Rattled (N)", "BUG, GHOST or DARK type moves scare it and boost its SPEED.", 5),
new Ability(Abilities.RATTLED, "Rattled (N)", "BUG, GHOST or DARK type moves scare it and boost its Speed.", 5),
new Ability(Abilities.REGENERATOR, "Regenerator (N)", "Restores a little HP when withdrawn from battle.", 5),
new Ability(Abilities.SAND_FORCE, "Sand Force (N)", "Boosts certain moves' power in a sandstorm.", 5),
new Ability(Abilities.SAND_RUSH, "Sand Rush (N)", "Boosts the POKéMON's SPEED in a sandstorm.", 5),
new Ability(Abilities.SAP_SIPPER, "Sap Sipper", "Boosts ATTACK when hit by a GRASS-type move.", 5)
new Ability(Abilities.SAND_RUSH, "Sand Rush (N)", "Boosts the Pokémon's Speed in a sandstorm.", 5),
new Ability(Abilities.SAP_SIPPER, "Sap Sipper", "Boosts Attack when hit by a Grass-type move.", 5)
.attr(TypeImmunityStatChangeAbAttr, Type.GRASS, BattleStat.ATK, 1),
new Ability(Abilities.SHEER_FORCE, "Sheer Force (N)", "Removes added effects to increase move damage.", 5),
new Ability(Abilities.TELEPATHY, "Telepathy (N)", "Anticipates an ally's ATTACK and dodges it.", 5),
new Ability(Abilities.TELEPATHY, "Telepathy (N)", "Anticipates an ally's Attack and dodges it.", 5),
new Ability(Abilities.TERAVOLT, "Teravolt (N)", "Moves can be used regardless of Abilities.", 5),
new Ability(Abilities.TOXIC_BOOST, "Toxic Boost (N)", "Powers up physical attacks when poisoned.", 5),
new Ability(Abilities.TURBOBLAZE, "Turboblaze (N)", "Moves can be used regardless of Abilities.", 5),
new Ability(Abilities.UNNERVE, "Unnerve (N)", "Makes the foe nervous and unable to eat Berries.", 5),
new Ability(Abilities.VICTORY_STAR, "Victory Star (N)", "Boosts the accuracy of its allies and itself.", 5),
new Ability(Abilities.WEAK_ARMOR, "Weak Armor (N)", "Physical attacks lower DEFENSE and raise SPEED.", 5),
new Ability(Abilities.VICTORY_STAR, "Victory Star (N)", "Boosts the Accuracy of its allies and itself.", 5),
new Ability(Abilities.WEAK_ARMOR, "Weak Armor (N)", "Physical attacks lower Defense and raise Speed.", 5),
new Ability(Abilities.WONDER_SKIN, "Wonder Skin (N)", "Makes status-changing moves more likely to miss.", 5),
new Ability(Abilities.ZEN_MODE, "Zen Mode (N)", "Changes form when HP drops below half.", 5),
new Ability(Abilities.COMPETITIVE, "Competitive (N)", "Sharply raises SP. ATK when the POKéMON's stats are lowered.", 6),
new Ability(Abilities.DARK_AURA, "Dark Aura (N)", "Raises power of DARK type moves for all POKéMON in battle.", 6),
new Ability(Abilities.FAIRY_AURA, "Fairy Aura (N)", "Raises power of FAIRY type moves for all POKéMON in battle.", 6),
new Ability(Abilities.PROTEAN, "Protean (N)", "Changes the POKéMON's type to its last used move.", 6),
new Ability(Abilities.SLUSH_RUSH, "Slush Rush (N)", "Boosts the POKéMON's SPEED stat in a hailstorm.", 7),
new Ability(Abilities.NEUTRALIZING_GAS, "Neutralizing Gas (N)", "Neutralizes abilities of all POKéMON in battle.", 8)
new Ability(Abilities.COMPETITIVE, "Competitive (N)", "Sharply raises Sp. Atk when the Pokémon's stats are lowered.", 6),
new Ability(Abilities.DARK_AURA, "Dark Aura (N)", "Raises power of DARK type moves for all Pokémon in battle.", 6),
new Ability(Abilities.FAIRY_AURA, "Fairy Aura (N)", "Raises power of FAIRY type moves for all Pokémon in battle.", 6),
new Ability(Abilities.PROTEAN, "Protean (N)", "Changes the Pokémon's type to its last used move.", 6),
new Ability(Abilities.SLUSH_RUSH, "Slush Rush (N)", "Boosts the Pokémon's Speed stat in a hailstorm.", 7),
new Ability(Abilities.NEUTRALIZING_GAS, "Neutralizing Gas (N)", "Neutralizes abilities of all Pokémon in battle.", 8)
);
}
+7 -7
View File
@@ -12,19 +12,19 @@ export enum BattleStat {
export function getBattleStatName(stat: BattleStat) {
switch (stat) {
case BattleStat.ATK:
return 'ATTACK';
return 'Attack';
case BattleStat.DEF:
return 'DEFENSE';
return 'Defense';
case BattleStat.SPATK:
return 'SP. ATK';
return 'Sp. Atk';
case BattleStat.SPDEF:
return 'SP. DEF';
return 'Sp. Def';
case BattleStat.SPD:
return 'SPEED';
return 'Speed';
case BattleStat.ACC:
return 'accuracy';
return 'Accuracy';
case BattleStat.EVA:
return 'evasiveness';
return 'Evasiveness';
default:
return '???';
}
+3 -2
View File
@@ -1,10 +1,11 @@
import { PokemonHealPhase, StatChangePhase } from "../battle-phases";
import { getPokemonMessage } from "../messages";
import Pokemon, { HitResult, MoveResult } from "../pokemon";
import Pokemon, { HitResult } from "../pokemon";
import { getBattleStatName } from "./battle-stat";
import { BattleStat } from "./battle-stat";
import { BattlerTagType } from "./battler-tag";
import { getStatusEffectHealText } from "./status-effect";
import * as Utils from "../utils";
export enum BerryType {
SITRUS,
@@ -20,7 +21,7 @@ export enum BerryType {
}
export function getBerryName(berryType: BerryType) {
return `${BerryType[berryType]} BERRY`;
return `${Utils.toReadableString(BerryType[berryType])} Berry`;
}
export function getBerryEffectDescription(berryType: BerryType) {
+6 -6
View File
@@ -41,17 +41,17 @@ export enum Biome {
export function getBiomeName(biome: Biome) {
switch (biome) {
case Biome.GRASS:
return 'GRASSY FIELD';
return 'Grassy Field';
case Biome.RUINS:
return 'ANCIENT RUINS';
return 'Ancient Ruins';
case Biome.ABYSS:
return 'THE ABYSS';
return 'The Abyss';
case Biome.SPACE:
return 'STRATOSPHERE';
return 'Stratosphere';
case Biome.END:
return 'FINAL DESTINATION';
return 'Final Destination';
default:
return Biome[biome].replace(/\_/g, ' ');
return Utils.toReadableString(Biome[biome]);
}
}
+8 -8
View File
@@ -70,7 +70,7 @@ export default class Move {
constructor(id: Moves, name: string, type: Type, category: MoveCategory, defaultMoveTarget: MoveTarget, power: integer, accuracy: integer, pp: integer, tm: integer, effect: string, chance: integer, priority: integer, generation: integer) {
this.id = id;
this.name = name.toUpperCase();
this.name = name;
this.type = type;
this.category = category;
this.moveTarget = defaultMoveTarget;
@@ -1926,7 +1926,7 @@ export class CopyBiomeTypeAttr extends MoveEffectAttr {
user.summonData.types = [ biomeType ];
user.scene.queueMessage(getPokemonMessage(user, ` transformed\ninto the ${Type[biomeType].toUpperCase()} type!`));
user.scene.queueMessage(getPokemonMessage(user, ` transformed\ninto the ${Utils.toReadableString(Type[biomeType])} type!`));
return true;
}
@@ -2237,7 +2237,7 @@ export function initMoves() {
new SelfStatusMove(Moves.SWORDS_DANCE, "Swords Dance", Type.NORMAL, -1, 20, 88, "Sharply raises user's Attack.", -1, 0, 1)
.attr(StatChangeAttr, BattleStat.ATK, 2, true),
new AttackMove(Moves.CUT, "Cut", Type.NORMAL, MoveCategory.PHYSICAL, 50, 95, 30, -1, "", -1, 0, 1),
new AttackMove(Moves.GUST, "Gust", Type.FLYING, MoveCategory.SPECIAL, 40, 100, 35, -1, "Hits Pokémon using FLY/BOUNCE/SKY DROP with double power.", -1, 0, 1)
new AttackMove(Moves.GUST, "Gust", Type.FLYING, MoveCategory.SPECIAL, 40, 100, 35, -1, "Hits Pokémon using Fly/Bounce/Sky Drop with double power.", -1, 0, 1)
.attr(HitsTagAttr, BattlerTagType.FLYING, true)
.target(MoveTarget.OTHER),
new AttackMove(Moves.WING_ATTACK, "Wing Attack", Type.FLYING, MoveCategory.PHYSICAL, 60, 100, 35, -1, "", -1, 0, 1)
@@ -2649,7 +2649,7 @@ export function initMoves() {
.target(MoveTarget.ENEMY_SIDE),
new AttackMove(Moves.ZAP_CANNON, "Zap Cannon", Type.ELECTRIC, MoveCategory.SPECIAL, 120, 50, 5, -1, "Paralyzes opponent.", 100, 0, 2)
.attr(StatusEffectAttr, StatusEffect.PARALYSIS),
new StatusMove(Moves.FORESIGHT, "Foresight (N)", Type.NORMAL, -1, 40, -1, "Resets opponent's Evasiveness, and allows Normal- and Fighting-type attacks to hit Ghosts.", -1, 0, 2), // TODO
new StatusMove(Moves.FORESIGHT, "Foresight (N)", Type.NORMAL, -1, 40, -1, "Resets opponent's Evasiveness, and allows Normal-type and Fighting-type attacks to hit Ghosts.", -1, 0, 2), // TODO
new StatusMove(Moves.DESTINY_BOND, "Destiny Bond (N)", Type.GHOST, -1, 5, -1, "If the user faints, the opponent also faints.", -1, 0, 2)
.ignoresProtect(),
new StatusMove(Moves.PERISH_SONG, "Perish Song (N)", Type.NORMAL, -1, 5, -1, "Any Pokémon in play when this attack is used faints in 3 turns.", -1, 0, 2)
@@ -2744,7 +2744,7 @@ export function initMoves() {
new AttackMove(Moves.HIDDEN_POWER, "Hidden Power (N)", Type.NORMAL, MoveCategory.SPECIAL, 60, 100, 15, -1, "Type and power depends on user's IVs.", -1, 0, 2),
new AttackMove(Moves.CROSS_CHOP, "Cross Chop", Type.FIGHTING, MoveCategory.PHYSICAL, 100, 80, 5, -1, "High critical hit ratio.", -1, 0, 2)
.attr(HighCritAttr),
new AttackMove(Moves.TWISTER, "Twister", Type.DRAGON, MoveCategory.SPECIAL, 40, 100, 20, -1, "May cause flinching. Hits Pokémon using FLY/BOUNCE with double power.", 20, 0, 2)
new AttackMove(Moves.TWISTER, "Twister", Type.DRAGON, MoveCategory.SPECIAL, 40, 100, 20, -1, "May cause flinching. Hits Pokémon using Fly/Bounce/Sky Drop with double power.", 20, 0, 2)
.attr(HitsTagAttr, BattlerTagType.FLYING, true)
.attr(FlinchAttr)
.target(MoveTarget.ALL_NEAR_ENEMIES), // TODO
@@ -2989,7 +2989,7 @@ export function initMoves() {
new SelfStatusMove(Moves.ROOST, "Roost", Type.FLYING, -1, 5, -1, "User recovers half of its max HP and loses the FLYING type temporarily.", -1, 0, 4)
.attr(HealAttr)
.attr(AddBattlerTagAttr, BattlerTagType.IGNORE_FLYING, true, 1),
new SelfStatusMove(Moves.GRAVITY, "Gravity", Type.PSYCHIC, -1, 5, -1, "Prevents moves like FLY and BOUNCE and the Ability LEVITATE for 5 turns.", -1, 0, 4)
new SelfStatusMove(Moves.GRAVITY, "Gravity", Type.PSYCHIC, -1, 5, -1, "Prevents moves like Fly and Bounce and the Ability Levitate for 5 turns.", -1, 0, 4)
.attr(AddArenaTagAttr, ArenaTagType.GRAVITY, 5)
.target(MoveTarget.BOTH_SIDES),
new StatusMove(Moves.MIRACLE_EYE, "Miracle Eye (N)", Type.PSYCHIC, -1, 40, -1, "Resets opponent's Evasiveness, removes DARK's PSYCHIC immunity.", -1, 0, 4),
@@ -3005,7 +3005,7 @@ export function initMoves() {
.attr(MovePowerMultiplierAttr, (user: Pokemon, target: Pokemon, move: Move) => target.getHpRatio() < 0.5 ? 2 : 1),
new AttackMove(Moves.NATURAL_GIFT, "Natural Gift (N)", Type.NORMAL, MoveCategory.PHYSICAL, -1, 100, 15, -1, "Power and type depend on the user's held berry.", -1, 0, 4)
.makesContact(false),
new AttackMove(Moves.FEINT, "Feint", Type.NORMAL, MoveCategory.PHYSICAL, 30, 100, 10, -1, "Only hits if opponent uses PROTECT or DETECT in the same turn.", -1, 2, 4)
new AttackMove(Moves.FEINT, "Feint", Type.NORMAL, MoveCategory.PHYSICAL, 30, 100, 10, -1, "Only hits if opponent uses Protect or Detect in the same turn.", -1, 2, 4)
.condition((user: Pokemon, target: Pokemon, move: Move) => !!target.getTag(BattlerTagType.PROTECTED))
.makesContact(false)
.ignoresProtect(),
@@ -3050,7 +3050,7 @@ export function initMoves() {
new AttackMove(Moves.PUNISHMENT, "Punishment (N)", Type.DARK, MoveCategory.PHYSICAL, -1, 100, 5, -1, "Power increases when opponent's stats have been raised.", -1, 0, 4),
new AttackMove(Moves.LAST_RESORT, "Last Resort", Type.NORMAL, MoveCategory.PHYSICAL, 140, 100, 5, -1, "Can only be used after all other moves are used.", -1, 0, 4)
.condition((user: Pokemon, target: Pokemon, move: Move) => !user.getMoveset().filter(m => m.moveId !== move.id && m.getPpRatio() > 0).length),
new StatusMove(Moves.WORRY_SEED, "Worry Seed (N)", Type.GRASS, 100, 10, -1, "Changes the opponent's Ability to INSOMNIA.", -1, 0, 4),
new StatusMove(Moves.WORRY_SEED, "Worry Seed (N)", Type.GRASS, 100, 10, -1, "Changes the opponent's Ability to Insomnia.", -1, 0, 4),
new AttackMove(Moves.SUCKER_PUNCH, "Sucker Punch (N)", Type.DARK, MoveCategory.PHYSICAL, 70, 100, 5, -1, "User attacks first, but only works if opponent is readying an attack.", -1, 0, 4),
new StatusMove(Moves.TOXIC_SPIKES, "Toxic Spikes", Type.POISON, -1, 20, 91, "Poisons opponents when they switch into battle.", -1, 0, 4)
.attr(AddArenaTrapTagAttr, ArenaTagType.TOXIC_SPIKES)
+1 -2
View File
@@ -1,5 +1,4 @@
import BattleScene from "../battle-scene";
import { toPokemonUpperCase } from "../utils";
export enum PokeballType {
POKEBALL,
@@ -43,7 +42,7 @@ export function getPokeballName(type: PokeballType): string {
ret = 'Luxury Ball';
break;
}
return toPokemonUpperCase(ret);
return ret;
}
export function getPokeballCatchMultiplier(type: PokeballType): number {
+8 -1
View File
@@ -902,7 +902,7 @@ export function initSpecies() {
new PokemonForm("Origin Forme", "origin", Type.GHOST, Type.DRAGON, 6.9, 650, Abilities.LEVITATE, Abilities.NONE, Abilities.NONE, 680, 150, 120, 100, 120, 100, 90, 3, 0, 306, GrowthRate.SLOW, "Undiscovered", null, null, 120, false)
),
new PokemonSpecies(Species.CRESSELIA, "Cresselia", 4, true, false, false, "Lunar Pokémon", Type.PSYCHIC, null, 1.5, 85.6, Abilities.LEVITATE, Abilities.NONE, Abilities.NONE, 600, 120, 70, 120, 75, 130, 85, 3, 100, 270, GrowthRate.SLOW, "Undiscovered", null, 0, 120, false),
new PokemonSpecies(Species.PHIONE, "Phione", 4, false, false, true, "Sea Drifter Pokémon", Type.WATER, null, 0.4, 3.1, Abilities.HYDRATION, Abilities.NONE, Abilities.NONE, 480, 80, 80, 80, 80, 80, 80, 30, 70, 216, GrowthRate.SLOW, "Fairy", "Water 1", null, 40, false),
new PokemonSpecies(Species.PHIONE, "Phione", 4, false, false, false, "Sea Drifter Pokémon", Type.WATER, null, 0.4, 3.1, Abilities.HYDRATION, Abilities.NONE, Abilities.NONE, 480, 80, 80, 80, 80, 80, 80, 30, 70, 216, GrowthRate.SLOW, "Fairy", "Water 1", null, 40, false),
new PokemonSpecies(Species.MANAPHY, "Manaphy", 4, false, false, true, "Seafaring Pokémon", Type.WATER, null, 0.3, 1.4, Abilities.HYDRATION, Abilities.NONE, Abilities.NONE, 600, 100, 100, 100, 100, 100, 100, 3, 70, 270, GrowthRate.SLOW, "Fairy", "Water 1", null, 10, false),
new PokemonSpecies(Species.DARKRAI, "Darkrai", 4, false, false, true, "Pitch-Black Pokémon", Type.DARK, null, 1.5, 50.5, Abilities.BAD_DREAMS, Abilities.NONE, Abilities.NONE, 600, 70, 90, 90, 135, 90, 125, 3, 0, 270, GrowthRate.SLOW, "Undiscovered", null, null, 120, false),
new PokemonSpecies(Species.SHAYMIN, "Shaymin", 4, false, false, true, "Gratitude Pokémon", Type.GRASS, null, 0.2, 2.1, Abilities.NATURAL_CURE, Abilities.NONE, Abilities.NONE, 600, 100, 100, 100, 100, 100, 100, 45, 100, 270, GrowthRate.MEDIUM_SLOW, "Undiscovered", null, null, 120, false, true,
@@ -1117,5 +1117,12 @@ export function initSpecies() {
return s;
}))].map(s => s.name));
}
const speciesFilter = (species: PokemonSpecies) => !species.legendary && !species.pseudoLegendary && !species.mythical && species.baseTotal >= 540;
console.log(!speciesFilter ? 'all' : [...new Set(allSpecies.slice(0, -1).filter(speciesFilter).map(s => {
while (pokemonPrevolutions.hasOwnProperty(s.speciesId))
s = getPokemonSpecies(pokemonPrevolutions[s.speciesId]);
return s;
}))].map(s => s.name));
}, 1000);
}*/
+1 -3
View File
@@ -1,5 +1,3 @@
import { toPokemonUpperCase } from "../utils";
export enum Stat {
HP = 0,
ATK,
@@ -31,5 +29,5 @@ export function getStatName(stat: Stat) {
ret = 'Speed';
break;
}
return toPokemonUpperCase(ret);
return ret;
}
+316 -41
View File
@@ -1,8 +1,10 @@
import BattleScene from "../battle-scene";
import { EnemyPokemon } from "../pokemon";
import * as Utils from "../utils";
import { Moves } from "./move";
import { pokemonEvolutions, pokemonPrevolutions } from "./pokemon-evolutions";
import { pokemonLevelMoves } from "./pokemon-level-moves";
import { PokemonSpeciesFilter } from "./pokemon-species";
import PokemonSpecies, { PokemonSpeciesFilter, getPokemonSpecies } from "./pokemon-species";
import { Species } from "./species";
import { tmSpecies } from "./tms";
import { Type } from "./type";
@@ -56,14 +58,13 @@ export enum TrainerType {
WAITER,
WORKER,
YOUNGSTER,
CYNTHIA,
RIVAL,
CYNTHIA
}
export enum TrainerPartyType {
DEFAULT,
BALANCED,
REPEATED
RIVAL_2,
RIVAL_3,
RIVAL_4,
RIVAL_5,
RIVAL_6
}
export enum TrainerPoolTier {
@@ -78,38 +79,185 @@ export interface TrainerTierPools {
[key: integer]: Species[]
}
export enum TrainerPartyMemberStrength {
WEAKER,
WEAK,
AVERAGE,
STRONG,
STRONGER
}
export class TrainerPartyTemplate {
public size: integer;
public strength: TrainerPartyMemberStrength;
public sameSpecies: boolean;
public balanced: boolean;
constructor(size: integer, strength: TrainerPartyMemberStrength, sameSpecies?: boolean, balanced?: boolean) {
this.size = size;
this.strength = strength;
this.sameSpecies = !!sameSpecies;
this.balanced = !!balanced;
}
getStrength(index: integer): TrainerPartyMemberStrength {
return this.strength;
}
isSameSpecies(index: integer): boolean {
return this.sameSpecies;
}
isBalanced(index: integer): boolean {
return this.balanced;
}
}
export class TrainerPartyCompoundTemplate extends TrainerPartyTemplate {
public templates: TrainerPartyTemplate[];
constructor(...templates: TrainerPartyTemplate[]) {
super(templates.reduce((total: integer, template: TrainerPartyTemplate) => {
total += template.size;
return total;
}, 0), TrainerPartyMemberStrength.AVERAGE);
this.templates = templates;
}
getStrength(index: integer): TrainerPartyMemberStrength {
let t = 0;
for (let template of this.templates) {
if (t + template.size > index)
return template.getStrength(index - t);
t += template.size;
}
return super.getStrength(index);
}
isSameSpecies(index: integer): boolean {
let t = 0;
for (let template of this.templates) {
if (t + template.size > index)
return template.isSameSpecies(index - t);
t += template.size;
}
return super.isSameSpecies(index);
}
isBalanced(index: integer): boolean {
let t = 0;
for (let template of this.templates) {
if (t + template.size > index)
return template.isBalanced(index - t);
t += template.size;
}
return super.isBalanced(index);
}
}
export const trainerPartyTemplates = {
ONE_AVG: new TrainerPartyTemplate(1, TrainerPartyMemberStrength.AVERAGE),
ONE_STRONG: new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONG),
ONE_STRONGER: new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONGER),
TWO_WEAKER: new TrainerPartyTemplate(2, TrainerPartyMemberStrength.WEAKER),
TWO_WEAK: new TrainerPartyTemplate(2, TrainerPartyMemberStrength.WEAK),
TWO_WEAK_SAME_ONE_AVG: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(2, TrainerPartyMemberStrength.WEAK, true), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.AVERAGE)),
TWO_WEAK_SAME_TWO_WEAK_SAME: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(2, TrainerPartyMemberStrength.WEAK, true), new TrainerPartyTemplate(2, TrainerPartyMemberStrength.WEAK, true)),
TWO_AVG: new TrainerPartyTemplate(2, TrainerPartyMemberStrength.AVERAGE),
TWO_AVG_SAME_ONE_AVG: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(2, TrainerPartyMemberStrength.AVERAGE, true), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.AVERAGE)),
TWO_AVG_SAME_ONE_STRONG: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(2, TrainerPartyMemberStrength.AVERAGE, true), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONG)),
TWO_AVG_SAME_TWO_AVG_SAME: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(2, TrainerPartyMemberStrength.AVERAGE, true), new TrainerPartyTemplate(2, TrainerPartyMemberStrength.AVERAGE, true)),
THREE_WEAK: new TrainerPartyTemplate(3, TrainerPartyMemberStrength.WEAK),
THREE_WEAK_SAME: new TrainerPartyTemplate(3, TrainerPartyMemberStrength.WEAK, true),
THREE_AVG: new TrainerPartyTemplate(3, TrainerPartyMemberStrength.AVERAGE),
THREE_AVG_SAME: new TrainerPartyTemplate(3, TrainerPartyMemberStrength.AVERAGE, true),
FOUR_WEAKER: new TrainerPartyTemplate(4, TrainerPartyMemberStrength.WEAKER),
FOUR_WEAKER_SAME: new TrainerPartyTemplate(4, TrainerPartyMemberStrength.WEAKER, true),
FOUR_WEAK: new TrainerPartyTemplate(4, TrainerPartyMemberStrength.WEAK),
FOUR_WEAK_SAME: new TrainerPartyTemplate(4, TrainerPartyMemberStrength.WEAK),
FIVE_WEAK: new TrainerPartyTemplate(5, TrainerPartyMemberStrength.WEAK, true),
SIX_WEAK_SAME: new TrainerPartyTemplate(6, TrainerPartyMemberStrength.WEAKER, true),
SIX_WEAKER: new TrainerPartyTemplate(6, TrainerPartyMemberStrength.WEAKER),
SIX_WEAKER_SAME: new TrainerPartyTemplate(6, TrainerPartyMemberStrength.WEAKER, true),
SIX_WEAK_BALANCED: new TrainerPartyTemplate(6, TrainerPartyMemberStrength.WEAK, false, true),
RIVAL: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONG), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.AVERAGE)),
RIVAL_2: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONG), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.AVERAGE)),
RIVAL_3: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONG), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.AVERAGE), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.AVERAGE, false, true)),
RIVAL_4: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONG), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.AVERAGE), new TrainerPartyTemplate(3, TrainerPartyMemberStrength.AVERAGE, false, true)),
RIVAL_5: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONG), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.AVERAGE), new TrainerPartyTemplate(3, TrainerPartyMemberStrength.AVERAGE, false, true), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONG)),
RIVAL_6: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONG), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.AVERAGE), new TrainerPartyTemplate(3, TrainerPartyMemberStrength.AVERAGE, false, true), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONGER))
};
type PartyMemberFunc = (scene: BattleScene, level: integer) => EnemyPokemon;
export interface PartyMemberFuncs {
[key: integer]: PartyMemberFunc
}
export class TrainerConfig {
public trainerType: TrainerType;
public name: string;
public nameFemale: string;
public hasGenders: boolean = false;
public isDouble: boolean = false;
public partyType: TrainerPartyType = TrainerPartyType.DEFAULT;
public staticParty: boolean = false;
public battleBgm: string;
public encounterBgm: string;
public femaleEncounterBgm: string;
public partyTemplates: TrainerPartyTemplate[];
public partyMemberFuncs: PartyMemberFuncs = {};
public speciesPools: TrainerTierPools;
public speciesFilter: PokemonSpeciesFilter;
public encounterMessages: string[] = [];
public victoryMessages: string[] = [];
public defeatMessages: string[] = [];
public femaleEncounterMessages: string[];
public femaleVictoryMessages: string[];
public femaleDefeatMessages: string[];
constructor(trainerType: TrainerType, allowLegendaries?: boolean) {
this.trainerType = trainerType;
this.name = Utils.toPokemonUpperCase(TrainerType[this.trainerType].toString().replace(/\_/g, ' '));
this.name = Utils.toReadableString(TrainerType[this.getDerivedType()]);
this.battleBgm = 'battle_trainer';
this.encounterBgm = this.name.toLowerCase();
this.partyTemplates = [ trainerPartyTemplates.TWO_AVG ];
this.speciesFilter = species => allowLegendaries || (!species.legendary && !species.pseudoLegendary && !species.mythical);
}
public getKey(female?: boolean): string {
let ret = TrainerType[this.trainerType].toString().toLowerCase();
getKey(female?: boolean): string {
let ret = TrainerType[this.getDerivedType()].toString().toLowerCase();
if (this.hasGenders)
ret += `_${female ? 'f' : 'm'}`;
return ret;
}
public setName(name: string): TrainerConfig {
setName(name: string): TrainerConfig {
this.name = name;
return this;
}
public setHasGenders(nameFemale?: string, femaleEncounterBgm?: TrainerType | string): TrainerConfig {
getDerivedType(): TrainerType {
let trainerType = this.trainerType;
switch (trainerType) {
case TrainerType.RIVAL_2:
case TrainerType.RIVAL_3:
case TrainerType.RIVAL_4:
case TrainerType.RIVAL_5:
case TrainerType.RIVAL_6:
trainerType = TrainerType.RIVAL;
break;
}
return trainerType;
}
setHasGenders(nameFemale?: string, femaleEncounterBgm?: TrainerType | string): TrainerConfig {
this.hasGenders = true;
this.nameFemale = nameFemale;
if (femaleEncounterBgm)
@@ -117,33 +265,66 @@ export class TrainerConfig {
return this;
}
public setDouble(): TrainerConfig {
setDouble(): TrainerConfig {
this.isDouble = true;
return this;
}
public setEncounterBgm(encounterBgm: TrainerType | string): TrainerConfig {
setStaticParty(): TrainerConfig {
this.staticParty = true;
return this;
}
setBattleBgm(battleBgm: string): TrainerConfig {
this.battleBgm = battleBgm;
return this;
}
setEncounterBgm(encounterBgm: TrainerType | string): TrainerConfig {
this.encounterBgm = typeof encounterBgm === 'number' ? TrainerType[encounterBgm].toString().replace(/\_/g, ' ').toLowerCase() : encounterBgm;
return this;
}
public setPartyType(partyType: TrainerPartyType): TrainerConfig {
this.partyType = partyType;
setPartyTemplates(...partyTemplates: TrainerPartyTemplate[]): TrainerConfig {
this.partyTemplates = partyTemplates;
return this;
}
public setSpeciesPools(speciesPools: TrainerTierPools | Species[]): TrainerConfig {
this.speciesPools = (Array.isArray(speciesPools) ? speciesPools : { [TrainerPoolTier.COMMON]: speciesPools }) as unknown as TrainerTierPools;
setPartyMemberFunc(slotIndex: integer, partyMemberFunc: PartyMemberFunc): TrainerConfig {
this.partyMemberFuncs[slotIndex] = partyMemberFunc;
return this;
}
public setSpeciesFilter(speciesFilter: PokemonSpeciesFilter, allowLegendaries?: boolean): TrainerConfig {
setSpeciesPools(speciesPools: TrainerTierPools | Species[]): TrainerConfig {
this.speciesPools = (Array.isArray(speciesPools) ? { [TrainerPoolTier.COMMON]: speciesPools } : speciesPools) as unknown as TrainerTierPools;
return this;
}
setSpeciesFilter(speciesFilter: PokemonSpeciesFilter, allowLegendaries?: boolean): TrainerConfig {
const baseFilter = this.speciesFilter;
this.speciesFilter = allowLegendaries ? speciesFilter : species => speciesFilter(species) && baseFilter(species);
return this;
}
public getName(female?: boolean): string {
setEncounterMessages(messages: string[], femaleMessages?: string[]): TrainerConfig {
this.encounterMessages = messages;
this.femaleEncounterMessages = femaleMessages;
return this;
}
setVictoryMessages(messages: string[], femaleMessages?: string[]): TrainerConfig {
this.victoryMessages = messages;
this.femaleVictoryMessages = femaleMessages;
return this;
}
setDefeatMessages(messages: string[], femaleMessages?: string[]): TrainerConfig {
this.defeatMessages = messages;
this.femaleDefeatMessages = femaleMessages;
return this;
}
getName(female?: boolean): string {
let ret = this.name;
if (this.hasGenders) {
@@ -157,11 +338,6 @@ export class TrainerConfig {
return ret;
}
public genPartySize(): integer {
// TODO
return this.isDouble ? 2 : 1;
}
loadAssets(scene: BattleScene, female: boolean): Promise<void> {
return new Promise(resolve => {
const trainerKey = this.getKey(female);
@@ -170,7 +346,7 @@ export class TrainerConfig {
const originalWarn = console.warn;
// Ignore warnings for missing frames, because there will be a lot
console.warn = () => {};
const frameNames = scene.anims.generateFrameNames(trainerKey, { zeroPad: 4, suffix: ".png", start: 1, end:24 });
const frameNames = scene.anims.generateFrameNames(trainerKey, { zeroPad: 4, suffix: ".png", start: 1, end: 24 });
console.warn = originalWarn;
scene.anims.create({
key: trainerKey,
@@ -192,30 +368,54 @@ interface TrainerConfigs {
[key: integer]: TrainerConfig
}
function getRandomPartyMemberFunc(species: Species[], postProcess?: (enemyPokemon: EnemyPokemon) => void): PartyMemberFunc {
return (scene: BattleScene, level: integer) => {
const ret = new EnemyPokemon(scene, getPokemonSpecies(Phaser.Math.RND.pick(species)), level);
if (postProcess)
postProcess(ret);
return ret;
};
}
function getSpeciesFilterRandomPartyMemberFunc(speciesFilter: PokemonSpeciesFilter, allowLegendaries?: boolean, postProcess?: (EnemyPokemon: EnemyPokemon) => void): PartyMemberFunc {
const originalSpeciesFilter = speciesFilter;
speciesFilter = (species: PokemonSpecies) => allowLegendaries || (!species.legendary && !species.pseudoLegendary && !species.mythical) && originalSpeciesFilter(species);
return (scene: BattleScene, level: integer) => {
const ret = new EnemyPokemon(scene, scene.randomSpecies(scene.currentBattle.waveIndex, level, speciesFilter), level);
if (postProcess)
postProcess(ret);
return ret;
};
}
export const trainerConfigs: TrainerConfigs = {
[TrainerType.ACE_TRAINER]: new TrainerConfig(++t).setHasGenders().setPartyType(TrainerPartyType.BALANCED),
[TrainerType.ARTIST]: new TrainerConfig(++t).setEncounterBgm(TrainerType.RICH).setSpeciesPools([ Species.SMEARGLE ]),
[TrainerType.ACE_TRAINER]: new TrainerConfig(++t).setHasGenders().setPartyTemplates(trainerPartyTemplates.SIX_WEAK_BALANCED),
[TrainerType.ARTIST]: new TrainerConfig(++t).setEncounterBgm(TrainerType.RICH).setPartyTemplates(trainerPartyTemplates.ONE_STRONG, trainerPartyTemplates.TWO_AVG, trainerPartyTemplates.THREE_AVG).setSpeciesPools([ Species.SMEARGLE ]),
[TrainerType.BACKERS]: new TrainerConfig(++t).setHasGenders().setEncounterBgm(TrainerType.CYCLIST).setDouble(),
[TrainerType.BACKPACKER]: new TrainerConfig(++t).setHasGenders().setSpeciesFilter(s => s.isOfType(Type.FLYING) || s.isOfType(Type.ROCK)),
[TrainerType.BAKER]: new TrainerConfig(++t).setEncounterBgm(TrainerType.CLERK).setSpeciesFilter(s => s.isOfType(Type.GRASS) || s.isOfType(Type.FIRE)),
[TrainerType.BEAUTY]: new TrainerConfig(++t).setEncounterBgm(TrainerType.PARASOL_LADY),
[TrainerType.BIKER]: new TrainerConfig(++t).setEncounterBgm(TrainerType.ROUGHNECK).setSpeciesFilter(s => s.isOfType(Type.POISON)),
[TrainerType.BLACK_BELT]: new TrainerConfig(++t).setHasGenders('Battle Girl', TrainerType.PSYCHIC).setEncounterBgm(TrainerType.ROUGHNECK).setSpeciesFilter(s => s.isOfType(Type.FIGHTING)),
[TrainerType.BREEDER]: new TrainerConfig(++t).setHasGenders().setDouble().setEncounterBgm(TrainerType.POKEFAN),
[TrainerType.BREEDER]: new TrainerConfig(++t).setHasGenders().setDouble().setEncounterBgm(TrainerType.POKEFAN).setPartyTemplates(trainerPartyTemplates.SIX_WEAKER),
[TrainerType.CLERK]: new TrainerConfig(++t).setHasGenders(),
[TrainerType.CYCLIST]: new TrainerConfig(++t).setHasGenders().setSpeciesFilter(s => !!pokemonLevelMoves[s.speciesId].find(plm => plm[1] === Moves.QUICK_ATTACK)),
[TrainerType.DANCER]: new TrainerConfig(++t).setEncounterBgm(TrainerType.CYCLIST),
[TrainerType.DEPOT_AGENT]: new TrainerConfig(++t).setEncounterBgm(TrainerType.CLERK),
[TrainerType.DOCTOR]: new TrainerConfig(++t).setEncounterBgm(TrainerType.CLERK),
[TrainerType.FISHERMAN]: new TrainerConfig(++t).setEncounterBgm(TrainerType.BACKPACKER).setSpeciesPools({
[TrainerPoolTier.COMMON]: [ Species.TENTACOOL, Species.MAGIKARP, Species.GOLDEEN, Species.STARYU, Species.REMORAID ],
[TrainerPoolTier.UNCOMMON]: [ Species.POLIWAG, Species.SHELLDER, Species.KRABBY, Species.HORSEA, Species.CARVANHA, Species.BARBOACH, Species.CORPHISH, Species.FINNEON, Species.TYMPOLE, Species.BASCULIN, Species.FRILLISH ],
[TrainerPoolTier.RARE]: [ Species.CHINCHOU, Species.CORSOLA, Species.WAILMER, Species.CLAMPERL, Species.LUVDISC, Species.MANTYKE, Species.ALOMOMOLA ],
[TrainerPoolTier.SUPER_RARE]: [ Species.LAPRAS, Species.FEEBAS, Species.RELICANTH ]
}),
[TrainerType.FISHERMAN]: new TrainerConfig(++t).setEncounterBgm(TrainerType.BACKPACKER)
.setPartyTemplates(trainerPartyTemplates.TWO_WEAK_SAME_ONE_AVG, trainerPartyTemplates.ONE_AVG, trainerPartyTemplates.THREE_WEAK_SAME, trainerPartyTemplates.ONE_STRONG, trainerPartyTemplates.SIX_WEAKER)
.setSpeciesPools({
[TrainerPoolTier.COMMON]: [ Species.TENTACOOL, Species.MAGIKARP, Species.GOLDEEN, Species.STARYU, Species.REMORAID ],
[TrainerPoolTier.UNCOMMON]: [ Species.POLIWAG, Species.SHELLDER, Species.KRABBY, Species.HORSEA, Species.CARVANHA, Species.BARBOACH, Species.CORPHISH, Species.FINNEON, Species.TYMPOLE, Species.BASCULIN, Species.FRILLISH ],
[TrainerPoolTier.RARE]: [ Species.CHINCHOU, Species.CORSOLA, Species.WAILMER, Species.CLAMPERL, Species.LUVDISC, Species.MANTYKE, Species.ALOMOMOLA ],
[TrainerPoolTier.SUPER_RARE]: [ Species.LAPRAS, Species.FEEBAS, Species.RELICANTH ]
}
),
[TrainerType.GUITARIST]: new TrainerConfig(++t).setEncounterBgm(TrainerType.ROUGHNECK).setSpeciesFilter(s => s.isOfType(Type.ELECTRIC)),
[TrainerType.HARLEQUIN]: new TrainerConfig(++t).setEncounterBgm(TrainerType.PSYCHIC).setSpeciesFilter(s => tmSpecies[Moves.TRICK_ROOM].indexOf(s.speciesId) > -1),
[TrainerType.HIKER]: new TrainerConfig(++t).setEncounterBgm(TrainerType.BACKPACKER).setSpeciesFilter(s => s.isOfType(Type.GROUND) || s.isOfType(Type.ROCK)),
[TrainerType.HIKER]: new TrainerConfig(++t).setEncounterBgm(TrainerType.BACKPACKER).setSpeciesFilter(s => s.isOfType(Type.GROUND) || s.isOfType(Type.ROCK))
.setPartyTemplates(trainerPartyTemplates.TWO_AVG_SAME_ONE_AVG, trainerPartyTemplates.TWO_AVG_SAME_ONE_STRONG, trainerPartyTemplates.TWO_AVG, trainerPartyTemplates.FOUR_WEAK, trainerPartyTemplates.ONE_STRONG),
[TrainerType.HOOLIGANS]: new TrainerConfig(++t).setDouble().setEncounterBgm(TrainerType.ROUGHNECK).setSpeciesFilter(s => s.isOfType(Type.POISON) || s.isOfType(Type.DARK)),
[TrainerType.HOOPSTER]: new TrainerConfig(++t).setEncounterBgm(TrainerType.CYCLIST),
[TrainerType.INFIELDER]: new TrainerConfig(++t).setEncounterBgm(TrainerType.CYCLIST),
@@ -228,7 +428,8 @@ export const trainerConfigs: TrainerConfigs = {
[TrainerType.OFFICER]: new TrainerConfig(++t).setEncounterBgm(TrainerType.CLERK).setSpeciesPools([ Species.VULPIX, Species.GROWLITHE, Species.SNUBBULL, Species.HOUNDOUR, Species.POOCHYENA, Species.ELECTRIKE, Species.LILLIPUP ]),
[TrainerType.PARASOL_LADY]: new TrainerConfig(++t).setSpeciesFilter(s => s.isOfType(Type.WATER)),
[TrainerType.PILOT]: new TrainerConfig(++t).setEncounterBgm(TrainerType.CLERK).setSpeciesFilter(s => tmSpecies[Moves.FLY].indexOf(s.speciesId) > -1),
[TrainerType.POKEFAN]: new TrainerConfig(++t).setHasGenders(),
[TrainerType.POKEFAN]: new TrainerConfig(++t).setHasGenders()
.setPartyTemplates(trainerPartyTemplates.SIX_WEAKER, trainerPartyTemplates.FOUR_WEAK, trainerPartyTemplates.TWO_AVG, trainerPartyTemplates.ONE_STRONG, trainerPartyTemplates.FOUR_WEAK_SAME, trainerPartyTemplates.FIVE_WEAK, trainerPartyTemplates.SIX_WEAKER_SAME),
[TrainerType.PRESCHOOLER]: new TrainerConfig(++t).setEncounterBgm(TrainerType.YOUNGSTER).setHasGenders(undefined, 'lass'),
[TrainerType.PSYCHIC]: new TrainerConfig(++t).setHasGenders(),
[TrainerType.RANGER]: new TrainerConfig(++t).setEncounterBgm(TrainerType.BACKPACKER).setHasGenders(),
@@ -250,7 +451,81 @@ export const trainerConfigs: TrainerConfigs = {
[TrainerType.VETERAN]: new TrainerConfig(++t).setHasGenders().setEncounterBgm(TrainerType.RICH),
[TrainerType.WAITER]: new TrainerConfig(++t).setHasGenders().setEncounterBgm(TrainerType.CLERK),
[TrainerType.WORKER]: new TrainerConfig(++t).setEncounterBgm(TrainerType.CLERK).setSpeciesFilter(s => s.isOfType(Type.ROCK) || s.isOfType(Type.STEEL)),
[TrainerType.YOUNGSTER]: new TrainerConfig(++t).setHasGenders('Lass', 'lass').setEncounterBgm(TrainerType.YOUNGSTER),
[TrainerType.RIVAL]: new TrainerConfig(++t).setHasGenders(),
[TrainerType.YOUNGSTER]: new TrainerConfig(++t).setHasGenders('Lass', 'lass').setPartyTemplates(trainerPartyTemplates.TWO_WEAKER).setEncounterBgm(TrainerType.YOUNGSTER).setEncounterMessages([
`Hey, wanna battle?`,
`Are you a new trainer too?`,
`Hey, I haven't seen you before. Let's battle!`
], [
`Let's have a battle, shall we?`,
`You look like a new trainer. Let's have a battle!`,
`I don't recognize you. How about a battle?`
]).setVictoryMessages([
`Wow! You're strong!`,
`I didn't stand a chance, huh.`,
`I'll find you again when I'm older and beat you!`
], [
`That was impressive! I've got a lot to learn.`,
`I didn't think you'd beat me that bad…`,
`I hope we get to have a rematch some day.`
]),
[TrainerType.CYNTHIA]: new TrainerConfig(++t),
[TrainerType.RIVAL]: new TrainerConfig(++t).setStaticParty().setBattleBgm('battle_rival').setPartyTemplates(trainerPartyTemplates.RIVAL).setEncounterMessages([
`There you are! I've been looking everywhere for you!\nDid you forget to say goodbye to your best friend?
$So you're finally pursuing your dream, huh?\nI knew you'd do it one day…
$Anyway, I'll forgive you for forgetting me, but on one condition. You have to battle me!
$You'd better give it your best! Wouldn't want your adventure to be over before it started, right?`
]).setDefeatMessages([
`You already have three Pokémon?!\nThat's not fair at all!
$Just kidding! I lost fair and square, and now I know you'll do fine out there.
$Do your best like always! I believe in you!`
]).setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.BULBASAUR, Species.CHARMANDER, Species.SQUIRTLE, Species.CHIKORITA, Species.CYNDAQUIL, Species.TOTODILE, Species.TREECKO, Species.TORCHIC, Species.MUDKIP, Species.TURTWIG, Species.CHIMCHAR, Species.PIPLUP, Species.SNIVY, Species.TEPIG, Species.OSHAWOTT ]))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEY, Species.HOOTHOOT, Species.TAILLOW, Species.STARLY, Species.PIDOVE ])),
[TrainerType.RIVAL_2]: new TrainerConfig(++t).setStaticParty().setBattleBgm('battle_rival').setPartyTemplates(trainerPartyTemplates.RIVAL_2).setEncounterMessages([
`Oh, fancy meeting you here. Looks like you're still undefeated. Right on!
$I know what you're thinking, and no, I wasn't following you. I just happened to be in the area.
$I'm happy for you but I just want to let you know that it's OK to lose sometimes.
$We learn from our mistakes, often more than we would if we kept succeeding.
$In any case, I've been training hard for our rematch, so you'd better give it your all!`
]).setDefeatMessages([
`I… wasn't supposed to lose that time…`
]).setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.IVYSAUR, Species.CHARMELEON, Species.WARTORTLE, Species.BAYLEEF, Species.QUILAVA, Species.CROCONAW, Species.GROVYLE, Species.COMBUSKEN, Species.MARSHTOMP, Species.GROTLE, Species.MONFERNO, Species.PRINPLUP, Species.SERVINE, Species.PIGNITE, Species.DEWOTT ]))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEOTTO, Species.HOOTHOOT, Species.TAILLOW, Species.STARAVIA, Species.TRANQUILL ]))
.setPartyMemberFunc(2, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && !pokemonPrevolutions.hasOwnProperty(species.speciesId) && species.baseTotal >= 450)),
[TrainerType.RIVAL_3]: new TrainerConfig(++t).setStaticParty().setBattleBgm('battle_rival').setPartyTemplates(trainerPartyTemplates.RIVAL_3).setEncounterMessages([
`Long time no see! Still haven't lost, huh.\nYou're starting to get on my nerves. Just kidding!
$But really, I think it's about time you came home.\nYour family and friends miss you, you know.
$I know your dream means a lot to you, but the reality is you're going to lose sooner or later.
$And when you do, I'll be there for you like always.\nNow, let me show you how strong I've become!`
]).setDefeatMessages([
`After all that… it wasn't enough…?`
]).setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE, Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR, Species.SCEPTILE, Species.BLAZIKEN, Species.SWAMPERT, Species.TORTERRA, Species.INFERNAPE, Species.EMPOLEON, Species.SERPERIOR, Species.EMBOAR, Species.SAMUROTT ]))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEOT, Species.NOCTOWL, Species.SWELLOW, Species.STARAPTOR, Species.UNFEZANT ]))
.setPartyMemberFunc(2, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && !pokemonPrevolutions.hasOwnProperty(species.speciesId) && species.baseTotal >= 450))
.setSpeciesFilter(species => species.baseTotal >= 540),
[TrainerType.RIVAL_4]: new TrainerConfig(++t).setStaticParty().setBattleBgm('battle_rival_2').setPartyTemplates(trainerPartyTemplates.RIVAL_4).setEncounterMessages([
`It's me! You didn't forget about me again did you?
$You made it really far! I'm proud of you.\nBut it looks like it's the end of your journey.
$You've awoken something in me I never knew was there.\nIt seems like all I do now is train.
$I hardly even eat or sleep now, I just train my Pokémon all day, getting stronger every time.
$And now, I've finally reached peak performance.\nI don't think anyone could beat me now.
$And you know what? It's all because of you.\nI don't know whether to thank you or hate you.
$Prepare yourself.`
]).setDefeatMessages([
`What…@d{64} what are you?`
]).setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE, Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR, Species.SCEPTILE, Species.BLAZIKEN, Species.SWAMPERT, Species.TORTERRA, Species.INFERNAPE, Species.EMPOLEON, Species.SERPERIOR, Species.EMBOAR, Species.SAMUROTT ]))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEOT, Species.NOCTOWL, Species.SWELLOW, Species.STARAPTOR, Species.UNFEZANT ]))
.setPartyMemberFunc(2, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && !pokemonPrevolutions.hasOwnProperty(species.speciesId) && species.baseTotal >= 450))
.setSpeciesFilter(species => species.baseTotal >= 540),
[TrainerType.RIVAL_5]: new TrainerConfig(++t).setStaticParty().setBattleBgm('battle_rival_3').setPartyTemplates(trainerPartyTemplates.RIVAL_5).setEncounterMessages([ `…` ]).setDefeatMessages([ '…' ])
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE, Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR, Species.SCEPTILE, Species.BLAZIKEN, Species.SWAMPERT, Species.TORTERRA, Species.INFERNAPE, Species.EMPOLEON, Species.SERPERIOR, Species.EMBOAR, Species.SAMUROTT ]))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEOT, Species.NOCTOWL, Species.SWELLOW, Species.STARAPTOR, Species.UNFEZANT ]))
.setPartyMemberFunc(2, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && !pokemonPrevolutions.hasOwnProperty(species.speciesId) && species.baseTotal >= 450))
.setSpeciesFilter(species => species.baseTotal >= 540)
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.RAYQUAZA ])),
[TrainerType.RIVAL_6]: new TrainerConfig(++t).setStaticParty().setBattleBgm('battle_rival_3').setPartyTemplates(trainerPartyTemplates.RIVAL_6)
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE, Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR, Species.SCEPTILE, Species.BLAZIKEN, Species.SWAMPERT, Species.TORTERRA, Species.INFERNAPE, Species.EMPOLEON, Species.SERPERIOR, Species.EMBOAR, Species.SAMUROTT ]))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEOT, Species.NOCTOWL, Species.SWELLOW, Species.STARAPTOR, Species.UNFEZANT ]))
.setPartyMemberFunc(2, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && !pokemonPrevolutions.hasOwnProperty(species.speciesId) && species.baseTotal >= 450))
.setSpeciesFilter(species => species.baseTotal >= 540)
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.RAYQUAZA ])),
}
+1 -1
View File
@@ -316,7 +316,7 @@ export function getRandomWeatherType(biome: Biome): WeatherType {
let totalWeight = 0;
weatherPool.forEach(w => totalWeight += w.weight);
const rand = Utils.randInt(totalWeight);
const rand = Utils.randSeedInt(totalWeight);
let w = 0;
for (let weather of weatherPool) {
w += weather.weight;