From fb1c28322a41515fce66aee3a5b2ef2da5f37978 Mon Sep 17 00:00:00 2001 From: Elvis Wei <57282833+ewei068@users.noreply.github.com> Date: Wed, 8 Jan 2025 22:33:01 -0600 Subject: [PATCH] Gen3 Wrap up Part 1 (#75) * archie kyogre * fully finish archie's kyogre * maxie groudon * add numel and camerupt * magma camerupt * aqua sharpedo * update changelog * update gitignore * new banners * new dungeon * add butler npc * aqua vs magma event base --- .gitignore | 1 + changelog.md | 17 +- src/battle/data/abilities.js | 175 +++++++++++++++- src/battle/data/effects.js | 29 ++- src/battle/data/moves.js | 226 ++++++++++++++++++++- src/battle/engine/Battle.js | 4 + src/battle/engine/BattlePokemon.js | 40 +++- src/battle/engine/events.js | 2 +- src/battle/types.js | 1 + src/config/battleConfig.js | 21 +- src/config/commandConfig.js | 1 + src/config/gachaConfig.js | 26 +++ src/config/helpConfig.js | 24 ++- src/config/npcConfig.js | 312 ++++++++++++++++++++++++++++- src/config/pokemonConfig.js | 154 +++++++++++++- src/config/types.js | 1 + src/enums/battleEnums.js | 14 +- src/enums/pokemonEnums.js | 7 + 18 files changed, 1034 insertions(+), 21 deletions(-) diff --git a/.gitignore b/.gitignore index 33dc38d5..e5c55272 100644 --- a/.gitignore +++ b/.gitignore @@ -112,3 +112,4 @@ ssh.txt .DS_Store notes.md venv/ +Heap.* diff --git a/changelog.md b/changelog.md index 08281e74..50471407 100644 --- a/changelog.md +++ b/changelog.md @@ -4,22 +4,27 @@ TODO: -- Increase spawn duration -- Gen 3 wrap-up event - - Special Groudon and Kyogre Variants - - Special epic variants of Gen 3 Pokemon +- Gen 3 wrap-up update - Add Jirachi - - New event - Add some more Pokemon - - New raids? + - New raids +- Gen 3 wrap-up event + - Special Groudon and Kyogre Variants + - Special Aqua Sharpedo and Magma Camerupt + - New limited dungeon + - New limited NPC + - Temp increase rewards from new Gen 3 raid - Rebalance raids - Add raid tokens or something - Maybe revamp shop for this - New player UX analysis +- Make party add/remove easier +- Add Pokemon Emojis wherever possible **Stretch** - Stretch: Quests (Achievements) +- Stretch: Ability slots ### 1.1.1 (1/8) diff --git a/src/battle/data/abilities.js b/src/battle/data/abilities.js index 4bf04893..5632ada1 100644 --- a/src/battle/data/abilities.js +++ b/src/battle/data/abilities.js @@ -1,7 +1,16 @@ /* eslint-disable no-param-reassign */ -const { abilityIdEnum, battleEventEnum } = require("../../enums/battleEnums"); +const { weatherConditions } = require("../../config/battleConfig"); +const { types: pokemonTypes } = require("../../config/pokemonConfig"); +const { + abilityIdEnum, + battleEventEnum, + effectIdEnum, +} = require("../../enums/battleEnums"); const { logger } = require("../../log"); -const { getIsActivePokemonCallback } = require("../engine/eventConditions"); +const { + getIsActivePokemonCallback, + getIsTargetPokemonCallback, +} = require("../engine/eventConditions"); /** * @template T @@ -43,6 +52,113 @@ class Ability { } const abilitiesToRegister = Object.freeze({ + [abilityIdEnum.AQUA_POWER]: new Ability({ + id: abilityIdEnum.AQUA_POWER, + name: "Aqua Power", + description: + "At the start of battle, if there's only one other Water or Dark type ally, increase its highest base stat (excluding HP or Speed) by 2x for 3 turns, and start rain.", + abilityAdd({ battle, target }) { + return { + listenerId: battle.registerListenerFunction({ + eventName: battleEventEnum.BATTLE_BEGIN, + callback: () => { + const allyPokemons = target.getPartyPokemon(); + const otherWaterDarkAllies = allyPokemons.filter( + (pokemon) => + pokemon !== target && + pokemon && + !pokemon.isFainted && + (pokemon.hasType(pokemonTypes.WATER) || + pokemon.hasType(pokemonTypes.DARK)) + ); + if (otherWaterDarkAllies.length !== 1) { + return; + } + const [allyPokemon] = otherWaterDarkAllies; + battle.addToLog(`${target.name} blesses ${allyPokemon.name}!`); + const baseStats = allyPokemon.getAllBaseStats(); + const highestStatIndex = + baseStats + .slice(1, 5) + .reduce( + (maxIndex, stat, index, arr) => + stat > arr[maxIndex] ? index : maxIndex, + 0 + ) + 1; // +1 to account for HP + allyPokemon.applyEffect(effectIdEnum.AQUA_BLESSING, 3, target, { + // @ts-ignore + stat: highestStatIndex, + }); + + battle.createWeather(weatherConditions.RAIN, target); + }, + }), + }; + }, + abilityRemove({ battle, properties }) { + battle.unregisterListener(properties.listenerId); + }, + }), + [abilityIdEnum.MAGMA_POWER]: new Ability({ + id: abilityIdEnum.MAGMA_POWER, + name: "Magma Power", + description: + "At the start of battle, if there's only one other Ground or Fire type ally, increase its combat readiness by 35%, and start harsh sunlight.", + abilityAdd({ battle, target }) { + return { + listenerId: battle.registerListenerFunction({ + eventName: battleEventEnum.BATTLE_BEGIN, + callback: () => { + const allyPokemons = target.getPartyPokemon(); + const otherFireGroundAllies = allyPokemons.filter( + (pokemon) => + pokemon !== target && + pokemon && + !pokemon.isFainted && + (pokemon.hasType(pokemonTypes.FIRE) || + pokemon.hasType(pokemonTypes.GROUND)) + ); + if (otherFireGroundAllies.length !== 1) { + return; + } + const [allyPokemon] = otherFireGroundAllies; + battle.addToLog(`${target.name} blesses ${allyPokemon.name}!`); + allyPokemon.boostCombatReadiness(target, 35); + + battle.createWeather(weatherConditions.SUN, target); + }, + }), + }; + }, + abilityRemove({ battle, properties }) { + battle.unregisterListener(properties.listenerId); + }, + }), + [abilityIdEnum.ANGER_POINT]: new Ability({ + id: abilityIdEnum.ANGER_POINT, + name: "Anger Point", + description: + "When the user takes more than 33% of its health of damage at once, sharply raise its Atk and Spa for 3 turns.", + abilityAdd({ battle, target }) { + return { + listenerId: battle.registerListenerFunction({ + eventName: battleEventEnum.AFTER_DAMAGE_TAKEN, + callback: ({ damage }) => { + if (damage < target.maxHp * 0.33) { + return; + } + battle.addToLog(`${target.name}'s Anger Point activates!`); + target.applyEffect("greaterAtkUp", 3, target, {}); + target.applyEffect("greaterSpaUp", 3, target, {}); + }, + conditionCallback: getIsTargetPokemonCallback(target), + }), + }; + }, + abilityRemove({ battle, properties }) { + battle.unregisterListener(properties.listenerId); + }, + }), [abilityIdEnum.REGENERATOR]: new Ability({ id: abilityIdEnum.REGENERATOR, name: "Regenerator", @@ -69,6 +185,61 @@ const abilitiesToRegister = Object.freeze({ battle.unregisterListener(properties.listenerId); }, }), + [abilityIdEnum.BURNING_DRAFT]: new Ability({ + id: abilityIdEnum.BURNING_DRAFT, + name: "Burning Draft", + description: + "When the user's turn ends, increase the combat readiness of all allies by 10%.", + abilityAdd({ battle, target }) { + return { + listenerId: battle.registerListenerFunction({ + eventName: battleEventEnum.TURN_END, + callback: () => { + const allyPokemons = target.getPartyPokemon(); + battle.addToLog( + `${target.name}'s Burning Draft increases its allies' combat readiness!` + ); + allyPokemons.forEach((ally) => { + if (!ally) { + return; + } + ally.boostCombatReadiness(target, 10); + }); + }, + conditionCallback: getIsActivePokemonCallback(battle, target), + }), + }; + }, + abilityRemove({ battle, properties }) { + battle.unregisterListener(properties.listenerId); + }, + }), + [abilityIdEnum.JET_SPEED]: new Ability({ + id: abilityIdEnum.JET_SPEED, + name: "Jet Speed", + description: + "When the weather is set to rain, increase the user's combat readiness by 20% and raise its Special Attack for 2 turns.", + abilityAdd({ battle, target }) { + return { + listenerId: battle.registerListenerFunction({ + eventName: battleEventEnum.AFTER_WEATHER_SET, + callback: () => { + const { weather } = battle; + if (weather.weatherId !== weatherConditions.RAIN) { + return; + } + + battle.addToLog(`${target.name} is pumped by the Rain!`); + target.boostCombatReadiness(target, 20); + target.applyEffect("spaUp", 2, target, {}); + }, + }), + }; + }, + abilityRemove({ battle, properties }) { + battle.unregisterListener(properties.listenerId); + }, + }), }); module.exports = { diff --git a/src/battle/data/effects.js b/src/battle/data/effects.js index 3904e60e..7276ab80 100644 --- a/src/battle/data/effects.js +++ b/src/battle/data/effects.js @@ -1,5 +1,5 @@ /* eslint-disable no-param-reassign */ -const { effectTypes } = require("../../config/battleConfig"); +const { effectTypes, statToBattleStat } = require("../../config/battleConfig"); const { effectIdEnum, battleEventEnum } = require("../../enums/battleEnums"); const { getIsTargetPokemonCallback } = require("../engine/eventConditions"); const { getEffect } = require("./effectRegistry"); @@ -130,6 +130,33 @@ const effectsToRegister = Object.freeze({ battle.unregisterListener(properties.listenerId); }, }), + [effectIdEnum.AQUA_BLESSING]: new Effect({ + id: effectIdEnum.AQUA_BLESSING, + name: "Aqua Blessing", + description: "The target's stat is increased by 2x.", + type: effectTypes.BUFF, + dispellable: true, + /** + * @param {EffectAddBasicArgs & {initialArgs: {stat: StatEnum}}} args + */ + effectAdd({ battle, target, initialArgs }) { + const { stat } = initialArgs; + const baseStatValue = target.getAllBaseStats()[stat]; + const statToIncrease = statToBattleStat[stat]; + + battle.addToLog(`${target.name}'s ${statToIncrease} rose!`); + target[statToIncrease] += baseStatValue; + return {}; + }, + effectRemove({ battle, target, initialArgs }) { + const { stat } = initialArgs; + const baseStatValue = target.getAllBaseStats()[stat]; + const statToIncrease = statToBattleStat[stat]; + + battle.addToLog(`${target.name}'s ${statToIncrease} boost wore off!`); + target[statToIncrease] -= baseStatValue; + }, + }), }); module.exports = { diff --git a/src/battle/data/moves.js b/src/battle/data/moves.js index 2f009615..26bef313 100644 --- a/src/battle/data/moves.js +++ b/src/battle/data/moves.js @@ -5,9 +5,11 @@ const { targetPatterns, damageTypes, moveTiers, + statusConditions, } = require("../../config/battleConfig"); const { getMove } = require("./moveRegistry"); const { moveIdEnum } = require("../../enums/battleEnums"); +const { drawIterable } = require("../../utils/gachaUtils"); class Move { /** @@ -65,8 +67,11 @@ class Move { allTargets, missedTargets = [], offTargetDamageMultiplier = 0.8, + calculateDamageFunction = undefined, }) { - const damageToDeal = source.calculateMoveDamage({ + const damageFunc = + calculateDamageFunction || ((args) => source.calculateMoveDamage(args)); + const damageToDeal = damageFunc({ move: getMove(this.id), target, primaryTarget, @@ -87,6 +92,7 @@ class Move { * @param {Array} param0.allTargets * @param {Array=} param0.missedTargets * @param {number=} param0.offTargetDamageMultiplier + * @param {CalculateMoveDamageImpl=} param0.calculateDamageFunction */ genericDealAllDamage({ source, @@ -94,6 +100,7 @@ class Move { allTargets, missedTargets = [], offTargetDamageMultiplier = 0.8, + calculateDamageFunction = undefined, }) { for (const target of allTargets) { this.genericDealSingleDamage({ @@ -103,12 +110,95 @@ class Move { allTargets, missedTargets, offTargetDamageMultiplier, + calculateDamageFunction, + }); + } + } + + // eslint-disable-next-line class-methods-use-this + genericApplySingleStatus({ + source, + target, + // eslint-disable-next-line no-unused-vars + primaryTarget, + // eslint-disable-next-line no-unused-vars + allTargets, + missedTargets = [], + statusId, + options, + probablity = 1, + }) { + if (!missedTargets.includes(target) && Math.random() < probablity) { + return target.applyStatus(statusId, source, options); + } + return false; + } + + /** + * @param {object} param0 + * @param {BattlePokemon} param0.source + * @param {BattlePokemon} param0.primaryTarget + * @param {Array} param0.allTargets + * @param {Array=} param0.missedTargets + * @param {StatusConditionEnum} param0.statusId + * @param {object=} param0.options + * @param {number=} param0.probablity + */ + genericApplyAllStatus({ + source, + primaryTarget, + allTargets, + missedTargets = [], + statusId, + options, + probablity = 1, + }) { + for (const target of allTargets) { + this.genericApplySingleStatus({ + source, + target, + primaryTarget, + allTargets, + missedTargets, + statusId, + options, + probablity, }); } } } const movesToRegister = Object.freeze({ + [moveIdEnum.FIRE_PUNCH]: new Move({ + id: moveIdEnum.FIRE_PUNCH, + name: "Fire Punch", + type: pokemonTypes.FIRE, + power: 75, + accuracy: 100, + cooldown: 2, + targetType: targetTypes.ENEMY, + targetPosition: targetPositions.FRONT, + targetPattern: targetPatterns.SINGLE, + tier: moveTiers.POWER, + damageType: damageTypes.PHYSICAL, + description: + "The target is punched with a fiery fist. It may also leave the target with a burn with a 50% chance.", + execute({ source, primaryTarget, allTargets, missedTargets }) { + this.genericDealAllDamage({ + source, + primaryTarget, + allTargets, + missedTargets, + }); + this.genericApplyAllStatus({ + source, + primaryTarget, + allTargets, + statusId: statusConditions.BURN, + probablity: 0.5, + }); + }, + }), [moveIdEnum.VINE_WHIP]: new Move({ id: moveIdEnum.VINE_WHIP, name: "Vine Whip", @@ -132,6 +222,140 @@ const movesToRegister = Object.freeze({ }); }, }), + [moveIdEnum.AQUA_IMPACT]: new Move({ + id: moveIdEnum.AQUA_IMPACT, + name: "Aqua Impact", + type: pokemonTypes.WATER, + power: 50, + accuracy: 90, + cooldown: 5, + targetType: targetTypes.ENEMY, + targetPosition: targetPositions.FRONT, + targetPattern: targetPatterns.ALL, + tier: moveTiers.ULTIMATE, + damageType: damageTypes.SPECIAL, + description: + "The targets are struck with a high-pressure flood of water. If hit, does true damage equal to 5% of the highest stat (excluding HP) among other Water or Dark type Pokemon on your team.", + execute({ source, primaryTarget, allTargets, missedTargets }) { + const sourceTeamPokemons = source.getPartyPokemon(); + let highestStat = 0; + for (const pokemon of sourceTeamPokemons) { + if ( + pokemon === source || + !pokemon || + pokemon.isFainted || + !( + pokemon.hasType(pokemonTypes.WATER) || + pokemon.hasType(pokemonTypes.DARK) + ) + ) { + continue; + } + const pokemonHighestNonHpStat = pokemon + .getAllStats() + .slice(1, undefined) + .reduce((highest, stat) => (stat > highest ? stat : highest), 0); + if (pokemonHighestNonHpStat > highestStat) { + highestStat = pokemonHighestNonHpStat; + } + } + + this.genericDealAllDamage({ + source, + primaryTarget, + allTargets, + missedTargets, + calculateDamageFunction: (args) => { + const { target } = args; + const baseDamage = source.calculateMoveDamage(args); + if (!missedTargets.includes(target)) { + const trueDamage = Math.floor(highestStat * 0.05); + return baseDamage + trueDamage; + } + return baseDamage; + }, + }); + }, + }), + [moveIdEnum.MAGMA_IMPACT]: new Move({ + id: moveIdEnum.MAGMA_IMPACT, + name: "Magma Impact", + type: pokemonTypes.FIRE, + power: 45, + accuracy: 90, + cooldown: 5, + targetType: targetTypes.ENEMY, + targetPosition: targetPositions.FRONT, + targetPattern: targetPatterns.ALL, + tier: moveTiers.ULTIMATE, + damageType: damageTypes.PHYSICAL, + description: + "The targets are struck with blades of magma. If hit and the target is not a full HP, deals 1.5x damage.", + execute({ source, primaryTarget, allTargets, missedTargets }) { + this.genericDealAllDamage({ + source, + primaryTarget, + allTargets, + missedTargets, + calculateDamageFunction: (args) => { + const { target } = args; + const baseDamage = source.calculateMoveDamage(args); + if (!missedTargets.includes(target) && target.hp < target.maxHp) { + return Math.floor(baseDamage * 1.5); + } + return baseDamage; + }, + }); + }, + }), + [moveIdEnum.FLAME_BALL]: new Move({ + id: moveIdEnum.FLAME_BALL, + name: "Flame Ball", + type: pokemonTypes.FIRE, + power: 60, + accuracy: 90, + cooldown: 3, + targetType: targetTypes.ENEMY, + targetPosition: targetPositions.FRONT, + targetPattern: targetPatterns.SQUARE, + tier: moveTiers.POWER, + damageType: damageTypes.PHYSICAL, + description: + "The user strikes the targets with an exploding fiery ball, heating up its allies. For each hit, boosts the combat readiness of a random Fire or Ground type ally by 15%.", + execute({ battle, source, primaryTarget, allTargets, missedTargets }) { + this.genericDealAllDamage({ + source, + primaryTarget, + allTargets, + missedTargets, + }); + + const sourceTeamPokemons = source.getPartyPokemon(); + const fireGroundAllies = sourceTeamPokemons.filter( + (pokemon) => + pokemon !== source && + pokemon && + !pokemon.isFainted && + (pokemon.hasType(pokemonTypes.FIRE) || + pokemon.hasType(pokemonTypes.GROUND)) + ); + if (fireGroundAllies.length === 0) { + return; + } + const [randomAlly] = drawIterable(fireGroundAllies, 1); + const hitCount = allTargets.reduce( + (count, target) => + !missedTargets.includes(target) ? count + 1 : count, + 0 + ); + if (hitCount > 0) { + battle.addToLog( + `${randomAlly.name} is burning up from the Flame Ball!` + ); + randomAlly.boostCombatReadiness(source, hitCount * 15); + } + }, + }), }); module.exports = { diff --git a/src/battle/engine/Battle.js b/src/battle/engine/Battle.js index f5f32137..c4dbc716 100644 --- a/src/battle/engine/Battle.js +++ b/src/battle/engine/Battle.js @@ -507,6 +507,8 @@ class Battle { return false; } + // TODO: extend/clear weather events? should this be done? + // apply weather this.weather = { weatherId, @@ -530,6 +532,8 @@ class Battle { break; } + this.emitEvent(battleEventEnum.AFTER_WEATHER_SET, {}); // no args because weather can be retrieved from this.weather + return true; } diff --git a/src/battle/engine/BattlePokemon.js b/src/battle/engine/BattlePokemon.js index 47e0a852..9ff94062 100644 --- a/src/battle/engine/BattlePokemon.js +++ b/src/battle/engine/BattlePokemon.js @@ -156,6 +156,14 @@ class BattlePokemon { this.shiny = pokemonData.shiny; } + /** + * @param {PokemonTypeEnum} type + * @returns {boolean} + */ + hasType(type) { + return this.type1 === type || this.type2 === type; + } + /** * @param {Pokemon} pokemonData */ @@ -1386,6 +1394,7 @@ class BattlePokemon { if (!effect.isLegacyEffect) { this.effectIds[effectId].args = + // @ts-ignore effect.effectAdd({ battle: this.battle, source, @@ -1863,8 +1872,16 @@ class BattlePokemon { return { row, col }; } + getParty() { + return this.battle.parties[this.teamName]; + } + + getPartyPokemon() { + return this.getParty().pokemons; + } + getPartyRowColumn() { - const party = this.battle.parties[this.teamName]; + const party = this.getParty(); return { party, ...this.getRowAndColumn() }; } @@ -1922,6 +1939,27 @@ class BattlePokemon { return spe; } + + /** + * @returns {StatArray} + */ + getAllStats() { + return [ + this.hp, + this.atk, + this.getDef(), + this.spa, + this.getSpd(), + this.getSpe(), + ]; + } + + /** + * @returns {StatArray} + */ + getAllBaseStats() { + return [this.maxHp, this.batk, this.bdef, this.bspa, this.bspd, this.bspe]; + } } module.exports = { diff --git a/src/battle/engine/events.js b/src/battle/engine/events.js index fd6895bb..16eca754 100644 --- a/src/battle/engine/events.js +++ b/src/battle/engine/events.js @@ -43,7 +43,7 @@ class BattleEventHandler { } emit(eventName, args) { - const listenerIds = this.eventNames[eventName]; + const listenerIds = [...(this.eventNames[eventName] ?? [])]; // copy, incase listeners are modified in loop if (!listenerIds) { return; } diff --git a/src/battle/types.js b/src/battle/types.js index 46a8e2bb..6f3c96e7 100644 --- a/src/battle/types.js +++ b/src/battle/types.js @@ -2,6 +2,7 @@ * @typedef {import("./engine/Battle").Battle} Battle * @typedef {import("./engine/BattlePokemon").BattlePokemon} BattlePokemon * @typedef {import("./engine/npcs").BattleNPC} BattleNPC + * @typedef {(...args: Parameters) => ReturnType} CalculateMoveDamageImpl */ /** diff --git a/src/config/battleConfig.js b/src/config/battleConfig.js index 705ed92a..fcb5dd83 100644 --- a/src/config/battleConfig.js +++ b/src/config/battleConfig.js @@ -290,6 +290,23 @@ const targetPatterns = Object.freeze({ X: "X-shape", }); +const statToBattleStat = /** @type {const} */ ([ + "hp", + "atk", + "def", + "spa", + "spd", + "spe", +]); +const statToBaseStat = /** @type {const} */ ([ + "maxHp", + "batk", + "bdef", + "bspa", + "bspd", + "bspe", +]); + /** @typedef {Enum} EffectTypeEnum */ const effectTypes = Object.freeze({ BUFF: "Buff", @@ -3077,7 +3094,7 @@ const moveConfig = Object.freeze({ m88: { name: "Rock Throw", type: pokemonTypes.ROCK, - power: 70, + power: 65, accuracy: 70, cooldown: 0, targetType: targetTypes.ENEMY, @@ -16507,4 +16524,6 @@ module.exports = { calculateDamage, abilityConfig, damageTypes, + statToBaseStat, + statToBattleStat, }; diff --git a/src/config/commandConfig.js b/src/config/commandConfig.js index 3211203b..a0c02af2 100644 --- a/src/config/commandConfig.js +++ b/src/config/commandConfig.js @@ -781,6 +781,7 @@ const commandConfigRaw = { "steven", "palmer", "professorWillow", + "butler", ], }, difficulty: { diff --git a/src/config/gachaConfig.js b/src/config/gachaConfig.js index 28d5904a..2b31d36d 100644 --- a/src/config/gachaConfig.js +++ b/src/config/gachaConfig.js @@ -8,6 +8,7 @@ const { } = require("./pokemonConfig"); const { drawIterable } = require("../utils/gachaUtils"); const { getFullUTCDate } = require("../utils/utils"); +const { pokemonIdEnum } = require("../enums/pokemonEnums"); const dailyRewardChances = Object.freeze({ [backpackItems.POKEBALL]: 0.7, @@ -89,6 +90,30 @@ const bannerTypeConfig = Object.freeze({ */ const bannerConfigRaw = [ { + bannerType: bannerTypes.SPECIAL, + name: "[EVENT] Team Aqua Banner", + description: + "Team Aqua is here to conquer the seas! Pull for the limited Aqua Leader Archie's Kyogre and Team Aqua's Sharpedo!", + rateUp: () => ({ + [rarities.LEGENDARY]: [pokemonIdEnum.ARCHIES_KYOGRE], + [rarities.EPIC]: [pokemonIdEnum.AQUAS_SHARPEDO], + }), + image: + "https://raw.githubusercontent.com/ewei068/pokestar/main/media/images/events/pokestar-aqua-magma-banner.png", + }, + { + bannerType: bannerTypes.SPECIAL, + name: "[EVENT] Team Magma Banner", + description: + "Team Magma is here to conquer the land! Pull for the limited Magma Leader Maxie's Groudon and Team Magma's Camerupt!", + rateUp: () => ({ + [rarities.LEGENDARY]: [pokemonIdEnum.MAXIES_GROUDON], + [rarities.EPIC]: [pokemonIdEnum.MAGMAS_CAMERUPT], + }), + image: + "https://raw.githubusercontent.com/ewei068/pokestar/main/media/images/events/pokestar-aqua-magma-banner.png", + }, + /* { bannerType: bannerTypes.SPECIAL, name: "[EVENT] Launch Celebration Re-Run", description: @@ -403,6 +428,7 @@ const bannerConfigRaw = [ bannerType: bannerTypes.STANDARD, name: "Standard", description: "Standard banner with all currently available gacha Pokemon.", + // @ts-ignore rateUp: () => {}, }, ]; diff --git a/src/config/helpConfig.js b/src/config/helpConfig.js index 9a8f7ef8..ae2282ff 100644 --- a/src/config/helpConfig.js +++ b/src/config/helpConfig.js @@ -128,6 +128,22 @@ Pokestar is officially out of Beta, and our support server has hit 100 members! * Shiny Hat Pikachu: https://www.deviantart.com/lukethefoxen/art/Pikachu-with-Ash-s-Hat-923733788 `; +const AQUA_VS_MAGMA_DESCRIPTION = `🌊🔥**Aqua vs Magma**🔥🌊 + +Team Aqua and Team Magma are clashing for control of the climate in Pokestar! + +<:aquakyogre:1325287152979939348> <:magmagroudon:1325287156268404878> **Event Pokemon:** New limited Pokemon with the "Aqua vs Magma" theme have arrived! Use \`/gacha\` to try your luck! + +🌋 **Limited Dungeon:** Stop the Double Crisis in the new limited Sootopolis City dungeon for tons of rewards! Use \`/dungeons\` to challenge it! + +<:acetrainergen4:1326704756172787723> **Limited NPC:** Defeat Butler to free Jirachi from Meta Groudon's control in a limited-time PvE stage for daily Great Balls and additional Raid Passes! Use \`/pve butler\` to challenge him! + +<:385:1132497393431105588> **Jirachi and Raids:** Jirachi has arrived, alongside improvements to raids. For a limited time, the Gen 3 raids and Champion Steven will give improved rewards! Challenge these raids to catch Jirachi! + +🖌️ **Art Credits** +* Event banner backgroud art: https://8pxl.tumblr.com/post/619650615905288192/turbulant +`; + /** * @typedef {{ * name: string, @@ -141,12 +157,18 @@ Pokestar is officially out of Beta, and our support server has hit 100 members! */ const gameEventConfig = [ { + name: "Aqua vs Magma", + description: AQUA_VS_MAGMA_DESCRIPTION, + image: + "https://raw.githubusercontent.com/ewei068/pokestar/main/media/images/events/pokestar-aqua-magma-banner.png", + }, + /* { name: "100 Members + Official Launch", description: HUNDRED_MEMBERS_DESCRIPTION, image: "https://raw.githubusercontent.com/ewei068/pokestar/main/media/images/events/pokestar-launch-banner.png", }, - /* { + { "name": "One Piece", "description": ONE_PIECE_DESCRIPTION, "image": "https://raw.githubusercontent.com/ewei068/pokestar/main/media/images/events/pokestar-op-banner.png" diff --git a/src/config/npcConfig.js b/src/config/npcConfig.js index 0b7ddbd9..359620b4 100644 --- a/src/config/npcConfig.js +++ b/src/config/npcConfig.js @@ -8,6 +8,7 @@ const { getFullUTCDate } = require("../utils/utils"); const { rarities, rarityBins } = require("./pokemonConfig"); const { drawIterable } = require("../utils/gachaUtils"); const { stageNames } = require("./stageConfig"); +const { pokemonIdEnum } = require("../enums/pokemonEnums"); /** @typedef {Enum} NpcEnum */ const npcs = Object.freeze({ @@ -27,6 +28,7 @@ const npcs = Object.freeze({ ACE_TRAINER: "aceTrainer", PALMER: "palmer", PROFESSOR_WILLOW: "professorWillow", + BUTLER: "butler", // STRAW_HATS: "strawHats", // TEAM_ROCKET: "teamRocket", // GOLD_RUSH: "goldRush", @@ -442,7 +444,7 @@ const npcConfig = Object.freeze({ dailyRewards: { backpack: { [backpackCategories.POKEBALLS]: { - [backpackItems.POKEBALL]: 1 * 2, + [backpackItems.POKEBALL]: 1, }, }, }, @@ -456,7 +458,7 @@ const npcConfig = Object.freeze({ dailyRewards: { backpack: { [backpackCategories.POKEBALLS]: { - [backpackItems.POKEBALL]: 1 * 3, + [backpackItems.POKEBALL]: 1, }, }, }, @@ -478,7 +480,7 @@ const npcConfig = Object.freeze({ dailyRewards: { backpack: { [backpackCategories.POKEBALLS]: { - [backpackItems.POKEBALL]: 2 * 2, + [backpackItems.POKEBALL]: 2, }, }, }, @@ -538,7 +540,7 @@ const npcConfig = Object.freeze({ dailyRewards: { backpack: { [backpackCategories.POKEBALLS]: { - [backpackItems.POKEBALL]: 1, + [backpackItems.POKEBALL]: 1 * 2, }, }, }, @@ -552,7 +554,7 @@ const npcConfig = Object.freeze({ dailyRewards: { backpack: { [backpackCategories.POKEBALLS]: { - [backpackItems.POKEBALL]: 2, + [backpackItems.POKEBALL]: 2 * 2, }, }, }, @@ -607,6 +609,58 @@ const npcConfig = Object.freeze({ }, }, }, + [npcs.BUTLER]: { + name: "Butler", + sprite: + "https://archives.bulbagarden.net/media/upload/b/b9/Spr_DP_Ace_Trainer_M_1.png", + emoji: "<:acetrainergen4:1326704756172787723>", + catchphrase: + "With the power of Meta Groudon and Jirachi, I will have my revenge on Team Magma!", + difficulties: { + [difficulties.HARD]: { + minLevel: 65, + maxLevel: 74, + numPokemon: 6, + pokemonIds: [ + pokemonIdEnum.GARDEVOIR, + pokemonIdEnum.MIGHTYENA, + pokemonIdEnum.DUSCLOPS, + pokemonIdEnum.BUTTERFREE, + pokemonIdEnum.ALTARIA, + ], + aceId: pokemonIdEnum.SALAMENCE, + dailyRewards: { + backpack: { + [backpackCategories.POKEBALLS]: { + [backpackItems.GREATBALL]: 1, + }, + }, + }, + }, + [difficulties.VERY_HARD]: { + minLevel: 125, + maxLevel: 144, + numPokemon: 6, + pokemonIds: [ + pokemonIdEnum.GARDEVOIR, + pokemonIdEnum.MIGHTYENA, + pokemonIdEnum.DUSCLOPS, + pokemonIdEnum.BUTTERFREE, + pokemonIdEnum.ALTARIA, + pokemonIdEnum.SALAMENCE, + // TODO: Jirachi + ], + aceId: pokemonIdEnum.META_GROUDON, + dailyRewards: { + backpack: { + [backpackCategories.CONSUMABLES]: { + [backpackItems.RAID_PASS]: 1, + }, + }, + }, + }, + }, + }, /* [npcs.STRAW_HATS]: { name: "Straw Hats", sprite: "https://raw.githubusercontent.com/ewei068/pokestar/main/media/images/sprites/luffy-resized.png", @@ -1028,6 +1082,7 @@ const dungeons = Object.freeze({ SOUL_CAVE: "soulCave", SPIRIT_ALTAR: "spiritAltar", NEW_ISLAND: "newIsland", + SOOTOPOLIS_CITY: "sootopolisCity", // ONIGASHIMA: "onigashima", // BLOODY_SUNDAY: "bloodySunday", }); @@ -2052,6 +2107,253 @@ const dungeonConfig = Object.freeze({ }, }, }, + [dungeons.SOOTOPOLIS_CITY]: { + name: "Sootopolis City: Double Crisis!", + sprite: + "https://pa1.aminoapps.com/5778/fcbf7bc4d36716837e2fb264d879b1fb7883796f_hq.gif", + emoji: "🌋", + description: + "Archie and Maxie have awakened the ancient titans, clashing in Sootopolis city! However, they are not the only ones who have come to stop them...", + bosses: [ + pokemonIdEnum.ARCHIES_KYOGRE, + pokemonIdEnum.MAXIES_GROUDON, + pokemonIdEnum.PALMERS_RAYQUAZA, + ], + difficulties: { + [difficulties.HARD]: { + phases: [ + { + rows: 3, + cols: 5, + pokemons: [ + { + speciesId: pokemonIdEnum.MUK, + level: 100, + position: 1, + }, + { + speciesId: pokemonIdEnum.MUK, + level: 100, + position: 2, + }, + { + speciesId: pokemonIdEnum.MUK, + level: 100, + position: 4, + }, + { + speciesId: pokemonIdEnum.MUK, + level: 100, + position: 5, + }, + { + speciesId: pokemonIdEnum.AQUAS_SHARPEDO, + level: 120, + position: 8, + }, + { + speciesId: pokemonIdEnum.ARCHIES_KYOGRE, + level: 125, + position: 13, + }, + ], + }, + { + rows: 3, + cols: 5, + pokemons: [ + { + speciesId: pokemonIdEnum.MIGHTYENA, + level: 100, + position: 1, + }, + { + speciesId: pokemonIdEnum.MIGHTYENA, + level: 100, + position: 2, + }, + { + speciesId: pokemonIdEnum.MIGHTYENA, + level: 100, + position: 4, + }, + { + speciesId: pokemonIdEnum.MIGHTYENA, + level: 100, + position: 5, + }, + { + speciesId: pokemonIdEnum.MAGMAS_CAMERUPT, + level: 120, + position: 8, + }, + { + speciesId: pokemonIdEnum.MAXIES_GROUDON, + level: 125, + position: 13, + }, + ], + }, + { + rows: 3, + cols: 5, + pokemons: [ + { + speciesId: pokemonIdEnum.DEOXYS, + level: 120, + position: 1, + }, + { + speciesId: pokemonIdEnum.DEOXYS_DEFENSE, + level: 120, + position: 5, + }, + { + speciesId: pokemonIdEnum.DEOXYS_SPEED, + level: 120, + position: 7, + }, + { + speciesId: pokemonIdEnum.DEOXYS_ATTACK, + level: 120, + position: 9, + }, + { + speciesId: pokemonIdEnum.PALMERS_RAYQUAZA, + level: 130, + position: 13, + }, + ], + }, + ], + rewards: { + backpack: { + [backpackCategories.MATERIALS]: { + [backpackItems.KNOWLEDGE_SHARD]: 10, + [backpackItems.EMOTION_SHARD]: 10, + [backpackItems.WILLPOWER_SHARD]: 10, + }, + }, + }, + }, + [difficulties.VERY_HARD]: { + phases: [ + { + rows: 3, + cols: 5, + pokemons: [ + { + speciesId: pokemonIdEnum.MUK, + level: 140, + position: 1, + }, + { + speciesId: pokemonIdEnum.MUK, + level: 140, + position: 2, + }, + { + speciesId: pokemonIdEnum.MUK, + level: 140, + position: 4, + }, + { + speciesId: pokemonIdEnum.MUK, + level: 140, + position: 5, + }, + { + speciesId: pokemonIdEnum.AQUAS_SHARPEDO, + level: 145, + position: 8, + }, + { + speciesId: pokemonIdEnum.ARCHIES_KYOGRE, + level: 150, + position: 13, + }, + ], + }, + { + rows: 3, + cols: 5, + pokemons: [ + { + speciesId: pokemonIdEnum.MIGHTYENA, + level: 140, + position: 1, + }, + { + speciesId: pokemonIdEnum.MIGHTYENA, + level: 140, + position: 2, + }, + { + speciesId: pokemonIdEnum.MIGHTYENA, + level: 140, + position: 4, + }, + { + speciesId: pokemonIdEnum.MIGHTYENA, + level: 140, + position: 5, + }, + { + speciesId: pokemonIdEnum.MAGMAS_CAMERUPT, + level: 145, + position: 8, + }, + { + speciesId: pokemonIdEnum.MAXIES_GROUDON, + level: 150, + position: 13, + }, + ], + }, + { + rows: 3, + cols: 5, + pokemons: [ + { + speciesId: pokemonIdEnum.DEOXYS, + level: 150, + position: 1, + }, + { + speciesId: pokemonIdEnum.DEOXYS_DEFENSE, + level: 150, + position: 5, + }, + { + speciesId: pokemonIdEnum.DEOXYS_SPEED, + level: 150, + position: 7, + }, + { + speciesId: pokemonIdEnum.DEOXYS_ATTACK, + level: 150, + position: 9, + }, + { + speciesId: pokemonIdEnum.PALMERS_RAYQUAZA, + level: 169, + position: 13, + }, + ], + }, + ], + rewards: { + backpack: { + [backpackCategories.MATERIALS]: { + [backpackItems.KNOWLEDGE_SHARD]: 10, + [backpackItems.EMOTION_SHARD]: 10, + [backpackItems.WILLPOWER_SHARD]: 10, + }, + }, + }, + }, + }, + }, /* [dungeons.ONIGASHIMA]: { name: "Onigashima", sprite: "https://i.pinimg.com/736x/61/75/09/61750983442c10bc384f5909f1c7558a.jpg", diff --git a/src/config/pokemonConfig.js b/src/config/pokemonConfig.js index 40edd9a0..c79a8a33 100644 --- a/src/config/pokemonConfig.js +++ b/src/config/pokemonConfig.js @@ -1,4 +1,5 @@ -const { moveIdEnum } = require("../enums/battleEnums"); +const { moveIdEnum, abilityIdEnum } = require("../enums/battleEnums"); +const { pokemonIdEnum } = require("../enums/pokemonEnums"); /** @typedef {Enum} PokemonTypeEnum */ const types = Object.freeze({ @@ -5124,6 +5125,7 @@ const pokemonConfigRaw = { "248-1", "289-1", "319-1", + pokemonIdEnum.LITTENYAN, ], }, }, @@ -6379,6 +6381,27 @@ const pokemonConfigRaw = { battleEligible: true, rarity: rarities.EPIC, growthRate: growthRates.MEDIUMFAST, + noGacha: true, + }, + [pokemonIdEnum.AQUAS_SHARPEDO]: { + name: "Aqua's Sharpedo", + emoji: "<:aquasharpedo:1325287154125111420>", + description: + "A Sharpedo controlled by Team Aqua. It is said to be able to cause tsunamis where it swims.", + type: [types.WATER, types.DARK], + baseStats: [80, 100, 50, 145, 60, 115], + sprite: + "https://raw.githubusercontent.com/ewei068/pokestar/main/media/images/sprites/aqua-sharpedo-resized.gif", + shinySprite: + "https://raw.githubusercontent.com/ewei068/pokestar/main/media/images/sprites/aqua-sharpedo-shiny-resized.gif", + abilities: { + [abilityIdEnum.JET_SPEED]: 1, + }, + moveIds: ["m246", "m57", "m399", "m212"], + battleEligible: true, + rarity: rarities.EPIC, + growthRate: growthRates.MEDIUMFAST, + noGacha: true, }, 320: { name: "Wailmer", @@ -6428,6 +6451,74 @@ const pokemonConfigRaw = { rarity: rarities.EPIC, growthRate: growthRates.MEDIUMSLOW, }, + [pokemonIdEnum.NUMEL]: { + name: "Numel", + emoji: "<:322:1132496591115276389>", + description: + "Numel is extremely dull witted - it doesn't notice being hit. However, it can't stand hunger for even a second. This Pokémon's body is a seething cauldron of boiling magma.", + type: [types.FIRE, types.GROUND], + baseStats: [60, 60, 40, 65, 45, 35], + sprite: + "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/322.png", + shinySprite: + "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/shiny/322.png", + evolution: [ + { + level: 33, + id: "323", + }, + ], + abilities: { + 12: 0.45, + 86: 0.45, + 20: 0.1, + }, + moveIds: ["m33", "m52", "m281", "m414"], + battleEligible: true, + rarity: rarities.RARE, + growthRate: growthRates.MEDIUMFAST, + }, + [pokemonIdEnum.CAMERUPT]: { + name: "Camerupt", + emoji: "<:323:1132496592709111869>", + description: + "Camerupt has a volcano inside its body. Magma of 18,000 degrees Fahrenheit courses through its body. Occasionally, the humps on this Pokémon's back erupt, spewing the superheated magma.", + type: [types.FIRE, types.GROUND], + baseStats: [70, 100, 70, 105, 75, 40], + sprite: + "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/323.png", + shinySprite: + "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/shiny/323.png", + abilities: { + 40: 0.45, + 116: 0.45, + 83: 0.1, + }, + moveIds: ["m52", "m281", "m414", "m284"], + battleEligible: true, + rarity: rarities.EPIC, + growthRate: growthRates.MEDIUMFAST, + }, + [pokemonIdEnum.MAGMAS_CAMERUPT]: { + name: "Magma's Camerupt", + emoji: "<:magmacamerupt:1325287155198722160>", + description: + "A Camerupt controlled by Team Magma. It is said to be able to cause volcanic eruptions with a single stomp.", + type: [types.FIRE, types.GROUND], + baseStats: [70, 135, 90, 90, 95, 70], + sprite: + "https://raw.githubusercontent.com/ewei068/pokestar/main/media/images/sprites/magma-camerupt-resized.gif", + shinySprite: + "https://raw.githubusercontent.com/ewei068/pokestar/main/media/images/sprites/magma-camerupt-shiny-resized.gif", + abilities: { + [abilityIdEnum.BURNING_DRAFT]: 1, + }, + moveIds: ["m98", "m523", moveIdEnum.FLAME_BALL, "m157"], + battleEligible: true, + rarity: rarities.EPIC, + growthRate: growthRates.MEDIUMFAST, + noGacha: true, + }, 324: { name: "Torkoal", emoji: "<:324:1132496594567188584>", @@ -7132,6 +7223,26 @@ const pokemonConfigRaw = { rarity: rarities.LEGENDARY, growthRate: growthRates.SLOW, }, + [pokemonIdEnum.ARCHIES_KYOGRE]: { + name: "Archie's Kyogre", + emoji: "<:aquakyogre:1325287152979939348>", + description: + "A Kyogre under the control of Archie, the leader of Team Aqua. It summons heavy rain to flood the world.", + type: [types.WATER, types.DARK], + baseStats: [110, 80, 100, 145, 140, 85], + sprite: + "https://raw.githubusercontent.com/ewei068/pokestar/main/media/images/sprites/aqua-kyogre-resized.gif", + shinySprite: + "https://raw.githubusercontent.com/ewei068/pokestar/main/media/images/sprites/aqua-kyogre-shiny-resized.gif", + abilities: { + [abilityIdEnum.AQUA_POWER]: 1, + }, + moveIds: ["m239", "m347", "m399", moveIdEnum.AQUA_IMPACT], + battleEligible: true, + rarity: rarities.LEGENDARY, + growthRate: growthRates.SLOW, + noGacha: true, + }, 383: { name: "Groudon", emoji: "<:383:1132497390079852674>", @@ -7151,6 +7262,26 @@ const pokemonConfigRaw = { rarity: rarities.LEGENDARY, growthRate: growthRates.SLOW, }, + [pokemonIdEnum.MAXIES_GROUDON]: { + name: "Maxie's Groudon", + emoji: "<:magmagroudon:1325287156268404878>", + description: + "A Groudon under the control of Maxie, the leader of Team Magma. It uses its power to expand the land.", + type: [types.GROUND, types.FIRE], + baseStats: [99, 166, 130, 90, 90, 85], + sprite: + "https://raw.githubusercontent.com/ewei068/pokestar/main/media/images/sprites/magma-groudon-resized.gif", + shinySprite: + "https://raw.githubusercontent.com/ewei068/pokestar/main/media/images/sprites/magma-groudon-shiny-resized.gif", + abilities: { + [abilityIdEnum.MAGMA_POWER]: 1, + }, + moveIds: ["m479", "m14", "m523", moveIdEnum.MAGMA_IMPACT], + battleEligible: true, + rarity: rarities.LEGENDARY, + growthRate: growthRates.SLOW, + noGacha: true, + }, 384: { name: "Rayquaza", emoji: "<:384:1132497391535272016>", @@ -7271,6 +7402,7 @@ const pokemonConfigRaw = { battleEligible: true, rarity: rarities.EPIC, growthRate: growthRates.SLOW, + noGacha: true, }, "828-1": { name: "Scammer Thievul", @@ -7512,6 +7644,26 @@ const pokemonConfigRaw = { growthRate: growthRates.SLOW, unobtainable: true, }, + [pokemonIdEnum.META_GROUDON]: { + name: "Meta Groudon", + emoji: "<:magmagroudon:1325287156268404878>", + description: + "Groudon brought back to life from an ancient fossil. A failed experiment rendered it an abomination, consuming humans and Pokemon alike.", + type: [types.GROUND, types.STEEL], + baseStats: [100, 200, 200, 200, 100, 70], + sprite: + "https://raw.githubusercontent.com/ewei068/pokestar/main/media/images/sprites/magma-groudon-resized.gif", + shinySprite: + "https://raw.githubusercontent.com/ewei068/pokestar/main/media/images/sprites/magma-groudon-shiny-resized.gif", + abilities: { + 70: 1, + }, + moveIds: ["m53", "m202", "m76", "m231", "m619"], + battleEligible: true, + rarity: rarities.MYTHICAL, + growthRate: growthRates.SLOW, + unobtainable: true, + }, 20384: { name: "Palmer's Rayquaza", emoji: "<:384:1132497391535272016>", diff --git a/src/config/types.js b/src/config/types.js index d427a2a2..2ccd3750 100644 --- a/src/config/types.js +++ b/src/config/types.js @@ -2,6 +2,7 @@ /** @typedef {import("./pokemonConfig").GrowthRateEnum} GrowthRateEnum */ /** @typedef {import("./pokemonConfig").NatureEnum} NatureEnum */ /** @typedef {import("./pokemonConfig").RarityEnum} RarityEnum */ +/** @typedef {import("./pokemonConfig").StatEnum} StatEnum */ /** @typedef {import("./equipmentConfig").EquipmentModifierSlotEnum} EquipmentModifierSlotEnum */ /** @typedef {import("./equipmentConfig").EquipmentModifierTypeEnum} EquipmentModifierTypeEnum */ /** @typedef {import("./equipmentConfig").EquipmentTypeEnum} EquipmentTypeEnum */ diff --git a/src/enums/battleEnums.js b/src/enums/battleEnums.js index 2bff3135..666d9121 100644 --- a/src/enums/battleEnums.js +++ b/src/enums/battleEnums.js @@ -8,6 +8,7 @@ const effectIdEnum = Object.freeze({ ATK_UP: "atkUp", SHIELD: "shield", DEBUFF_IMMUNITY: "debuffImmunity", + AQUA_BLESSING: "aquaBlessing", }); /** @@ -18,7 +19,11 @@ const effectIdEnum = Object.freeze({ const moveIdEnum = Object.freeze({ TEST_MOVE: "999", TEST_MOVE2: "998", + FIRE_PUNCH: "m7", VINE_WHIP: "m22", + AQUA_IMPACT: "m618-1", + MAGMA_IMPACT: "m619-1", + FLAME_BALL: "m780-1", }); /** @@ -28,7 +33,12 @@ const moveIdEnum = Object.freeze({ */ const abilityIdEnum = Object.freeze({ TEST_ABILITY: "testAbility", + AQUA_POWER: "2-1", + MAGMA_POWER: "70-1", + ANGER_POINT: "83", REGENERATOR: "144", + BURNING_DRAFT: "20018", + JET_SPEED: "20019", }); /** @typedef {Enum} BattleEventEnum */ @@ -57,6 +67,7 @@ const battleEventEnum = Object.freeze({ CALCULATE_TYPE_MULTIPLIER: "calculateTypeMultiplier", CALCULATE_MISS: "calculateMiss", GET_ELIGIBLE_TARGETS: "getEligibleTargets", + AFTER_WEATHER_SET: "afterWeatherSet", }); /** @@ -71,7 +82,7 @@ const battleEventEnum = Object.freeze({ * [battleEventEnum.BEFORE_DAMAGE_DEALT]: any, * [battleEventEnum.AFTER_DAMAGE_DEALT]: any, * [battleEventEnum.BEFORE_DAMAGE_TAKEN]: any, - * [battleEventEnum.AFTER_DAMAGE_TAKEN]: any, + * [battleEventEnum.AFTER_DAMAGE_TAKEN]: { target: BattlePokemon, source: BattlePokemon, damage: number, damageInfo: any }, * [battleEventEnum.BEFORE_CR_GAINED]: any, * [battleEventEnum.AFTER_CR_GAINED]: any, * [battleEventEnum.BEFORE_EFFECT_ADD]: { target: BattlePokemon, source: BattlePokemon, effectId: EffectIdEnum, duration: number, initialArgs: any, canAdd: boolean }, @@ -86,6 +97,7 @@ const battleEventEnum = Object.freeze({ * [battleEventEnum.CALCULATE_TYPE_MULTIPLIER]: any, * [battleEventEnum.CALCULATE_MISS]: any, * [battleEventEnum.GET_ELIGIBLE_TARGETS]: any, + * [battleEventEnum.AFTER_WEATHER_SET]: any, * }[K]} BattleEventArgsWithoutEventName */ diff --git a/src/enums/pokemonEnums.js b/src/enums/pokemonEnums.js index 77f920a8..63a22f47 100644 --- a/src/enums/pokemonEnums.js +++ b/src/enums/pokemonEnums.js @@ -230,8 +230,12 @@ const pokemonIdEnum = Object.freeze({ MANECTRIC: "310", CARVANHA: "318", SHARPEDO: "319", + AQUAS_SHARPEDO: "319-2", WAILMER: "320", WAILORD: "321", + NUMEL: "322", + CAMERUPT: "323", + MAGMAS_CAMERUPT: "323-1", TORKOAL: "324", TRAPINCH: "328", VIBRAVA: "329", @@ -305,8 +309,11 @@ const pokemonIdEnum = Object.freeze({ TEMPLE_GUARDIAN_ARTICUNO: "20144", SPIRIT_PRIEST_DRAGONITE: "20149", SPIRIT_PRIEST_MEWTWO: "20150", + META_GROUDON: "20383", PALMERS_RAYQUAZA: "20384", WILLOWS_MELMETAL: "20809", + ARCHIES_KYOGRE: "382-1", + MAXIES_GROUDON: "383-1", }); module.exports = { pokemonIdEnum };