/*
* PokemonMove.java
*
* Created on December 15, 2006, 3:42 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, visit the Free Software Foundation, Inc.
* online at http://gnu.org.
*/
package org.pokenet.server.battle.mechanics.moves;
import org.pokenet.server.battle.BattleField;
import org.pokenet.server.battle.BattleTurn;
import org.pokenet.server.battle.Pokemon;
import org.pokenet.server.battle.mechanics.BattleMechanics;
import org.pokenet.server.battle.mechanics.PokemonType;
/**
* This class represents a move that a pokemon can use on its turn.
* @author Colin
*/
public class PokemonMove implements Cloneable {
protected PokemonType m_type;
protected int m_power;
protected double m_accuracy;
protected int m_pp;
protected MoveListEntry m_entry;
/**
* Initialise a typical attacking move.
*/
public PokemonMove(PokemonType type, int power, double accuracy, int pp) {
m_type = type;
m_power = power;
m_accuracy = accuracy;
m_pp = pp;
}
/**
* Set this move's entry in the move list.
*/
/*package*/ void setMoveListEntry(MoveListEntry e) {
m_entry = e;
}
/**
* Return this move's entry in the move list.
*/
public MoveListEntry getMoveListEntry() {
return m_entry;
}
/**
* Return whether this move should use special attack and defence.
*/
public boolean isSpecial(BattleMechanics mech) {
return mech.isMoveSpecial(this);
}
/**
* Clone this move.
*/
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
/* unreachable */
return null;
}
}
/**
* Attempt to hit an enemy.
*/
public boolean attemptHit(BattleMechanics mech, Pokemon user, Pokemon target) {
return mech.attemptHit(this, user, target);
}
/**
* Cause a pokemon to use this move on another pokemon.
*/
public int use(BattleMechanics mech, Pokemon user, Pokemon target) {
int damage = mech.calculateDamage(this, user, target);
target.changeHealth(-damage);
return damage;
}
/**
* Get PP.
*/
public int getPp() {
return m_pp;
}
/**
* Return whether this move deals damage.
*/
public boolean isDamaging() {
return isAttack();
}
/**
* Get accuracy.
*/
public double getAccuracy() {
return m_accuracy;
}
/**
* Set the accuracy of this move.
*/
public void setAccuracy(double accuracy) {
if (accuracy > 1.0) {
m_accuracy = 1.0;
} else if (accuracy < 0.0) {
m_accuracy = 0.0;
} else {
m_accuracy = accuracy;
}
}
/**
* Get the type of this move.
*/
public PokemonType getType() {
return m_type;
}
/**
* Some moves can be used even if a status effect (e.g. sleep) would
* normally prevent it. If this move can be used a such, the class
* of the status effect is returned by this method. Otherwise, the method
* returns null.
*/
@SuppressWarnings("unchecked")
public Class getStatusException() {
return null;
}
/**
* Get the effectiveness of this move against a denfending pokemon.
*/
public double getEffectiveness(Pokemon user, Pokemon defender) {
return getEffectiveness(m_type, user, defender);
}
/**
* Get the effectiveness of one type of move against an arbitrary pokemon.
*/
public static double getEffectiveness(PokemonType type, Pokemon user, Pokemon defender) {
PokemonType[] defTypes = defender.getTypes();
double multiplier = 1.0;
for (int i = 0; i < defTypes.length; ++i) {
double expected = type.getMultiplier(defTypes[i]);
double factor;
PokemonType def = defTypes[i];
if (user != null) {
factor = user.getEffectiveness(type, def, false);
if (factor == expected) {
factor = defender.getEffectiveness(type, def, true);
}
} else {
BattleField field = defender.getField();
factor = field.getEffectiveness(type, def, false);
if (factor == expected) {
factor = field.getEffectiveness(type, def, true);
}
}
multiplier *= factor;
}
return multiplier;
}
/**
* This method is called when a pokemon who has this move is switched into
* the field.
*/
public void switchIn(Pokemon p) {
}
/**
* Return whether this move can strike critical.
*/
public boolean canCriticalHit() {
return true;
}
/**
* Set the type of this move.
*/
public void setType(PokemonType type) {
m_type = type;
}
/**
* Get the power of this move.
*/
public int getPower() {
return m_power;
}
/**
* Set the power of this move.
*/
public void setPower(int power) {
m_power = power;
}
/**
* Get the priority of this move. Priority determines when this move will
* be used during the turn.
*/
public int getPriority() {
return 0;
}
/**
* Determine whether this move has a high chance of striking a critical
* hit.
*/
public boolean hasHighCriticalHitRate() {
return false;
}
/**
* Returns whether this move is an attack. This method is shoddy and should
* be overridden by any exceptions.
*/
public boolean isAttack() {
return m_power != 0;
}
/**
* This function is called at the beginning on a turn on which this move
* is about to be used.
* @param turn the moves about to be used on this turn
* @param index the position of the source pokemon in the turn array
* @param source the pokemon who is using the move
*/
public void beginTurn(BattleTurn[] turn, int index, Pokemon source) {
}
/**
* Return whether this move is buggy.
*/
public boolean isBuggy() {
return false;
}
}