From 68e0bcb75fa9cf5f35eb07c759518b75a39ece55 Mon Sep 17 00:00:00 2001 From: The Immortal Date: Tue, 28 Jan 2020 13:21:23 +0400 Subject: [PATCH] Refactor single-use items This adds a `boosts` property to items that runs in `useItem`. This allows it to be added to `datasearch` or similar plugins. The item activation messages are now as accurate as in-game. The Gem activation message is also consolidated in `useItem`. --- data/items.js | 227 ++++++++++++++++++++------------------------ sim/battle.ts | 2 + sim/global-types.ts | 1 + sim/pokemon.ts | 7 +- 4 files changed, 114 insertions(+), 123 deletions(-) diff --git a/data/items.js b/data/items.js index d8014ce627..8e600d866a 100644 --- a/data/items.js +++ b/data/items.js @@ -42,10 +42,13 @@ let BattleItems = { basePower: 30, }, onAfterDamage(damage, target, source, move) { - if (move.type === 'Water' && target.useItem()) { - this.boost({spa: 1}); + if (move.type === 'Water') { + target.useItem(); } }, + boosts: { + spa: 1, + }, num: 545, gen: 5, desc: "Raises holder's Sp. Atk by 1 stage if hit by a Water-type attack. Single use.", @@ -76,10 +79,13 @@ let BattleItems = { basePower: 30, }, onAfterBoost(boost, target, source, effect) { - if (effect.id === 'intimidate' && target.useItem()) { - this.boost({spe: 1}); + if (effect.id === 'intimidate') { + target.useItem(); } }, + boosts: { + spe: 1, + }, num: 846, gen: 7, desc: "Raises holder's Speed by 1 stage if it gets affected by Intimidate. Single use.", @@ -649,11 +655,8 @@ let BattleItems = { isGem: true, onSourceTryPrimaryHit(target, source, move) { if (target === source || move.category === 'Status') return; - if (move.type === 'Bug') { - if (source.useItem()) { - this.add('-enditem', source, 'Bug Gem', '[from] gem', '[move] ' + move.name); - source.addVolatile('gem'); - } + if (move.type === 'Bug' && source.useItem()) { + source.addVolatile('gem'); } }, num: 558, @@ -734,10 +737,13 @@ let BattleItems = { basePower: 30, }, onAfterDamage(damage, target, source, move) { - if (move.type === 'Electric' && target.useItem()) { - this.boost({atk: 1}); + if (move.type === 'Electric') { + target.useItem(); } }, + boosts: { + atk: 1, + }, num: 546, gen: 5, desc: "Raises holder's Attack by 1 if hit by an Electric-type attack. Single use.", @@ -1170,11 +1176,8 @@ let BattleItems = { isGem: true, onSourceTryPrimaryHit(target, source, move) { if (target === source || move.category === 'Status') return; - if (move.type === 'Dark') { - if (source.useItem()) { - this.add('-enditem', source, 'Dark Gem', '[from] gem', '[move] ' + move.name); - source.addVolatile('gem'); - } + if (move.type === 'Dark' && source.useItem()) { + source.addVolatile('gem'); } }, num: 562, @@ -1394,11 +1397,8 @@ let BattleItems = { isGem: true, onSourceTryPrimaryHit(target, source, move) { if (target === source || move.category === 'Status') return; - if (move.type === 'Dragon') { - if (source.useItem()) { - this.add('-enditem', source, 'Dragon Gem', '[from] gem', '[move] ' + move.name); - source.addVolatile('gem'); - } + if (move.type === 'Dragon' && source.useItem()) { + source.addVolatile('gem'); } }, num: 561, @@ -1632,11 +1632,8 @@ let BattleItems = { isGem: true, onSourceTryPrimaryHit(target, source, move) { if (target === source || move.category === 'Status' || ['firepledge', 'grasspledge', 'waterpledge'].includes(move.id)) return; - if (move.type === 'Electric') { - if (source.useItem()) { - this.add('-enditem', source, 'Electric Gem', '[from] gem', '[move] ' + move.name); - source.addVolatile('gem'); - } + if (move.type === 'Electric' && source.useItem()) { + source.addVolatile('gem'); } }, num: 550, @@ -1669,16 +1666,19 @@ let BattleItems = { basePower: 10, }, onStart(pokemon) { - if (!pokemon.ignoringItem() && this.field.isTerrain('electricterrain') && pokemon.useItem()) { - this.boost({def: 1}); + if (!pokemon.ignoringItem() && this.field.isTerrain('electricterrain')) { + pokemon.useItem(); } }, onAnyTerrainStart() { const pokemon = this.effectData.target; - if (this.field.isTerrain('electricterrain') && pokemon.useItem()) { - this.boost({def: 1}, pokemon); + if (this.field.isTerrain('electricterrain')) { + pokemon.useItem(); } }, + boosts: { + def: 1, + }, num: 881, gen: 7, desc: "If the terrain is Electric Terrain, raises holder's Defense by 1 stage. Single use.", @@ -1794,11 +1794,8 @@ let BattleItems = { isGem: true, onSourceTryPrimaryHit(target, source, move) { if (target === source || move.category === 'Status') return; - if (move.type === 'Fairy') { - if (source.useItem()) { - this.add('-enditem', source, 'Fairy Gem', '[from] gem', '[move] ' + move.name); - source.addVolatile('gem'); - } + if (move.type === 'Fairy' && source.useItem()) { + source.addVolatile('gem'); } }, num: 715, @@ -1839,11 +1836,8 @@ let BattleItems = { isGem: true, onSourceTryPrimaryHit(target, source, move) { if (target === source || move.category === 'Status') return; - if (move.type === 'Fighting') { - if (source.useItem()) { - this.add('-enditem', source, 'Fighting Gem', '[from] gem', '[move] ' + move.name); - source.addVolatile('gem'); - } + if (move.type === 'Fighting' && source.useItem()) { + source.addVolatile('gem'); } }, num: 553, @@ -1916,11 +1910,8 @@ let BattleItems = { isGem: true, onSourceTryPrimaryHit(target, source, move) { if (target === source || move.category === 'Status' || ['firepledge', 'grasspledge', 'waterpledge'].includes(move.id)) return; - if (move.type === 'Fire') { - if (source.useItem()) { - this.add('-enditem', source, 'Fire Gem', '[from] gem', '[move] ' + move.name); - source.addVolatile('gem'); - } + if (move.type === 'Fire' && source.useItem()) { + source.addVolatile('gem'); } }, num: 548, @@ -2064,11 +2055,8 @@ let BattleItems = { isGem: true, onSourceTryPrimaryHit(target, source, move) { if (target === source || move.category === 'Status') return; - if (move.type === 'Flying') { - if (source.useItem()) { - this.add('-enditem', source, 'Flying Gem', '[from] gem', '[move] ' + move.name); - source.addVolatile('gem'); - } + if (move.type === 'Flying' && source.useItem()) { + source.addVolatile('gem'); } }, num: 556, @@ -2305,11 +2293,8 @@ let BattleItems = { isGem: true, onSourceTryPrimaryHit(target, source, move) { if (target === source || move.category === 'Status') return; - if (move.type === 'Ghost') { - if (source.useItem()) { - this.add('-enditem', source, 'Ghost Gem', '[from] gem', '[move] ' + move.name); - source.addVolatile('gem'); - } + if (move.type === 'Ghost' && source.useItem()) { + source.addVolatile('gem'); } }, num: 560, @@ -2382,11 +2367,8 @@ let BattleItems = { isGem: true, onSourceTryPrimaryHit(target, source, move) { if (target === source || move.category === 'Status' || ['firepledge', 'grasspledge', 'waterpledge'].includes(move.id)) return; - if (move.type === 'Grass') { - if (source.useItem()) { - this.add('-enditem', source, 'Grass Gem', '[from] gem', '[move] ' + move.name); - source.addVolatile('gem'); - } + if (move.type === 'Grass' && source.useItem()) { + source.addVolatile('gem'); } }, num: 551, @@ -2433,16 +2415,19 @@ let BattleItems = { basePower: 10, }, onStart(pokemon) { - if (!pokemon.ignoringItem() && this.field.isTerrain('grassyterrain') && pokemon.useItem()) { - this.boost({def: 1}); + if (!pokemon.ignoringItem() && this.field.isTerrain('grassyterrain')) { + pokemon.useItem(); } }, onAnyTerrainStart() { const pokemon = this.effectData.target; - if (this.field.isTerrain('grassyterrain') && pokemon.useItem()) { - this.boost({def: 1}, pokemon); + if (this.field.isTerrain('grassyterrain')) { + pokemon.useItem(); } }, + boosts: { + def: 1, + }, num: 884, gen: 7, desc: "If the terrain is Grassy Terrain, raises holder's Defense by 1 stage. Single use.", @@ -2514,11 +2499,8 @@ let BattleItems = { isGem: true, onSourceTryPrimaryHit(target, source, move) { if (target === source || move.category === 'Status') return; - if (move.type === 'Ground') { - if (source.useItem()) { - this.add('-enditem', source, 'Ground Gem', '[from] gem', '[move] ' + move.name); - source.addVolatile('gem'); - } + if (move.type === 'Ground' && source.useItem()) { + source.addVolatile('gem'); } }, num: 555, @@ -2746,11 +2728,8 @@ let BattleItems = { isGem: true, onSourceTryPrimaryHit(target, source, move) { if (target === source || move.category === 'Status') return; - if (move.type === 'Ice') { - if (source.useItem()) { - this.add('-enditem', source, 'Ice Gem', '[from] gem', '[move] ' + move.name); - source.addVolatile('gem'); - } + if (move.type === 'Ice' && source.useItem()) { + source.addVolatile('gem'); } }, num: 552, @@ -3426,10 +3405,13 @@ let BattleItems = { basePower: 30, }, onAfterDamage(damage, target, source, move) { - if (move.type === 'Water' && target.useItem()) { - this.boost({spd: 1}); + if (move.type === 'Water') { + target.useItem(); } }, + boosts: { + spd: 1, + }, num: 648, gen: 6, desc: "Raises holder's Sp. Def by 1 stage if hit by a Water-type attack. Single use.", @@ -3975,16 +3957,19 @@ let BattleItems = { basePower: 10, }, onStart(pokemon) { - if (!pokemon.ignoringItem() && this.field.isTerrain('mistyterrain') && pokemon.useItem()) { - this.boost({spd: 1}); + if (!pokemon.ignoringItem() && this.field.isTerrain('mistyterrain')) { + pokemon.useItem(); } }, onAnyTerrainStart() { const pokemon = this.effectData.target; - if (this.field.isTerrain('mistyterrain') && pokemon.useItem()) { - this.boost({spd: 1}, pokemon); + if (this.field.isTerrain('mistyterrain')) { + pokemon.useItem(); } }, + boosts: { + spd: 1, + }, num: 883, gen: 7, desc: "If the terrain is Misty Terrain, raises holder's Sp. Def by 1 stage. Single use.", @@ -4116,11 +4101,8 @@ let BattleItems = { isGem: true, onSourceTryPrimaryHit(target, source, move) { if (target === source || move.category === 'Status' || ['firepledge', 'grasspledge', 'waterpledge'].includes(move.id)) return; - if (move.type === 'Normal') { - if (source.useItem()) { - this.add('-enditem', source, 'Normal Gem', '[from] gem', '[move] ' + move.name); - source.addVolatile('gem'); - } + if (move.type === 'Normal' && source.useItem()) { + source.addVolatile('gem'); } }, num: 564, @@ -4492,11 +4474,8 @@ let BattleItems = { isGem: true, onSourceTryPrimaryHit(target, source, move) { if (target === source || move.category === 'Status') return; - if (move.type === 'Poison') { - if (source.useItem()) { - this.add('-enditem', source, 'Poison Gem', '[from] gem', '[move] ' + move.name); - source.addVolatile('gem'); - } + if (move.type === 'Poison' && source.useItem()) { + source.addVolatile('gem'); } }, num: 554, @@ -4765,11 +4744,8 @@ let BattleItems = { isGem: true, onSourceTryPrimaryHit(target, source, move) { if (target === source || move.category === 'Status') return; - if (move.type === 'Psychic') { - if (source.useItem()) { - this.add('-enditem', source, 'Psychic Gem', '[from] gem', '[move] ' + move.name); - source.addVolatile('gem'); - } + if (move.type === 'Psychic' && source.useItem()) { + source.addVolatile('gem'); } }, num: 557, @@ -4802,16 +4778,19 @@ let BattleItems = { basePower: 10, }, onStart(pokemon) { - if (!pokemon.ignoringItem() && this.field.isTerrain('psychicterrain') && pokemon.useItem()) { - this.boost({spd: 1}); + if (!pokemon.ignoringItem() && this.field.isTerrain('psychicterrain')) { + pokemon.useItem(); } }, onAnyTerrainStart() { const pokemon = this.effectData.target; - if (this.field.isTerrain('psychicterrain') && pokemon.useItem()) { - this.boost({spd: 1}, pokemon); + if (this.field.isTerrain('psychicterrain')) { + pokemon.useItem(); } }, + boosts: { + spd: 1, + }, num: 882, gen: 7, desc: "If the terrain is Psychic Terrain, raises holder's Sp. Def by 1 stage. Single use.", @@ -5109,11 +5088,8 @@ let BattleItems = { isGem: true, onSourceTryPrimaryHit(target, source, move) { if (target === source || move.category === 'Status') return; - if (move.type === 'Rock') { - if (source.useItem()) { - this.add('-enditem', source, 'Rock Gem', '[from] gem', '[move] ' + move.name); - source.addVolatile('gem'); - } + if (move.type === 'Rock' && source.useItem()) { + source.addVolatile('gem'); } }, num: 559, @@ -5194,10 +5170,13 @@ let BattleItems = { basePower: 100, }, onUpdate(pokemon) { - if (this.field.getPseudoWeather('trickroom') && pokemon.useItem()) { - this.boost({spe: -1}, pokemon, pokemon); + if (this.field.getPseudoWeather('trickroom')) { + pokemon.useItem(); } }, + boosts: { + spe: -1, + }, num: 1122, gen: 8, desc: "If Trick Room is active, lowers holder's Speed by 1 stage. Single use.", @@ -5734,10 +5713,13 @@ let BattleItems = { basePower: 30, }, onAfterDamage(damage, target, source, move) { - if (move.type === 'Ice' && target.useItem()) { - this.boost({atk: 1}); + if (move.type === 'Ice') { + target.useItem(); } }, + boosts: { + atk: 1, + }, num: 649, gen: 6, desc: "Raises holder's Attack by 1 if hit by an Ice-type attack. Single use.", @@ -5943,11 +5925,8 @@ let BattleItems = { isGem: true, onSourceTryPrimaryHit(target, source, move) { if (target === source || move.category === 'Status') return; - if (move.type === 'Steel') { - if (source.useItem()) { - this.add('-enditem', source, 'Steel Gem', '[from] gem', '[move] ' + move.name); - source.addVolatile('gem'); - } + if (move.type === 'Steel' && source.useItem()) { + source.addVolatile('gem'); } }, num: 563, @@ -6198,10 +6177,13 @@ let BattleItems = { basePower: 30, }, onAfterMoveSecondarySelf(target, source, move) { - if (move.flags['sound'] && target.useItem()) { - this.boost({spa: 1}); // TODO: Find exact value, and whether this activates before or after use + if (move.flags['sound']) { + target.useItem(); } }, + boosts: { + spa: 1, + }, num: 1118, gen: 8, desc: "Raises holder's Special Attack by 1 stage after using a sound move. Single use.", @@ -6391,11 +6373,8 @@ let BattleItems = { isGem: true, onSourceTryPrimaryHit(target, source, move) { if (target === source || move.category === 'Status' || ['firepledge', 'grasspledge', 'waterpledge'].includes(move.id)) return; - if (move.type === 'Water') { - if (source.useItem()) { - this.add('-enditem', source, 'Water Gem', '[from] gem', '[move] ' + move.name); - source.addVolatile('gem'); - } + if (move.type === 'Water' && source.useItem()) { + source.addVolatile('gem'); } }, num: 549, @@ -6487,10 +6466,14 @@ let BattleItems = { }, onHitPriority: 1, onHit(target, source, move) { - if (target.hp && move.category !== 'Status' && !move.damage && !move.damageCallback && target.getMoveHitData(move).typeMod > 0 && target.useItem()) { - this.boost({atk: 2, spa: 2}); + if (target.hp && move.category !== 'Status' && !move.damage && !move.damageCallback && target.getMoveHitData(move).typeMod > 0) { + target.useItem(); } }, + boosts: { + atk: 2, + spa: 2, + }, num: 639, gen: 6, desc: "If holder is hit super effectively, raises Attack, Sp. Atk by 2 stages. Single use.", diff --git a/sim/battle.ts b/sim/battle.ts index 434d8658fb..247bfc14f3 100644 --- a/sim/battle.ts +++ b/sim/battle.ts @@ -1637,6 +1637,8 @@ export class Battle { if (!effect) break; if (effect.effectType === 'Move') { this.add(msg, target, boostName, boostBy); + } else if (effect.effectType === 'Item') { + this.add(msg, target, boostName, boostBy, '[from] item: ' + effect.name); } else { if (effect.effectType === 'Ability' && !boosted) { this.add('-ability', target, effect.name, 'boost'); diff --git a/sim/global-types.ts b/sim/global-types.ts index b223295b59..58808020eb 100644 --- a/sim/global-types.ts +++ b/sim/global-types.ts @@ -782,6 +782,7 @@ interface ItemData extends EffectData, ItemEventMethods, EventMethods { zMoveFrom?: string zMoveType?: string itemUser?: string[] + boosts?: SparseBoostsTable | false } interface ModdedItemData extends Partial, ModdedEffectData { diff --git a/sim/pokemon.ts b/sim/pokemon.ts index 7bf30e3de4..8c88b12a80 100644 --- a/sim/pokemon.ts +++ b/sim/pokemon.ts @@ -1419,9 +1419,14 @@ export class Pokemon { this.battle.add('-enditem', this, item, '[of] ' + source); break; default: - if (!item.isGem) { + if (item.isGem) { + this.battle.add('-enditem', this, item, '[from] gem'); + } else { this.battle.add('-enditem', this, item); } + if (item.boosts) { + this.battle.boost(item.boosts, this, source, item); + } break; }