mirror of
https://github.com/smogon/pokemon-showdown.git
synced 2026-04-25 07:22:09 -05:00
Let's Go: Implement itemless megas (#10212)
This commit is contained in:
parent
e34d184c2b
commit
76c2e598c6
|
|
@ -4,8 +4,71 @@ export const Scripts: ModdedBattleScriptsData = {
|
|||
this.modData('Abilities', 'noability').isNonstandard = null;
|
||||
for (const i in this.data.Pokedex) {
|
||||
this.modData('Pokedex', i).abilities = {0: 'No Ability'};
|
||||
delete this.modData('Pokedex', i).requiredItem;
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
canMegaEvo(pokemon) {
|
||||
const species = pokemon.baseSpecies;
|
||||
const altForme = this.dex.species.get(species.otherFormes?.find(f => f.endsWith('-Mega')));
|
||||
if (
|
||||
altForme.exists && !this.battle.ruleTable.check(`pokemon:${altForme.id}`) &&
|
||||
!this.battle.ruleTable.check('pokemontag:mega')
|
||||
) {
|
||||
return altForme.name;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
canMegaEvoX(pokemon) {
|
||||
const species = pokemon.baseSpecies;
|
||||
const altForme = this.dex.species.get(species.otherFormes?.find(f => f.endsWith('-Mega-X')));
|
||||
if (
|
||||
altForme.exists && !this.battle.ruleTable.check(`pokemon:${altForme.id}`) &&
|
||||
!this.battle.ruleTable.check('pokemontag:mega')
|
||||
) {
|
||||
return altForme.name;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
canMegaEvoY(pokemon) {
|
||||
const species = pokemon.baseSpecies;
|
||||
const altForme = this.dex.species.get(species.otherFormes?.find(f => f.endsWith('-Mega-Y')));
|
||||
if (
|
||||
altForme.exists && !this.battle.ruleTable.check(`pokemon:${altForme.id}`) &&
|
||||
!this.battle.ruleTable.check('pokemontag:mega')
|
||||
) {
|
||||
return altForme.name;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
runMegaEvo(pokemon) {
|
||||
const speciesid = pokemon.canMegaEvo || pokemon.canMegaEvoX || pokemon.canMegaEvoY;
|
||||
if (!speciesid) return false;
|
||||
|
||||
pokemon.formeChange(speciesid, null, true);
|
||||
this.battle.add('-mega', pokemon, this.dex.species.get(speciesid).baseSpecies);
|
||||
|
||||
// Limit one mega evolution
|
||||
for (const ally of pokemon.side.pokemon) {
|
||||
ally.canMegaEvo = null;
|
||||
ally.canMegaEvoX = null;
|
||||
ally.canMegaEvoY = null;
|
||||
}
|
||||
|
||||
this.battle.runEvent('AfterMega', pokemon);
|
||||
return true;
|
||||
},
|
||||
runMegaEvoX(pokemon) {
|
||||
if (!pokemon.canMegaEvoX) return false;
|
||||
pokemon.canMegaEvoY = null;
|
||||
return this.runMegaEvo(pokemon);
|
||||
},
|
||||
runMegaEvoY(pokemon) {
|
||||
if (!pokemon.canMegaEvoY) return false;
|
||||
pokemon.canMegaEvoX = null;
|
||||
return this.runMegaEvo(pokemon);
|
||||
},
|
||||
},
|
||||
/**
|
||||
* Given a table of base stats and a pokemon set, return the actual stats.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1896,6 +1896,12 @@ export class BattleActions {
|
|||
return true;
|
||||
}
|
||||
|
||||
// Let's Go
|
||||
canMegaEvoX?: (this: BattleActions, pokemon: Pokemon) => string | null;
|
||||
canMegaEvoY?: (this: BattleActions, pokemon: Pokemon) => string | null;
|
||||
runMegaEvoX?: (this: BattleActions, pokemon: Pokemon) => boolean;
|
||||
runMegaEvoY?: (this: BattleActions, pokemon: Pokemon) => boolean;
|
||||
|
||||
canTerastallize(pokemon: Pokemon) {
|
||||
if (pokemon.getItem().zMove || pokemon.canMegaEvo || this.dex.gen !== 9) {
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ export interface FieldAction {
|
|||
/** A generic action done by a single pokemon */
|
||||
export interface PokemonAction {
|
||||
/** action type */
|
||||
choice: 'megaEvo' | 'shift' | 'runPrimal' | 'runSwitch' | 'event' | 'runUnnerve' | 'runDynamax' | 'terastallize';
|
||||
choice: 'megaEvo' | 'megaEvoX' | 'megaEvoY' | 'shift' | 'runPrimal' | 'runSwitch' | 'event' | 'runUnnerve' | 'runDynamax' | 'terastallize';
|
||||
/** priority of the action (lower first) */
|
||||
priority: number;
|
||||
/** speed of pokemon doing action (higher first if priority tie) */
|
||||
|
|
@ -179,6 +179,8 @@ export class BattleQueue {
|
|||
runPrimal: 102,
|
||||
switch: 103,
|
||||
megaEvo: 104,
|
||||
megaEvoX: 104,
|
||||
megaEvoY: 104,
|
||||
runDynamax: 105,
|
||||
terastallize: 106,
|
||||
priorityChargeMove: 107,
|
||||
|
|
@ -210,6 +212,18 @@ export class BattleQueue {
|
|||
pokemon: action.pokemon,
|
||||
}));
|
||||
}
|
||||
if (action.megax && !action.pokemon.isSkyDropped()) {
|
||||
actions.unshift(...this.resolveAction({
|
||||
choice: 'megaEvoX',
|
||||
pokemon: action.pokemon,
|
||||
}));
|
||||
}
|
||||
if (action.megay && !action.pokemon.isSkyDropped()) {
|
||||
actions.unshift(...this.resolveAction({
|
||||
choice: 'megaEvoY',
|
||||
pokemon: action.pokemon,
|
||||
}));
|
||||
}
|
||||
if (action.terastallize && !action.pokemon.terastallized) {
|
||||
actions.unshift(...this.resolveAction({
|
||||
choice: 'terastallize',
|
||||
|
|
|
|||
|
|
@ -2556,6 +2556,12 @@ export class Battle {
|
|||
case 'megaEvo':
|
||||
this.actions.runMegaEvo(action.pokemon);
|
||||
break;
|
||||
case 'megaEvoX':
|
||||
this.actions.runMegaEvoX?.(action.pokemon);
|
||||
break;
|
||||
case 'megaEvoY':
|
||||
this.actions.runMegaEvoY?.(action.pokemon);
|
||||
break;
|
||||
case 'runDynamax':
|
||||
action.pokemon.addVolatile('dynamax');
|
||||
action.pokemon.side.dynamaxUsed = true;
|
||||
|
|
@ -2686,7 +2692,7 @@ export class Battle {
|
|||
// in gen 3 or earlier, switching in fainted pokemon is done after
|
||||
// every move, rather than only at the end of the turn.
|
||||
this.checkFainted();
|
||||
} else if (action.choice === 'megaEvo' && this.gen === 7) {
|
||||
} else if (['megaEvo', 'megaEvoX', 'megaEvoY'].includes(action.choice) && this.gen === 7) {
|
||||
this.eachEvent('Update');
|
||||
// In Gen 7, the action order is recalculated for a Pokémon that mega evolves.
|
||||
for (const [i, queuedAction] of this.queue.list.entries()) {
|
||||
|
|
|
|||
|
|
@ -194,10 +194,6 @@ export class DexItems {
|
|||
if (item.gen > this.dex.gen) {
|
||||
(item as any).isNonstandard = 'Future';
|
||||
}
|
||||
// hack for allowing mega evolution in LGPE
|
||||
if (this.dex.currentMod === 'gen7letsgo' && !item.isNonstandard && !item.megaStone) {
|
||||
(item as any).isNonstandard = 'Past';
|
||||
}
|
||||
} else {
|
||||
item = new Item({name: id, exists: false});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -219,6 +219,8 @@ interface ModdedBattleActions {
|
|||
afterMoveSecondaryEvent?: (this: BattleActions, targets: Pokemon[], pokemon: Pokemon, move: ActiveMove) => undefined;
|
||||
calcRecoilDamage?: (this: BattleActions, damageDealt: number, move: Move, pokemon: Pokemon) => number;
|
||||
canMegaEvo?: (this: BattleActions, pokemon: Pokemon) => string | undefined | null;
|
||||
canMegaEvoX?: (this: BattleActions, pokemon: Pokemon) => string | null;
|
||||
canMegaEvoY?: (this: BattleActions, pokemon: Pokemon) => string | null;
|
||||
canUltraBurst?: (this: BattleActions, pokemon: Pokemon) => string | null;
|
||||
canZMove?: (this: BattleActions, pokemon: Pokemon) => ZMoveOptions | void;
|
||||
canDynamax?: (this: BattleActions, pokemon: Pokemon, skipChecks?: boolean) => DynamaxOptions | void;
|
||||
|
|
@ -250,6 +252,8 @@ interface ModdedBattleActions {
|
|||
) => number | undefined | false;
|
||||
runAction?: (this: BattleActions, action: Action) => void;
|
||||
runMegaEvo?: (this: BattleActions, pokemon: Pokemon) => boolean;
|
||||
runMegaEvoX?: (this: BattleActions, pokemon: Pokemon) => boolean;
|
||||
runMegaEvoY?: (this: BattleActions, pokemon: Pokemon) => boolean;
|
||||
runMove?: (
|
||||
this: BattleActions, moveOrMoveName: Move | string, pokemon: Pokemon, targetLoc: number, sourceEffect?: Effect | null,
|
||||
zMove?: string, externalMove?: boolean, maxMove?: string, originalTarget?: Pokemon
|
||||
|
|
|
|||
|
|
@ -253,6 +253,8 @@ export class Pokemon {
|
|||
abilityOrder: number;
|
||||
|
||||
canMegaEvo: string | null | undefined;
|
||||
canMegaEvoX: string | null | undefined;
|
||||
canMegaEvoY: string | null | undefined;
|
||||
canUltraBurst: string | null | undefined;
|
||||
readonly canGigantamax: string | null;
|
||||
/**
|
||||
|
|
@ -468,6 +470,8 @@ export class Pokemon {
|
|||
this.abilityOrder = 0;
|
||||
|
||||
this.canMegaEvo = this.battle.actions.canMegaEvo(this);
|
||||
this.canMegaEvoX = this.battle.actions.canMegaEvoX?.(this);
|
||||
this.canMegaEvoY = this.battle.actions.canMegaEvoY?.(this);
|
||||
this.canUltraBurst = this.battle.actions.canUltraBurst(this);
|
||||
this.canGigantamax = this.baseSpecies.canGigantamax || null;
|
||||
this.canTerastallize = this.battle.actions.canTerastallize(this);
|
||||
|
|
@ -1043,6 +1047,8 @@ export class Pokemon {
|
|||
trapped?: boolean,
|
||||
maybeTrapped?: boolean,
|
||||
canMegaEvo?: boolean,
|
||||
canMegaEvoX?: boolean,
|
||||
canMegaEvoY?: boolean,
|
||||
canUltraBurst?: boolean,
|
||||
canZMove?: AnyObject | null,
|
||||
canDynamax?: boolean,
|
||||
|
|
@ -1070,6 +1076,8 @@ export class Pokemon {
|
|||
|
||||
if (!lockedMove) {
|
||||
if (this.canMegaEvo) data.canMegaEvo = true;
|
||||
if (this.canMegaEvoX) data.canMegaEvoX = true;
|
||||
if (this.canMegaEvoY) data.canMegaEvoY = true;
|
||||
if (this.canUltraBurst) data.canUltraBurst = true;
|
||||
const canZMove = this.battle.actions.canZMove(this);
|
||||
if (canZMove) data.canZMove = canZMove;
|
||||
|
|
|
|||
28
sim/side.ts
28
sim/side.ts
|
|
@ -36,6 +36,8 @@ export interface ChosenAction {
|
|||
index?: number; // the chosen index in Team Preview
|
||||
side?: Side; // the action's side
|
||||
mega?: boolean | null; // true if megaing or ultra bursting
|
||||
megax?: boolean | null; // true if megaing x
|
||||
megay?: boolean | null; // true if megaing y
|
||||
zmove?: string; // if zmoving, the name of the zmove
|
||||
maxMove?: string; // if dynamaxed, the name of the max move
|
||||
terastallize?: string; // if terastallizing, tera type
|
||||
|
|
@ -408,7 +410,7 @@ export class Side {
|
|||
chooseMove(
|
||||
moveText?: string | number,
|
||||
targetLoc = 0,
|
||||
event: 'mega' | 'zmove' | 'ultra' | 'dynamax' | 'terastallize' | '' = ''
|
||||
event: 'mega' | 'megax' | 'megay' | 'zmove' | 'ultra' | 'dynamax' | 'terastallize' | '' = ''
|
||||
) {
|
||||
if (this.requestState !== 'move') {
|
||||
return this.emitChoiceError(`Can't move: You need a ${this.requestState} response`);
|
||||
|
|
@ -591,10 +593,18 @@ export class Side {
|
|||
// Mega evolution
|
||||
|
||||
const mega = (event === 'mega');
|
||||
const megax = (event === 'megax');
|
||||
const megay = (event === 'megay');
|
||||
if (mega && !pokemon.canMegaEvo) {
|
||||
return this.emitChoiceError(`Can't move: ${pokemon.name} can't mega evolve`);
|
||||
}
|
||||
if (mega && this.choice.mega) {
|
||||
if (megax && !pokemon.canMegaEvoX) {
|
||||
return this.emitChoiceError(`Can't move: ${pokemon.name} can't mega evolve X`);
|
||||
}
|
||||
if (megay && !pokemon.canMegaEvoY) {
|
||||
return this.emitChoiceError(`Can't move: ${pokemon.name} can't mega evolve Y`);
|
||||
}
|
||||
if ((mega || megax || megay) && this.choice.mega) {
|
||||
return this.emitChoiceError(`Can't move: You can only mega-evolve once per battle`);
|
||||
}
|
||||
const ultra = (event === 'ultra');
|
||||
|
|
@ -639,6 +649,8 @@ export class Side {
|
|||
targetLoc,
|
||||
moveid,
|
||||
mega: mega || ultra,
|
||||
megax: megax,
|
||||
megay: megay,
|
||||
zmove: zMove,
|
||||
maxMove: maxMove ? maxMove.id : undefined,
|
||||
terastallize: terastallize ? pokemon.teraType : undefined,
|
||||
|
|
@ -648,7 +660,7 @@ export class Side {
|
|||
this.choice.cantUndo = this.choice.cantUndo || pokemon.isLastActive();
|
||||
}
|
||||
|
||||
if (mega) this.choice.mega = true;
|
||||
if (mega || megax || megay) this.choice.mega = true;
|
||||
if (ultra) this.choice.ultra = true;
|
||||
if (zMove) this.choice.zMove = true;
|
||||
if (dynamax) this.choice.dynamax = true;
|
||||
|
|
@ -939,7 +951,7 @@ export class Side {
|
|||
const original = data;
|
||||
const error = () => this.emitChoiceError(`Conflicting arguments for "move": ${original}`);
|
||||
let targetLoc: number | undefined;
|
||||
let event: 'mega' | 'zmove' | 'ultra' | 'dynamax' | 'terastallize' | '' = '';
|
||||
let event: 'mega' | 'megax' | 'megay' | 'zmove' | 'ultra' | 'dynamax' | 'terastallize' | '' = '';
|
||||
while (true) {
|
||||
// If data ends with a number, treat it as a target location.
|
||||
// We need to special case 'Conversion 2' so it doesn't get
|
||||
|
|
@ -953,6 +965,14 @@ export class Side {
|
|||
if (event) return error();
|
||||
event = 'mega';
|
||||
data = data.slice(0, -5);
|
||||
} else if (data.endsWith(' megax')) {
|
||||
if (event) return error();
|
||||
event = 'megax';
|
||||
data = data.slice(0, -6);
|
||||
} else if (data.endsWith(' megay')) {
|
||||
if (event) return error();
|
||||
event = 'megay';
|
||||
data = data.slice(0, -6);
|
||||
} else if (data.endsWith(' zmove')) {
|
||||
if (event) return error();
|
||||
event = 'zmove';
|
||||
|
|
|
|||
|
|
@ -682,7 +682,7 @@ export class TeamValidator {
|
|||
if (dex.gen === 4 && item.id === 'griseousorb' && species.num !== 487) {
|
||||
problems.push(`${set.name} cannot hold the Griseous Orb.`, `(In Gen 4, only Giratina could hold the Griseous Orb).`);
|
||||
}
|
||||
if (dex.gen <= 1) {
|
||||
if (dex.gen <= 1 || dex.currentMod === 'gen7letsgo') {
|
||||
if (item.id) {
|
||||
// no items allowed
|
||||
set.item = '';
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user