mirror of
https://github.com/smogon/pokemon-showdown.git
synced 2026-07-26 12:56:31 -05:00
* Make a mod file * Add Pokemon in Champions (#3) * Add new Megas abilities (#4) * Add new Megas abilities * Apply suggestion from @KrisXV --------- Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com> * Add conditions for Champions (#5) * Add conditions for Champions * Add a turn limit to freeze * Swap the order of the checks Co-authored-by: André Bastos Dias <80102738+andrebastosdias@users.noreply.github.com> --------- Co-authored-by: André Bastos Dias <80102738+andrebastosdias@users.noreply.github.com> * Disable Fake Out if it is not the first active move action (#7) * Disable Fake Out if it is not the first active move action * Remove unnecessary code --------- Co-authored-by: André Bastos Dias <dias.andre@siemens.com> * Implement Piercing Drill, Spicy Spray and Unseen Fist (#2) * Add Piercing Drill and Spicy Spray Fix ability numbers Refactor condition Disallow Piercing Drill/Spicy Spray in formats !Obtainable Abilities without +Future Refactor condition * Rename blockStatus * CFZ-moves completely bypass Protect * Update Gen 4 Protect * Old gen Wide Guard and Quick Guard * Fix Wide Guard * Clean Mat Block implementation * Nerf Unseen Fist * Fix condition * Update sim/battle.ts --------- Co-authored-by: André Bastos Dias <dias.andre@siemens.com> Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com> * Implement PP mechanics (#8) * Implement PP mechanics * Clip all moves to 20 PP * Apply suggestion from @KrisXV * Update scripts.ts --------- Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com> * Add Champions stat calculaiton * Fix conflicts with smogon/master (#11) * Fix stat formula (#12) * Implement PP mechanics (#8) * Implement PP mechanics * Clip all moves to 20 PP * Apply suggestion from @KrisXV * Update scripts.ts --------- Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com> * Fix stat formula * For clarity like we do with friendship in letsgo * If we don't allow IVs and Level to be modifiable, there is not point in having `Adjust Level = 50` --------- Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com> * Add Champions Items (#9) * Remove Mega Raichus, Mega Z, and Greninja-Bond (#10) * Remove Mega Raichus and Mega Z * Remove Greninja-Bond * Implement Mega Sol's activation message (#13) * Implement Mega Sol's activation message * Update ModdedBattlePokemon interface * Implement move changes (#6) * Implement move changes * Re-implement Salt Cure changes * Update moves * Implement Blood Moon package * Mimic https://github.com/smogon/pokemon-showdown/pull/11838/ https://github.com/smogon/pokemon-showdown/pull/11838/ * Implement accuracy and PP changes * Mark Double Shock and Revival Blessing as Past moves * Import learnsets from Serebii (#19) * Import learnsets from serebii * floette -> floetteeternal * Update learnsets * Apparently I forgot to give Gourgeist-Small its tier (#15) * Move Pikachu to NFE (#21) * Oops * Add Pokemon I forgot the first time (#24) * Add 'Past' moves (#23) * Add past moves * Fix move availability * AfterHit effects should activate even if the source faints (#20) * AfterHit effects should activate even if the source faints * Change Gens 3-4 event order * Ups * Announce 4x and 0.25x effectiveness (#14) * Reset Encore priority and choose random target (#17) * Reset Encore priority and choose random target * Allow onOverrideAction * Quash + Encore interaction * Don't send target targetLoc was actually thing being checked but wtv * Activate White Herb after choosing the Parting Shot switch (#26) * Activate White Herb after choosing the Parting Shot switch * Add comment * Add formats * Implement flag changes (#25) * Implement flag changes * Fix Gen 5 Rage Powder (remove poder immunity check) * Add moves and abilities descriptions * Apply suggestion from @KrisXV * Comment Rage Powder Leave this comment and I would choose the implementation depending on what we see from the healing flag. --------- Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com> * Announce status immunities from abilities (#22) * Mega Sol boosts the damage of Fire-type moves as if they were under sun (#18) * Remove hardcoded Utility Umbrella * Check effective weather on attacker * Don't activate Mega Sol under sun * Add TODO comment * TODO: check interaction with Utility Umbrella * Move implementation to base mod * Do not revert Mega Evolutions upon fainting (#16) * Revert Mega Evolutions on fainting * Allow diferent levels in the team builder * TODO: confirm interaction with Revival Blessing * Add Species Clause and Obtainable * Update team-validator.ts --------- Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com> * Update abilities percentages (#27) * Healer has a 50% chance of curing the status conditions of its allies * Update Shed Skin --------- Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com> * Fix crashes * add custom game * Fix typo * update flat rules * Update data/mods/champions/scripts.ts Co-authored-by: Slayer95 <ivojulca@hotmail.com> --------- Co-authored-by: shrianshChari <30420527+shrianshChari@users.noreply.github.com> Co-authored-by: André Bastos Dias <80102738+andrebastosdias@users.noreply.github.com> Co-authored-by: André Bastos Dias <dias.andre@siemens.com> Co-authored-by: Karthik Bandagonda <32044378+Karthik99999@users.noreply.github.com> Co-authored-by: Slayer95 <ivojulca@hotmail.com>
232 lines
7.0 KiB
TypeScript
232 lines
7.0 KiB
TypeScript
import type { PokemonEventMethods, ConditionData, ModdedConditionData } from './dex-conditions';
|
|
import { assignMissingFields, BasicEffect, toID } from './dex-data';
|
|
import { Utils } from '../lib/utils';
|
|
|
|
interface FlingData {
|
|
basePower: number;
|
|
status?: string;
|
|
volatileStatus?: string;
|
|
effect?: CommonHandlers['ResultMove'];
|
|
}
|
|
|
|
export interface ItemData extends Partial<Item>, PokemonEventMethods {
|
|
name: string;
|
|
}
|
|
|
|
export type ModdedItemData = ItemData | Partial<Omit<ItemData, 'name'>> & {
|
|
inherit: true,
|
|
onCustap?: (this: Battle, pokemon: Pokemon) => void,
|
|
onWhiteHerb?: (this: Battle, pokemon: Pokemon) => void,
|
|
condition?: ModdedConditionData,
|
|
};
|
|
|
|
export interface ItemDataTable { [itemid: IDEntry]: ItemData }
|
|
export interface ModdedItemDataTable { [itemid: IDEntry]: ModdedItemData }
|
|
|
|
export class Item extends BasicEffect implements Readonly<BasicEffect> {
|
|
declare readonly effectType: 'Item';
|
|
|
|
/** just controls location on the item spritesheet */
|
|
declare readonly num: number;
|
|
|
|
/**
|
|
* A Move-like object depicting what happens when Fling is used on
|
|
* this item.
|
|
*/
|
|
readonly fling?: FlingData;
|
|
/**
|
|
* If this is a Drive: The type it turns Techno Blast into.
|
|
* undefined, if not a Drive.
|
|
*/
|
|
readonly onDrive?: string;
|
|
/**
|
|
* If this is a Memory: The type it turns Multi-Attack into.
|
|
* undefined, if not a Memory.
|
|
*/
|
|
readonly onMemory?: string;
|
|
/**
|
|
* If this is a mega stone: A pair (e.g. Charizard: Charizard-Mega-X) of the
|
|
* forme this allows transformation from and into.
|
|
* undefined, if not a mega stone.
|
|
*/
|
|
readonly megaStone?: { [megaEvolves: string]: string };
|
|
/**
|
|
* If this is a Z crystal: true if the Z Crystal is generic
|
|
* (e.g. Firium Z). If species-specific, the name
|
|
* (e.g. Inferno Overdrive) of the Z Move this crystal allows
|
|
* the use of.
|
|
* undefined, if not a Z crystal.
|
|
*/
|
|
readonly zMove?: true | string;
|
|
/**
|
|
* If this is a generic Z crystal: The type (e.g. Fire) of the
|
|
* Z Move this crystal allows the use of (e.g. Fire)
|
|
* undefined, if not a generic Z crystal
|
|
*/
|
|
readonly zMoveType?: string;
|
|
/**
|
|
* If this is a species-specific Z crystal: The name
|
|
* (e.g. Play Rough) of the move this crystal requires its
|
|
* holder to know to use its Z move.
|
|
* undefined, if not a species-specific Z crystal
|
|
*/
|
|
readonly zMoveFrom?: string;
|
|
/**
|
|
* If this is a species-specific Z crystal: An array of the
|
|
* species of Pokemon that can use this crystal's Z move.
|
|
* Note that these are the full names, e.g. 'Mimikyu-Busted'
|
|
* undefined, if not a species-specific Z crystal
|
|
*/
|
|
readonly itemUser?: string[];
|
|
/** Is this item a Berry? */
|
|
readonly isBerry: boolean;
|
|
/** Whether or not this item ignores the Klutz ability. */
|
|
readonly ignoreKlutz: boolean;
|
|
/** The type the holder will change into if it is an Arceus. */
|
|
readonly onPlate?: string;
|
|
/** Is this item a Gem? */
|
|
readonly isGem: boolean;
|
|
/** Is this item a Pokeball? */
|
|
readonly isPokeball: boolean;
|
|
/** Is this item a Red or Blue Orb? */
|
|
readonly isPrimalOrb: boolean;
|
|
|
|
declare readonly condition?: ConditionData;
|
|
declare readonly forcedForme?: string;
|
|
declare readonly isChoice?: boolean;
|
|
declare readonly naturalGift?: { basePower: number, type: string };
|
|
declare readonly spritenum?: number;
|
|
declare readonly boosts?: SparseBoostsTable | false;
|
|
|
|
declare readonly onEat?: ((this: Battle, pokemon: Pokemon) => void) | false;
|
|
declare readonly onUse?: ((this: Battle, pokemon: Pokemon) => void) | false;
|
|
declare readonly onStart?: (this: Battle, target: Pokemon) => void;
|
|
declare readonly onEnd?: (this: Battle, target: Pokemon) => void;
|
|
|
|
constructor(data: AnyObject) {
|
|
super(data);
|
|
|
|
this.fullname = `item: ${this.name}`;
|
|
this.effectType = 'Item';
|
|
this.fling = data.fling || undefined;
|
|
this.onDrive = data.onDrive || undefined;
|
|
this.onMemory = data.onMemory || undefined;
|
|
this.megaStone = data.megaStone || undefined;
|
|
this.zMove = data.zMove || undefined;
|
|
this.zMoveType = data.zMoveType || undefined;
|
|
this.zMoveFrom = data.zMoveFrom || undefined;
|
|
this.itemUser = data.itemUser || undefined;
|
|
this.isBerry = !!data.isBerry;
|
|
this.ignoreKlutz = !!data.ignoreKlutz;
|
|
this.onPlate = data.onPlate || undefined;
|
|
this.isGem = !!data.isGem;
|
|
this.isPokeball = !!data.isPokeball;
|
|
this.isPrimalOrb = !!data.isPrimalOrb;
|
|
|
|
if (!this.gen) {
|
|
if (this.num >= 1124) {
|
|
this.gen = 9;
|
|
} else if (this.num >= 927) {
|
|
this.gen = 8;
|
|
} else if (this.num >= 689) {
|
|
this.gen = 7;
|
|
} else if (this.num >= 577) {
|
|
this.gen = 6;
|
|
} else if (this.num >= 537) {
|
|
this.gen = 5;
|
|
} else if (this.num >= 377) {
|
|
this.gen = 4;
|
|
} else {
|
|
this.gen = 3;
|
|
}
|
|
// Due to difference in gen 2 item numbering, gen 2 items must be
|
|
// specified manually
|
|
}
|
|
|
|
if (this.isBerry) this.fling = { basePower: 10 };
|
|
if (this.id.endsWith('plate')) this.fling = { basePower: 90 };
|
|
if (this.onDrive) this.fling = { basePower: 70 };
|
|
if (this.megaStone) this.fling = { basePower: 80 };
|
|
if (this.onMemory) this.fling = { basePower: 50 };
|
|
|
|
assignMissingFields(this, data);
|
|
}
|
|
}
|
|
|
|
const EMPTY_ITEM = Utils.deepFreeze(new Item({ name: '', exists: false }));
|
|
|
|
export class DexItems {
|
|
readonly dex: ModdedDex;
|
|
readonly itemCache = new Map<ID, Item>();
|
|
allCache: readonly Item[] | null = null;
|
|
|
|
constructor(dex: ModdedDex) {
|
|
this.dex = dex;
|
|
}
|
|
|
|
get(name?: string | Item): Item {
|
|
if (name && typeof name !== 'string') return name;
|
|
const id = name ? toID(name.trim()) : '' as ID;
|
|
return this.getByID(id);
|
|
}
|
|
|
|
getByID(id: ID): Item {
|
|
if (id === '' || id === 'constructor') return EMPTY_ITEM;
|
|
let item = this.itemCache.get(id);
|
|
if (item) return item;
|
|
if (this.dex.getAlias(id)) {
|
|
item = this.get(this.dex.getAlias(id));
|
|
if (item.exists) {
|
|
this.itemCache.set(id, item);
|
|
}
|
|
return item;
|
|
}
|
|
if (id && !this.dex.data.Items[id] && this.dex.data.Items[id + 'berry']) {
|
|
item = this.getByID(id + 'berry' as ID);
|
|
this.itemCache.set(id, item);
|
|
return item;
|
|
}
|
|
if (id && this.dex.data.Items.hasOwnProperty(id)) {
|
|
const itemData = this.dex.data.Items[id] as any;
|
|
const itemTextData = this.dex.getDescs('Items', id, itemData);
|
|
item = new Item({
|
|
name: id,
|
|
...itemData,
|
|
...itemTextData,
|
|
});
|
|
if (item.gen > this.dex.gen) {
|
|
(item as any).isNonstandard = 'Future';
|
|
}
|
|
if (this.dex.parentMod) {
|
|
// If this item is exactly identical to parentMod's item, reuse parentMod's copy
|
|
const parent = this.dex.mod(this.dex.parentMod);
|
|
if (itemData === parent.data.Items[id]) {
|
|
const parentItem = parent.items.getByID(id);
|
|
if (
|
|
item.isNonstandard === parentItem.isNonstandard &&
|
|
item.desc === parentItem.desc &&
|
|
item.shortDesc === parentItem.shortDesc
|
|
) {
|
|
item = parentItem;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
item = new Item({ name: id, exists: false });
|
|
}
|
|
|
|
if (item.exists) this.itemCache.set(id, this.dex.deepFreeze(item));
|
|
return item;
|
|
}
|
|
|
|
all(): readonly Item[] {
|
|
if (this.allCache) return this.allCache;
|
|
const items = [];
|
|
for (const id in this.dex.data.Items) {
|
|
items.push(this.getByID(id as ID));
|
|
}
|
|
this.allCache = Object.freeze(items);
|
|
return this.allCache;
|
|
}
|
|
}
|