[Move] Implements Conversion 2 (#2943)
* Creates function to get type resistances, implements conversion 2 * Removes unimplemented tag, adds condition for move history to exist * Cleans up type selection, creates i18n entries for typeChanged * Uses typeChanged i18n in Conversion move * More detailed docs, early return with stellar/unknown type * Adds note that it wont track type-changing moves properly * Rephrases doc description, adds partial since it can't track type-changing moves * Updates localization, removes typeChanged entry to use move-trigger entry * Missed locale de entry in last commit * Adds comment for reason of .partial() * Fixes localization error due to revert, removes improper merge conflict from prior commit
This commit is contained in:
parent
21f2e6981c
commit
b215de1628
|
@ -5,7 +5,7 @@ import { EncoreTag, HelpingHandTag, SemiInvulnerableTag, TypeBoostTag } from "./
|
|||
import { getPokemonMessage, getPokemonNameWithAffix } from "../messages";
|
||||
import Pokemon, { AttackMoveResult, EnemyPokemon, HitResult, MoveResult, PlayerPokemon, PokemonMove, TurnMove } from "../field/pokemon";
|
||||
import { StatusEffect, getStatusEffectHealText, isNonVolatileStatusEffect, getNonVolatileStatusEffects} from "./status-effect";
|
||||
import { Type } from "./type";
|
||||
import { getTypeResistances, Type } from "./type";
|
||||
import { Constructor } from "#app/utils";
|
||||
import * as Utils from "../utils";
|
||||
import { WeatherType } from "./weather";
|
||||
|
@ -4804,10 +4804,8 @@ export class FirstMoveTypeAttr extends MoveEffectAttr {
|
|||
}
|
||||
|
||||
const firstMoveType = target.getMoveset()[0].getMove().type;
|
||||
|
||||
user.summonData.types = [ firstMoveType ];
|
||||
|
||||
user.scene.queueMessage(getPokemonMessage(user, ` transformed\ninto to the ${Utils.toReadableString(Type[firstMoveType])} type!`));
|
||||
user.scene.queueMessage(i18next.t("battle:transformedIntoType", {pokemonName: getPokemonNameWithAffix(user), type: Utils.toReadableString(Type[firstMoveType])}));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -5651,6 +5649,62 @@ export class hitsSameTypeAttr extends VariableMoveTypeMultiplierAttr {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attribute used for Conversion 2, to convert the user's type to a random type that resists the target's last used move.
|
||||
* Fails if the user already has ALL types that resist the target's last used move.
|
||||
* Fails if the opponent has not used a move yet
|
||||
* Fails if the type is unknown or stellar
|
||||
*
|
||||
* TODO:
|
||||
* If a move has its type changed (e.g. {@linkcode Moves.HIDDEN_POWER}), it will check the new type.
|
||||
*/
|
||||
export class ResistLastMoveTypeAttr extends MoveEffectAttr {
|
||||
constructor() {
|
||||
super(true);
|
||||
}
|
||||
/**
|
||||
* User changes its type to a random type that resists the target's last used move
|
||||
* @param {Pokemon} user Pokemon that used the move and will change types
|
||||
* @param {Pokemon} target Opposing pokemon that recently used a move
|
||||
* @param {Move} move Move being used
|
||||
* @param {any[]} args Unused
|
||||
* @returns {boolean} true if the function succeeds
|
||||
*/
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
if (!super.apply(user, target, move, args)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const [targetMove] = target.getLastXMoves(1); // target's most recent move
|
||||
if (!targetMove) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const moveData = allMoves[targetMove.move];
|
||||
if (moveData.type === Type.STELLAR || moveData.type === Type.UNKNOWN) {
|
||||
return false;
|
||||
}
|
||||
const userTypes = user.getTypes();
|
||||
const validTypes = getTypeResistances(moveData.type).filter(t => !userTypes.includes(t)); // valid types are ones that are not already the user's types
|
||||
if (!validTypes.length) {
|
||||
return false;
|
||||
}
|
||||
const type = validTypes[user.randSeedInt(validTypes.length)];
|
||||
user.summonData.types = [ type ];
|
||||
user.scene.queueMessage(i18next.t("battle:transformedIntoType", {pokemonName: getPokemonNameWithAffix(user), type: Utils.toReadableString(Type[type])}));
|
||||
user.updateInfo();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
getCondition(): MoveConditionFunc {
|
||||
return (user, target, move) => {
|
||||
const moveHistory = target.getLastXMoves();
|
||||
return !!moveHistory.length;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const unknownTypeCondition: MoveConditionFunc = (user, target, move) => !user.getTypes().includes(Type.UNKNOWN);
|
||||
|
||||
export type MoveTargetSet = {
|
||||
|
@ -6198,7 +6252,8 @@ export function initMoves() {
|
|||
new AttackMove(Moves.FLAIL, Type.NORMAL, MoveCategory.PHYSICAL, -1, 100, 15, -1, 0, 2)
|
||||
.attr(LowHpPowerAttr),
|
||||
new StatusMove(Moves.CONVERSION_2, Type.NORMAL, -1, 30, -1, 0, 2)
|
||||
.unimplemented(),
|
||||
.attr(ResistLastMoveTypeAttr)
|
||||
.partial(), // Checks the move's original typing and not if its type is changed through some other means
|
||||
new AttackMove(Moves.AEROBLAST, Type.FLYING, MoveCategory.SPECIAL, 100, 95, 5, -1, 0, 2)
|
||||
.attr(HighCritAttr),
|
||||
new StatusMove(Moves.COTTON_SPORE, Type.GRASS, 100, 40, -1, 0, 2)
|
||||
|
|
|
@ -501,6 +501,55 @@ export function getTypeDamageMultiplier(attackType: integer, defType: integer):
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the types resisting a given type
|
||||
* @returns An array populated with Types, or an empty array if no resistances exist (Unknown or Stellar type)
|
||||
*/
|
||||
export function getTypeResistances(type: integer): Type[] {
|
||||
switch (type) {
|
||||
case Type.NORMAL:
|
||||
return [Type.ROCK, Type.STEEL, Type.GHOST];
|
||||
case Type.FIGHTING:
|
||||
return [Type.FLYING, Type.POISON, Type.BUG, Type.PSYCHIC, Type.FAIRY, Type.GHOST];
|
||||
case Type.FLYING:
|
||||
return [Type.ROCK, Type.ELECTRIC, Type.STEEL];
|
||||
case Type.POISON:
|
||||
return [Type.POISON, Type.GROUND, Type.ROCK, Type.GHOST, Type.STEEL];
|
||||
case Type.GROUND:
|
||||
return [Type.BUG, Type.GRASS, Type.FLYING];
|
||||
case Type.ROCK:
|
||||
return [Type.FIGHTING, Type.GROUND, Type.STEEL];
|
||||
case Type.BUG:
|
||||
return [Type.FIGHTING, Type.FLYING, Type.POISON, Type.GHOST, Type.STEEL, Type.FIRE, Type.FAIRY];
|
||||
case Type.GHOST:
|
||||
return [Type.DARK, Type.NORMAL];
|
||||
case Type.STEEL:
|
||||
return [Type.STEEL, Type.FIRE, Type.WATER, Type.ELECTRIC];
|
||||
case Type.FIRE:
|
||||
return [Type.ROCK, Type.FIRE, Type.WATER, Type.DRAGON];
|
||||
case Type.WATER:
|
||||
return [Type.WATER, Type.GRASS, Type.DRAGON];
|
||||
case Type.GRASS:
|
||||
return [Type.FLYING, Type.POISON, Type.BUG, Type.STEEL, Type.FIRE, Type.GRASS, Type.DRAGON];
|
||||
case Type.ELECTRIC:
|
||||
return [Type.GRASS, Type.ELECTRIC, Type.DRAGON, Type.GROUND];
|
||||
case Type.PSYCHIC:
|
||||
return [Type.STEEL, Type.PSYCHIC];
|
||||
case Type.ICE:
|
||||
return [Type.STEEL, Type.FIRE, Type.WATER, Type.ICE];
|
||||
case Type.DRAGON:
|
||||
return [Type.STEEL, Type.FAIRY];
|
||||
case Type.DARK:
|
||||
return [Type.FIGHTING, Type.DARK, Type.FAIRY];
|
||||
case Type.FAIRY:
|
||||
return [Type.POISON, Type.STEEL, Type.FIRE];
|
||||
case Type.UNKNOWN:
|
||||
case Type.STELLAR:
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the color corresponding to a specific damage multiplier
|
||||
* @returns A color or undefined if the default color should be used
|
||||
|
|
|
@ -89,6 +89,7 @@ export const battle: SimpleTranslationEntries = {
|
|||
"statSeverelyFell_other": "{{stats}} von {{pokemonNameWithAffix}} sinken drastisch!",
|
||||
"statWontGoAnyLower_one": "{{stats}} von {{pokemonNameWithAffix}} kann nicht weiter sinken!",
|
||||
"statWontGoAnyLower_other": "{{stats}} von {{pokemonNameWithAffix}} können nicht weiter sinken!",
|
||||
"transformedIntoType": "{{pokemonName}} transformed\ninto the {{type}} type!",
|
||||
"ppReduced": "{{moveName}} von {{targetName}} wird um {{reduction}} AP reduziert!",
|
||||
"retryBattle": "Möchtest du vom Beginn des Kampfes neustarten?",
|
||||
"unlockedSomething": "{{unlockedThing}} wurde freigeschaltet.",
|
||||
|
|
|
@ -89,6 +89,7 @@ export const battle: SimpleTranslationEntries = {
|
|||
"statSeverelyFell_other": "{{pokemonNameWithAffix}}'s {{stats}} severely fell!",
|
||||
"statWontGoAnyLower_one": "{{pokemonNameWithAffix}}'s {{stats}} won't go any lower!",
|
||||
"statWontGoAnyLower_other": "{{pokemonNameWithAffix}}'s {{stats}} won't go any lower!",
|
||||
"transformedIntoType": "{{pokemonName}} transformed\ninto the {{type}} type!",
|
||||
"retryBattle": "Would you like to retry from the start of the battle?",
|
||||
"unlockedSomething": "{{unlockedThing}}\nhas been unlocked.",
|
||||
"congratulations": "Congratulations!",
|
||||
|
|
|
@ -89,6 +89,7 @@ export const battle: SimpleTranslationEntries = {
|
|||
"statSeverelyFell_other": "¡{{stats}} de\n{{pokemonNameWithAffix}} han bajado muchísimo!",
|
||||
"statWontGoAnyLower_one": "¡El {{stats}} de {{pokemonNameWithAffix}} no puede bajar más!",
|
||||
"statWontGoAnyLower_other": "¡{{stats}} de\n{{pokemonNameWithAffix}} no pueden bajar más!",
|
||||
"transformedIntoType": "{{pokemonName}} transformed\ninto the {{type}} type!",
|
||||
"retryBattle": "Would you like to retry from the start of the battle?",
|
||||
"unlockedSomething": "{{unlockedThing}}\nhas been unlocked.",
|
||||
"congratulations": "Congratulations!",
|
||||
|
|
|
@ -89,6 +89,7 @@ export const battle: SimpleTranslationEntries = {
|
|||
"statSeverelyFell_other": "{{stats}} de {{pokemonNameWithAffix}}\nbaissent énormément !",
|
||||
"statWontGoAnyLower_one": "{{stats}} de {{pokemonNameWithAffix}}\nne peut plus baisser !",
|
||||
"statWontGoAnyLower_other": "{{stats}} de {{pokemonNameWithAffix}}\nne peuvent plus baisser !",
|
||||
"transformedIntoType": "{{pokemonName}} transformed\ninto the {{type}} type!",
|
||||
"ppReduced": "Les PP de la capacité {{moveName}}\nde {{targetName}} baissent de {{reduction}} !",
|
||||
"retryBattle": "Voulez-vous réessayer depuis le début du combat ?",
|
||||
"unlockedSomething": "{{unlockedThing}}\na été débloqué.",
|
||||
|
|
|
@ -89,6 +89,7 @@ export const battle: SimpleTranslationEntries = {
|
|||
"statSeverelyFell_other": "{{pokemonNameWithAffix}}'s {{stats}} severely fell!",
|
||||
"statWontGoAnyLower_one": "{{pokemonNameWithAffix}}'s {{stats}} non può diminuire più di così!",
|
||||
"statWontGoAnyLower_other": "{{pokemonNameWithAffix}}'s {{stats}} won't go any lower!",
|
||||
"transformedIntoType": "{{pokemonName}} transformed\ninto the {{type}} type!",
|
||||
"retryBattle": "Vuoi riprovare dall'inizio della lotta?",
|
||||
"unlockedSomething": "{{unlockedThing}}\nè stato/a sbloccato/a.",
|
||||
"congratulations": "Congratulazioni!",
|
||||
|
|
|
@ -89,6 +89,7 @@ export const battle: SimpleTranslationEntries = {
|
|||
"statSeverelyFell_other": "{{pokemonNameWithAffix}}의\n{{stats}}[[가]] 매우 크게 떨어졌다!",
|
||||
"statWontGoAnyLower_one": "{{pokemonNameWithAffix}}의\n{{stats}}[[는]] 더 떨어지지 않는다!",
|
||||
"statWontGoAnyLower_other": "{{pokemonNameWithAffix}}의\n{{stats}}[[는]] 더 떨어지지 않는다!",
|
||||
"transformedIntoType": "{{pokemonName}} transformed\ninto the {{type}} type!",
|
||||
"retryBattle": "이 배틀의 처음부터 재도전하시겠습니까?",
|
||||
"unlockedSomething": "{{unlockedThing}}[[가]]\n해금되었다.",
|
||||
"congratulations": "축하합니다!",
|
||||
|
|
|
@ -89,6 +89,7 @@ export const battle: SimpleTranslationEntries = {
|
|||
"statSeverelyFell_other": "{{stats}} de {{pokemonNameWithAffix}} diminuíram severamente!",
|
||||
"statWontGoAnyLower_one": "{{stats}} de {{pokemonNameWithAffix}} não vai mais diminuir!",
|
||||
"statWontGoAnyLower_other": "{{stats}} de {{pokemonNameWithAffix}} não vão mais diminuir!",
|
||||
"transformedIntoType": "{{pokemonName}} transformed\ninto the {{type}} type!",
|
||||
"ppReduced": "O PP do movimento {{moveName}} de\n{{targetName}} foi reduzido em {{reduction}}!",
|
||||
"retryBattle": "Você gostaria de tentar novamente desde o início da batalha?",
|
||||
"unlockedSomething": "{{unlockedThing}}\nfoi desbloqueado.",
|
||||
|
|
|
@ -81,6 +81,7 @@ export const battle: SimpleTranslationEntries = {
|
|||
"statHarshlyFell_other": "{{pokemonNameWithAffix}}的 {{stats}}大幅降低了!",
|
||||
"statSeverelyFell_other": "{{pokemonNameWithAffix}}的 {{stats}}极大幅降低了!",
|
||||
"statWontGoAnyLower_other": "{{pokemonNameWithAffix}}的 {{stats}}已经无法再降低了!",
|
||||
"transformedIntoType": "{{pokemonName}} transformed\ninto the {{type}} type!",
|
||||
"ppReduced": "降低了{{targetName}}的\n{{moveName}}的PP{{reduction}}点!",
|
||||
"retryBattle": "你要从对战开始时重试么?",
|
||||
"unlockedSomething": "{{unlockedThing}}\n已解锁。",
|
||||
|
|
|
@ -78,6 +78,7 @@ export const battle: SimpleTranslationEntries = {
|
|||
"statHarshlyFell_other": "{{pokemonNameWithAffix}}'s {{stats}} harshly fell!",
|
||||
"statSeverelyFell_other": "{{pokemonNameWithAffix}}'s {{stats}} severely fell!",
|
||||
"statWontGoAnyLower_other": "{{pokemonNameWithAffix}}'s {{stats}} won't go any lower!",
|
||||
"transformedIntoType": "{{pokemonName}} transformed\ninto the {{type}} type!",
|
||||
"ppReduced": "降低了 {{targetName}} 的\n{{moveName}} 的PP{{reduction}}點!",
|
||||
"retryBattle": "Would you like to retry from the start of the battle?",
|
||||
"unlockedSomething": "{{unlockedThing}}\nhas been unlocked.",
|
||||
|
|
Loading…
Reference in New Issue