Refactor source files and add berries
This commit is contained in:
1 parent
6135243641
commit
3546f3b5a7
103 files changed
+2598
-1171
No files matched your search
@@ -0,0 +1,360 @@
|
||||
export class Ability {
|
||||
public id: Abilities;
|
||||
public name: string;
|
||||
public description: string;
|
||||
public generation: integer;
|
||||
|
||||
constructor(id: Abilities, name: string, description: string, generation: integer) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.generation = generation;
|
||||
}
|
||||
}
|
||||
|
||||
export enum Abilities {
|
||||
NONE,
|
||||
AIR_LOCK = 1,
|
||||
ARENA_TRAP,
|
||||
BATTLE_ARMOR,
|
||||
BLAZE,
|
||||
CHLOROPHYLL,
|
||||
CLEAR_BODY,
|
||||
CLOUD_NINE,
|
||||
COLOR_CHANGE,
|
||||
COMPOUND_EYES,
|
||||
CUTE_CHARM,
|
||||
DAMP,
|
||||
DRIZZLE,
|
||||
DROUGHT,
|
||||
EARLY_BIRD,
|
||||
EFFECT_SPORE,
|
||||
FLAME_BODY,
|
||||
FLASH_FIRE,
|
||||
FORECAST,
|
||||
GUTS,
|
||||
HUGE_POWER,
|
||||
HUSTLE,
|
||||
HYPER_CUTTER,
|
||||
ILLUMINATE,
|
||||
IMMUNITY,
|
||||
INNER_FOCUS,
|
||||
INSOMNIA,
|
||||
INTIMIDATE,
|
||||
KEEN_EYE,
|
||||
LEVITATE,
|
||||
LIGHTNING_ROD,
|
||||
LIMBER,
|
||||
LIQUID_OOZE,
|
||||
MAGMA_ARMOR,
|
||||
MAGNET_PULL,
|
||||
MARVEL_SCALE,
|
||||
MINUS,
|
||||
NATURAL_CURE,
|
||||
OBLIVIOUS,
|
||||
OVERGROW,
|
||||
OWN_TEMPO,
|
||||
PICKUP,
|
||||
PLUS,
|
||||
POISON_POINT,
|
||||
PRESSURE,
|
||||
PURE_POWER,
|
||||
RAIN_DISH,
|
||||
ROCK_HEAD,
|
||||
ROUGH_SKIN,
|
||||
RUN_AWAY,
|
||||
SAND_STREAM,
|
||||
SAND_VEIL,
|
||||
SERENE_GRACE,
|
||||
SHADOW_TAG,
|
||||
SHED_SKIN,
|
||||
SHELL_ARMOR,
|
||||
SHIELD_DUST,
|
||||
SOUNDPROOF,
|
||||
SPEED_BOOST,
|
||||
STATIC,
|
||||
STENCH,
|
||||
STICKY_HOLD,
|
||||
STURDY,
|
||||
SUCTION_CUPS,
|
||||
SWARM,
|
||||
SWIFT_SWIM,
|
||||
SYNCHRONIZE,
|
||||
THICK_FAT,
|
||||
TORRENT,
|
||||
TRACE,
|
||||
TRUANT,
|
||||
VITAL_SPIRIT,
|
||||
VOLT_ABSORB,
|
||||
WATER_ABSORB,
|
||||
WATER_VEIL,
|
||||
WHITE_SMOKE,
|
||||
WONDER_GUARD,
|
||||
ADAPTABILITY,
|
||||
AFTERMATH,
|
||||
ANGER_POINT,
|
||||
ANTICIPATION,
|
||||
BAD_DREAMS,
|
||||
DOWNLOAD,
|
||||
DRY_SKIN,
|
||||
FILTER,
|
||||
FLOWER_GIFT,
|
||||
FOREWARN,
|
||||
FRISK,
|
||||
GLUTTONY,
|
||||
HEATPROOF,
|
||||
HONEY_GATHER,
|
||||
HYDRATION,
|
||||
ICE_BODY,
|
||||
IRON_FIST,
|
||||
KLUTZ,
|
||||
LEAF_GUARD,
|
||||
MAGIC_GUARD,
|
||||
MOLD_BREAKER,
|
||||
MOTOR_DRIVE,
|
||||
MULTITYPE,
|
||||
NO_GUARD,
|
||||
NORMALIZE,
|
||||
POISON_HEAL,
|
||||
QUICK_FEET,
|
||||
RECKLESS,
|
||||
RIVALRY,
|
||||
SCRAPPY,
|
||||
SIMPLE,
|
||||
SKILL_LINK,
|
||||
SLOW_START,
|
||||
SNIPER,
|
||||
SNOW_CLOAK,
|
||||
SNOW_WARNING,
|
||||
SOLAR_POWER,
|
||||
SOLID_ROCK,
|
||||
STALL,
|
||||
STEADFAST,
|
||||
STORM_DRAIN,
|
||||
SUPER_LUCK,
|
||||
TANGLED_FEET,
|
||||
TECHNICIAN,
|
||||
TINTED_LENS,
|
||||
UNAWARE,
|
||||
UNBURDEN,
|
||||
ANALYTIC,
|
||||
BIG_PECKS,
|
||||
CONTRARY,
|
||||
CURSED_BODY,
|
||||
DEFEATIST,
|
||||
DEFIANT,
|
||||
FLARE_BOOST,
|
||||
FRIEND_GUARD,
|
||||
HARVEST,
|
||||
HEALER,
|
||||
HEAVY_METAL,
|
||||
ILLUSION,
|
||||
IMPOSTER,
|
||||
INFILTRATOR,
|
||||
IRON_BARBS,
|
||||
JUSTIFIED,
|
||||
LIGHT_METAL,
|
||||
MAGIC_BOUNCE,
|
||||
MOODY,
|
||||
MOXIE,
|
||||
MULTISCALE,
|
||||
MUMMY,
|
||||
OVERCOAT,
|
||||
PICKPOCKET,
|
||||
POISON_TOUCH,
|
||||
PRANKSTER,
|
||||
RATTLED,
|
||||
REGENERATOR,
|
||||
SAND_FORCE,
|
||||
SAND_RUSH,
|
||||
SAP_SIPPER,
|
||||
SHEER_FORCE,
|
||||
TELEPATHY,
|
||||
TERAVOLT,
|
||||
TOXIC_BOOST,
|
||||
TURBOBLAZE,
|
||||
UNNERVE,
|
||||
VICTORY_STAR,
|
||||
WEAK_ARMOR,
|
||||
WONDER_SKIN,
|
||||
ZEN_MODE,
|
||||
COMPETITIVE,
|
||||
DARK_AURA,
|
||||
FAIRY_AURA,
|
||||
PROTEAN,
|
||||
SLUSH_RUSH,
|
||||
NEUTRALIZING_GAS
|
||||
}
|
||||
|
||||
export const abilities = [
|
||||
new Ability(Abilities.AIR_LOCK, "Air Lock", "Eliminates the effects of weather.", 3),
|
||||
new Ability(Abilities.ARENA_TRAP, "Arena Trap", "Prevents the foe from fleeing.", 3),
|
||||
new Ability(Abilities.BATTLE_ARMOR, "Battle Armor", "The POKéMON is protected against critical hits.", 3),
|
||||
new Ability(Abilities.BLAZE, "Blaze", "Powers up Fire-type moves in a pinch.", 3),
|
||||
new Ability(Abilities.CHLOROPHYLL, "Chlorophyll", "Boosts the POKéMON's SPEED in sunshine.", 3),
|
||||
new Ability(Abilities.CLEAR_BODY, "Clear Body", "Prevents other POKéMON from lowering its stats.", 3),
|
||||
new Ability(Abilities.CLOUD_NINE, "Cloud Nine", "Eliminates the effects of weather.", 3),
|
||||
new Ability(Abilities.COLOR_CHANGE, "Color Change", "Changes the POKéMON's type to the foe's move.", 3),
|
||||
new Ability(Abilities.COMPOUND_EYES, "Compound Eyes", "The POKéMON's accuracy is boosted.", 3),
|
||||
new Ability(Abilities.CUTE_CHARM, "Cute Charm", "Contact with the POKéMON may cause infatuation.", 3),
|
||||
new Ability(Abilities.DAMP, "Damp", "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.DROUGHT, "Drought", "Turns the sunlight harsh when the POKéMON enters a battle.", 3),
|
||||
new Ability(Abilities.EARLY_BIRD, "Early Bird", "The POKéMON awakens quickly from sleep.", 3),
|
||||
new Ability(Abilities.EFFECT_SPORE, "Effect Spore", "Contact may poison or cause paralysis or sleep.", 3),
|
||||
new Ability(Abilities.FLAME_BODY, "Flame Body", "Contact with the POKéMON may burn the attacker.", 3),
|
||||
new Ability(Abilities.FLASH_FIRE, "Flash Fire", "It powers up Fire-type moves if it's hit by one.", 3),
|
||||
new Ability(Abilities.FORECAST, "Forecast", "Castform transforms with the weather.", 3),
|
||||
new Ability(Abilities.GUTS, "Guts", "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.HUSTLE, "Hustle", "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.ILLUMINATE, "Illuminate", "Raises the likelihood of meeting wild POKéMON.", 3),
|
||||
new Ability(Abilities.IMMUNITY, "Immunity", "Prevents the POKéMON from getting poisoned.", 3),
|
||||
new Ability(Abilities.INNER_FOCUS, "Inner Focus", "The POKéMON is protected from flinching.", 3),
|
||||
new Ability(Abilities.INSOMNIA, "Insomnia", "Prevents the POKéMON from falling asleep.", 3),
|
||||
new Ability(Abilities.INTIMIDATE, "Intimidate", "Lowers the foe's ATTACK stat.", 3),
|
||||
new Ability(Abilities.KEEN_EYE, "Keen Eye", "Prevents other POKéMON from lowering accuracy.", 3),
|
||||
new Ability(Abilities.LEVITATE, "Levitate", "Gives immunity to Ground type moves.", 3),
|
||||
new Ability(Abilities.LIGHTNING_ROD, "Lightning Rod", "Draws in all Electric-type moves to up SP. ATK.", 3),
|
||||
new Ability(Abilities.LIMBER, "Limber", "The POKéMON is protected from paralysis.", 3),
|
||||
new Ability(Abilities.LIQUID_OOZE, "Liquid Ooze", "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.MAGNET_PULL, "Magnet Pull", "Prevents Steel-type POKéMON from escaping.", 3),
|
||||
new Ability(Abilities.MARVEL_SCALE, "Marvel Scale", "Ups DEFENSE if there is a status problem.", 3),
|
||||
new Ability(Abilities.MINUS, "Minus", "Ups SP. ATK if another POKéMON has Plus or Minus.", 3),
|
||||
new Ability(Abilities.NATURAL_CURE, "Natural Cure", "All status problems heal when it switches out.", 3),
|
||||
new Ability(Abilities.OBLIVIOUS, "Oblivious", "Prevents it from becoming infatuated.", 3),
|
||||
new Ability(Abilities.OVERGROW, "Overgrow", "Powers up Grass-type moves in a pinch.", 3),
|
||||
new Ability(Abilities.OWN_TEMPO, "Own Tempo", "Prevents the POKéMON from becoming confused.", 3),
|
||||
new Ability(Abilities.PICKUP, "Pickup", "The POKéMON may pick up items.", 3),
|
||||
new Ability(Abilities.PLUS, "Plus", "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.PRESSURE, "Pressure", "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.RAIN_DISH, "Rain Dish", "The POKéMON gradually regains HP in rain.", 3),
|
||||
new Ability(Abilities.ROCK_HEAD, "Rock Head", "Protects the POKéMON from recoil damage.", 3),
|
||||
new Ability(Abilities.ROUGH_SKIN, "Rough Skin", "Inflicts damage to the attacker on contact.", 3),
|
||||
new Ability(Abilities.RUN_AWAY, "Run Away", "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.SAND_VEIL, "Sand Veil", "Boosts the POKéMON's evasion in a sandstorm.", 3),
|
||||
new Ability(Abilities.SERENE_GRACE, "Serene Grace", "Boosts the likelihood of added effects appearing.", 3),
|
||||
new Ability(Abilities.SHADOW_TAG, "Shadow Tag", "Prevents the foe from escaping.", 3),
|
||||
new Ability(Abilities.SHED_SKIN, "Shed Skin", "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.SHIELD_DUST, "Shield Dust", "Blocks the added effects of attacks taken.", 3),
|
||||
new Ability(Abilities.SOUNDPROOF, "Soundproof", "Gives immunity to sound-based moves.", 3),
|
||||
new Ability(Abilities.SPEED_BOOST, "Speed Boost", "Its SPEED stat is gradually boosted.", 3),
|
||||
new Ability(Abilities.STATIC, "Static", "Contact with the POKéMON may cause paralysis.", 3),
|
||||
new Ability(Abilities.STENCH, "Stench", "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.STURDY, "Sturdy", "It cannot be knocked out with one hit.", 3),
|
||||
new Ability(Abilities.SUCTION_CUPS, "Suction Cups", "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.SWIFT_SWIM, "Swift Swim", "Boosts the POKéMON's SPEED in rain.", 3),
|
||||
new Ability(Abilities.SYNCHRONIZE, "Synchronize", "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.TORRENT, "Torrent", "Powers up Water-type moves in a pinch.", 3),
|
||||
new Ability(Abilities.TRACE, "Trace", "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.VITAL_SPIRIT, "Vital Spirit", "Prevents the POKéMON from falling asleep.", 3),
|
||||
new Ability(Abilities.VOLT_ABSORB, "Volt Absorb", "Restores HP if hit by an Electric-type move.", 3),
|
||||
new Ability(Abilities.WATER_ABSORB, "Water Absorb", "Restores HP if hit by a Water-type move.", 3),
|
||||
new Ability(Abilities.WATER_VEIL, "Water Veil", "Prevents the POKéMON from getting a burn.", 3),
|
||||
new Ability(Abilities.WHITE_SMOKE, "White Smoke", "Prevents other POKéMON from lowering its stats.", 3),
|
||||
new Ability(Abilities.WONDER_GUARD, "Wonder Guard", "Only supereffective moves will hit.", 3),
|
||||
new Ability(Abilities.ADAPTABILITY, "Adaptability", "Powers up moves of the same type.", 4),
|
||||
new Ability(Abilities.AFTERMATH, "Aftermath", "Damages the attacker landing the finishing hit.", 4),
|
||||
new Ability(Abilities.ANGER_POINT, "Anger Point", "Maxes ATTACK after taking a critical hit.", 4),
|
||||
new Ability(Abilities.ANTICIPATION, "Anticipation", "Senses a foe's dangerous moves.", 4),
|
||||
new Ability(Abilities.BAD_DREAMS, "Bad Dreams", "Reduces a sleeping foe's HP.", 4),
|
||||
new Ability(Abilities.DOWNLOAD, "Download", "Adjusts power according to a foe's defenses.", 4),
|
||||
new Ability(Abilities.DRY_SKIN, "Dry Skin", "Reduces HP if it is hot. Water restores HP.", 4),
|
||||
new Ability(Abilities.FILTER, "Filter", "Reduces damage from super-effective attacks.", 4),
|
||||
new Ability(Abilities.FLOWER_GIFT, "Flower Gift", "Powers up party POKéMON when it is sunny.", 4),
|
||||
new Ability(Abilities.FOREWARN, "Forewarn", "Determines what moves a foe has.", 4),
|
||||
new Ability(Abilities.FRISK, "Frisk", "The POKéMON can check a foe's held item.", 4),
|
||||
new Ability(Abilities.GLUTTONY, "Gluttony", "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.HONEY_GATHER, "Honey Gather", "The POKéMON may gather Honey from somewhere.", 4),
|
||||
new Ability(Abilities.HYDRATION, "Hydration", "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.IRON_FIST, "Iron Fist", "Boosts the power of punching moves.", 4),
|
||||
new Ability(Abilities.KLUTZ, "Klutz", "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),
|
||||
new Ability(Abilities.MAGIC_GUARD, "Magic Guard", "Protects the POKéMON from indirect damage.", 4),
|
||||
new Ability(Abilities.MOLD_BREAKER, "Mold Breaker", "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.MULTITYPE, "Multitype", "Changes type to match the held Plate.", 4),
|
||||
new Ability(Abilities.NO_GUARD, "No Guard", "Ensures attacks by or against the POKéMON land.", 4),
|
||||
new Ability(Abilities.NORMALIZE, "Normalize", "All the POKéMON's moves become the Normal type.", 4),
|
||||
new Ability(Abilities.POISON_HEAL, "Poison Heal", "Restores HP if the POKéMON is poisoned.", 4),
|
||||
new Ability(Abilities.QUICK_FEET, "Quick Feet", "Boosts SPEED if there is a status problem.", 4),
|
||||
new Ability(Abilities.RECKLESS, "Reckless", "Powers up moves that have recoil damage.", 4),
|
||||
new Ability(Abilities.RIVALRY, "Rivalry", "Deals more damage to a POKéMON of same gender.", 4),
|
||||
new Ability(Abilities.SCRAPPY, "Scrappy", "Enables moves to hit Ghost-type POKéMON.", 4),
|
||||
new Ability(Abilities.SIMPLE, "Simple", "Doubles all stat changes.", 4),
|
||||
new Ability(Abilities.SKILL_LINK, "Skill Link", "Increases the frequency of multi-strike moves.", 4),
|
||||
new Ability(Abilities.SLOW_START, "Slow Start", "Temporarily halves ATTACK and SPEED.", 4),
|
||||
new Ability(Abilities.SNIPER, "Sniper", "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_WARNING, "Snow Warning", "The POKéMON summons a hailstorm in battle.", 4),
|
||||
new Ability(Abilities.SOLAR_POWER, "Solar Power", "In sunshine, SP. ATK is boosted but HP decreases.", 4),
|
||||
new Ability(Abilities.SOLID_ROCK, "Solid Rock", "Reduces damage from super-effective attacks.", 4),
|
||||
new Ability(Abilities.STALL, "Stall", "The POKéMON moves after all other POKéMON do.", 4),
|
||||
new Ability(Abilities.STEADFAST, "Steadfast", "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.SUPER_LUCK, "Super Luck", "Heightens the critical-hit ratios of moves.", 4),
|
||||
new Ability(Abilities.TANGLED_FEET, "Tangled Feet", "Raises evasion if the POKéMON is confused.", 4),
|
||||
new Ability(Abilities.TECHNICIAN, "Technician", "Powers up the POKéMON's weaker moves.", 4),
|
||||
new Ability(Abilities.TINTED_LENS, "Tinted Lens", "Powers up “not very effective” moves.", 4),
|
||||
new Ability(Abilities.UNAWARE, "Unaware", "Ignores any stat changes in the POKéMON.", 4),
|
||||
new Ability(Abilities.UNBURDEN, "Unburden", "Raises SPEED if a held item is used.", 4),
|
||||
new Ability(Abilities.ANALYTIC, "Analytic", "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.CONTRARY, "Contrary", "Makes stat changes have an opposite effect.", 5),
|
||||
new Ability(Abilities.CURSED_BODY, "Cursed Body", "May disable a move used on the POKéMON.", 5),
|
||||
new Ability(Abilities.DEFEATIST, "Defeatist", "Lowers stats when HP drops below half.", 5),
|
||||
new Ability(Abilities.DEFIANT, "Defiant", "Sharply raises ATTACK when the POKéMON's stats are lowered.", 5),
|
||||
new Ability(Abilities.FLARE_BOOST, "Flare Boost", "Powers up special attacks when burned.", 5),
|
||||
new Ability(Abilities.FRIEND_GUARD, "Friend Guard", "Reduces damage done to allies.", 5),
|
||||
new Ability(Abilities.HARVEST, "Harvest", "May create another Berry after one is used.", 5),
|
||||
new Ability(Abilities.HEALER, "Healer", "May heal an ally's status conditions.", 5),
|
||||
new Ability(Abilities.HEAVY_METAL, "Heavy Metal", "Doubles the POKéMON's weight.", 5),
|
||||
new Ability(Abilities.ILLUSION, "Illusion", "Enters battle disguised as the last POKéMON in the party.", 5),
|
||||
new Ability(Abilities.IMPOSTER, "Imposter", "It transforms itself into the POKéMON it is facing.", 5),
|
||||
new Ability(Abilities.INFILTRATOR, "Infiltrator", "Passes through the foe's barrier and strikes.", 5),
|
||||
new Ability(Abilities.IRON_BARBS, "Iron Barbs", "Inflicts damage to the POKéMON on contact.", 5),
|
||||
new Ability(Abilities.JUSTIFIED, "Justified", "Raises ATTACK when hit by a Dark-type move.", 5),
|
||||
new Ability(Abilities.LIGHT_METAL, "Light Metal", "Halves the POKéMON's weight.", 5),
|
||||
new Ability(Abilities.MAGIC_BOUNCE, "Magic Bounce", "Reflects status- changing moves.", 5),
|
||||
new Ability(Abilities.MOODY, "Moody", "Raises one stat and lowers another.", 5),
|
||||
new Ability(Abilities.MOXIE, "Moxie", "Boosts ATTACK after knocking out any POKéMON.", 5),
|
||||
new Ability(Abilities.MULTISCALE, "Multiscale", "Reduces damage when HP is full.", 5),
|
||||
new Ability(Abilities.MUMMY, "Mummy", "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.PICKPOCKET, "Pickpocket", "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.PRANKSTER, "Prankster", "Gives priority to a status move.", 5),
|
||||
new Ability(Abilities.RATTLED, "Rattled", "Bug, Ghost or Dark type moves scare it and boost its SPEED.", 5),
|
||||
new Ability(Abilities.REGENERATOR, "Regenerator", "Restores a little HP when withdrawn from battle.", 5),
|
||||
new Ability(Abilities.SAND_FORCE, "Sand Force", "Boosts certain moves' power in a sandstorm.", 5),
|
||||
new Ability(Abilities.SAND_RUSH, "Sand Rush", "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.SHEER_FORCE, "Sheer Force", "Removes added effects to increase move damage.", 5),
|
||||
new Ability(Abilities.TELEPATHY, "Telepathy", "Anticipates an ally's ATTACK and dodges it.", 5),
|
||||
new Ability(Abilities.TERAVOLT, "Teravolt", "Moves can be used regardless of Abilities.", 5),
|
||||
new Ability(Abilities.TOXIC_BOOST, "Toxic Boost", "Powers up physical attacks when poisoned.", 5),
|
||||
new Ability(Abilities.TURBOBLAZE, "Turboblaze", "Moves can be used regardless of Abilities.", 5),
|
||||
new Ability(Abilities.UNNERVE, "Unnerve", "Makes the foe nervous and unable to eat Berries.", 5),
|
||||
new Ability(Abilities.VICTORY_STAR, "Victory Star", "Boosts the accuracy of its allies and itself.", 5),
|
||||
new Ability(Abilities.WEAK_ARMOR, "Weak Armor", "Physical attacks lower DEFENSE and raise SPEED.", 5),
|
||||
new Ability(Abilities.WONDER_SKIN, "Wonder Skin", "Makes status-changing moves more likely to miss.", 5),
|
||||
new Ability(Abilities.ZEN_MODE, "Zen Mode", "Changes form when HP drops below half.", 5),
|
||||
new Ability(Abilities.COMPETITIVE, "Competitive", "Sharply raises SP. ATK when the POKéMON's stats are lowered.", 6),
|
||||
new Ability(Abilities.DARK_AURA, "Dark Aura", "Raises power of Dark type moves for all POKéMON in battle.", 6),
|
||||
new Ability(Abilities.FAIRY_AURA, "Fairy Aura", "Raises power of Fairy type moves for all POKéMON in battle.", 6),
|
||||
new Ability(Abilities.PROTEAN, "Protean", "Changes the POKéMON's type to its last used move.", 6),
|
||||
new Ability(Abilities.SLUSH_RUSH, "Slush Rush", "Boosts the POKéMON's SPEED stat in a hailstorm.", 7),
|
||||
new Ability(Abilities.NEUTRALIZING_GAS, "Neutralizing Gas", "Neutralizes abilities of all POKéMON in battle.", 8)
|
||||
];
|
||||
@@ -0,0 +1,974 @@
|
||||
//import { battleAnimRawData } from "./battle-anim-raw-data";
|
||||
import BattleScene from "../battle-scene";
|
||||
import { ChargeAttr, Moves, allMoves } from "./move";
|
||||
import Pokemon from "../pokemon";
|
||||
import * as Utils from "../utils";
|
||||
//import fs from 'vite-plugin-fs/browser';
|
||||
|
||||
export enum AnimFrameTarget {
|
||||
USER,
|
||||
TARGET,
|
||||
GRAPHIC
|
||||
}
|
||||
|
||||
enum AnimFocus {
|
||||
USER = 1,
|
||||
TARGET,
|
||||
USER_TARGET,
|
||||
SCREEN
|
||||
}
|
||||
|
||||
enum AnimBlendType {
|
||||
NORMAL,
|
||||
ADD,
|
||||
SUBTRACT
|
||||
}
|
||||
|
||||
export enum ChargeAnim {
|
||||
FLY_CHARGING = 1000,
|
||||
BOUNCE_CHARGING,
|
||||
DIG_CHARGING,
|
||||
DIVE_CHARGING,
|
||||
SOLAR_BEAM_CHARGING,
|
||||
SHADOW_FORCE_CHARGING,
|
||||
SKULL_BASH_CHARGING,
|
||||
FREEZE_SHOCK_CHARGING,
|
||||
SKY_DROP_CHARGING,
|
||||
SKY_ATTACK_CHARGING,
|
||||
ICE_BURN_CHARGING,
|
||||
DOOM_DESIRE_CHARGING,
|
||||
RAZOR_WIND_CHARGING
|
||||
}
|
||||
|
||||
export enum CommonAnim {
|
||||
USE_ITEM = 2000,
|
||||
HEALTH_UP,
|
||||
POISON = 2010,
|
||||
TOXIC,
|
||||
PARALYSIS,
|
||||
SLEEP,
|
||||
FROZEN,
|
||||
BURN,
|
||||
CONFUSION,
|
||||
ATTRACT,
|
||||
BIND,
|
||||
WRAP,
|
||||
CURSE_NO_GHOST,
|
||||
LEECH_SEED,
|
||||
FIRE_SPIN,
|
||||
PROTECT,
|
||||
COVET,
|
||||
WHIRLPOOL,
|
||||
BIDE,
|
||||
SAND_TOMB,
|
||||
QUICK_GUARD,
|
||||
WIDE_GUARD,
|
||||
CURSE,
|
||||
MAGMA_STORM,
|
||||
CLAMP,
|
||||
SUNNY = 2100,
|
||||
RAIN,
|
||||
SANDSTORM,
|
||||
HAIL,
|
||||
WIND,
|
||||
HEAVY_RAIN,
|
||||
HARSH_SUN,
|
||||
STRONG_WINDS,
|
||||
MISTY_TERRAIN = 2110,
|
||||
ELECTRIC_TERRAIN,
|
||||
GRASSY_TERRAIN,
|
||||
PSYCHIC_TERRAIN
|
||||
}
|
||||
|
||||
export class AnimConfig {
|
||||
public id: integer;
|
||||
public graphic: string;
|
||||
public frames: AnimFrame[][];
|
||||
public frameTimedEvents: Map<integer, AnimTimedEvent[]>;
|
||||
public position: integer;
|
||||
public hue: integer;
|
||||
|
||||
constructor(source?: any) {
|
||||
this.frameTimedEvents = new Map<integer, AnimTimedEvent[]>;
|
||||
|
||||
if (source) {
|
||||
this.id = source.id;
|
||||
this.graphic = source.graphic;
|
||||
this.frames = source.frames;
|
||||
|
||||
const frameTimedEvents = source.frameTimedEvents;
|
||||
for (let fte of Object.keys(frameTimedEvents)) {
|
||||
const timedEvents: AnimTimedEvent[] = [];
|
||||
for (let te of frameTimedEvents[fte]) {
|
||||
let timedEvent: AnimTimedEvent;
|
||||
switch (te.eventType) {
|
||||
case 'AnimTimedSoundEvent':
|
||||
timedEvent = new AnimTimedSoundEvent(te.frameIndex, te.resourceName, te);
|
||||
break;
|
||||
case 'AnimTimedAddBgEvent':
|
||||
timedEvent = new AnimTimedAddBgEvent(te.frameIndex, te.resourceName, te);
|
||||
break;
|
||||
case 'AnimTimedUpdateBgEvent':
|
||||
timedEvent = new AnimTimedUpdateBgEvent(te.frameIndex, te.resourceName, te);
|
||||
break;
|
||||
}
|
||||
timedEvents.push(timedEvent);
|
||||
}
|
||||
this.frameTimedEvents.set(parseInt(fte), timedEvents);
|
||||
}
|
||||
|
||||
this.position = source.position;
|
||||
this.hue = source.hue;
|
||||
} else
|
||||
this.frames = [];
|
||||
}
|
||||
|
||||
getSoundResourceNames(): string[] {
|
||||
const sounds = new Set<string>();
|
||||
|
||||
for (let ftes of this.frameTimedEvents.values()) {
|
||||
for (let fte of ftes) {
|
||||
if (fte instanceof AnimTimedSoundEvent && fte.resourceName)
|
||||
sounds.add(fte.resourceName);
|
||||
}
|
||||
}
|
||||
|
||||
return Array.from(sounds.values());
|
||||
}
|
||||
|
||||
getBackgroundResourceNames(): string[] {
|
||||
const backgrounds = new Set<string>();
|
||||
|
||||
for (let ftes of this.frameTimedEvents.values()) {
|
||||
for (let fte of ftes) {
|
||||
if (fte instanceof AnimTimedAddBgEvent && fte.resourceName)
|
||||
backgrounds.add(fte.resourceName);
|
||||
}
|
||||
}
|
||||
|
||||
return Array.from(backgrounds.values());
|
||||
}
|
||||
}
|
||||
|
||||
class AnimFrame {
|
||||
public x: number;
|
||||
public y: number;
|
||||
public zoomX: number;
|
||||
public zoomY: number;
|
||||
public angle: number;
|
||||
public mirror: boolean;
|
||||
public visible: boolean;
|
||||
public blendType: AnimBlendType;
|
||||
public target: AnimFrameTarget;
|
||||
public graphicFrame: integer;
|
||||
public opacity: integer;
|
||||
public color: integer[];
|
||||
public tone: integer[];
|
||||
public flash: integer[];
|
||||
public locked: boolean;
|
||||
public priority: integer;
|
||||
public focus: AnimFocus;
|
||||
|
||||
constructor(x: number, y: number, zoomX: number, zoomY: number, angle: number, mirror: boolean, visible: boolean, blendType: AnimBlendType, pattern: integer,
|
||||
opacity: integer, colorR: integer, colorG: integer, colorB: integer, colorA: integer, toneR: integer, toneG: integer, toneB: integer, toneA: integer,
|
||||
flashR: integer, flashG: integer, flashB: integer, flashA: integer, locked: boolean, priority: integer, focus: AnimFocus) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.zoomX = zoomX;
|
||||
this.zoomY = zoomY;
|
||||
this.angle = angle;
|
||||
this.mirror = mirror;
|
||||
this.visible = visible;
|
||||
this.blendType = blendType;
|
||||
let target = AnimFrameTarget.GRAPHIC;
|
||||
switch (pattern) {
|
||||
case -2:
|
||||
target = AnimFrameTarget.TARGET;
|
||||
this.x -= 384;
|
||||
this.y -= 96;
|
||||
break;
|
||||
case -1:
|
||||
target = AnimFrameTarget.USER;
|
||||
this.x -= 128;
|
||||
this.y -= 224;
|
||||
break;
|
||||
default:
|
||||
this.x = (this.x - 128) * 0.5;
|
||||
this.y = (this.y - 224) * 0.5;
|
||||
}
|
||||
this.target = target;
|
||||
this.graphicFrame = pattern >= 0 ? pattern : 0;
|
||||
this.opacity = opacity;
|
||||
this.color = [ colorR, colorG, colorB, colorA ];
|
||||
this.tone = [ toneR, toneG, toneB, toneA ];
|
||||
this.flash = [ flashR, flashG, flashB, flashA ];
|
||||
this.locked = locked;
|
||||
this.priority = priority;
|
||||
this.focus = focus;
|
||||
}
|
||||
}
|
||||
|
||||
abstract class AnimTimedEvent {
|
||||
public frameIndex: integer;
|
||||
public resourceName: string;
|
||||
|
||||
constructor(frameIndex: integer, resourceName: string) {
|
||||
this.frameIndex = frameIndex;
|
||||
this.resourceName = resourceName;
|
||||
}
|
||||
|
||||
abstract execute(scene: BattleScene, battleAnim: BattleAnim): integer;
|
||||
|
||||
abstract getEventType(): string;
|
||||
}
|
||||
|
||||
class AnimTimedSoundEvent extends AnimTimedEvent {
|
||||
public volume: number;
|
||||
public pitch: number;
|
||||
|
||||
constructor(frameIndex: integer, resourceName: string, source?: any) {
|
||||
super(frameIndex, resourceName + (resourceName && resourceName.indexOf('.') === -1 ? resourceName.startsWith('PRSFX-') ? '.wav' : '.ogg' : ''));
|
||||
|
||||
if (source) {
|
||||
this.volume = source.volume;
|
||||
this.pitch = source.pitch;
|
||||
} else
|
||||
this.pitch = 100;
|
||||
}
|
||||
|
||||
execute(scene: BattleScene, battleAnim: BattleAnim): integer {
|
||||
const soundConfig = { rate: (this.pitch * 0.01), volume: (this.volume * 0.01) };
|
||||
if (this.resourceName) {
|
||||
try {
|
||||
scene.sound.play(this.resourceName, soundConfig);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
return Math.ceil((scene.sound.get(this.resourceName).totalDuration * 1000) / 33.33);
|
||||
} else
|
||||
return Math.ceil(battleAnim.user.cry(soundConfig) / 33.33);
|
||||
}
|
||||
|
||||
getEventType(): string {
|
||||
return 'AnimTimedSoundEvent';
|
||||
}
|
||||
}
|
||||
|
||||
abstract class AnimTimedBgEvent extends AnimTimedEvent {
|
||||
public bgX: number;
|
||||
public bgY: number;
|
||||
public opacity: integer;
|
||||
public colorRed: integer;
|
||||
public colorGreen: integer;
|
||||
public colorBlue: integer;
|
||||
public colorAlpha: integer;
|
||||
public duration: integer;
|
||||
public flashScope: integer;
|
||||
public flashRed: integer;
|
||||
public flashGreen: integer;
|
||||
public flashBlue: integer;
|
||||
public flashAlpha: integer;
|
||||
public flashDuration: integer;
|
||||
|
||||
constructor(frameIndex: integer, resourceName: string, source: any) {
|
||||
super(frameIndex, resourceName);
|
||||
|
||||
if (source) {
|
||||
this.bgX = source.bgX;
|
||||
this.bgY = source.bgY;
|
||||
this.opacity = source.opacity;
|
||||
this.colorRed = source.colorRed;
|
||||
this.colorGreen = source.colorGreen;
|
||||
this.colorBlue = source.colorBlue;
|
||||
this.colorAlpha = source.colorAlpha;
|
||||
this.duration = source.duration;
|
||||
this.flashScope = source.flashScope;
|
||||
this.flashRed = source.flashRed;
|
||||
this.flashGreen = source.flashGreen;
|
||||
this.flashBlue = source.flashBlue;
|
||||
this.flashAlpha = source.flashAlpha;
|
||||
this.flashDuration = source.flashDuration;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AnimTimedUpdateBgEvent extends AnimTimedBgEvent {
|
||||
constructor(frameIndex: integer, resourceName: string, source?: any) {
|
||||
super(frameIndex, resourceName, source);
|
||||
}
|
||||
|
||||
execute(scene: BattleScene, moveAnim: MoveAnim): integer {
|
||||
const tweenProps = {};
|
||||
if (this.bgX !== undefined)
|
||||
tweenProps['x'] = (this.bgX * 0.5) - 320;
|
||||
if (this.bgY !== undefined)
|
||||
tweenProps['y'] = (this.bgY * 0.5) - 284;
|
||||
if (this.opacity !== undefined)
|
||||
tweenProps['alpha'] = this.opacity / 255;
|
||||
if (Object.keys(tweenProps).length) {
|
||||
scene.tweens.add(Object.assign({
|
||||
targets: moveAnim.bgSprite,
|
||||
duration: this.duration * 3,
|
||||
useFrames: true
|
||||
}, tweenProps))
|
||||
}
|
||||
return this.duration * 2;
|
||||
}
|
||||
|
||||
getEventType(): string {
|
||||
return 'AnimTimedUpdateBgEvent';
|
||||
}
|
||||
}
|
||||
|
||||
class AnimTimedAddBgEvent extends AnimTimedBgEvent {
|
||||
constructor(frameIndex: integer, resourceName: string, source?: any) {
|
||||
super(frameIndex, resourceName, source);
|
||||
}
|
||||
|
||||
execute(scene: BattleScene, moveAnim: MoveAnim): integer {
|
||||
if (moveAnim.bgSprite)
|
||||
moveAnim.bgSprite.destroy();
|
||||
moveAnim.bgSprite = scene.add.tileSprite(this.bgX - 320, this.bgY - 284, 896, 576, this.resourceName);
|
||||
moveAnim.bgSprite.setOrigin(0, 0);
|
||||
moveAnim.bgSprite.setScale(1.25);
|
||||
moveAnim.bgSprite.setAlpha(0);
|
||||
scene.field.add(moveAnim.bgSprite);
|
||||
scene.field.moveBelow(moveAnim.bgSprite, scene.getEnemyPokemon());
|
||||
|
||||
scene.tweens.add({
|
||||
targets: moveAnim.bgSprite,
|
||||
alpha: 1,
|
||||
duration: this.duration * 3,
|
||||
useFrames: true
|
||||
});
|
||||
|
||||
return this.duration * 2;
|
||||
}
|
||||
|
||||
getEventType(): string {
|
||||
return 'AnimTimedAddBgEvent';
|
||||
}
|
||||
}
|
||||
|
||||
export const moveAnims = new Map<Moves, AnimConfig | [AnimConfig, AnimConfig]>();
|
||||
export const chargeAnims = new Map<ChargeAnim, AnimConfig | [AnimConfig, AnimConfig]>();
|
||||
export const commonAnims = new Map<CommonAnim, AnimConfig>();
|
||||
|
||||
export function initCommonAnims(): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
const commonAnimNames = Utils.getEnumKeys(CommonAnim);
|
||||
const commonAnimIds = Utils.getEnumValues(CommonAnim);
|
||||
const commonAnimFetches = [];
|
||||
for (let ca = 0; ca < commonAnimIds.length; ca++) {
|
||||
const commonAnimId = commonAnimIds[ca];
|
||||
commonAnimFetches.push(fetch(`./battle-anims/common-${commonAnimNames[ca].toLowerCase().replace(/\_/g, '-')}.json`)
|
||||
.then(response => response.json())
|
||||
.then(cas => commonAnims.set(commonAnimId, new AnimConfig(cas))));
|
||||
}
|
||||
Promise.allSettled(commonAnimFetches).then(() => resolve());
|
||||
});
|
||||
}
|
||||
|
||||
export function initMoveAnim(move: Moves): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
if (moveAnims.has(move)) {
|
||||
if (moveAnims.get(move) !== null)
|
||||
resolve();
|
||||
else {
|
||||
let loadedCheckTimer = setInterval(() => {
|
||||
if (moveAnims.get(move) !== null) {
|
||||
clearInterval(loadedCheckTimer);
|
||||
resolve();
|
||||
}
|
||||
}, 50);
|
||||
}
|
||||
} else {
|
||||
moveAnims.set(move, null);
|
||||
fetch(`./battle-anims/${Moves[move].toLowerCase().replace(/\_/g, '-')}.json`)
|
||||
.then(response => response.json())
|
||||
.then(ba => {
|
||||
if (Array.isArray(ba)) {
|
||||
populateMoveAnim(move, ba[0]);
|
||||
populateMoveAnim(move, ba[1]);
|
||||
} else
|
||||
populateMoveAnim(move, ba);
|
||||
const chargeAttr = allMoves[move - 1].getAttrs(ChargeAttr) as ChargeAttr[];
|
||||
if (chargeAttr.length)
|
||||
initMoveChargeAnim(chargeAttr[0].chargeAnim).then(() => resolve());
|
||||
else
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function initMoveChargeAnim(chargeAnim: ChargeAnim): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
if (chargeAnims.has(chargeAnim)) {
|
||||
if (chargeAnims.get(chargeAnim) !== null)
|
||||
resolve();
|
||||
else {
|
||||
let loadedCheckTimer = setInterval(() => {
|
||||
if (chargeAnims.get(chargeAnim) !== null) {
|
||||
clearInterval(loadedCheckTimer);
|
||||
resolve();
|
||||
}
|
||||
}, 50);
|
||||
}
|
||||
} else {
|
||||
chargeAnims.set(chargeAnim, null);
|
||||
fetch(`./battle-anims/${ChargeAnim[chargeAnim].toLowerCase().replace(/\_/g, '-')}.json`)
|
||||
.then(response => response.json())
|
||||
.then(ca => {
|
||||
if (Array.isArray(ca)) {
|
||||
populateMoveChargeAnim(chargeAnim, ca[0]);
|
||||
populateMoveChargeAnim(chargeAnim, ca[1]);
|
||||
} else
|
||||
populateMoveChargeAnim(chargeAnim, ca);
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function populateMoveAnim(move: Moves, animSource: any): void {
|
||||
const moveAnim = new AnimConfig(animSource);
|
||||
if (moveAnims.get(move) === null) {
|
||||
moveAnims.set(move, moveAnim);
|
||||
return;
|
||||
}
|
||||
moveAnims.set(move, [ moveAnims.get(move) as AnimConfig, moveAnim ]);
|
||||
}
|
||||
|
||||
function populateMoveChargeAnim(chargeAnim: ChargeAnim, animSource: any) {
|
||||
const moveChargeAnim = new AnimConfig(animSource);
|
||||
if (chargeAnims.get(chargeAnim) === null) {
|
||||
chargeAnims.set(chargeAnim, moveChargeAnim);
|
||||
return;
|
||||
}
|
||||
chargeAnims.set(chargeAnim, [ chargeAnims.get(chargeAnim) as AnimConfig, moveChargeAnim ]);
|
||||
}
|
||||
|
||||
export function loadCommonAnimAssets(scene: BattleScene, startLoad?: boolean): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
loadAnimAssets(scene, Array.from(commonAnims.values()), startLoad).then(() => resolve());
|
||||
});
|
||||
}
|
||||
|
||||
export function loadMoveAnimAssets(scene: BattleScene, moveIds: Moves[], startLoad?: boolean): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
const moveAnimations = moveIds.map(m => moveAnims.get(m) as AnimConfig).flat();
|
||||
for (let moveId of moveIds) {
|
||||
const chargeAttr = allMoves[moveId - 1].getAttrs(ChargeAttr) as ChargeAttr[];
|
||||
if (chargeAttr.length) {
|
||||
const moveChargeAnims = chargeAnims.get(chargeAttr[0].chargeAnim);
|
||||
moveAnimations.push(moveChargeAnims instanceof AnimConfig ? moveChargeAnims : moveChargeAnims[0]);
|
||||
if (Array.isArray(moveChargeAnims))
|
||||
moveAnimations.push(moveChargeAnims[1]);
|
||||
}
|
||||
}
|
||||
loadAnimAssets(scene, moveAnimations, startLoad).then(() => resolve());
|
||||
});
|
||||
}
|
||||
|
||||
function loadAnimAssets(scene: BattleScene, anims: AnimConfig[], startLoad?: boolean): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
const backgrounds = new Set<string>();
|
||||
const sounds = new Set<string>();
|
||||
for (let a of anims) {
|
||||
const animSounds = a.getSoundResourceNames();
|
||||
for (let ms of animSounds)
|
||||
sounds.add(ms);
|
||||
const animBackgrounds = a.getBackgroundResourceNames();
|
||||
for (let abg of animBackgrounds)
|
||||
backgrounds.add(abg);
|
||||
if (a.graphic)
|
||||
scene.loadSpritesheet(a.graphic, 'battle_anims', 96);
|
||||
}
|
||||
for (let bg of backgrounds)
|
||||
scene.loadImage(bg, 'battle_anims');
|
||||
for (let s of sounds)
|
||||
scene.loadSe(s, 'battle_anims', s);
|
||||
if (startLoad) {
|
||||
scene.load.once(Phaser.Loader.Events.COMPLETE, () => resolve());
|
||||
if (!scene.load.isLoading())
|
||||
scene.load.start();
|
||||
} else
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
interface GraphicFrameData {
|
||||
x: number,
|
||||
y: number,
|
||||
angle: number
|
||||
}
|
||||
|
||||
export abstract class BattleAnim {
|
||||
public user: Pokemon;
|
||||
public target: Pokemon;
|
||||
public sprites: Phaser.GameObjects.Sprite[];
|
||||
public bgSprite: Phaser.GameObjects.TileSprite;
|
||||
|
||||
constructor(user: Pokemon, target: Pokemon) {
|
||||
this.user = user;
|
||||
this.target = target;
|
||||
this.sprites = [];
|
||||
}
|
||||
|
||||
abstract getAnim(): AnimConfig;
|
||||
|
||||
abstract isOppAnim(): boolean;
|
||||
|
||||
abstract isReverseCoords(): boolean;
|
||||
|
||||
getGraphicScale(): number {
|
||||
return 1;
|
||||
}
|
||||
|
||||
private getGraphicFrameData(scene: BattleScene, frames: AnimFrame[]): Map<integer, GraphicFrameData> {
|
||||
const ret = new Map<integer, GraphicFrameData>();
|
||||
|
||||
const isOppAnim = this.isOppAnim();
|
||||
const user = !isOppAnim ? this.user : this.target;
|
||||
const target = !isOppAnim ? this.target : this.user;
|
||||
const isReverseCoords = this.isReverseCoords();
|
||||
const graphicScale = this.getGraphicScale();
|
||||
|
||||
const userInitialX = user.x;
|
||||
const userInitialY = user.y;
|
||||
const userHalfHeight = user.getSprite().displayHeight / 2;
|
||||
const targetInitialX = target.x;
|
||||
const targetInitialY = target.y;
|
||||
const targetHalfHeight = target.getSprite().displayHeight / 2;
|
||||
|
||||
let g = 0;
|
||||
|
||||
for (let frame of frames) {
|
||||
if (frame.target !== AnimFrameTarget.GRAPHIC)
|
||||
continue;
|
||||
|
||||
const xProgress = frame.focus !== AnimFocus.SCREEN ? Math.min(Math.max(frame.x, 0) / 128, 1) : 0;
|
||||
const initialX = targetInitialX;
|
||||
const initialY = targetInitialY;
|
||||
let xOffset = (!isReverseCoords ? (userInitialX - targetInitialX) : (targetInitialX - userInitialX));
|
||||
let yOffset = (!isReverseCoords ? (userInitialY - targetInitialY) : (targetInitialY - userInitialY));
|
||||
const ySpriteOffset = ((userHalfHeight * (1 - xProgress)) + (targetHalfHeight * xProgress)) * -1;
|
||||
if (graphicScale > 1) {
|
||||
xOffset -= ((scene.game.canvas.width / 6) * (graphicScale - 1)) / 2;
|
||||
yOffset -= ((scene.game.canvas.height / 6) * (graphicScale - 1)) / 2;
|
||||
}
|
||||
const x = initialX + xOffset * (!isReverseCoords ? 1 : -1) + (frame.x * graphicScale) * (!isReverseCoords ? 1 : -1);
|
||||
const y = ((initialY + yOffset * (!isReverseCoords || frame.focus === AnimFocus.USER || frame.focus === AnimFocus.SCREEN ? 1 : -1)
|
||||
+ (frame.y * graphicScale) * (!isReverseCoords || (frame.focus !== AnimFocus.USER_TARGET) ? 1 : -1) + ySpriteOffset));
|
||||
const angle = -frame.angle * (!isReverseCoords ? 1 : -1);
|
||||
ret.set(g++, { x: x, y: y, angle: angle });
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
play(scene: BattleScene, callback?: Function) {
|
||||
const isOppAnim = this.isOppAnim();
|
||||
const user = !isOppAnim ? this.user : this.target;
|
||||
const target = !isOppAnim ? this.target : this.user;
|
||||
|
||||
const anim = this.getAnim();
|
||||
|
||||
const userInitialX = user.x;
|
||||
const userInitialY = user.y;
|
||||
const targetInitialX = target.x;
|
||||
const targetInitialY = target.y;
|
||||
|
||||
const isReverseCoords = this.isReverseCoords();
|
||||
|
||||
let r = anim.frames.length;
|
||||
let f = 0;
|
||||
|
||||
const sprites: Phaser.GameObjects.Sprite[] = [];
|
||||
const spritePriorities: integer[] = [];
|
||||
|
||||
scene.tweens.addCounter({
|
||||
useFrames: true,
|
||||
duration: 3,
|
||||
repeat: anim.frames.length,
|
||||
onRepeat: () => {
|
||||
const spriteFrames = anim.frames[f];
|
||||
const frameData = this.getGraphicFrameData(scene, anim.frames[f]);
|
||||
let g = 0;
|
||||
for (let frame of spriteFrames) {
|
||||
switch (frame.target) {
|
||||
case AnimFrameTarget.USER:
|
||||
user.setPosition(userInitialX + frame.x / (!isReverseCoords ? 2 : -2), userInitialY + frame.y / (!isOppAnim ? 2 : -2));
|
||||
break;
|
||||
case AnimFrameTarget.TARGET:
|
||||
target.setPosition(targetInitialX + frame.x / (!isReverseCoords ? 2 : -2), targetInitialY + frame.y / (!isOppAnim ? 2 : -2));
|
||||
break;
|
||||
case AnimFrameTarget.GRAPHIC:
|
||||
if (g === sprites.length) {
|
||||
const newSprite = scene.add.sprite(0, 0, anim.graphic, 1);
|
||||
sprites.push(newSprite);
|
||||
scene.field.add(newSprite);
|
||||
spritePriorities.push(1);
|
||||
}
|
||||
|
||||
const graphicIndex = g++;
|
||||
const moveSprite = sprites[graphicIndex];
|
||||
if (spritePriorities[graphicIndex] !== frame.priority) {
|
||||
spritePriorities[graphicIndex] = frame.priority;
|
||||
const setSpritePriority = (priority: integer) => {
|
||||
switch (priority) {
|
||||
case 0:
|
||||
scene.field.moveBelow(moveSprite, scene.getEnemyPokemon());
|
||||
break;
|
||||
case 1:
|
||||
scene.field.moveTo(moveSprite, scene.field.getAll().length - 1);
|
||||
break;
|
||||
case 2:
|
||||
switch (frame.focus) {
|
||||
case AnimFocus.USER:
|
||||
if (this.bgSprite)
|
||||
scene.field.moveAbove(moveSprite, this.bgSprite);
|
||||
else
|
||||
scene.field.moveBelow(moveSprite, this.user);
|
||||
break;
|
||||
case AnimFocus.TARGET:
|
||||
scene.field.moveBelow(moveSprite, this.target);
|
||||
break;
|
||||
default:
|
||||
setSpritePriority(1);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
switch (frame.focus) {
|
||||
case AnimFocus.USER:
|
||||
scene.field.moveAbove(moveSprite, this.user);
|
||||
break;
|
||||
case AnimFocus.TARGET:
|
||||
scene.field.moveAbove(moveSprite, this.target);
|
||||
break;
|
||||
default:
|
||||
setSpritePriority(1);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
setSpritePriority(1);
|
||||
}
|
||||
};
|
||||
setSpritePriority(frame.priority);
|
||||
}
|
||||
moveSprite.setFrame(frame.graphicFrame);
|
||||
//console.log(AnimFocus[frame.focus]);
|
||||
const graphicScale = this.getGraphicScale();
|
||||
|
||||
moveSprite.setPosition(frameData.get(graphicIndex).x, frameData.get(graphicIndex).y);
|
||||
moveSprite.setAngle(frameData.get(graphicIndex).angle);
|
||||
const scaleX = graphicScale * (isReverseCoords === frame.mirror ? 1 : -1);
|
||||
const scaleY = graphicScale;
|
||||
moveSprite.setScale(scaleX, scaleY);
|
||||
|
||||
moveSprite.setAlpha(frame.opacity / 255);
|
||||
moveSprite.setBlendMode(frame.blendType === AnimBlendType.NORMAL ? Phaser.BlendModes.NORMAL : frame.blendType === AnimBlendType.ADD ? Phaser.BlendModes.ADD : Phaser.BlendModes.DIFFERENCE);
|
||||
break;
|
||||
}
|
||||
if (frame.target !== AnimFrameTarget.GRAPHIC) {
|
||||
const pokemon = frame.target === AnimFrameTarget.USER ? user : target;
|
||||
pokemon.setScale(!frame.mirror ? 1 : -1)
|
||||
pokemon.setAlpha(frame.opacity / 255);
|
||||
pokemon.setAngle(-frame.angle * (!isReverseCoords ? 1 : -1));
|
||||
const zoomScaleX = frame.zoomX / 100;
|
||||
const zoomScaleY = frame.zoomY / 100;
|
||||
const zoomSprite = pokemon.getZoomSprite();
|
||||
zoomSprite.setY(zoomSprite.displayHeight * (zoomScaleY - 1) * 0.5);
|
||||
zoomSprite.setScale(zoomScaleX, zoomScaleY);
|
||||
}
|
||||
}
|
||||
if (anim.frameTimedEvents.has(f)) {
|
||||
for (let event of anim.frameTimedEvents.get(f))
|
||||
r = Math.max((anim.frames.length - f) + event.execute(scene, this), r);
|
||||
}
|
||||
if (g < sprites.length) {
|
||||
const removedSprites = sprites.splice(g, sprites.length - g);
|
||||
spritePriorities.splice(g, sprites.length - g);
|
||||
for (let rs of removedSprites)
|
||||
rs.destroy();
|
||||
}
|
||||
f++;
|
||||
r--;
|
||||
},
|
||||
onComplete: () => {
|
||||
const cleanUpAndComplete = () => {
|
||||
user.setPosition(userInitialX, userInitialY);
|
||||
user.setScale(1);
|
||||
user.setAlpha(1);
|
||||
user.setAngle(0);
|
||||
target.setPosition(targetInitialX, targetInitialY);
|
||||
target.setScale(1);
|
||||
target.setAlpha(1);
|
||||
target.setAngle(0);
|
||||
if (this.bgSprite)
|
||||
this.bgSprite.destroy();
|
||||
if (callback)
|
||||
callback();
|
||||
};
|
||||
for (let ms of sprites) {
|
||||
if (ms)
|
||||
ms.destroy();
|
||||
}
|
||||
if (r) {
|
||||
scene.tweens.addCounter({
|
||||
duration: r,
|
||||
useFrames: true,
|
||||
onComplete: () => cleanUpAndComplete()
|
||||
});
|
||||
} else
|
||||
cleanUpAndComplete();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class CommonBattleAnim extends BattleAnim {
|
||||
public commonAnim: CommonAnim;
|
||||
|
||||
constructor(commonAnim: CommonAnim, user: Pokemon, target?: Pokemon) {
|
||||
super(user, target || user);
|
||||
|
||||
this.commonAnim = commonAnim;
|
||||
}
|
||||
|
||||
getAnim(): AnimConfig {
|
||||
return commonAnims.get(this.commonAnim);
|
||||
}
|
||||
|
||||
isOppAnim(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
isReverseCoords(): boolean {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export class MoveAnim extends BattleAnim {
|
||||
public move: Moves;
|
||||
|
||||
constructor(move: Moves, user: Pokemon, target: Pokemon) {
|
||||
super(user, target);
|
||||
|
||||
this.move = move;
|
||||
}
|
||||
|
||||
getAnim(): AnimConfig {
|
||||
return moveAnims.get(this.move) instanceof AnimConfig
|
||||
? moveAnims.get(this.move) as AnimConfig
|
||||
: moveAnims.get(this.move)[this.user.isPlayer() ? 0 : 1] as AnimConfig;
|
||||
}
|
||||
|
||||
isOppAnim(): boolean {
|
||||
const ret = !this.user.isPlayer() && Array.isArray(moveAnims.get(this.move));
|
||||
|
||||
switch (this.move) {
|
||||
case Moves.TELEPORT:
|
||||
return !ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
isReverseCoords(): boolean {
|
||||
return !this.user.isPlayer() === !this.isOppAnim();
|
||||
}
|
||||
|
||||
getGraphicScale(): number {
|
||||
switch (this.move) {
|
||||
case Moves.FISSURE:
|
||||
return 1.25;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
export class MoveChargeAnim extends MoveAnim {
|
||||
private chargeAnim: ChargeAnim;
|
||||
|
||||
constructor(chargeAnim: ChargeAnim, move: Moves, user: Pokemon, target: Pokemon) {
|
||||
super(move, user, target);
|
||||
|
||||
this.chargeAnim = chargeAnim;
|
||||
}
|
||||
|
||||
getAnim(): AnimConfig {
|
||||
return chargeAnims.get(this.chargeAnim) instanceof AnimConfig
|
||||
? chargeAnims.get(this.chargeAnim) as AnimConfig
|
||||
: chargeAnims.get(this.chargeAnim)[this.user.isPlayer() ? 0 : 1] as AnimConfig;
|
||||
}
|
||||
}
|
||||
|
||||
export function populateAnims() {
|
||||
return;
|
||||
const commonAnimNames = Utils.getEnumKeys(CommonAnim).map(k => k.toLowerCase());
|
||||
const commonAnimMatchNames = commonAnimNames.map(k => k.replace(/\_/g, ''));
|
||||
const commonAnimIds = Utils.getEnumValues(CommonAnim) as CommonAnim[];
|
||||
const chargeAnimNames = Utils.getEnumKeys(ChargeAnim).map(k => k.toLowerCase());
|
||||
const chargeAnimMatchNames = chargeAnimNames.map(k => k.replace(/\_/g, ' '));
|
||||
const chargeAnimIds = Utils.getEnumValues(ChargeAnim) as ChargeAnim[];
|
||||
const commonNamePattern = /name: (?:Common:)?(Opp )?(.*)/;
|
||||
const moveNameToId = {};
|
||||
for (let move of Utils.getEnumValues(Moves)) {
|
||||
const moveName = Moves[move].toUpperCase().replace(/\_/g, '');
|
||||
moveNameToId[moveName] = move;
|
||||
}
|
||||
const animsData = [];//battleAnimRawData.split('!ruby/array:PBAnimation').slice(1);
|
||||
for (let a = 0; a < animsData.length; a++) {
|
||||
const fields = animsData[a].split('@').slice(1);
|
||||
|
||||
let isOppMove: boolean;
|
||||
let commonAnimId: CommonAnim;
|
||||
let chargeAnimId: ChargeAnim;
|
||||
if (!fields[1].startsWith('name: Move:') && !(isOppMove = fields[1].startsWith('name: OppMove:'))) {
|
||||
const nameMatch = commonNamePattern.exec(fields[1]);
|
||||
const name = nameMatch[2].toLowerCase();
|
||||
if (commonAnimMatchNames.indexOf(name) > -1)
|
||||
commonAnimId = commonAnimIds[commonAnimMatchNames.indexOf(name)];
|
||||
else if (chargeAnimMatchNames.indexOf(name) > -1)
|
||||
chargeAnimId = chargeAnimIds[chargeAnimMatchNames.indexOf(name)];
|
||||
}
|
||||
const nameIndex = fields[1].indexOf(':', 5) + 1;
|
||||
const animName = fields[1].slice(nameIndex, fields[1].indexOf('\n', nameIndex));
|
||||
if (!moveNameToId.hasOwnProperty(animName) && !commonAnimId && !chargeAnimId)
|
||||
continue;
|
||||
let anim = commonAnimId || chargeAnimId ? new AnimConfig() : new AnimConfig();
|
||||
if (anim instanceof AnimConfig)
|
||||
(anim as AnimConfig).id = moveNameToId[animName];
|
||||
if (commonAnimId)
|
||||
commonAnims.set(commonAnimId, anim);
|
||||
else if (chargeAnimId)
|
||||
chargeAnims.set(chargeAnimId, !isOppMove ? anim : [ chargeAnims.get(chargeAnimId) as AnimConfig, anim ]);
|
||||
else
|
||||
moveAnims.set(moveNameToId[animName], !isOppMove ? anim as AnimConfig : [ moveAnims.get(moveNameToId[animName]) as AnimConfig, anim as AnimConfig ]);
|
||||
for (let f = 0; f < fields.length; f++) {
|
||||
const field = fields[f];
|
||||
const fieldName = field.slice(0, field.indexOf(':'));
|
||||
const fieldData = field.slice(fieldName.length + 1, field.lastIndexOf('\n')).trim();
|
||||
switch (fieldName) {
|
||||
case 'array':
|
||||
const framesData = fieldData.split(' - - - ').slice(1);
|
||||
for (let fd = 0; fd < framesData.length; fd++) {
|
||||
anim.frames.push([]);
|
||||
const frameData = framesData[fd];
|
||||
const focusFramesData = frameData.split(' - - ');
|
||||
for (let tf = 0; tf < focusFramesData.length; tf++) {
|
||||
const values = focusFramesData[tf].replace(/ \- /g, '').split('\n');
|
||||
const targetFrame = new AnimFrame(parseFloat(values[0]), parseFloat(values[1]), parseFloat(values[2]), parseFloat(values[11]), parseFloat(values[3]),
|
||||
values[4] === '1', values[6] === '1', parseInt(values[5]), parseInt(values[7]), parseInt(values[8]), parseInt(values[12]), parseInt(values[13]),
|
||||
parseInt(values[14]), parseInt(values[15]), parseInt(values[16]), parseInt(values[17]), parseInt(values[18]), parseInt(values[19]),
|
||||
parseInt(values[21]), parseInt(values[22]), parseInt(values[23]), parseInt(values[24]), values[20] === '1', parseInt(values[25]), parseInt(values[26]) as AnimFocus);
|
||||
anim.frames[fd].push(targetFrame);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'graphic':
|
||||
anim.graphic = fieldData !== "''" ? fieldData.slice(0, fieldData.indexOf('.')) : '';
|
||||
break;
|
||||
case 'timing':
|
||||
const timingEntries = fieldData.split('- !ruby/object:PBAnimTiming ').slice(1);
|
||||
for (let t = 0; t < timingEntries.length; t++) {
|
||||
const timingData = timingEntries[t].replace(/\n/g, ' ').replace(/[ ]{2,}/g, ' ').replace(/[a-z]+: ! '', /ig, '').replace(/name: (.*?),/, 'name: "$1",')
|
||||
.replace(/flashColor: !ruby\/object:Color { alpha: ([\d\.]+), blue: ([\d\.]+), green: ([\d\.]+), red: ([\d\.]+)}/, 'flashRed: $4, flashGreen: $3, flashBlue: $2, flashAlpha: $1');
|
||||
const frameIndex = parseInt(/frame: (\d+)/.exec(timingData)[1]);
|
||||
const resourceName = /name: "(.*?)"/.exec(timingData)[1].replace("''", '');
|
||||
const timingType = parseInt(/timingType: (\d)/.exec(timingData)[1]);
|
||||
let timedEvent: AnimTimedEvent;
|
||||
switch (timingType) {
|
||||
case 0:
|
||||
timedEvent = new AnimTimedSoundEvent(frameIndex, resourceName);
|
||||
break;
|
||||
case 1:
|
||||
timedEvent = new AnimTimedAddBgEvent(frameIndex, resourceName.slice(0, resourceName.indexOf('.')));
|
||||
break;
|
||||
case 2:
|
||||
timedEvent = new AnimTimedUpdateBgEvent(frameIndex, resourceName.slice(0, resourceName.indexOf('.')));
|
||||
break;
|
||||
}
|
||||
if (!timedEvent)
|
||||
continue;
|
||||
const propPattern = /([a-z]+): (.*?)(?:,|\})/ig;
|
||||
let propMatch: RegExpExecArray;
|
||||
while ((propMatch = propPattern.exec(timingData))) {
|
||||
const prop = propMatch[1];
|
||||
let value: any = propMatch[2];
|
||||
switch (prop) {
|
||||
case 'bgX':
|
||||
case 'bgY':
|
||||
value = parseFloat(value);
|
||||
break;
|
||||
case 'volume':
|
||||
case 'pitch':
|
||||
case 'opacity':
|
||||
case 'colorRed':
|
||||
case 'colorGreen':
|
||||
case 'colorBlue':
|
||||
case 'colorAlpha':
|
||||
case 'duration':
|
||||
case 'flashScope':
|
||||
case 'flashRed':
|
||||
case 'flashGreen':
|
||||
case 'flashBlue':
|
||||
case 'flashAlpha':
|
||||
case 'flashDuration':
|
||||
value = parseInt(value);
|
||||
break;
|
||||
}
|
||||
if (timedEvent.hasOwnProperty(prop))
|
||||
timedEvent[prop] = value;
|
||||
}
|
||||
if (!anim.frameTimedEvents.has(frameIndex))
|
||||
anim.frameTimedEvents.set(frameIndex, []);
|
||||
anim.frameTimedEvents.get(frameIndex).push(timedEvent);
|
||||
}
|
||||
break;
|
||||
case 'position':
|
||||
anim.position = parseInt(fieldData);
|
||||
break;
|
||||
case 'hue':
|
||||
anim.hue = parseInt(fieldData);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const animReplacer = (k, v) => {
|
||||
if (k === 'id' && !v)
|
||||
return undefined;
|
||||
if (v instanceof Map)
|
||||
return Object.fromEntries(v);
|
||||
if (v instanceof AnimTimedEvent)
|
||||
v['eventType'] = v.getEventType();
|
||||
return v;
|
||||
}
|
||||
|
||||
/*for (let ma of moveAnims.keys()) {
|
||||
const data = moveAnims.get(ma);
|
||||
(async () => {
|
||||
await fs.writeFile(`../public/battle-anims/${Moves[ma].toLowerCase().replace(/\_/g, '-')}.json`, JSON.stringify(data, animReplacer, ' '));
|
||||
})();
|
||||
}
|
||||
|
||||
for (let ca of chargeAnims.keys()) {
|
||||
const data = chargeAnims.get(ca);
|
||||
(async () => {
|
||||
await fs.writeFile(`../public/battle-anims/${chargeAnimNames[chargeAnimIds.indexOf(ca)].replace(/\_/g, '-')}.json`, JSON.stringify(data, animReplacer, ' '));
|
||||
})();
|
||||
}
|
||||
|
||||
for (let cma of commonAnims.keys()) {
|
||||
const data = commonAnims.get(cma);
|
||||
(async () => {
|
||||
await fs.writeFile(`../public/battle-anims/common-${commonAnimNames[commonAnimIds.indexOf(cma)].replace(/\_/g, '-')}.json`, JSON.stringify(data, animReplacer, ' '));
|
||||
})();
|
||||
}*/
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
export enum BattleStat {
|
||||
ATK,
|
||||
DEF,
|
||||
SPATK,
|
||||
SPDEF,
|
||||
SPD,
|
||||
ACC,
|
||||
EVA,
|
||||
RAND
|
||||
}
|
||||
|
||||
export function getBattleStatName(stat: BattleStat) {
|
||||
switch (stat) {
|
||||
case BattleStat.ATK:
|
||||
return 'ATTACK';
|
||||
case BattleStat.DEF:
|
||||
return 'DEFENSE';
|
||||
case BattleStat.SPATK:
|
||||
return 'SP. ATK';
|
||||
case BattleStat.SPDEF:
|
||||
return 'SP. DEF';
|
||||
case BattleStat.SPD:
|
||||
return 'SPEED';
|
||||
case BattleStat.ACC:
|
||||
return 'accuracy';
|
||||
case BattleStat.EVA:
|
||||
return 'evasiveness';
|
||||
default:
|
||||
return '???';
|
||||
}
|
||||
}
|
||||
|
||||
export function getBattleStatLevelChangeDescription(levels: integer, up: boolean) {
|
||||
if (up) {
|
||||
switch (levels) {
|
||||
case 1:
|
||||
return 'rose';
|
||||
case 2:
|
||||
return 'sharply rose';
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
return 'rose drastically';
|
||||
default:
|
||||
return 'won\'t go any higher';
|
||||
}
|
||||
} else {
|
||||
switch (levels) {
|
||||
case 1:
|
||||
return 'fell';
|
||||
case 2:
|
||||
return 'harshly fell';
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
return 'severely fell';
|
||||
default:
|
||||
return 'won\'t go any lower';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,322 @@
|
||||
import { CommonAnim, CommonBattleAnim } from "./battle-anims";
|
||||
import { CommonAnimPhase, DamagePhase, MessagePhase, MovePhase, ObtainStatusEffectPhase, PokemonHealPhase } from "../battle-phases";
|
||||
import { getPokemonMessage } from "../messages";
|
||||
import Pokemon from "../pokemon";
|
||||
import { Stat } from "./pokemon-stat";
|
||||
import { StatusEffect } from "./status-effect";
|
||||
import * as Utils from "../utils";
|
||||
|
||||
export enum BattleTagType {
|
||||
NONE,
|
||||
FLINCHED,
|
||||
CONFUSED,
|
||||
SEEDED,
|
||||
NIGHTMARE,
|
||||
FRENZY,
|
||||
INGRAIN,
|
||||
AQUA_RING,
|
||||
DROWSY,
|
||||
PROTECTED,
|
||||
FLYING,
|
||||
UNDERGROUND,
|
||||
NO_CRIT,
|
||||
BYPASS_SLEEP,
|
||||
IGNORE_FLYING
|
||||
}
|
||||
|
||||
export enum BattleTagLapseType {
|
||||
FAINT,
|
||||
MOVE,
|
||||
AFTER_MOVE,
|
||||
MOVE_EFFECT,
|
||||
TURN_END,
|
||||
CUSTOM
|
||||
}
|
||||
|
||||
export class BattleTag {
|
||||
public tagType: BattleTagType;
|
||||
public lapseType: BattleTagLapseType;
|
||||
public turnCount: integer;
|
||||
|
||||
constructor(tagType: BattleTagType, lapseType: BattleTagLapseType, turnCount: integer) {
|
||||
this.tagType = tagType;
|
||||
this.lapseType = lapseType;
|
||||
this.turnCount = turnCount;
|
||||
}
|
||||
|
||||
onAdd(pokemon: Pokemon): void { }
|
||||
|
||||
onRemove(pokemon: Pokemon): void { }
|
||||
|
||||
onOverlap(pokemon: Pokemon): void { }
|
||||
|
||||
lapse(pokemon: Pokemon, lapseType: BattleTagLapseType): boolean {
|
||||
return --this.turnCount > 0;
|
||||
}
|
||||
}
|
||||
|
||||
export class FlinchedTag extends BattleTag {
|
||||
constructor() {
|
||||
super(BattleTagType.FLINCHED, BattleTagLapseType.MOVE, 0);
|
||||
}
|
||||
|
||||
lapse(pokemon: Pokemon, lapseType: BattleTagLapseType): boolean {
|
||||
super.lapse(pokemon, lapseType);
|
||||
|
||||
(pokemon.scene.getCurrentPhase() as MovePhase).cancel();
|
||||
pokemon.scene.unshiftPhase(new MessagePhase(pokemon.scene, getPokemonMessage(pokemon, ' flinched!')));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export class PseudoStatusTag extends BattleTag {
|
||||
constructor(tagType: BattleTagType, lapseType: BattleTagLapseType, turnCount: integer) {
|
||||
super(tagType, lapseType, turnCount);
|
||||
}
|
||||
}
|
||||
|
||||
export class ConfusedTag extends PseudoStatusTag {
|
||||
constructor(turnCount: integer) {
|
||||
super(BattleTagType.CONFUSED, BattleTagLapseType.MOVE, turnCount);
|
||||
}
|
||||
|
||||
onAdd(pokemon: Pokemon): void {
|
||||
super.onAdd(pokemon);
|
||||
|
||||
pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, pokemon.isPlayer(), CommonAnim.CONFUSION));
|
||||
pokemon.scene.unshiftPhase(new MessagePhase(pokemon.scene, getPokemonMessage(pokemon, ' became\nconfused!')));
|
||||
}
|
||||
|
||||
onRemove(pokemon: Pokemon): void {
|
||||
super.onRemove(pokemon);
|
||||
|
||||
pokemon.scene.unshiftPhase(new MessagePhase(pokemon.scene, getPokemonMessage(pokemon, ' snapped\nout of confusion!')));
|
||||
}
|
||||
|
||||
onOverlap(pokemon: Pokemon): void {
|
||||
super.onOverlap(pokemon);
|
||||
|
||||
pokemon.scene.unshiftPhase(new MessagePhase(pokemon.scene, getPokemonMessage(pokemon, ' is\nalready confused!')));
|
||||
}
|
||||
|
||||
lapse(pokemon: Pokemon, lapseType: BattleTagLapseType): boolean {
|
||||
const ret = lapseType !== BattleTagLapseType.CUSTOM && super.lapse(pokemon, lapseType);
|
||||
|
||||
if (ret) {
|
||||
pokemon.scene.unshiftPhase(new MessagePhase(pokemon.scene, getPokemonMessage(pokemon, ' is\nconfused!')));
|
||||
pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, pokemon.isPlayer(), CommonAnim.CONFUSION));
|
||||
|
||||
if (Utils.randInt(2)) {
|
||||
const atk = pokemon.getBattleStat(Stat.ATK);
|
||||
const def = pokemon.getBattleStat(Stat.DEF);
|
||||
const damage = Math.ceil(((((2 * pokemon.level / 5 + 2) * 40 * atk / def) / 50) + 2) * ((Utils.randInt(15) + 85) / 100));
|
||||
pokemon.damage(damage);
|
||||
pokemon.scene.unshiftPhase(new MessagePhase(pokemon.scene, 'It hurt itself in its\nconfusion!'));
|
||||
pokemon.scene.unshiftPhase(new DamagePhase(pokemon.scene, pokemon.isPlayer()));
|
||||
(pokemon.scene.getCurrentPhase() as MovePhase).cancel();
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
export class SeedTag extends PseudoStatusTag {
|
||||
constructor() {
|
||||
super(BattleTagType.SEEDED, BattleTagLapseType.AFTER_MOVE, 1);
|
||||
}
|
||||
|
||||
onAdd(pokemon: Pokemon): void {
|
||||
super.onAdd(pokemon);
|
||||
|
||||
pokemon.scene.unshiftPhase(new MessagePhase(pokemon.scene, getPokemonMessage(pokemon, ' was seeded!')));
|
||||
}
|
||||
|
||||
lapse(pokemon: Pokemon, lapseType: BattleTagLapseType): boolean {
|
||||
console.trace(lapseType);
|
||||
const ret = lapseType !== BattleTagLapseType.CUSTOM || super.lapse(pokemon, lapseType);
|
||||
|
||||
if (ret) {
|
||||
pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, !pokemon.isPlayer(), CommonAnim.LEECH_SEED));
|
||||
|
||||
const damage = Math.max(Math.floor(pokemon.getMaxHp() / 8), 1);
|
||||
pokemon.damage(damage);
|
||||
pokemon.scene.unshiftPhase(new DamagePhase(pokemon.scene, pokemon.isPlayer()));
|
||||
pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, !pokemon.isPlayer(), damage, getPokemonMessage(pokemon, '\'s health is\nsapped by LEECH SEED!'), false, true));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
export class NightmareTag extends PseudoStatusTag {
|
||||
constructor() {
|
||||
super(BattleTagType.NIGHTMARE, BattleTagLapseType.AFTER_MOVE, 1);
|
||||
}
|
||||
|
||||
onAdd(pokemon: Pokemon): void {
|
||||
super.onAdd(pokemon);
|
||||
|
||||
pokemon.scene.unshiftPhase(new MessagePhase(pokemon.scene, getPokemonMessage(pokemon, ' began\nhaving a NIGHTMARE!')));
|
||||
}
|
||||
|
||||
onOverlap(pokemon: Pokemon): void {
|
||||
super.onOverlap(pokemon);
|
||||
|
||||
pokemon.scene.unshiftPhase(new MessagePhase(pokemon.scene, getPokemonMessage(pokemon, ' is\nalready locked in a NIGHTMARE!')));
|
||||
}
|
||||
|
||||
lapse(pokemon: Pokemon, lapseType: BattleTagLapseType): boolean {
|
||||
const ret = lapseType !== BattleTagLapseType.CUSTOM || super.lapse(pokemon, lapseType);
|
||||
|
||||
if (ret) {
|
||||
pokemon.scene.unshiftPhase(new MessagePhase(pokemon.scene, getPokemonMessage(pokemon, ' is locked\nin a NIGHTMARE!')));
|
||||
pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, pokemon.isPlayer(), CommonAnim.CURSE)); // TODO: Update animation type
|
||||
|
||||
const damage = Math.ceil(pokemon.getMaxHp() / 4);
|
||||
pokemon.damage(damage);
|
||||
pokemon.scene.unshiftPhase(new DamagePhase(pokemon.scene, pokemon.isPlayer()));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
export class IngrainTag extends PseudoStatusTag {
|
||||
constructor() {
|
||||
super(BattleTagType.INGRAIN, BattleTagLapseType.TURN_END, 1);
|
||||
}
|
||||
|
||||
onAdd(pokemon: Pokemon): void {
|
||||
super.onAdd(pokemon);
|
||||
|
||||
pokemon.scene.unshiftPhase(new MessagePhase(pokemon.scene, getPokemonMessage(pokemon, ' planted its roots!')));
|
||||
}
|
||||
|
||||
lapse(pokemon: Pokemon, lapseType: BattleTagLapseType): boolean {
|
||||
const ret = lapseType !== BattleTagLapseType.CUSTOM || super.lapse(pokemon, lapseType);
|
||||
|
||||
if (ret)
|
||||
pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, pokemon.isPlayer(), Math.floor(pokemon.getMaxHp() / 16),
|
||||
getPokemonMessage(pokemon, ` absorbed\nnutrients with its roots!`), true));
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
export class AquaRingTag extends PseudoStatusTag {
|
||||
constructor() {
|
||||
super(BattleTagType.AQUA_RING, BattleTagLapseType.TURN_END, 1);
|
||||
}
|
||||
|
||||
onAdd(pokemon: Pokemon): void {
|
||||
super.onAdd(pokemon);
|
||||
|
||||
pokemon.scene.unshiftPhase(new MessagePhase(pokemon.scene, getPokemonMessage(pokemon, ' surrounded\nitself with a veil of water!')));
|
||||
}
|
||||
|
||||
lapse(pokemon: Pokemon, lapseType: BattleTagLapseType): boolean {
|
||||
const ret = lapseType !== BattleTagLapseType.CUSTOM || super.lapse(pokemon, lapseType);
|
||||
|
||||
if (ret)
|
||||
pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, pokemon.isPlayer(), Math.floor(pokemon.getMaxHp() / 16), `AQUA RING restored\n${pokemon.name}\'s HP!`, true));
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
export class DrowsyTag extends BattleTag {
|
||||
constructor() {
|
||||
super(BattleTagType.DROWSY, BattleTagLapseType.TURN_END, 2);
|
||||
}
|
||||
|
||||
onAdd(pokemon: Pokemon): void {
|
||||
super.onAdd(pokemon);
|
||||
|
||||
pokemon.scene.unshiftPhase(new MessagePhase(pokemon.scene, getPokemonMessage(pokemon, ' grew drowsy!')));
|
||||
}
|
||||
|
||||
lapse(pokemon: Pokemon, lapseType: BattleTagLapseType): boolean {
|
||||
if (!super.lapse(pokemon, lapseType)) {
|
||||
pokemon.scene.unshiftPhase(new ObtainStatusEffectPhase(pokemon.scene, pokemon.isPlayer(), StatusEffect.SLEEP));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export class ProtectedTag extends BattleTag {
|
||||
constructor() {
|
||||
super(BattleTagType.PROTECTED, BattleTagLapseType.CUSTOM, 0);
|
||||
}
|
||||
|
||||
onAdd(pokemon: Pokemon): void {
|
||||
super.onAdd(pokemon);
|
||||
|
||||
pokemon.scene.unshiftPhase(new MessagePhase(pokemon.scene, getPokemonMessage(pokemon, '\nprotected itself!')));
|
||||
}
|
||||
|
||||
lapse(pokemon: Pokemon, lapseType: BattleTagLapseType): boolean {
|
||||
console.log(pokemon, BattleTagLapseType[lapseType]);
|
||||
if (lapseType === BattleTagLapseType.CUSTOM) {
|
||||
new CommonBattleAnim(CommonAnim.PROTECT, pokemon).play(pokemon.scene);
|
||||
pokemon.scene.unshiftPhase(new MessagePhase(pokemon.scene, getPokemonMessage(pokemon, '\nprotected itself!')));
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.lapse(pokemon, lapseType);
|
||||
}
|
||||
}
|
||||
|
||||
export class HideSpriteTag extends BattleTag {
|
||||
constructor(tagType: BattleTagType, turnCount: integer) {
|
||||
super(tagType, BattleTagLapseType.MOVE_EFFECT, turnCount);
|
||||
}
|
||||
|
||||
onAdd(pokemon: Pokemon): void {
|
||||
super.onAdd(pokemon);
|
||||
|
||||
pokemon.setVisible(false);
|
||||
}
|
||||
|
||||
onRemove(pokemon: Pokemon): void {
|
||||
// Wait 2 frames before setting visible for battle animations that don't immediately show the sprite invisible
|
||||
pokemon.scene.tweens.addCounter({
|
||||
duration: 2,
|
||||
useFrames: true,
|
||||
onComplete: () => pokemon.setVisible(true)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function getBattleTag(tagType: BattleTagType, turnCount: integer): BattleTag {
|
||||
switch (tagType) {
|
||||
case BattleTagType.FLINCHED:
|
||||
return new FlinchedTag();
|
||||
case BattleTagType.CONFUSED:
|
||||
return new ConfusedTag(turnCount);
|
||||
case BattleTagType.SEEDED:
|
||||
return new SeedTag();
|
||||
case BattleTagType.NIGHTMARE:
|
||||
return new NightmareTag();
|
||||
case BattleTagType.AQUA_RING:
|
||||
return new AquaRingTag();
|
||||
case BattleTagType.DROWSY:
|
||||
return new DrowsyTag();
|
||||
case BattleTagType.PROTECTED:
|
||||
return new ProtectedTag();
|
||||
case BattleTagType.FLYING:
|
||||
case BattleTagType.UNDERGROUND:
|
||||
return new HideSpriteTag(tagType, turnCount);
|
||||
case BattleTagType.NO_CRIT:
|
||||
return new BattleTag(tagType, BattleTagLapseType.AFTER_MOVE, turnCount);
|
||||
case BattleTagType.BYPASS_SLEEP:
|
||||
return new BattleTag(BattleTagType.BYPASS_SLEEP, BattleTagLapseType.TURN_END, turnCount);
|
||||
case BattleTagType.IGNORE_FLYING:
|
||||
return new BattleTag(tagType, BattleTagLapseType.TURN_END, turnCount);
|
||||
default:
|
||||
return new BattleTag(tagType, BattleTagLapseType.CUSTOM, turnCount);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import { MessagePhase, PokemonHealPhase } from "../battle-phases";
|
||||
import { getPokemonMessage } from "../messages";
|
||||
import Pokemon from "../pokemon";
|
||||
import { BattleTagType } from "./battle-tag";
|
||||
import { getStatusEffectHealText } from "./status-effect";
|
||||
|
||||
export enum BerryType {
|
||||
SITRUS,
|
||||
LUM
|
||||
}
|
||||
|
||||
export function getBerryName(berryType: BerryType) {
|
||||
switch (berryType) {
|
||||
case BerryType.SITRUS:
|
||||
return 'SITRUS BERRY';
|
||||
case BerryType.LUM:
|
||||
return 'LUM BERRY';
|
||||
}
|
||||
}
|
||||
|
||||
export function getBerryEffectDescription(berryType: BerryType) {
|
||||
switch (berryType) {
|
||||
case BerryType.SITRUS:
|
||||
return 'Restores 25% HP if HP is below 50%';
|
||||
case BerryType.LUM:
|
||||
return 'Cures any non-volatile status condition and confusion';
|
||||
}
|
||||
}
|
||||
|
||||
export type BerryPredicate = (pokemon: Pokemon) => boolean;
|
||||
|
||||
export function getBerryPredicate(berryType: BerryType): BerryPredicate {
|
||||
switch (berryType) {
|
||||
case BerryType.SITRUS:
|
||||
return (pokemon: Pokemon) => pokemon.getHpRatio() < 0.5;
|
||||
case BerryType.LUM:
|
||||
return (pokemon: Pokemon) => !!pokemon.status || !!pokemon.getTag(BattleTagType.CONFUSED);
|
||||
}
|
||||
}
|
||||
|
||||
export type BerryEffectFunc = (pokemon: Pokemon) => void;
|
||||
|
||||
export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc {
|
||||
switch (berryType) {
|
||||
case BerryType.SITRUS:
|
||||
return (pokemon: Pokemon) => {
|
||||
pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, true, Math.floor(pokemon.getMaxHp() / 4), getPokemonMessage(pokemon, `'s ${getBerryName(berryType)}\nrestored its HP!`), true));
|
||||
};
|
||||
case BerryType.LUM:
|
||||
return (pokemon: Pokemon) => {
|
||||
if (pokemon.status) {
|
||||
pokemon.scene.unshiftPhase(new MessagePhase(pokemon.scene,
|
||||
getPokemonMessage(pokemon, getStatusEffectHealText(pokemon.status.effect))));
|
||||
pokemon.resetStatus();
|
||||
pokemon.updateInfo();
|
||||
} else if (pokemon.getTag(BattleTagType.CONFUSED))
|
||||
pokemon.lapseTag(BattleTagType.CONFUSED);
|
||||
};
|
||||
}
|
||||
}
|
||||
+3891
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,25 @@
|
||||
export enum GrowthRate {
|
||||
ERRATIC = 0,
|
||||
FAST,
|
||||
MEDIUM_FAST,
|
||||
MEDIUM_SLOW,
|
||||
SLOW,
|
||||
FLUCTUATING
|
||||
};
|
||||
|
||||
const expLevels = [
|
||||
[ 0, 15, 52, 122, 237, 406, 637, 942, 1326, 1800, 2369, 3041, 3822, 4719, 5737, 6881, 8155, 9564, 11111, 12800, 14632, 16610, 18737, 21012, 23437, 26012, 28737, 31610, 34632, 37800, 41111, 44564, 48155, 51881, 55737, 59719, 63822, 68041, 72369, 76800, 81326, 85942, 90637, 95406, 100237, 105122, 110052, 115015, 120001, 125000, 131324, 137795, 144410, 151165, 158056, 165079, 172229, 179503, 186894, 194400, 202013, 209728, 217540, 225443, 233431, 241496, 249633, 257834, 267406, 276458, 286328, 296358, 305767, 316074, 326531, 336255, 346965, 357812, 367807, 378880, 390077, 400293, 411686, 423190, 433572, 445239, 457001, 467489, 479378, 491346, 501878, 513934, 526049, 536557, 548720, 560922, 571333, 583539, 591882, 600000 ],
|
||||
[ 0, 6, 21, 51, 100, 172, 274, 409, 583, 800, 1064, 1382, 1757, 2195, 2700, 3276, 3930, 4665, 5487, 6400, 7408, 8518, 9733, 11059, 12500, 14060, 15746, 17561, 19511, 21600, 23832, 26214, 28749, 31443, 34300, 37324, 40522, 43897, 47455, 51200, 55136, 59270, 63605, 68147, 72900, 77868, 83058, 88473, 94119, 100000, 106120, 112486, 119101, 125971, 133100, 140492, 148154, 156089, 164303, 172800, 181584, 190662, 200037, 209715, 219700, 229996, 240610, 251545, 262807, 274400, 286328, 298598, 311213, 324179, 337500, 351180, 365226, 379641, 394431, 409600, 425152, 441094, 457429, 474163, 491300, 508844, 526802, 545177, 563975, 583200, 602856, 622950, 643485, 664467, 685900, 707788, 730138, 752953, 776239, 800000 ],
|
||||
[ 0, 8, 27, 64, 125, 216, 343, 512, 729, 1000, 1331, 1728, 2197, 2744, 3375, 4096, 4913, 5832, 6859, 8000, 9261, 10648, 12167, 13824, 15625, 17576, 19683, 21952, 24389, 27000, 29791, 32768, 35937, 39304, 42875, 46656, 50653, 54872, 59319, 64000, 68921, 74088, 79507, 85184, 91125, 97336, 103823, 110592, 117649, 125000, 132651, 140608, 148877, 157464, 166375, 175616, 185193, 195112, 205379, 216000, 226981, 238328, 250047, 262144, 274625, 287496, 300763, 314432, 328509, 343000, 357911, 373248, 389017, 405224, 421875, 438976, 456533, 474552, 493039, 512000, 531441, 551368, 571787, 592704, 614125, 636056, 658503, 681472, 704969, 729000, 753571, 778688, 804357, 830584, 857375, 884736, 912673, 941192, 970299, 1000000 ],
|
||||
[ 0, 9, 57, 96, 135, 179, 236, 314, 419, 560, 742, 973, 1261, 1612, 2035, 2535, 3120, 3798, 4575, 5460, 6458, 7577, 8825, 10208, 11735, 13411, 15244, 17242, 19411, 21760, 24294, 27021, 29949, 33084, 36435, 40007, 43808, 47846, 52127, 56660, 61450, 66505, 71833, 77440, 83335, 89523, 96012, 102810, 109923, 117360, 125126, 133229, 141677, 150476, 159635, 169159, 179056, 189334, 199999, 211060, 222522, 234393, 246681, 259392, 272535, 286115, 300140, 314618, 329555, 344960, 360838, 377197, 394045, 411388, 429235, 447591, 466464, 485862, 505791, 526260, 547274, 568841, 590969, 613664, 636935, 660787, 685228, 710266, 735907, 762160, 789030, 816525, 844653, 873420, 902835, 932903, 963632, 995030, 1027103, 1059860 ],
|
||||
[ 0, 10, 33, 80, 156, 270, 428, 640, 911, 1250, 1663, 2160, 2746, 3430, 4218, 5120, 6141, 7290, 8573, 10000, 11576, 13310, 15208, 17280, 19531, 21970, 24603, 27440, 30486, 33750, 37238, 40960, 44921, 49130, 53593, 58320, 63316, 68590, 74148, 80000, 86151, 92610, 99383, 106480, 113906, 121670, 129778, 138240, 147061, 156250, 165813, 175760, 186096, 196830, 207968, 219520, 231491, 243890, 256723, 270000, 283726, 297910, 312558, 327680, 343281, 359370, 375953, 393040, 410636, 428750, 447388, 466560, 486271, 506530, 527343, 548720, 570666, 593190, 616298, 640000, 664301, 689210, 714733, 740880, 767656, 795070, 823128, 851840, 881211, 911250, 941963, 973360, 1005446, 1038230, 1071718, 1105920, 1140841, 1176490, 1212873, 1250000 ],
|
||||
[ 0, 4, 13, 32, 65, 112, 178, 276, 393, 540, 745, 967, 1230, 1591, 1957, 2457, 3046, 3732, 4526, 5440, 6482, 7666, 9003, 10506, 12187, 14060, 16140, 18439, 20974, 23760, 26811, 30146, 33780, 37731, 42017, 46656, 50653, 55969, 60505, 66560, 71677, 78533, 84277, 91998, 98415, 107069, 114205, 123863, 131766, 142500, 151222, 163105, 172697, 185807, 196322, 210739, 222231, 238036, 250562, 267840, 281456, 300293, 315059, 335544, 351520, 373744, 390991, 415050, 433631, 459620, 479600, 507617, 529063, 559209, 582187, 614566, 639146, 673863, 700115, 737280, 765275, 804997, 834809, 877201, 908905, 954084, 987754, 1035837, 1071552, 1122660, 1160499, 1214753, 1254796, 1312322, 1354652, 1415577, 1460276, 1524731, 1571884, 1640000 ]
|
||||
];
|
||||
|
||||
export function getLevelTotalExp(level: integer, growthRate: integer) {
|
||||
return expLevels[growthRate][level - 1];
|
||||
};
|
||||
|
||||
export function getLevelRelExp(level: integer, growthRate: integer) {
|
||||
return getLevelTotalExp(level, growthRate) - getLevelTotalExp(level - 1, growthRate);
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
export enum Gender {
|
||||
GENDERLESS = -1,
|
||||
MALE,
|
||||
FEMALE
|
||||
}
|
||||
|
||||
export function getGenderSymbol(gender: Gender) {
|
||||
switch (gender) {
|
||||
case Gender.MALE:
|
||||
return '♂';
|
||||
case Gender.FEMALE:
|
||||
return '♀';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
export function getGenderColor(gender: Gender, shadow?: boolean) {
|
||||
switch (gender) {
|
||||
case Gender.MALE:
|
||||
return shadow ? '#006090' : '#40c8f8';
|
||||
case Gender.FEMALE:
|
||||
return shadow ? '#984038' : '#f89890';
|
||||
}
|
||||
return '#ffffff';
|
||||
}
|
||||
+1995
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,114 @@
|
||||
import BattleScene from "../battle-scene";
|
||||
import { toPokemonUpperCase } from "../utils";
|
||||
|
||||
export enum PokeballType {
|
||||
POKEBALL,
|
||||
GREAT_BALL,
|
||||
ULTRA_BALL,
|
||||
MASTER_BALL,
|
||||
LUXURY_BALL
|
||||
};
|
||||
|
||||
export function getPokeballAtlasKey(type: PokeballType): string {
|
||||
switch (type) {
|
||||
case PokeballType.POKEBALL:
|
||||
return 'pb';
|
||||
case PokeballType.GREAT_BALL:
|
||||
return 'gb';
|
||||
case PokeballType.ULTRA_BALL:
|
||||
return 'ub';
|
||||
case PokeballType.MASTER_BALL:
|
||||
return 'mb';
|
||||
case PokeballType.LUXURY_BALL:
|
||||
return 'lb';
|
||||
}
|
||||
}
|
||||
|
||||
export function getPokeballName(type: PokeballType): string {
|
||||
let ret: string;
|
||||
switch (type) {
|
||||
case PokeballType.POKEBALL:
|
||||
ret = 'Poké ball';
|
||||
break;
|
||||
case PokeballType.GREAT_BALL:
|
||||
ret = 'Great Ball';
|
||||
break;
|
||||
case PokeballType.ULTRA_BALL:
|
||||
ret = 'Ultra Ball';
|
||||
break;
|
||||
case PokeballType.MASTER_BALL:
|
||||
ret = 'Master Ball';
|
||||
break;
|
||||
case PokeballType.LUXURY_BALL:
|
||||
ret = 'Luxury Ball';
|
||||
break;
|
||||
}
|
||||
return toPokemonUpperCase(ret);
|
||||
}
|
||||
|
||||
export function getPokeballCatchMultiplier(type: PokeballType): number {
|
||||
switch (type) {
|
||||
case PokeballType.POKEBALL:
|
||||
return 1;
|
||||
case PokeballType.GREAT_BALL:
|
||||
return 1.5;
|
||||
case PokeballType.ULTRA_BALL:
|
||||
return 2;
|
||||
case PokeballType.MASTER_BALL:
|
||||
return -1;
|
||||
case PokeballType.LUXURY_BALL:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
export function getPokeballTintColor(type: PokeballType): number {
|
||||
switch (type) {
|
||||
case PokeballType.POKEBALL:
|
||||
return 0xd52929;
|
||||
case PokeballType.GREAT_BALL:
|
||||
return 0x94b4de;
|
||||
case PokeballType.ULTRA_BALL:
|
||||
return 0xe6cd31;
|
||||
case PokeballType.MASTER_BALL:
|
||||
return 0xa441bd;
|
||||
case PokeballType.LUXURY_BALL:
|
||||
return 0xffde6a;
|
||||
}
|
||||
}
|
||||
|
||||
export function doPokeballBounceAnim(scene: BattleScene, pokeball: Phaser.GameObjects.Sprite, y1: number, y2: number, baseBounceDuration: integer, callback: Function) {
|
||||
let bouncePower = 1;
|
||||
let bounceYOffset = y1;
|
||||
let bounceY = y2;
|
||||
let yd = y2 - y1;
|
||||
|
||||
const doBounce = () => {
|
||||
scene.tweens.add({
|
||||
targets: pokeball,
|
||||
y: y2,
|
||||
duration: bouncePower * baseBounceDuration,
|
||||
ease: 'Cubic.easeIn',
|
||||
onComplete: () => {
|
||||
scene.sound.play('pb_bounce_1', { volume: bouncePower });
|
||||
|
||||
bouncePower = bouncePower > 0.01 ? bouncePower * 0.5 : 0;
|
||||
|
||||
if (bouncePower) {
|
||||
bounceYOffset = yd * bouncePower;
|
||||
bounceY = y2 - bounceYOffset;
|
||||
|
||||
scene.tweens.add({
|
||||
targets: pokeball,
|
||||
y: bounceY,
|
||||
duration: bouncePower * baseBounceDuration,
|
||||
ease: 'Cubic.easeOut',
|
||||
onComplete: () => doBounce()
|
||||
});
|
||||
} else if (callback)
|
||||
callback();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
doBounce();
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,35 @@
|
||||
import { toPokemonUpperCase } from "../utils";
|
||||
|
||||
export enum Stat {
|
||||
HP = 0,
|
||||
ATK,
|
||||
DEF,
|
||||
SPATK,
|
||||
SPDEF,
|
||||
SPD
|
||||
};
|
||||
|
||||
export function getStatName(stat: Stat) {
|
||||
let ret: string;
|
||||
switch (stat) {
|
||||
case Stat.HP:
|
||||
ret = 'Max. HP';
|
||||
break;
|
||||
case Stat.ATK:
|
||||
ret = 'Attack';
|
||||
break;
|
||||
case Stat.DEF:
|
||||
ret = 'Defense';
|
||||
break;
|
||||
case Stat.SPATK:
|
||||
ret = 'Sp. Atk';
|
||||
break;
|
||||
case Stat.SPDEF:
|
||||
ret = 'Sp. Def';
|
||||
break;
|
||||
case Stat.SPD:
|
||||
ret = 'Speed';
|
||||
break;
|
||||
}
|
||||
return toPokemonUpperCase(ret);
|
||||
}
|
||||
@@ -0,0 +1,653 @@
|
||||
export enum Species {
|
||||
BULBASAUR = 1,
|
||||
IVYSAUR,
|
||||
VENUSAUR,
|
||||
CHARMANDER,
|
||||
CHARMELEON,
|
||||
CHARIZARD,
|
||||
SQUIRTLE,
|
||||
WARTORTLE,
|
||||
BLASTOISE,
|
||||
CATERPIE,
|
||||
METAPOD,
|
||||
BUTTERFREE,
|
||||
WEEDLE,
|
||||
KAKUNA,
|
||||
BEEDRILL,
|
||||
PIDGEY,
|
||||
PIDGEOTTO,
|
||||
PIDGEOT,
|
||||
RATTATA,
|
||||
RATICATE,
|
||||
SPEAROW,
|
||||
FEAROW,
|
||||
EKANS,
|
||||
ARBOK,
|
||||
PIKACHU,
|
||||
RAICHU,
|
||||
SANDSHREW,
|
||||
SANDSLASH,
|
||||
NIDORAN_F,
|
||||
NIDORINA,
|
||||
NIDOQUEEN,
|
||||
NIDORAN_M,
|
||||
NIDORINO,
|
||||
NIDOKING,
|
||||
CLEFAIRY,
|
||||
CLEFABLE,
|
||||
VULPIX,
|
||||
NINETALES,
|
||||
JIGGLYPUFF,
|
||||
WIGGLYTUFF,
|
||||
ZUBAT,
|
||||
GOLBAT,
|
||||
ODDISH,
|
||||
GLOOM,
|
||||
VILEPLUME,
|
||||
PARAS,
|
||||
PARASECT,
|
||||
VENONAT,
|
||||
VENOMOTH,
|
||||
DIGLETT,
|
||||
DUGTRIO,
|
||||
MEOWTH,
|
||||
PERSIAN,
|
||||
PSYDUCK,
|
||||
GOLDUCK,
|
||||
MANKEY,
|
||||
PRIMEAPE,
|
||||
GROWLITHE,
|
||||
ARCANINE,
|
||||
POLIWAG,
|
||||
POLIWHIRL,
|
||||
POLIWRATH,
|
||||
ABRA,
|
||||
KADABRA,
|
||||
ALAKAZAM,
|
||||
MACHOP,
|
||||
MACHOKE,
|
||||
MACHAMP,
|
||||
BELLSPROUT,
|
||||
WEEPINBELL,
|
||||
VICTREEBEL,
|
||||
TENTACOOL,
|
||||
TENTACRUEL,
|
||||
GEODUDE,
|
||||
GRAVELER,
|
||||
GOLEM,
|
||||
PONYTA,
|
||||
RAPIDASH,
|
||||
SLOWPOKE,
|
||||
SLOWBRO,
|
||||
MAGNEMITE,
|
||||
MAGNETON,
|
||||
FARFETCHD,
|
||||
DODUO,
|
||||
DODRIO,
|
||||
SEEL,
|
||||
DEWGONG,
|
||||
GRIMER,
|
||||
MUK,
|
||||
SHELLDER,
|
||||
CLOYSTER,
|
||||
GASTLY,
|
||||
HAUNTER,
|
||||
GENGAR,
|
||||
ONIX,
|
||||
DROWZEE,
|
||||
HYPNO,
|
||||
KRABBY,
|
||||
KINGLER,
|
||||
VOLTORB,
|
||||
ELECTRODE,
|
||||
EXEGGCUTE,
|
||||
EXEGGUTOR,
|
||||
CUBONE,
|
||||
MAROWAK,
|
||||
HITMONLEE,
|
||||
HITMONCHAN,
|
||||
LICKITUNG,
|
||||
KOFFING,
|
||||
WEEZING,
|
||||
RHYHORN,
|
||||
RHYDON,
|
||||
CHANSEY,
|
||||
TANGELA,
|
||||
KANGASKHAN,
|
||||
HORSEA,
|
||||
SEADRA,
|
||||
GOLDEEN,
|
||||
SEAKING,
|
||||
STARYU,
|
||||
STARMIE,
|
||||
MR_MIME,
|
||||
SCYTHER,
|
||||
JYNX,
|
||||
ELECTABUZZ,
|
||||
MAGMAR,
|
||||
PINSIR,
|
||||
TAUROS,
|
||||
MAGIKARP,
|
||||
GYARADOS,
|
||||
LAPRAS,
|
||||
DITTO,
|
||||
EEVEE,
|
||||
VAPOREON,
|
||||
JOLTEON,
|
||||
FLAREON,
|
||||
PORYGON,
|
||||
OMANYTE,
|
||||
OMASTAR,
|
||||
KABUTO,
|
||||
KABUTOPS,
|
||||
AERODACTYL,
|
||||
SNORLAX,
|
||||
ARTICUNO,
|
||||
ZAPDOS,
|
||||
MOLTRES,
|
||||
DRATINI,
|
||||
DRAGONAIR,
|
||||
DRAGONITE,
|
||||
MEWTWO,
|
||||
MEW,
|
||||
CHIKORITA,
|
||||
BAYLEEF,
|
||||
MEGANIUM,
|
||||
CYNDAQUIL,
|
||||
QUILAVA,
|
||||
TYPHLOSION,
|
||||
TOTODILE,
|
||||
CROCONAW,
|
||||
FERALIGATR,
|
||||
SENTRET,
|
||||
FURRET,
|
||||
HOOTHOOT,
|
||||
NOCTOWL,
|
||||
LEDYBA,
|
||||
LEDIAN,
|
||||
SPINARAK,
|
||||
ARIADOS,
|
||||
CROBAT,
|
||||
CHINCHOU,
|
||||
LANTURN,
|
||||
PICHU,
|
||||
CLEFFA,
|
||||
IGGLYBUFF,
|
||||
TOGEPI,
|
||||
TOGETIC,
|
||||
NATU,
|
||||
XATU,
|
||||
MAREEP,
|
||||
FLAAFFY,
|
||||
AMPHAROS,
|
||||
BELLOSSOM,
|
||||
MARILL,
|
||||
AZUMARILL,
|
||||
SUDOWOODO,
|
||||
POLITOED,
|
||||
HOPPIP,
|
||||
SKIPLOOM,
|
||||
JUMPLUFF,
|
||||
AIPOM,
|
||||
SUNKERN,
|
||||
SUNFLORA,
|
||||
YANMA,
|
||||
WOOPER,
|
||||
QUAGSIRE,
|
||||
ESPEON,
|
||||
UMBREON,
|
||||
MURKROW,
|
||||
SLOWKING,
|
||||
MISDREAVUS,
|
||||
UNOWN,
|
||||
WOBBUFFET,
|
||||
GIRAFARIG,
|
||||
PINECO,
|
||||
FORRETRESS,
|
||||
DUNSPARCE,
|
||||
GLIGAR,
|
||||
STEELIX,
|
||||
SNUBBULL,
|
||||
GRANBULL,
|
||||
QWILFISH,
|
||||
SCIZOR,
|
||||
SHUCKLE,
|
||||
HERACROSS,
|
||||
SNEASEL,
|
||||
TEDDIURSA,
|
||||
URSARING,
|
||||
SLUGMA,
|
||||
MAGCARGO,
|
||||
SWINUB,
|
||||
PILOSWINE,
|
||||
CORSOLA,
|
||||
REMORAID,
|
||||
OCTILLERY,
|
||||
DELIBIRD,
|
||||
MANTINE,
|
||||
SKARMORY,
|
||||
HOUNDOUR,
|
||||
HOUNDOOM,
|
||||
KINGDRA,
|
||||
PHANPY,
|
||||
DONPHAN,
|
||||
PORYGON2,
|
||||
STANTLER,
|
||||
SMEARGLE,
|
||||
TYROGUE,
|
||||
HITMONTOP,
|
||||
SMOOCHUM,
|
||||
ELEKID,
|
||||
MAGBY,
|
||||
MILTANK,
|
||||
BLISSEY,
|
||||
RAIKOU,
|
||||
ENTEI,
|
||||
SUICUNE,
|
||||
LARVITAR,
|
||||
PUPITAR,
|
||||
TYRANITAR,
|
||||
LUGIA,
|
||||
HO_OH,
|
||||
CELEBI,
|
||||
TREECKO,
|
||||
GROVYLE,
|
||||
SCEPTILE,
|
||||
TORCHIC,
|
||||
COMBUSKEN,
|
||||
BLAZIKEN,
|
||||
MUDKIP,
|
||||
MARSHTOMP,
|
||||
SWAMPERT,
|
||||
POOCHYENA,
|
||||
MIGHTYENA,
|
||||
ZIGZAGOON,
|
||||
LINOONE,
|
||||
WURMPLE,
|
||||
SILCOON,
|
||||
BEAUTIFLY,
|
||||
CASCOON,
|
||||
DUSTOX,
|
||||
LOTAD,
|
||||
LOMBRE,
|
||||
LUDICOLO,
|
||||
SEEDOT,
|
||||
NUZLEAF,
|
||||
SHIFTRY,
|
||||
TAILLOW,
|
||||
SWELLOW,
|
||||
WINGULL,
|
||||
PELIPPER,
|
||||
RALTS,
|
||||
KIRLIA,
|
||||
GARDEVOIR,
|
||||
SURSKIT,
|
||||
MASQUERAIN,
|
||||
SHROOMISH,
|
||||
BRELOOM,
|
||||
SLAKOTH,
|
||||
VIGOROTH,
|
||||
SLAKING,
|
||||
NINCADA,
|
||||
NINJASK,
|
||||
SHEDINJA,
|
||||
WHISMUR,
|
||||
LOUDRED,
|
||||
EXPLOUD,
|
||||
MAKUHITA,
|
||||
HARIYAMA,
|
||||
AZURILL,
|
||||
NOSEPASS,
|
||||
SKITTY,
|
||||
DELCATTY,
|
||||
SABLEYE,
|
||||
MAWILE,
|
||||
ARON,
|
||||
LAIRON,
|
||||
AGGRON,
|
||||
MEDITITE,
|
||||
MEDICHAM,
|
||||
ELECTRIKE,
|
||||
MANECTRIC,
|
||||
PLUSLE,
|
||||
MINUN,
|
||||
VOLBEAT,
|
||||
ILLUMISE,
|
||||
ROSELIA,
|
||||
GULPIN,
|
||||
SWALOT,
|
||||
CARVANHA,
|
||||
SHARPEDO,
|
||||
WAILMER,
|
||||
WAILORD,
|
||||
NUMEL,
|
||||
CAMERUPT,
|
||||
TORKOAL,
|
||||
SPOINK,
|
||||
GRUMPIG,
|
||||
SPINDA,
|
||||
TRAPINCH,
|
||||
VIBRAVA,
|
||||
FLYGON,
|
||||
CACNEA,
|
||||
CACTURNE,
|
||||
SWABLU,
|
||||
ALTARIA,
|
||||
ZANGOOSE,
|
||||
SEVIPER,
|
||||
LUNATONE,
|
||||
SOLROCK,
|
||||
BARBOACH,
|
||||
WHISCASH,
|
||||
CORPHISH,
|
||||
CRAWDAUNT,
|
||||
BALTOY,
|
||||
CLAYDOL,
|
||||
LILEEP,
|
||||
CRADILY,
|
||||
ANORITH,
|
||||
ARMALDO,
|
||||
FEEBAS,
|
||||
MILOTIC,
|
||||
CASTFORM,
|
||||
KECLEON,
|
||||
SHUPPET,
|
||||
BANETTE,
|
||||
DUSKULL,
|
||||
DUSCLOPS,
|
||||
TROPIUS,
|
||||
CHIMECHO,
|
||||
ABSOL,
|
||||
WYNAUT,
|
||||
SNORUNT,
|
||||
GLALIE,
|
||||
SPHEAL,
|
||||
SEALEO,
|
||||
WALREIN,
|
||||
CLAMPERL,
|
||||
HUNTAIL,
|
||||
GOREBYSS,
|
||||
RELICANTH,
|
||||
LUVDISC,
|
||||
BAGON,
|
||||
SHELGON,
|
||||
SALAMENCE,
|
||||
BELDUM,
|
||||
METANG,
|
||||
METAGROSS,
|
||||
REGIROCK,
|
||||
REGICE,
|
||||
REGISTEEL,
|
||||
LATIAS,
|
||||
LATIOS,
|
||||
KYOGRE,
|
||||
GROUDON,
|
||||
RAYQUAZA,
|
||||
JIRACHI,
|
||||
DEOXYS,
|
||||
TURTWIG,
|
||||
GROTLE,
|
||||
TORTERRA,
|
||||
CHIMCHAR,
|
||||
MONFERNO,
|
||||
INFERNAPE,
|
||||
PIPLUP,
|
||||
PRINPLUP,
|
||||
EMPOLEON,
|
||||
STARLY,
|
||||
STARAVIA,
|
||||
STARAPTOR,
|
||||
BIDOOF,
|
||||
BIBAREL,
|
||||
KRICKETOT,
|
||||
KRICKETUNE,
|
||||
SHINX,
|
||||
LUXIO,
|
||||
LUXRAY,
|
||||
BUDEW,
|
||||
ROSERADE,
|
||||
CRANIDOS,
|
||||
RAMPARDOS,
|
||||
SHIELDON,
|
||||
BASTIODON,
|
||||
BURMY,
|
||||
WORMADAM,
|
||||
MOTHIM,
|
||||
COMBEE,
|
||||
VESPIQUEN,
|
||||
PACHIRISU,
|
||||
BUIZEL,
|
||||
FLOATZEL,
|
||||
CHERUBI,
|
||||
CHERRIM,
|
||||
SHELLOS,
|
||||
GASTRODON,
|
||||
AMBIPOM,
|
||||
DRIFLOON,
|
||||
DRIFBLIM,
|
||||
BUNEARY,
|
||||
LOPUNNY,
|
||||
MISMAGIUS,
|
||||
HONCHKROW,
|
||||
GLAMEOW,
|
||||
PURUGLY,
|
||||
CHINGLING,
|
||||
STUNKY,
|
||||
SKUNTANK,
|
||||
BRONZOR,
|
||||
BRONZONG,
|
||||
BONSLY,
|
||||
MIME_JR,
|
||||
HAPPINY,
|
||||
CHATOT,
|
||||
SPIRITOMB,
|
||||
GIBLE,
|
||||
GABITE,
|
||||
GARCHOMP,
|
||||
MUNCHLAX,
|
||||
RIOLU,
|
||||
LUCARIO,
|
||||
HIPPOPOTAS,
|
||||
HIPPOWDON,
|
||||
SKORUPI,
|
||||
DRAPION,
|
||||
CROAGUNK,
|
||||
TOXICROAK,
|
||||
CARNIVINE,
|
||||
FINNEON,
|
||||
LUMINEON,
|
||||
MANTYKE,
|
||||
SNOVER,
|
||||
ABOMASNOW,
|
||||
WEAVILE,
|
||||
MAGNEZONE,
|
||||
LICKILICKY,
|
||||
RHYPERIOR,
|
||||
TANGROWTH,
|
||||
ELECTIVIRE,
|
||||
MAGMORTAR,
|
||||
TOGEKISS,
|
||||
YANMEGA,
|
||||
LEAFEON,
|
||||
GLACEON,
|
||||
GLISCOR,
|
||||
MAMOSWINE,
|
||||
PORYGON_Z,
|
||||
GALLADE,
|
||||
PROBOPASS,
|
||||
DUSKNOIR,
|
||||
FROSLASS,
|
||||
ROTOM,
|
||||
UXIE,
|
||||
MESPRIT,
|
||||
AZELF,
|
||||
DIALGA,
|
||||
PALKIA,
|
||||
HEATRAN,
|
||||
REGIGIGAS,
|
||||
GIRATINA,
|
||||
CRESSELIA,
|
||||
PHIONE,
|
||||
MANAPHY,
|
||||
DARKRAI,
|
||||
SHAYMIN,
|
||||
ARCEUS,
|
||||
VICTINI,
|
||||
SNIVY,
|
||||
SERVINE,
|
||||
SERPERIOR,
|
||||
TEPIG,
|
||||
PIGNITE,
|
||||
EMBOAR,
|
||||
OSHAWOTT,
|
||||
DEWOTT,
|
||||
SAMUROTT,
|
||||
PATRAT,
|
||||
WATCHOG,
|
||||
LILLIPUP,
|
||||
HERDIER,
|
||||
STOUTLAND,
|
||||
PURRLOIN,
|
||||
LIEPARD,
|
||||
PANSAGE,
|
||||
SIMISAGE,
|
||||
PANSEAR,
|
||||
SIMISEAR,
|
||||
PANPOUR,
|
||||
SIMIPOUR,
|
||||
MUNNA,
|
||||
MUSHARNA,
|
||||
PIDOVE,
|
||||
TRANQUILL,
|
||||
UNFEZANT,
|
||||
BLITZLE,
|
||||
ZEBSTRIKA,
|
||||
ROGGENROLA,
|
||||
BOLDORE,
|
||||
GIGALITH,
|
||||
WOOBAT,
|
||||
SWOOBAT,
|
||||
DRILBUR,
|
||||
EXCADRILL,
|
||||
AUDINO,
|
||||
TIMBURR,
|
||||
GURDURR,
|
||||
CONKELDURR,
|
||||
TYMPOLE,
|
||||
PALPITOAD,
|
||||
SEISMITOAD,
|
||||
THROH,
|
||||
SAWK,
|
||||
SEWADDLE,
|
||||
SWADLOON,
|
||||
LEAVANNY,
|
||||
VENIPEDE,
|
||||
WHIRLIPEDE,
|
||||
SCOLIPEDE,
|
||||
COTTONEE,
|
||||
WHIMSICOTT,
|
||||
PETILIL,
|
||||
LILLIGANT,
|
||||
BASCULIN,
|
||||
SANDILE,
|
||||
KROKOROK,
|
||||
KROOKODILE,
|
||||
DARUMAKA,
|
||||
DARMANITAN,
|
||||
MARACTUS,
|
||||
DWEBBLE,
|
||||
CRUSTLE,
|
||||
SCRAGGY,
|
||||
SCRAFTY,
|
||||
SIGILYPH,
|
||||
YAMASK,
|
||||
COFAGRIGUS,
|
||||
TIRTOUGA,
|
||||
CARRACOSTA,
|
||||
ARCHEN,
|
||||
ARCHEOPS,
|
||||
TRUBBISH,
|
||||
GARBODOR,
|
||||
ZORUA,
|
||||
ZOROARK,
|
||||
MINCCINO,
|
||||
CINCCINO,
|
||||
GOTHITA,
|
||||
GOTHORITA,
|
||||
GOTHITELLE,
|
||||
SOLOSIS,
|
||||
DUOSION,
|
||||
REUNICLUS,
|
||||
DUCKLETT,
|
||||
SWANNA,
|
||||
VANILLITE,
|
||||
VANILLISH,
|
||||
VANILLUXE,
|
||||
DEERLING,
|
||||
SAWSBUCK,
|
||||
EMOLGA,
|
||||
KARRABLAST,
|
||||
ESCAVALIER,
|
||||
FOONGUS,
|
||||
AMOONGUSS,
|
||||
FRILLISH,
|
||||
JELLICENT,
|
||||
ALOMOMOLA,
|
||||
JOLTIK,
|
||||
GALVANTULA,
|
||||
FERROSEED,
|
||||
FERROTHORN,
|
||||
KLINK,
|
||||
KLANG,
|
||||
KLINKLANG,
|
||||
TYNAMO,
|
||||
EELEKTRIK,
|
||||
EELEKTROSS,
|
||||
ELGYEM,
|
||||
BEHEEYEM,
|
||||
LITWICK,
|
||||
LAMPENT,
|
||||
CHANDELURE,
|
||||
AXEW,
|
||||
FRAXURE,
|
||||
HAXORUS,
|
||||
CUBCHOO,
|
||||
BEARTIC,
|
||||
CRYOGONAL,
|
||||
SHELMET,
|
||||
ACCELGOR,
|
||||
STUNFISK,
|
||||
MIENFOO,
|
||||
MIENSHAO,
|
||||
DRUDDIGON,
|
||||
GOLETT,
|
||||
GOLURK,
|
||||
PAWNIARD,
|
||||
BISHARP,
|
||||
BOUFFALANT,
|
||||
RUFFLET,
|
||||
BRAVIARY,
|
||||
VULLABY,
|
||||
MANDIBUZZ,
|
||||
HEATMOR,
|
||||
DURANT,
|
||||
DEINO,
|
||||
ZWEILOUS,
|
||||
HYDREIGON,
|
||||
LARVESTA,
|
||||
VOLCARONA,
|
||||
COBALION,
|
||||
TERRAKION,
|
||||
VIRIZION,
|
||||
TORNADUS,
|
||||
THUNDURUS,
|
||||
RESHIRAM,
|
||||
ZEKROM,
|
||||
LANDORUS,
|
||||
KYUREM,
|
||||
KELDEO,
|
||||
MELOETTA,
|
||||
GENESECT,
|
||||
XERNEAS = 716,
|
||||
YVELTAL
|
||||
};
|
||||
@@ -0,0 +1,137 @@
|
||||
import * as Utils from "../utils";
|
||||
|
||||
export enum StatusEffect {
|
||||
NONE,
|
||||
POISON,
|
||||
TOXIC,
|
||||
PARALYSIS,
|
||||
SLEEP,
|
||||
FREEZE,
|
||||
BURN,
|
||||
FAINT
|
||||
}
|
||||
|
||||
export class Status {
|
||||
public effect: StatusEffect;
|
||||
public turnCount: integer;
|
||||
public cureTurn: integer;
|
||||
|
||||
constructor(effect: StatusEffect) {
|
||||
this.effect = effect;
|
||||
this.turnCount = 0;
|
||||
if (effect === StatusEffect.SLEEP)
|
||||
this.cureTurn = Utils.randInt(3, 1);
|
||||
}
|
||||
|
||||
incrementTurn(): void {
|
||||
this.turnCount++;
|
||||
}
|
||||
|
||||
isPostTurn(): boolean {
|
||||
return this.effect === StatusEffect.POISON || this.effect === StatusEffect.TOXIC || this.effect === StatusEffect.BURN;
|
||||
}
|
||||
}
|
||||
|
||||
export function getStatusEffectObtainText(statusEffect: StatusEffect): string {
|
||||
switch (statusEffect) {
|
||||
case StatusEffect.POISON:
|
||||
return '\nwas poisoned!';
|
||||
case StatusEffect.TOXIC:
|
||||
return '\nwas badly poisoned!';
|
||||
case StatusEffect.PARALYSIS:
|
||||
return ' is paralyzed!\nIt may be unable to move!';
|
||||
case StatusEffect.SLEEP:
|
||||
return '\nfell asleep!';
|
||||
case StatusEffect.FREEZE:
|
||||
return '\nwas frozen solid!';
|
||||
case StatusEffect.BURN:
|
||||
return '\nwas burned!';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
export function getStatusEffectActivationText(statusEffect: StatusEffect): string {
|
||||
switch (statusEffect) {
|
||||
case StatusEffect.POISON:
|
||||
case StatusEffect.TOXIC:
|
||||
return ' is hurt\nby poison!';
|
||||
case StatusEffect.PARALYSIS:
|
||||
return ' is paralyzed!\nIt can\'t move!';
|
||||
case StatusEffect.SLEEP:
|
||||
return ' is fast asleep.';
|
||||
case StatusEffect.FREEZE:
|
||||
return ' is\nfrozen solid!';
|
||||
case StatusEffect.BURN:
|
||||
return ' is hurt\nby its burn!';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
export function getStatusEffectOverlapText(statusEffect: StatusEffect): string {
|
||||
switch (statusEffect) {
|
||||
case StatusEffect.POISON:
|
||||
case StatusEffect.TOXIC:
|
||||
return ' is\nalready poisoned!';
|
||||
case StatusEffect.PARALYSIS:
|
||||
return ' is\nalready paralyzed!';
|
||||
case StatusEffect.SLEEP:
|
||||
return ' is\nalready asleep!';
|
||||
case StatusEffect.FREEZE:
|
||||
return ' is\nalready frozen!';
|
||||
case StatusEffect.BURN:
|
||||
return ' is\nalready burned!';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
export function getStatusEffectHealText(statusEffect: StatusEffect) {
|
||||
switch (statusEffect) {
|
||||
case StatusEffect.POISON:
|
||||
case StatusEffect.TOXIC:
|
||||
return ' was\ncured of its poison!';
|
||||
case StatusEffect.PARALYSIS:
|
||||
return ' was\nhealed of paralysis!';
|
||||
case StatusEffect.SLEEP:
|
||||
return ' woke up!';
|
||||
case StatusEffect.FREEZE:
|
||||
return ' was\ndefrosted!';
|
||||
case StatusEffect.BURN:
|
||||
return ' is hurt\nby its burn!';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
export function getStatusEffectDescriptor(statusEffect: StatusEffect) {
|
||||
switch (statusEffect) {
|
||||
case StatusEffect.POISON:
|
||||
case StatusEffect.TOXIC:
|
||||
return 'poisoning';
|
||||
case StatusEffect.PARALYSIS:
|
||||
return 'paralysis';
|
||||
case StatusEffect.SLEEP:
|
||||
return 'sleep';
|
||||
case StatusEffect.FREEZE:
|
||||
return 'freezing';
|
||||
case StatusEffect.BURN:
|
||||
return 'burn';
|
||||
}
|
||||
}
|
||||
|
||||
export function getStatusEffectCatchRateMultiplier(statusEffect: StatusEffect) {
|
||||
switch (statusEffect) {
|
||||
case StatusEffect.POISON:
|
||||
case StatusEffect.TOXIC:
|
||||
case StatusEffect.PARALYSIS:
|
||||
case StatusEffect.BURN:
|
||||
return 1.5;
|
||||
case StatusEffect.SLEEP:
|
||||
case StatusEffect.FREEZE:
|
||||
return 2.5;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import { BattleStat, getBattleStatName } from "./battle-stat";
|
||||
|
||||
export enum TempBattleStat {
|
||||
ATK,
|
||||
DEF,
|
||||
SPATK,
|
||||
SPDEF,
|
||||
SPD,
|
||||
ACC,
|
||||
CRIT
|
||||
}
|
||||
|
||||
export function getTempBattleStatName(tempBattleStat: TempBattleStat) {
|
||||
if (tempBattleStat === TempBattleStat.CRIT)
|
||||
return 'critical-hit ratio';
|
||||
return getBattleStatName(tempBattleStat as integer as BattleStat);
|
||||
}
|
||||
|
||||
export function getTempBattleStatBoosterItemName(tempBattleStat: TempBattleStat) {
|
||||
switch (tempBattleStat) {
|
||||
case TempBattleStat.ATK:
|
||||
return 'X Attack';
|
||||
case TempBattleStat.DEF:
|
||||
return 'X Defense';
|
||||
case TempBattleStat.SPATK:
|
||||
return 'X Sp. Atk';
|
||||
case TempBattleStat.SPDEF:
|
||||
return 'X Sp. Def';
|
||||
case TempBattleStat.SPD:
|
||||
return 'X Speed';
|
||||
case TempBattleStat.ACC:
|
||||
return 'X Accuracy';
|
||||
case TempBattleStat.CRIT:
|
||||
return 'Dire Hit';
|
||||
}
|
||||
}
|
||||
+30930
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,492 @@
|
||||
export enum Type {
|
||||
NORMAL = 0,
|
||||
FIGHTING,
|
||||
FLYING,
|
||||
POISON,
|
||||
GROUND,
|
||||
ROCK,
|
||||
BUG,
|
||||
GHOST,
|
||||
STEEL,
|
||||
FIRE,
|
||||
WATER,
|
||||
GRASS,
|
||||
ELECTRIC,
|
||||
PSYCHIC,
|
||||
ICE,
|
||||
DRAGON,
|
||||
DARK,
|
||||
FAIRY
|
||||
};
|
||||
|
||||
export function getTypeDamageMultiplier(attackType: integer, defType: integer) {
|
||||
switch (defType) {
|
||||
case Type.NORMAL:
|
||||
switch (attackType) {
|
||||
case Type.FIGHTING:
|
||||
return 2;
|
||||
case Type.NORMAL:
|
||||
case Type.FLYING:
|
||||
case Type.POISON:
|
||||
case Type.GROUND:
|
||||
case Type.ROCK:
|
||||
case Type.BUG:
|
||||
case Type.STEEL:
|
||||
case Type.FIRE:
|
||||
case Type.WATER:
|
||||
case Type.GRASS:
|
||||
case Type.ELECTRIC:
|
||||
case Type.PSYCHIC:
|
||||
case Type.ICE:
|
||||
case Type.DRAGON:
|
||||
case Type.DARK:
|
||||
case Type.FAIRY:
|
||||
return 1;
|
||||
case Type.GHOST:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case Type.FIGHTING:
|
||||
switch (attackType) {
|
||||
case Type.FLYING:
|
||||
case Type.PSYCHIC:
|
||||
case Type.FAIRY:
|
||||
return 2;
|
||||
case Type.NORMAL:
|
||||
case Type.FIGHTING:
|
||||
case Type.POISON:
|
||||
case Type.GROUND:
|
||||
case Type.GHOST:
|
||||
case Type.STEEL:
|
||||
case Type.FIRE:
|
||||
case Type.WATER:
|
||||
case Type.GRASS:
|
||||
case Type.ELECTRIC:
|
||||
case Type.ICE:
|
||||
case Type.DRAGON:
|
||||
case Type.DARK:
|
||||
return 1;
|
||||
case Type.ROCK:
|
||||
case Type.BUG:
|
||||
return 0.5;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case Type.FLYING:
|
||||
switch (attackType) {
|
||||
case Type.ROCK:
|
||||
case Type.ELECTRIC:
|
||||
case Type.ICE:
|
||||
return 2;
|
||||
case Type.NORMAL:
|
||||
case Type.FLYING:
|
||||
case Type.POISON:
|
||||
case Type.GHOST:
|
||||
case Type.STEEL:
|
||||
case Type.FIRE:
|
||||
case Type.WATER:
|
||||
case Type.PSYCHIC:
|
||||
case Type.DRAGON:
|
||||
case Type.DARK:
|
||||
case Type.FAIRY:
|
||||
return 1;
|
||||
case Type.FIGHTING:
|
||||
case Type.BUG:
|
||||
case Type.GRASS:
|
||||
return 0.5;
|
||||
case Type.GROUND:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case Type.POISON:
|
||||
switch (attackType) {
|
||||
case Type.GROUND:
|
||||
case Type.PSYCHIC:
|
||||
return 2;
|
||||
case Type.NORMAL:
|
||||
case Type.FLYING:
|
||||
case Type.ROCK:
|
||||
case Type.GHOST:
|
||||
case Type.STEEL:
|
||||
case Type.FIRE:
|
||||
case Type.WATER:
|
||||
case Type.ELECTRIC:
|
||||
case Type.ICE:
|
||||
case Type.DRAGON:
|
||||
case Type.DARK:
|
||||
return 1;
|
||||
case Type.FIGHTING:
|
||||
case Type.POISON:
|
||||
case Type.BUG:
|
||||
case Type.GRASS:
|
||||
case Type.FAIRY:
|
||||
return 0.5;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case Type.GROUND:
|
||||
switch (attackType) {
|
||||
case Type.WATER:
|
||||
case Type.GRASS:
|
||||
case Type.ICE:
|
||||
return 2;
|
||||
case Type.NORMAL:
|
||||
case Type.FIGHTING:
|
||||
case Type.FLYING:
|
||||
case Type.GROUND:
|
||||
case Type.BUG:
|
||||
case Type.GHOST:
|
||||
case Type.STEEL:
|
||||
case Type.FIRE:
|
||||
case Type.PSYCHIC:
|
||||
case Type.DRAGON:
|
||||
case Type.DARK:
|
||||
case Type.FAIRY:
|
||||
return 1;
|
||||
case Type.POISON:
|
||||
case Type.ROCK:
|
||||
return 0.5;
|
||||
case Type.ELECTRIC:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case Type.ROCK:
|
||||
switch (attackType) {
|
||||
case Type.FIGHTING:
|
||||
case Type.GROUND:
|
||||
case Type.STEEL:
|
||||
case Type.WATER:
|
||||
case Type.GRASS:
|
||||
return 2;
|
||||
case Type.ROCK:
|
||||
case Type.BUG:
|
||||
case Type.GHOST:
|
||||
case Type.ELECTRIC:
|
||||
case Type.PSYCHIC:
|
||||
case Type.ICE:
|
||||
case Type.DRAGON:
|
||||
case Type.DARK:
|
||||
case Type.FAIRY:
|
||||
return 1;
|
||||
case Type.NORMAL:
|
||||
case Type.FLYING:
|
||||
case Type.POISON:
|
||||
case Type.FIRE:
|
||||
return 0.5;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case Type.BUG:
|
||||
switch (attackType) {
|
||||
case Type.FLYING:
|
||||
case Type.ROCK:
|
||||
case Type.FIRE:
|
||||
return 2;
|
||||
case Type.NORMAL:
|
||||
case Type.POISON:
|
||||
case Type.BUG:
|
||||
case Type.GHOST:
|
||||
case Type.STEEL:
|
||||
case Type.WATER:
|
||||
case Type.ELECTRIC:
|
||||
case Type.PSYCHIC:
|
||||
case Type.ICE:
|
||||
case Type.DRAGON:
|
||||
case Type.DARK:
|
||||
case Type.FAIRY:
|
||||
return 1;
|
||||
case Type.FIGHTING:
|
||||
case Type.GROUND:
|
||||
case Type.GRASS:
|
||||
return 0.5;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case Type.GHOST:
|
||||
switch (attackType) {
|
||||
case Type.GHOST:
|
||||
case Type.DARK:
|
||||
return 2;
|
||||
case Type.FLYING:
|
||||
case Type.GROUND:
|
||||
case Type.ROCK:
|
||||
case Type.STEEL:
|
||||
case Type.FIRE:
|
||||
case Type.WATER:
|
||||
case Type.GRASS:
|
||||
case Type.ELECTRIC:
|
||||
case Type.PSYCHIC:
|
||||
case Type.ICE:
|
||||
case Type.DRAGON:
|
||||
case Type.FAIRY:
|
||||
return 1;
|
||||
case Type.POISON:
|
||||
case Type.BUG:
|
||||
return 0.5;
|
||||
case Type.NORMAL:
|
||||
case Type.FIGHTING:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case Type.STEEL:
|
||||
switch (attackType) {
|
||||
case Type.FIGHTING:
|
||||
case Type.GROUND:
|
||||
case Type.FIRE:
|
||||
return 2;
|
||||
case Type.GHOST:
|
||||
case Type.WATER:
|
||||
case Type.ELECTRIC:
|
||||
case Type.DARK:
|
||||
return 1;
|
||||
case Type.NORMAL:
|
||||
case Type.FLYING:
|
||||
case Type.ROCK:
|
||||
case Type.BUG:
|
||||
case Type.STEEL:
|
||||
case Type.GRASS:
|
||||
case Type.PSYCHIC:
|
||||
case Type.ICE:
|
||||
case Type.DRAGON:
|
||||
case Type.FAIRY:
|
||||
return 0.5;
|
||||
case Type.POISON:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case Type.FIRE:
|
||||
switch (attackType) {
|
||||
case Type.GROUND:
|
||||
case Type.ROCK:
|
||||
case Type.WATER:
|
||||
return 2;
|
||||
case Type.NORMAL:
|
||||
case Type.FIGHTING:
|
||||
case Type.FLYING:
|
||||
case Type.POISON:
|
||||
case Type.GHOST:
|
||||
case Type.ELECTRIC:
|
||||
case Type.PSYCHIC:
|
||||
case Type.DRAGON:
|
||||
case Type.DARK:
|
||||
return 1;
|
||||
case Type.BUG:
|
||||
case Type.STEEL:
|
||||
case Type.FIRE:
|
||||
case Type.GRASS:
|
||||
case Type.ICE:
|
||||
case Type.FAIRY:
|
||||
return 0.5;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case Type.WATER:
|
||||
switch (attackType) {
|
||||
case Type.GRASS:
|
||||
case Type.ELECTRIC:
|
||||
return 2;
|
||||
case Type.NORMAL:
|
||||
case Type.FIGHTING:
|
||||
case Type.FLYING:
|
||||
case Type.POISON:
|
||||
case Type.GROUND:
|
||||
case Type.ROCK:
|
||||
case Type.BUG:
|
||||
case Type.GHOST:
|
||||
case Type.PSYCHIC:
|
||||
case Type.DRAGON:
|
||||
case Type.DARK:
|
||||
case Type.FAIRY:
|
||||
return 1;
|
||||
case Type.STEEL:
|
||||
case Type.FIRE:
|
||||
case Type.WATER:
|
||||
case Type.ICE:
|
||||
return 0.5;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case Type.GRASS:
|
||||
switch (attackType) {
|
||||
case Type.FLYING:
|
||||
case Type.POISON:
|
||||
case Type.BUG:
|
||||
case Type.FIRE:
|
||||
case Type.ICE:
|
||||
return 2;
|
||||
case Type.NORMAL:
|
||||
case Type.FIGHTING:
|
||||
case Type.ROCK:
|
||||
case Type.GHOST:
|
||||
case Type.STEEL:
|
||||
case Type.PSYCHIC:
|
||||
case Type.DRAGON:
|
||||
case Type.DARK:
|
||||
case Type.FAIRY:
|
||||
return 1;
|
||||
case Type.GROUND:
|
||||
case Type.WATER:
|
||||
case Type.GRASS:
|
||||
case Type.ELECTRIC:
|
||||
return 0.5;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case Type.ELECTRIC:
|
||||
switch (attackType) {
|
||||
case Type.GROUND:
|
||||
return 2;
|
||||
case Type.NORMAL:
|
||||
case Type.FIGHTING:
|
||||
case Type.POISON:
|
||||
case Type.ROCK:
|
||||
case Type.BUG:
|
||||
case Type.GHOST:
|
||||
case Type.FIRE:
|
||||
case Type.WATER:
|
||||
case Type.GRASS:
|
||||
case Type.PSYCHIC:
|
||||
case Type.ICE:
|
||||
case Type.DRAGON:
|
||||
case Type.DARK:
|
||||
case Type.FAIRY:
|
||||
return 1;
|
||||
case Type.FLYING:
|
||||
case Type.STEEL:
|
||||
case Type.ELECTRIC:
|
||||
return 0.5;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case Type.PSYCHIC:
|
||||
switch (attackType) {
|
||||
case Type.BUG:
|
||||
case Type.GHOST:
|
||||
case Type.DARK:
|
||||
return 2;
|
||||
case Type.NORMAL:
|
||||
case Type.FLYING:
|
||||
case Type.POISON:
|
||||
case Type.GROUND:
|
||||
case Type.ROCK:
|
||||
case Type.STEEL:
|
||||
case Type.FIRE:
|
||||
case Type.WATER:
|
||||
case Type.GRASS:
|
||||
case Type.ELECTRIC:
|
||||
case Type.ICE:
|
||||
case Type.DRAGON:
|
||||
case Type.FAIRY:
|
||||
return 1;
|
||||
case Type.FIGHTING:
|
||||
case Type.PSYCHIC:
|
||||
return 0.5;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case Type.ICE:
|
||||
switch (attackType) {
|
||||
case Type.FIGHTING:
|
||||
case Type.ROCK:
|
||||
case Type.STEEL:
|
||||
case Type.FIRE:
|
||||
return 2;
|
||||
case Type.NORMAL:
|
||||
case Type.FLYING:
|
||||
case Type.POISON:
|
||||
case Type.GROUND:
|
||||
case Type.BUG:
|
||||
case Type.GHOST:
|
||||
case Type.WATER:
|
||||
case Type.GRASS:
|
||||
case Type.ELECTRIC:
|
||||
case Type.PSYCHIC:
|
||||
case Type.DRAGON:
|
||||
case Type.DARK:
|
||||
case Type.FAIRY:
|
||||
return 1;
|
||||
case Type.ICE:
|
||||
return 0.5;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case Type.DRAGON:
|
||||
switch (attackType) {
|
||||
case Type.ICE:
|
||||
case Type.DRAGON:
|
||||
case Type.FAIRY:
|
||||
return 2;
|
||||
case Type.NORMAL:
|
||||
case Type.FIGHTING:
|
||||
case Type.FLYING:
|
||||
case Type.POISON:
|
||||
case Type.GROUND:
|
||||
case Type.ROCK:
|
||||
case Type.BUG:
|
||||
case Type.GHOST:
|
||||
case Type.STEEL:
|
||||
case Type.PSYCHIC:
|
||||
case Type.DARK:
|
||||
return 1;
|
||||
case Type.FIRE:
|
||||
case Type.WATER:
|
||||
case Type.GRASS:
|
||||
case Type.ELECTRIC:
|
||||
return 0.5;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case Type.DARK:
|
||||
switch (attackType) {
|
||||
case Type.FIGHTING:
|
||||
case Type.BUG:
|
||||
case Type.FAIRY:
|
||||
return 2;
|
||||
case Type.NORMAL:
|
||||
case Type.FLYING:
|
||||
case Type.POISON:
|
||||
case Type.GROUND:
|
||||
case Type.ROCK:
|
||||
case Type.STEEL:
|
||||
case Type.FIRE:
|
||||
case Type.WATER:
|
||||
case Type.GRASS:
|
||||
case Type.ELECTRIC:
|
||||
case Type.ICE:
|
||||
case Type.DRAGON:
|
||||
return 1;
|
||||
case Type.GHOST:
|
||||
case Type.DARK:
|
||||
return 0.5;
|
||||
case Type.PSYCHIC:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case Type.FAIRY:
|
||||
switch (attackType) {
|
||||
case Type.POISON:
|
||||
case Type.STEEL:
|
||||
return 2;
|
||||
case Type.NORMAL:
|
||||
case Type.FLYING:
|
||||
case Type.GROUND:
|
||||
case Type.ROCK:
|
||||
case Type.GHOST:
|
||||
case Type.FIRE:
|
||||
case Type.WATER:
|
||||
case Type.GRASS:
|
||||
case Type.ELECTRIC:
|
||||
case Type.PSYCHIC:
|
||||
case Type.ICE:
|
||||
case Type.FAIRY:
|
||||
return 1;
|
||||
case Type.FIGHTING:
|
||||
case Type.BUG:
|
||||
case Type.DARK:
|
||||
return 0.5;
|
||||
case Type.DRAGON:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,317 @@
|
||||
import { Biome } from "./biome";
|
||||
import { getPokemonMessage } from "../messages";
|
||||
import Pokemon from "../pokemon";
|
||||
import { Type } from "./type";
|
||||
import Move, { AttackMove } from "./move";
|
||||
import * as Utils from "../utils";
|
||||
|
||||
export enum WeatherType {
|
||||
NONE,
|
||||
SUNNY,
|
||||
RAIN,
|
||||
SANDSTORM,
|
||||
HAIL,
|
||||
FOG,
|
||||
HEAVY_RAIN,
|
||||
HARSH_SUN,
|
||||
STRONG_WINDS
|
||||
}
|
||||
|
||||
export class Weather {
|
||||
public weatherType: WeatherType;
|
||||
public turnsLeft: integer;
|
||||
|
||||
constructor(weatherType: WeatherType, turnsLeft?: integer) {
|
||||
this.weatherType = weatherType;
|
||||
this.turnsLeft = turnsLeft || 0;
|
||||
}
|
||||
|
||||
lapse(): boolean {
|
||||
if (this.turnsLeft)
|
||||
return !!--this.turnsLeft;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
isImmutable(): boolean {
|
||||
switch (this.weatherType) {
|
||||
case WeatherType.HEAVY_RAIN:
|
||||
case WeatherType.HARSH_SUN:
|
||||
case WeatherType.STRONG_WINDS:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
isDamaging(): boolean {
|
||||
switch (this.weatherType) {
|
||||
case WeatherType.SANDSTORM:
|
||||
case WeatherType.HAIL:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
isTypeDamageImmune(type: Type): boolean {
|
||||
switch (this.weatherType) {
|
||||
case WeatherType.SANDSTORM:
|
||||
return type === Type.GROUND || type === Type.ROCK || type === Type.STEEL;
|
||||
case WeatherType.HAIL:
|
||||
return type === Type.ICE;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
getAttackTypeMultiplier(attackType: Type): number {
|
||||
switch (this.weatherType) {
|
||||
case WeatherType.SUNNY:
|
||||
case WeatherType.HARSH_SUN:
|
||||
if (attackType === Type.FIRE)
|
||||
return 1.5;
|
||||
if (attackType === Type.WATER)
|
||||
return 0.5;
|
||||
break;
|
||||
case WeatherType.RAIN:
|
||||
case WeatherType.HEAVY_RAIN:
|
||||
if (attackType === Type.FIRE)
|
||||
return 0.5;
|
||||
if (attackType === Type.WATER)
|
||||
return 1.5;
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
isMoveWeatherCancelled(move: Move): boolean {
|
||||
switch (this.weatherType) {
|
||||
case WeatherType.HARSH_SUN:
|
||||
return move instanceof AttackMove && move.type === Type.WATER;
|
||||
case WeatherType.HEAVY_RAIN:
|
||||
return move instanceof AttackMove && move.type === Type.FIRE;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function getWeatherStartMessage(weatherType: WeatherType) {
|
||||
switch (weatherType) {
|
||||
case WeatherType.SUNNY:
|
||||
return 'The sunlight got bright!';
|
||||
case WeatherType.RAIN:
|
||||
return 'A downpour started!';
|
||||
case WeatherType.SANDSTORM:
|
||||
return 'A sandstorm brewed!';
|
||||
case WeatherType.HAIL:
|
||||
return 'It started to hail!';
|
||||
case WeatherType.FOG:
|
||||
return 'A thick fog emerged!'
|
||||
case WeatherType.HEAVY_RAIN:
|
||||
return 'A heavy downpour started!'
|
||||
case WeatherType.HARSH_SUN:
|
||||
return 'The sunlight got hot!'
|
||||
case WeatherType.STRONG_WINDS:
|
||||
return 'A heavy wind began!';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export function getWeatherLapseMessage(weatherType: WeatherType) {
|
||||
switch (weatherType) {
|
||||
case WeatherType.SUNNY:
|
||||
return 'The sunlight is strong.';
|
||||
case WeatherType.RAIN:
|
||||
return 'The downpour continues.';
|
||||
case WeatherType.SANDSTORM:
|
||||
return 'The sandstorm rages.';
|
||||
case WeatherType.HAIL:
|
||||
return 'Hail continues to fall.';
|
||||
case WeatherType.FOG:
|
||||
return 'The fog continues.';
|
||||
case WeatherType.HEAVY_RAIN:
|
||||
return 'The heavy downpour continues.'
|
||||
case WeatherType.HARSH_SUN:
|
||||
return 'The sun is scorching hot.'
|
||||
case WeatherType.STRONG_WINDS:
|
||||
return 'The wind blows intensely.';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export function getWeatherDamageMessage(weatherType: WeatherType, pokemon: Pokemon) {
|
||||
switch (weatherType) {
|
||||
case WeatherType.SANDSTORM:
|
||||
return getPokemonMessage(pokemon, ' is buffeted\nby the sandstorm!');
|
||||
case WeatherType.HAIL:
|
||||
return getPokemonMessage(pokemon, ' is pelted\nby the hail!');
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export function getWeatherClearMessage(weatherType: WeatherType) {
|
||||
switch (weatherType) {
|
||||
case WeatherType.SUNNY:
|
||||
return 'The sunlight faded.';
|
||||
case WeatherType.RAIN:
|
||||
return 'The rain stopped.';
|
||||
case WeatherType.SANDSTORM:
|
||||
return 'The sandstorm subsided.';
|
||||
case WeatherType.HAIL:
|
||||
return 'The hail stopped.';
|
||||
case WeatherType.FOG:
|
||||
return 'The fog disappeared.'
|
||||
case WeatherType.HEAVY_RAIN:
|
||||
return 'The heavy rain stopped.'
|
||||
case WeatherType.HARSH_SUN:
|
||||
return 'The harsh sunlight faded.'
|
||||
case WeatherType.STRONG_WINDS:
|
||||
return 'The heavy wind stopped.';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
interface WeatherPoolEntry {
|
||||
weatherType: WeatherType;
|
||||
weight: integer;
|
||||
}
|
||||
|
||||
export function getRandomWeatherType(biome: Biome): WeatherType {
|
||||
let weatherPool: WeatherPoolEntry[] = [];
|
||||
switch (biome) {
|
||||
case Biome.GRASS:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 7 },
|
||||
{ weatherType: WeatherType.SUNNY, weight: 3 }
|
||||
];
|
||||
break;
|
||||
case Biome.TALL_GRASS:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.SUNNY, weight: 8 },
|
||||
{ weatherType: WeatherType.RAIN, weight: 5 },
|
||||
{ weatherType: WeatherType.FOG, weight: 2 }
|
||||
];
|
||||
break;
|
||||
case Biome.FOREST:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 8 },
|
||||
{ weatherType: WeatherType.RAIN, weight: 5 },
|
||||
{ weatherType: WeatherType.HEAVY_RAIN, weight: 2 }
|
||||
];
|
||||
break;
|
||||
case Biome.SEA:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 3 },
|
||||
{ weatherType: WeatherType.RAIN, weight: 7 },
|
||||
{ weatherType: WeatherType.HEAVY_RAIN, weight: 5 }
|
||||
];
|
||||
break;
|
||||
case Biome.SWAMP:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 2 },
|
||||
{ weatherType: WeatherType.RAIN, weight: 5 },
|
||||
{ weatherType: WeatherType.FOG, weight: 8 }
|
||||
];
|
||||
break;
|
||||
case Biome.BEACH:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 5 },
|
||||
{ weatherType: WeatherType.SUNNY, weight: 8 },
|
||||
{ weatherType: WeatherType.RAIN, weight: 2 }
|
||||
];
|
||||
break;
|
||||
case Biome.LAKE:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 10 },
|
||||
{ weatherType: WeatherType.RAIN, weight: 5 },
|
||||
{ weatherType: WeatherType.FOG, weight: 3 },
|
||||
{ weatherType: WeatherType.HEAVY_RAIN, weight: 2 }
|
||||
];
|
||||
break;
|
||||
case Biome.SEABED:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.HEAVY_RAIN, weight: 1 }
|
||||
];
|
||||
break;
|
||||
case Biome.MOUNTAIN:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.STRONG_WINDS, weight: 1 }
|
||||
];
|
||||
break;
|
||||
case Biome.LAND:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 8 },
|
||||
{ weatherType: WeatherType.SUNNY, weight: 3 },
|
||||
{ weatherType: WeatherType.SANDSTORM, weight: 2 },
|
||||
{ weatherType: WeatherType.HARSH_SUN, weight: 5 }
|
||||
];
|
||||
break;
|
||||
case Biome.DESERT:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.SANDSTORM, weight: 1 },
|
||||
{ weatherType: WeatherType.HARSH_SUN, weight: 1 }
|
||||
];
|
||||
break;
|
||||
case Biome.ICE_CAVE:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.HAIL, weight: 1 }
|
||||
];
|
||||
break;
|
||||
case Biome.MEADOW:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.SUNNY, weight: 1 }
|
||||
];
|
||||
case Biome.VOLCANO:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.HARSH_SUN, weight: 1 }
|
||||
];
|
||||
break;
|
||||
case Biome.GRAVEYARD:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.FOG, weight: 1 }
|
||||
];
|
||||
break;
|
||||
case Biome.RUINS:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 4 },
|
||||
{ weatherType: WeatherType.FOG, weight: 1 }
|
||||
];
|
||||
break;
|
||||
case Biome.WASTELAND:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 4 },
|
||||
{ weatherType: WeatherType.FOG, weight: 1 }
|
||||
];
|
||||
break;
|
||||
case Biome.ABYSS:
|
||||
weatherPool = [
|
||||
{ weatherType: WeatherType.NONE, weight: 4 },
|
||||
{ weatherType: WeatherType.FOG, weight: 1 }
|
||||
];
|
||||
break;
|
||||
}
|
||||
|
||||
if (weatherPool.length > 1) {
|
||||
let totalWeight = 0;
|
||||
weatherPool.forEach(w => totalWeight += w.weight);
|
||||
|
||||
const rand = Utils.randInt(totalWeight);
|
||||
let w = 0;
|
||||
for (let weather of weatherPool) {
|
||||
w += weather.weight;
|
||||
if (rand < w)
|
||||
return weather.weatherType;
|
||||
}
|
||||
}
|
||||
|
||||
return weatherPool.length
|
||||
? weatherPool[0].weatherType
|
||||
: WeatherType.NONE;
|
||||
}
|
||||
Reference in new issue
Block a user