/*
* HoldItem.java
*
* Created on February 14, 2007, 9:16 PM
*
* This file is a part of Shoddy Battle.
* Copyright (C) 2006 Colin Fitzpatrick
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
package org.pokenet.server.battle.mechanics.statuses.items;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import org.pokenet.server.battle.BattleField;
import org.pokenet.server.battle.Pokemon;
import org.pokenet.server.battle.mechanics.JewelMechanics;
import org.pokenet.server.battle.mechanics.PokemonType;
import org.pokenet.server.battle.mechanics.moves.MoveList;
import org.pokenet.server.battle.mechanics.moves.MoveListEntry;
import org.pokenet.server.battle.mechanics.moves.PokemonMove;
import org.pokenet.server.battle.mechanics.statuses.BurnEffect;
import org.pokenet.server.battle.mechanics.statuses.ConfuseEffect;
import org.pokenet.server.battle.mechanics.statuses.FreezeEffect;
import org.pokenet.server.battle.mechanics.statuses.ParalysisEffect;
import org.pokenet.server.battle.mechanics.statuses.PoisonEffect;
import org.pokenet.server.battle.mechanics.statuses.SleepEffect;
import org.pokenet.server.battle.mechanics.statuses.StatChangeEffect;
import org.pokenet.server.battle.mechanics.statuses.StatusEffect;
import org.pokenet.server.battle.mechanics.statuses.StatusListener;
import org.pokenet.server.battle.mechanics.statuses.ToxicEffect;
import org.pokenet.server.battle.mechanics.statuses.abilities.IntrinsicAbility;
import org.pokenet.server.battle.mechanics.statuses.field.FieldEffect;
/**
* A hold item that cures a status effect.
*/
class StatusCureItem extends HoldItem implements StatusListener, Berry {
private Class<?> m_effect;
public StatusCureItem(String name, Class<?> eff) {
super(name);
m_effect = eff;
}
public boolean isCurable(StatusEffect eff) {
return m_effect.isAssignableFrom(eff.getClass());
}
public void informStatusApplied(Pokemon source, Pokemon p, StatusEffect eff) {
if (isCurable(eff)) {
cureEffect(p, eff);
}
}
public void cureEffect(Pokemon p, StatusEffect eff) {
p.removeStatus(eff);
p.removeStatus(this);
displayCureMessage(p, eff);
}
public void displayCureMessage(Pokemon p, StatusEffect eff) {
p.getField().showMessage(p.getName() + "'s " + getName() + " cured its "
+ eff.getName() + "!");
}
public void executeEffects(Pokemon p) {
List<StatusEffect> statuses = p.getNormalStatuses(StatusEffect.SPECIAL_EFFECT_LOCK);
Iterator<StatusEffect> i = statuses.iterator();
while (i.hasNext()) {
StatusEffect effect = (StatusEffect)i.next();
if (isCurable(effect)) {
cureEffect(p, effect);
}
}
}
public void informStatusRemoved(Pokemon p, StatusEffect eff) {
}
}
class WhiteHerbItem extends StatusCureItem {
public WhiteHerbItem() {
super("White Herb", StatChangeEffect.class);
}
public void displayCureMessage(Pokemon p, StatusEffect eff) {
p.getField().showMessage(p.getName() + "'s White Herb cured its "
+ "status!");
}
public void executeEffects(Pokemon p) {
List<StatusEffect> statuses = p.getNormalStatuses(0);
Iterator<StatusEffect> i = statuses.iterator();
while (i.hasNext()) {
StatusEffect effect = (StatusEffect)i.next();
if (isCurable(effect)) {
cureEffect(p, effect);
}
}
}
}
/**
* A hold item that restores health so long as the holder does not have a
* particular kind of nature; if he does then the item also confuses.
*/
class HealthBoostItem extends HoldItem implements Berry {
private int m_stat;
public HealthBoostItem(String name, int stat) {
super(name);
m_stat = stat;
}
public int getTier() {
return 3;
}
public boolean tick(Pokemon p) {
int hp = p.getHealth();
int max = p.getStat(Pokemon.S_HP);
if ((hp * 2) <= max) {
executeEffects(p);
p.removeStatus(this);
return true;
}
return false;
}
public void executeEffects(Pokemon p) {
p.getField().showMessage(
p.getName() + "'s " + getName() + " restored its health a little!");
// Restore a little health.
p.changeHealth(p.getStat(Pokemon.S_HP) / 8);
// Check if the pokemon hates the berry.
if (p.getNature().getEffect(m_stat) < 1.0) {
// Confuse the pokemon if it hated it.
p.getField().showMessage("The berry was the wrong flavour for " + p.getName() + "!");
p.addStatus(p, new ConfuseEffect());
}
}
}
/**
* A hold item that boosts a stat once health falls below 25%.
*/
class StatBoostItem extends HoldItem implements Berry {
private int m_stat;
public StatBoostItem(String name, int stat) {
super(name);
m_stat = stat;
}
public int getTier() {
return 3;
}
public int getStat(Pokemon p) {
return m_stat;
}
public int getStages() {
return 1;
}
public boolean tick(Pokemon p) {
int hp = p.getHealth();
int max = p.getStat(Pokemon.S_HP);
if (((hp * 4) <= max) || (p.hasAbility("Gluttony") && (hp * 2) <= max)) {
// Boost the stat.
executeEffects(p);
p.removeStatus(this);
return true;
}
return false;
}
public void executeEffects(Pokemon p) {
final int stat = getStat(p);
final int stages = getStages();
StatChangeEffect eff = new StatChangeEffect(stat, true, stages);
eff.setDescription("'s "
+ getName()
+ ((stages > 1) ? " sharply " : "") + " raised its "
+ Pokemon.getStatName(stat) + "!");
p.addStatus(p, eff);
}
}
/**
* A berry that restores a fixed amount of health.
*/
class ConstantHealthBoostItem extends HoldItem implements Berry {
private int m_change;
public ConstantHealthBoostItem(String name, int change) {
super(name);
m_change = change;
}
public void executeEffects(Pokemon p) {
p.getField().showMessage(p.getName() + "'s" + getName() + " restored health!");
p.changeHealth(m_change);
}
public boolean isListener() {
return true;
}
public void informDamaged(Pokemon source, Pokemon target, MoveListEntry entry, int damage) {
if (target.getHealth() <= target.getStat(Pokemon.S_HP) / 2) {
executeEffects(target);
target.removeStatus(this);
}
}
}
/**
* An Arceus plate: boosts the type of one move, and also changes Arceus to
* said type.
* @author Colin
*/
class ArceusPlate extends HoldItem {
private PokemonType[] m_oldType;
private PokemonType m_type;
private double m_factor = 1.1;
public ArceusPlate(String name, PokemonType type) {
super(name);
m_type = type;
}
public void switchIn(Pokemon p) {
BattleField field = p.getField();
if (p.hasAbility("Multitype") && (field != null)) {
field.showMessage("The foe's " + p.getName()
+ " transformed into the " + m_type + " type!");
}
}
public boolean apply(Pokemon p) {
if (p.hasAbility("Multitype")) {
m_oldType = p.getTypes();
p.setType(new PokemonType[] { m_type });
}
return true;
}
public void unapply(Pokemon p) {
if (p.hasAbility("Multitype")) {
p.setType(m_oldType);
}
}
public boolean isMoveTransformer(boolean enemy) {
return !enemy;
}
public MoveListEntry getTransformedMove(Pokemon p, MoveListEntry entry) {
PokemonMove move = entry.getMove();
if (move.getType().equals(m_type)) {
move.setPower((int)((double)move.getPower() * m_factor));
}
if (entry.getName().equals("Judgment")) {
move.setType(m_type);
}
return entry;
}
}
/**
* A hold item that makes one type of move more powerful.
* @author Colin
*/
class TypeBoostItem extends HoldItem {
protected PokemonType m_type;
protected double m_factor = 1.1;
/** Creates a new instance of TypeBoostItem */
public TypeBoostItem(String name, PokemonType type) {
super(name);
m_type = type;
}
public TypeBoostItem(String name, PokemonType type, double factor) {
this(name, type);
m_factor = factor;
}
public boolean isMoveTransformer(boolean enemy) {
return !enemy;
}
/**
* Boost the power of one type of move by 10%.
*/
public MoveListEntry getTransformedMove(Pokemon p, MoveListEntry entry) {
PokemonMove move = entry.getMove();
if (move.getType().equals(m_type)) {
move.setPower((int)((double)move.getPower() * m_factor));
}
return entry;
}
}
/**
* Raises the power of STAB moves for a particular pokemon.
*/
class StabOrbItem extends HoldItem {
private String m_pokemon;
public StabOrbItem(String name, String pokemon) {
super(name);
m_pokemon = pokemon;
}
public boolean isMoveTransformer(boolean enemy) {
return !enemy;
}
public MoveListEntry getTransformedMove(Pokemon p, MoveListEntry entry) {
if (!p.getSpeciesName().equals(m_pokemon)) {
// No effect for Pokemon other than the specified one.
return entry;
}
PokemonMove move = entry.getMove();
PokemonType type = move.getType();
if (p.isType(type)) {
move.setPower((int)((double)move.getPower() * 1.2));
}
return entry;
}
}
/**
* An item that cuts a stat of the opponent when the pokemon with the item
* switches in.
*/
class SwitchInBoostItem extends HoldItem {
private int m_stat;
private double m_mul;
public SwitchInBoostItem(String name, int stat, double mul) {
super(name);
m_stat = stat;
m_mul = mul;
}
public boolean apply(Pokemon p) {
p.getMultiplier(m_stat).multiplyBy(m_mul);
return true;
}
public void unapply(Pokemon p) {
p.getMultiplier(m_stat).divideBy(m_mul);
}
}
/**
* Raise the damage done by one type of move (physical/special).
*/
class SpecialnessBoostItem extends HoldItem {
private boolean m_special;
public SpecialnessBoostItem(String name, boolean special) {
super(name);
m_special = special;
}
public boolean isMoveTransformer(boolean enemy) {
return !enemy;
}
public MoveListEntry getTransformedMove(Pokemon p, MoveListEntry entry) {
PokemonMove move = entry.getMove();
if (move.isSpecial(p.getField().getMechanics()) == m_special) {
move.setPower((int)((double)move.getPower() * 1.1));
}
return entry;
}
}
/**
* Item that applies a special effect to the user.
*/
class SpecialEffectItem extends HoldItem {
private StatusEffect m_effect;
public SpecialEffectItem(String name, StatusEffect effect) {
super(name);
m_effect = effect;
}
public int getTier() {
return 3;
}
public boolean tick(Pokemon p) {
if (!p.hasEffect(StatusEffect.SPECIAL_EFFECT_LOCK)) {
p.addStatus(p, m_effect);
}
return false;
}
}
/**
* Destiny Knot: If attract is applied, foe is also attracted.
*/
class DestinyKnotItem extends HoldItem implements StatusListener {
public DestinyKnotItem() {
super("Destiny Knot");
}
public void informStatusApplied(Pokemon source, Pokemon p, StatusEffect eff) {
if ((eff instanceof MoveList.AttractEffect) && (source != null)) {
source.addStatus(p, eff);
}
}
public void informStatusRemoved(Pokemon p, StatusEffect eff) {
}
}
/**
* Weakens the super-effective moves of one type used against the holder.
*/
class EffectiveMoveWeakener extends HoldItem implements Berry {
private PokemonType m_type;
private boolean m_suitable;
public EffectiveMoveWeakener(String name, PokemonType type) {
super(name);
m_type = type;
}
public boolean isMoveTransformer(boolean enemy) {
return enemy;
}
private boolean isAppropriateMove(Pokemon p, PokemonMove move) {
return (PokemonType.T_NORMAL.equals(m_type)
|| (move.getEffectiveness(p.getOpponent(), p) > 1.0))
&& move.getType().equals(m_type) && move.isDamaging();
}
public MoveListEntry getEnemyTransformedMove(Pokemon p, MoveListEntry entry) {
PokemonMove move = entry.getMove();
m_suitable = (isAppropriateMove(p, move) && !p.hasSubstitute());
if (m_suitable) {
move.setPower((int)(((double)move.getPower()) * 0.5));
}
return entry;
}
public boolean isListener() {
return true;
}
public void informDamaged(Pokemon source, Pokemon target, MoveListEntry entry, int damage) {
@SuppressWarnings("unused")
PokemonMove move = entry.getMove();
if (m_suitable) {
target.getField().showMessage("The " + getName() + " weakened "
+ entry.getName() + "'s power!");
target.removeStatus(this);
}
}
public void executeEffects(Pokemon p) {
// Activating this wouldn't make very much sense.
}
}
/*
* Raises one of Clamperl's stats.
*/
class DeepSeaItem extends HoldItem {
private int m_stat;
public DeepSeaItem(String name, int stat) {
super(name);
m_stat = stat;
}
public boolean isSuitable(Pokemon p) {
return p.getSpeciesName().equals("Clamperl");
}
public boolean apply(Pokemon p) {
if (isSuitable(p)) {
p.getMultiplier(m_stat).multiplyBy(2.0);
}
return super.apply(p);
}
public void unapply(Pokemon p) {
if (isSuitable(p)) {
p.getMultiplier(m_stat).divideBy(2.0);
}
super.unapply(p);
}
}
/**
* This class implements an item that can be held by a pokemon during battle.
* These type of classes basically provide the same functionality as intrinsic
* abilities, so the class inherits from IntrinsicAbility, even though the
* semantic value of this is questionable.
*
* @author Colin
*/
public class HoldItem extends IntrinsicAbility {
private static HoldItemData m_default = new HoldItemData();
static {
new TypeBoostItem("Black Belt", PokemonType.T_FIGHTING);
new TypeBoostItem("BlackGlasses", PokemonType.T_DARK);
new TypeBoostItem("Charcoal", PokemonType.T_FIRE);
new TypeBoostItem("Dragon Fang", PokemonType.T_DRAGON);
new TypeBoostItem("Hard Stone", PokemonType.T_ROCK);
new TypeBoostItem("Magnet", PokemonType.T_ELECTRIC);
new TypeBoostItem("Metal Coat", PokemonType.T_STEEL);
new TypeBoostItem("Miracle Seed", PokemonType.T_GRASS);
new TypeBoostItem("Mystic Water", PokemonType.T_WATER);
new TypeBoostItem("Nevermeltice", PokemonType.T_ICE);
new TypeBoostItem("Poison Barb", PokemonType.T_POISON);
new TypeBoostItem("Sharp Beak", PokemonType.T_FLYING);
new TypeBoostItem("Silk Scarf", PokemonType.T_NORMAL);
new TypeBoostItem("Silverpowder", PokemonType.T_BUG);
new TypeBoostItem("Soft Sand", PokemonType.T_GROUND);
new TypeBoostItem("Spell Tag", PokemonType.T_GHOST);
new TypeBoostItem("Twisted Spoon", PokemonType.T_PSYCHIC);
new StatBoostItem("Liechi Berry", Pokemon.S_ATTACK);
new StatBoostItem("Ganlon Berry", Pokemon.S_DEFENCE);
new StatBoostItem("Salac Berry", Pokemon.S_SPEED);
new StatBoostItem("Petaya Berry", Pokemon.S_SPATTACK);
new StatBoostItem("Apicot Berry", Pokemon.S_SPDEFENCE);
// new StatBoostItem("Lansat Berry", Pokemon.S_CRITICAL_HITS);
new StatBoostItem("Starf Berry", -1) {
public int getStat(Pokemon p) {
Random random = p.getField().getMechanics().getRandom();
return random.nextInt(5) + 1;
}
public int getStages() {
return 2;
}
};
new HealthBoostItem("Figy Berry", Pokemon.S_ATTACK);
new HealthBoostItem("Wiki Berry", Pokemon.S_SPATTACK);
new HealthBoostItem("Mago Berry", Pokemon.S_SPEED);
new HealthBoostItem("Aguav Berry", Pokemon.S_SPDEFENCE);
new HealthBoostItem("Iapapa Berry", Pokemon.S_DEFENCE);
new ConstantHealthBoostItem("Oran Berry", 10);
new ConstantHealthBoostItem("Sitrus Berry", 30);
new StatusCureItem("Aspear Berry", FreezeEffect.class);
new StatusCureItem("Cheri Berry", ParalysisEffect.class);
new StatusCureItem("Chesto Berry", SleepEffect.class);
// Note: self-referential just for fun; parameter is unused.
new StatusCureItem("Lum Berry", Class.class) {
public boolean isCurable(StatusEffect eff) {
return (eff.getLock() == StatusEffect.SPECIAL_EFFECT_LOCK)
|| (eff instanceof ConfuseEffect);
}
};
new StatusCureItem("Pecha Berry", PoisonEffect.class);
new StatusCureItem("Persim Berry", ConfuseEffect.class);
new StatusCureItem("Rawst Berry", BurnEffect.class);
new StatusCureItem("Mental Herb", MoveList.AttractEffect.class);
new WhiteHerbItem();
new HoldItem("Leftovers") {
public int getTier() {
return 3;
}
public boolean tick(Pokemon p) {
int max = p.getStat(Pokemon.S_HP);
if (p.getHealth() < max) {
int restore = max / 16;
p.getField().showMessage(p.getName()
+ "'s leftovers restored its health a little!");
p.changeHealth(restore);
}
return false;
}
};
new ChoiceBandItem("Choice Band", Pokemon.S_ATTACK);
new HoldItem("Thick Club") {
public boolean isSuitable(Pokemon p) {
String name = p.getSpeciesName();
return (name.equals("Cubone") || name.equals("Marowak"));
}
public boolean apply(Pokemon p) {
if (isSuitable(p)) {
p.getMultiplier(Pokemon.S_ATTACK).multiplyBy(2.0);
}
return true;
}
public void unapply(Pokemon p) {
if (isSuitable(p)) {
p.getMultiplier(Pokemon.S_ATTACK).divideBy(2.0);
}
}
};
new HoldItem("Metal Powder") {
public boolean isSuitable(Pokemon p) {
return p.getSpeciesName().equals("Ditto");
}
public boolean apply(Pokemon p) {
if (isSuitable(p)) {
//TODO: these effects should be removed when transformed
p.getMultiplier(Pokemon.S_DEFENCE).multiplyBy(2.0);
p.getMultiplier(Pokemon.S_SPDEFENCE).multiplyBy(2.0);
}
return true;
}
public void unapply(Pokemon p) {
if (isSuitable(p)) {
p.getMultiplier(Pokemon.S_DEFENCE).multiplyBy(2.0);
p.getMultiplier(Pokemon.S_SPDEFENCE).multiplyBy(2.0);
}
}
};
/** Diamond/Pearl-exclusive items begin here. */
new ChoiceBandItem("Choice Specs", Pokemon.S_SPATTACK);
// Arceus plates.
new ArceusPlate("Draco Plate", PokemonType.T_DRAGON);
new ArceusPlate("Dread Plate", PokemonType.T_DARK);
new ArceusPlate("Earth Plate", PokemonType.T_GROUND);
new ArceusPlate("Flame Plate", PokemonType.T_FIRE);
new ArceusPlate("Fist Plate", PokemonType.T_FIGHTING);
new ArceusPlate("Icicle Plate", PokemonType.T_ICE);
new ArceusPlate("Insect Plate", PokemonType.T_BUG);
new ArceusPlate("Iron Plate", PokemonType.T_STEEL);
new ArceusPlate("Meadow Plate", PokemonType.T_GRASS);
new ArceusPlate("Mind Plate", PokemonType.T_PSYCHIC);
new ArceusPlate("Sky Plate", PokemonType.T_FLYING);
new ArceusPlate("Splash Plate", PokemonType.T_WATER);
new ArceusPlate("Stone Plate", PokemonType.T_ROCK);
new ArceusPlate("Toxic Plate", PokemonType.T_POISON);
new ArceusPlate("Zap Plate", PokemonType.T_ELECTRIC);
// TODO (tbd) : Full Incense
new SwitchInBoostItem("Lax Incense", Pokemon.S_EVASION, 1.05);
new HoldItem("Luck Incense"); // Does nothing.
new HoldItem("Pure Incense"); // Does nothing.
new TypeBoostItem("Odd Incense", PokemonType.T_PSYCHIC);
new TypeBoostItem("Rock Incense", PokemonType.T_ROCK);
new TypeBoostItem("Rose Incense", PokemonType.T_GRASS);
new TypeBoostItem("Sea Incense", PokemonType.T_WATER, 1.05);
new TypeBoostItem("Wave Incense", PokemonType.T_WATER);
new StabOrbItem("Adamant Orb", "Dialga");
new StabOrbItem("Lustrous Orb", "Palkia");
new HoldItem("Black Sludge") {
public int getTier() {
return 3;
}
public boolean tick(Pokemon p) {
int max = p.getStat(Pokemon.S_HP);
int delta = max / 16;
boolean damage = !p.isType(PokemonType.T_POISON);
if (damage) {
p.getField().showMessage(p.getName()
+ " was damaged by Black Sludge!");
p.changeHealth(-delta, true);
} else if (p.getHealth() < max) {
p.getField().showMessage(p.getName()
+ "'s Black Sludge restored a little health!");
p.changeHealth(delta);
}
return false;
}
};
new HoldItem("Blue Scarf"); // Does nothing.
new SwitchInBoostItem("Brightpowder", Pokemon.S_EVASION, 1.10);
new SpecialnessBoostItem("Muscle Band", false);
new DestinyKnotItem();
new HoldItem("Scope Lens");
new HoldItem("Life Orb") {
public void switchIn(Pokemon p) {
p.getField().applyEffect(new FieldEffect() {
private boolean[] m_damaged = new boolean[2];
public boolean applyToField(BattleField field) {
return true;
}
public int getTier() {
return -1;
}
public boolean apply(Pokemon p) {
m_damaged[p.getParty()] = false;
return true;
}
public void beginTick() {
super.beginTick();
Arrays.fill(m_damaged, false);
}
public String getName() {
return null;
}
public String getDescription() {
return null;
}
public boolean tickField(BattleField field) {
return false;
}
public boolean isListener() {
return true;
}
public void informDamaged(Pokemon source, Pokemon target, MoveListEntry move, int damage) {
if (source.getItemName().equals("Life Orb")) {
int idx = source.getParty();
if (!m_damaged[idx]) {
m_damaged[idx] = true;
source.changeHealth(-source.getStat(Pokemon.S_HP) / 10, true);
}
}
}
public boolean isMoveTransformer(boolean enemy) {
return !enemy;
}
public MoveListEntry getTransformedMove(Pokemon p, MoveListEntry entry) {
if (p.getItemName().equals("Life Orb")) {
PokemonMove move = entry.getMove();
move.setPower((int)(((double)move.getPower()) * 1.3));
}
return entry;
}
});
}
};
new HoldItem("Light Ball") {
public void modifyStats(Pokemon p, boolean apply) {
if (!p.getSpeciesName().equals("Pikachu")) {
return;
}
BattleField field = p.getField();
boolean dp = ((field != null) &&
(field.getMechanics() instanceof JewelMechanics));
if (apply) {
if (dp) {
p.getMultiplier(Pokemon.S_ATTACK).multiplyBy(2.0);
}
p.getMultiplier(Pokemon.S_SPATTACK).multiplyBy(2.0);
} else {
if (dp) {
p.getMultiplier(Pokemon.S_ATTACK).divideBy(2.0);
}
p.getMultiplier(Pokemon.S_SPATTACK).divideBy(2.0);
}
}
public boolean apply(Pokemon p) {
modifyStats(p, true);
return super.apply(p);
}
public void unapply(Pokemon p) {
modifyStats(p, false);
}
};
new HoldItem("Wide Lens") {
public boolean isMoveTransformer(boolean enemy) {
return !enemy;
}
public MoveListEntry getTransformedMove(Pokemon p, MoveListEntry entry) {
PokemonMove move = entry.getMove();
move.setAccuracy(move.getAccuracy() * 1.1);
return entry;
}
};
new HoldItem("Expert Belt") {
public boolean isMoveTransformer(boolean enemy) {
return !enemy;
}
public MoveListEntry getTransformedMove(Pokemon p, MoveListEntry entry) {
PokemonMove move = entry.getMove();
if (move.getEffectiveness(p, p.getOpponent()) > 1.0) {
move.setPower((int)(((double)move.getPower()) * 1.2));
}
return entry;
}
};
new SpecialnessBoostItem("Wise Glasses", true);
new ChoiceBandItem("Choice Scarf", Pokemon.S_SPEED);
new SpecialEffectItem("Toxic Orb", new ToxicEffect());
new SpecialEffectItem("Flame Orb", new BurnEffect());
new EffectiveMoveWeakener("Occa Berry", PokemonType.T_FIRE);
new EffectiveMoveWeakener("Passho Berry", PokemonType.T_WATER);
new EffectiveMoveWeakener("Wacan Berry", PokemonType.T_ELECTRIC);
new EffectiveMoveWeakener("Rindo Berry", PokemonType.T_GRASS);
new EffectiveMoveWeakener("Yache Berry", PokemonType.T_ICE);
new EffectiveMoveWeakener("Chople Berry", PokemonType.T_FIGHTING);
new EffectiveMoveWeakener("Kebia Berry", PokemonType.T_POISON);
new EffectiveMoveWeakener("Shuca Berry", PokemonType.T_GROUND);
new EffectiveMoveWeakener("Coba Berry", PokemonType.T_FLYING);
new EffectiveMoveWeakener("Payapa Berry", PokemonType.T_PSYCHIC);
new EffectiveMoveWeakener("Tanga Berry", PokemonType.T_BUG);
new EffectiveMoveWeakener("Charti Berry", PokemonType.T_ROCK);
new EffectiveMoveWeakener("Kasib Berry", PokemonType.T_GHOST);
new EffectiveMoveWeakener("Haban Berry", PokemonType.T_DRAGON);
new EffectiveMoveWeakener("Colbur Berry", PokemonType.T_DARK);
new EffectiveMoveWeakener("Babiri Berry", PokemonType.T_STEEL);
new EffectiveMoveWeakener("Chilan Berry", PokemonType.T_NORMAL);
new HoldItem("Soul Dew") {
public boolean isSuitable(Pokemon p) {
String name = p.getSpeciesName();
return (name.equals("Latios") || name.equals("Latias"));
}
public boolean apply(Pokemon p) {
if (isSuitable(p)) {
p.getMultiplier(Pokemon.S_SPATTACK).multiplyBy(1.5);
p.getMultiplier(Pokemon.S_SPDEFENCE).multiplyBy(1.5);
}
return true;
}
public void unapply(Pokemon p) {
if (isSuitable(p)) {
p.getMultiplier(Pokemon.S_SPATTACK).divideBy(1.5);
p.getMultiplier(Pokemon.S_SPDEFENCE).divideBy(1.5);
}
}
};
/** The actual logic for these two is in shoddybattle.Pokemon
* It is a bit ugly, but oh well. */
new HoldItem("Focus Sash");
new HoldItem("Focus Band");
// The implementation of these is in WeatherMove.
new HoldItem("Heat Rock");
new HoldItem("Damp Rock");
new HoldItem("Icy Rock");
new HoldItem("Smooth Rock");
// The implementation for this is in MoveList.TrappingEffect.
new HoldItem("Shed Shell");
/** The implementation for this is in the stupidly named
* MoveList.StatCutEffect class. */
new HoldItem("Light Clay");
new DeepSeaItem("Deepseatooth", Pokemon.S_SPATTACK);
new DeepSeaItem("Deepseascale", Pokemon.S_SPDEFENCE);
new HoldItem("Metronome") {
private int m_level = 0;
private MoveListEntry m_choice = null;
public void switchIn(Pokemon p) {
m_choice = null;
}
public boolean apply(Pokemon p) {
m_choice = null;
return true;
}
public boolean isMoveTransformer(boolean enemy) {
return !enemy;
}
public MoveListEntry getTransformedMove(Pokemon p, MoveListEntry entry) {
if (m_choice == null) {
m_choice = entry;
m_level = 0;
} else if (entry.equals(m_choice)) {
++m_level;
} else {
m_choice = null;
return entry;
}
PokemonMove move = entry.getMove();
move.setPower(move.getPower() * (10 + m_level) / 10);
return entry;
}
};
new HoldItem("Macho Brace") {
public boolean apply(Pokemon p) {
p.getMultiplier(Pokemon.S_SPEED).divideBy(2.0);
return super.apply(p);
}
public void unapply(Pokemon p) {
p.getMultiplier(Pokemon.S_SPEED).multiplyBy(2.0);
}
};
new HoldItem("Shell Bell") {
public void switchIn(Pokemon p) {
p.getField().applyEffect(new FieldEffect() {
private boolean[] m_damaged = new boolean[2];
public boolean applyToField(BattleField field) {
return true;
}
public int getTier() {
return -1;
}
public boolean apply(Pokemon p) {
m_damaged[p.getParty()] = false;
return true;
}
public void beginTick() {
super.beginTick();
Arrays.fill(m_damaged, false);
}
public String getName() {
return null;
}
public String getDescription() {
return null;
}
public boolean tickField(BattleField field) {
return false;
}
public boolean isListener() {
return true;
}
public void informDamaged(Pokemon source, Pokemon target, MoveListEntry move, int damage) {
if (source.getItemName().equals("Shell Bell")) {
int idx = source.getParty();
if (!m_damaged[idx]) {
m_damaged[idx] = true;
source.getField().showMessage(source.getName() + "'s Shell Bell " +
"restored a little health!");
int change = damage / 8;
if (change < 1) change = 1;
source.changeHealth(change);
}
}
}
});
}
};
}
protected void registerAbility() {
super.registerAbility();
m_default.m_items.add(getName());
}
/**
* Return the default item data.
*/
public static HoldItemData getDefaultData() {
return m_default;
}
/**
* Initialise a HoldItem that can be used only by certain named pokemon.
*/
public HoldItem(String name, String[] pokemon) {
super(false, name);
for (int i = 0; i < pokemon.length; ++i) {
m_default.addExclusiveItem(name, pokemon[i]);
}
}
public HoldItem(boolean register, String name) {
super(register, name);
}
/** Creates a new instance of HoldItem */
public HoldItem(String name) {
super(name);
}
}