From 7244fe8e28fa8bc4d0809ae30d183c608b62bb2b Mon Sep 17 00:00:00 2001 From: Guangcong Luo Date: Fri, 16 Oct 2026 17:41:38 -0700 Subject: [PATCH] Add Peat Block and PLA plates --- data/items.ts | 18 ++++++++++++++++++ data/pokedex.ts | 10 ++++++---- data/text/items.ts | 13 +++++++++++++ server/chat-commands/info.ts | 2 +- sim/dex-items.ts | 2 +- test/sim/data.js | 37 +++++++++++++++++++++++++++++++----- test/sim/dex.js | 7 +++++++ 7 files changed, 78 insertions(+), 11 deletions(-) diff --git a/data/items.ts b/data/items.ts index ff424a40c9..a55a707931 100644 --- a/data/items.ts +++ b/data/items.ts @@ -559,6 +559,12 @@ export const Items: import('../sim/dex-items').ItemDataTable = { num: 281, gen: 4, }, + blankplate: { + name: "Blank Plate", + num: 1780, + gen: 8, + isNonstandard: "Legends", + }, blastoisinite: { name: "Blastoisinite", spritenum: 583, @@ -3355,6 +3361,12 @@ export const Items: import('../sim/dex-items').ItemDataTable = { num: 234, gen: 2, }, + legendplate: { + name: "Legend Plate", + num: 1828, + gen: 8, + isNonstandard: "Legends", + }, leppaberry: { name: "Leppa Berry", spritenum: 244, @@ -4500,6 +4512,12 @@ export const Items: import('../sim/dex-items').ItemDataTable = { num: 193, gen: 4, }, + peatblock: { + name: "Peat Block", + num: 1692, + gen: 8, + isNonstandard: "Legends", + }, pechaberry: { name: "Pecha Berry", spritenum: 333, diff --git a/data/pokedex.ts b/data/pokedex.ts index 6fe6104478..3a20a7b24b 100644 --- a/data/pokedex.ts +++ b/data/pokedex.ts @@ -17293,7 +17293,7 @@ export const Pokedex: import('../sim/dex-species').SpeciesDataTable = { tags: ["Sub-Legendary"], prevo: "Kubfu", evoType: "other", - evoCondition: "Defeat the Single Strike Tower", + evoCondition: "Use a Scroll of Darkness", eggGroups: ["Undiscovered"], otherFormes: ["Urshifu-Rapid-Strike"], formeOrder: ["Urshifu", "Urshifu-Rapid-Strike"], @@ -17313,7 +17313,7 @@ export const Pokedex: import('../sim/dex-species').SpeciesDataTable = { color: "Gray", prevo: "Kubfu", evoType: "other", - evoCondition: "Defeat the Rapid Strike Tower", + evoCondition: "Use a Scroll of Waters", eggGroups: ["Undiscovered"], canGigantamax: "G-Max Rapid Flow", }, @@ -17502,6 +17502,7 @@ export const Pokedex: import('../sim/dex-species').SpeciesDataTable = { prevo: "Scyther", evoType: "useItem", evoItem: "Black Augurite", + evoCondition: "in Legends: Arceus or Legends: Z-A", eggGroups: ["Bug"], }, ursaluna: { @@ -17514,8 +17515,9 @@ export const Pokedex: import('../sim/dex-species').SpeciesDataTable = { weightkg: 290, color: "Brown", prevo: "Ursaring", - evoType: "other", - evoCondition: "Peat Block when there's a full moon", + evoType: "useItem", + evoItem: "Peat Block", + evoCondition: "in Legends: Arceus when there's a full moon", eggGroups: ["Field"], otherFormes: ["Ursaluna-Bloodmoon"], formeOrder: ["Ursaluna", "Ursaluna-Bloodmoon"], diff --git a/data/text/items.ts b/data/text/items.ts index 24be9a4f92..e62efcd264 100644 --- a/data/text/items.ts +++ b/data/text/items.ts @@ -173,6 +173,10 @@ export const ItemsText: { [id: IDEntry]: ItemText } = { shortDesc: "Holder's Dark-type attacks have 1.1× power.", }, }, + blankplate: { + name: "Blank Plate", + shortDesc: "Changes Arceus to the Normal type when used in Legends: Arceus.", + }, blastoisinite: { name: "Blastoisinite", shortDesc: "If held by a Blastoise, this item allows it to Mega Evolve in battle.", @@ -1061,6 +1065,11 @@ export const ItemsText: { [id: IDEntry]: ItemText } = { heal: " {POKEMON} restored a little HP using its Leftovers!", }, + legendplate: { + name: "Legend Plate", + desc: "When used on Arceus in Legends: Arceus, changes it to the Normal type. When Arceus uses Judgment, Arceus and the move change to a type that is most effective against the target.", + shortDesc: "In Legends: Arceus, Arceus's Judgment changes type to be supereffective.", + }, leppaberry: { name: "Leppa Berry", shortDesc: "Restores 10 PP to the first of the holder's moves to reach 0 PP. Single use.", @@ -1416,6 +1425,10 @@ export const ItemsText: { [id: IDEntry]: ItemText } = { name: "Payapa Berry", shortDesc: "Halves damage taken from a supereffective Psychic-type attack. Single use.", }, + peatblock: { + name: "Peat Block", + shortDesc: "Evolves Ursaring into Ursaluna when used during a full moon.", + }, pechaberry: { name: "Pecha Berry", shortDesc: "Holder is cured if it is poisoned. Single use.", diff --git a/server/chat-commands/info.ts b/server/chat-commands/info.ts index b85a3b4c44..35745fb6f5 100644 --- a/server/chat-commands/info.ts +++ b/server/chat-commands/info.ts @@ -711,7 +711,7 @@ export const commands: Chat.ChatCommands = { evos.push(`${name} (level-up holding ${evo.evoItem}${condition})`); break; case 'useItem': - evos.push(`${name} (${evo.evoItem})`); + evos.push(`${name} (${evo.evoItem}${condition})`); break; case 'levelMove': evos.push(`${name} (level-up with ${evo.evoMove}${condition})`); diff --git a/sim/dex-items.ts b/sim/dex-items.ts index d9ae93cc6b..99534dc0d7 100644 --- a/sim/dex-items.ts +++ b/sim/dex-items.ts @@ -144,7 +144,7 @@ export class Item extends BasicEffect implements Readonly { } if (this.isBerry) this.fling = { basePower: 10 }; - if (this.id.endsWith('plate')) this.fling = { basePower: 90 }; + if (this.onPlate && 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 }; diff --git a/test/sim/data.js b/test/sim/data.js index d8440cf944..3785e0b8cd 100644 --- a/test/sim/data.js +++ b/test/sim/data.js @@ -108,11 +108,6 @@ describe('Dex data', () => { } } - if (entry.evoItem) { - const item = Dex.items.get(entry.evoItem); - assert.equal(entry.evoItem, item.exists && item.name, `Misspelled/nonexistent evo item "${entry.evoItem}" of ${entry.name}`); - } - const battleOnly = (entry.forme || '').includes('Mega') || entry.forme === 'Primal' ? entry.baseSpecies : entry.battleOnly; if (entry.requiredAbility) { assert(entry.battleOnly, `Forme ${entry.name} with requiredAbility must have battleOnly`); @@ -123,6 +118,38 @@ describe('Dex data', () => { if (entry.requiredMove) { assert(battleOnly || entry.changesFrom, `Forme ${entry.name} with requiredMove must have battleOnly or changesFrom`); } + + // evolution + switch (entry.evoType) { + case 'useItem': + case 'levelHold': + assert(entry.evoItem, `${entry.name} with evoType ${entry.evoType} must have an evoItem`); + break; + case 'levelMove': + assert(entry.evoMove, `${entry.name} with evoType levelMove must have an evoMove`); + break; + case 'levelExtra': + case 'other': + assert(typeof entry.evoCondition === 'string' && entry.evoCondition.trim(), `${entry.name} with evoType ${entry.evoType} must have an evoCondition`); + break; + case 'trade': + case 'levelFriendship': + break; + default: + assert.equal(entry.evoType, undefined, `${entry.name} has an unrecognized evoType ${entry.evoType}`); + if (entry.prevo) assert(entry.evoLevel, `${entry.name} without an evoType must have an evoLevel`); + } + if (entry.evoItem) { + const item = Dex.items.get(entry.evoItem); + assert.equal(entry.evoItem, item.exists && item.name, `Misspelled/nonexistent evo item "${entry.evoItem}" of ${entry.name}`); + } + if (entry.evoMove) { + const move = Dex.moves.get(entry.evoMove); + assert.equal(entry.evoMove, move.exists && move.name, `Misspelled/nonexistent evo move "${entry.evoMove}" of ${entry.name}`); + } + if (entry.evoLevel !== undefined) { + assert(Number.isInteger(entry.evoLevel) && entry.evoLevel >= 1 && entry.evoLevel <= 100, `Evolution level of ${entry.name} must be an integer between 1 and 100`); + } } }); diff --git a/test/sim/dex.js b/test/sim/dex.js index 496778b8db..4974634efd 100644 --- a/test/sim/dex.js +++ b/test/sim/dex.js @@ -66,6 +66,13 @@ describe('Dex#getSpecies', () => { }); describe('Dex#getItem', () => { + it('should only assign Plate Fling power to held Plates', () => { + assert.equal(Dex.items.get('Flame Plate').fling.basePower, 90); + assert.equal(Dex.items.get('Blank Plate').fling, undefined); + assert.equal(Dex.items.get('Legend Plate').fling, undefined); + assert.equal(Dex.items.get('Firium Z').fling, undefined); + }); + it(`should correctly mark Gem legality`, () => { assert.false(Dex.forGen(5).items.get('Normal Gem').isNonstandard); assert.false(Dex.forGen(5).items.get('Rock Gem').isNonstandard);