package org.pokenet.server.battle; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import org.pokenet.server.backend.item.DropData; import org.pokenet.server.battle.Pokemon.ExpTypes; import org.pokenet.server.battle.mechanics.PokemonType; import org.pokenet.server.battle.mechanics.StatException; import org.pokenet.server.battle.mechanics.moves.MoveSet; import org.pokenet.server.battle.mechanics.moves.MoveSetData; import org.simpleframework.xml.Element; import org.simpleframework.xml.ElementArray; import org.simpleframework.xml.ElementList; import org.simpleframework.xml.ElementMap; public class PokemonSpecies { private static PokemonSpeciesData m_default = new PokemonSpeciesData(); @Element protected int m_species; @Element protected String m_name; /** * Gender constants. */ public static final int GENDER_MALE = 1; public static final int GENDER_FEMALE = 2; public static final int GENDER_BOTH = GENDER_MALE | GENDER_FEMALE; public static final int GENDER_NONE = 0; @ElementArray transient protected int[] m_base; @ElementArray transient protected PokemonType[] m_type; @Element transient protected int m_genders; // Possible genders. @Element protected String m_internalName; @Element protected String m_kind; @Element protected String m_pokedex; @Element protected String m_type1; @Element(required=false) protected String m_type2; @ElementArray protected int[] m_baseStats = new int[6]; @Element protected int m_rareness; @Element protected int m_baseEXP; @Element protected int m_happiness; @Element protected ExpTypes m_growthRate; @Element protected int m_stepsToHatch; @Element protected String m_color; @Element(required=false) protected String m_habitat; @ElementArray protected int[] m_effortPoints = new int[6]; @ElementList protected String [] m_abilities; @ElementArray protected int[] m_compatibility = new int[2]; @Element protected float m_height; @Element protected float m_weight; @Element protected int m_femalePercentage; @ElementMap protected Map<Integer, String> m_levelMoves; @ElementArray protected String [] m_starterMoves; @ElementArray protected String [] m_eggMoves; @ElementArray protected PokemonEvolution [] m_evolutions; @ElementArray protected String [] m_tmMoves; @ElementArray protected DropData [] m_drops; public DropData [] getDropData() { return m_drops; } public void setDropData(DropData [] d) { m_drops = d; } /** * Returns a random item dropped by the Pokemon, -1 if no item was dropped * @return */ public int getRandomItem() { if(m_drops == null) { System.err.println("INFO: Drop data null for " + m_name); return -1; } if(DataService.getBattleMechanics().getRandom().nextInt(99) < 30) { int r = 100; ArrayList<Integer> m_result = new ArrayList<Integer>(); for(int i = 0; i < m_drops.length; i++) { r = DataService.getBattleMechanics().getRandom().nextInt(100) + 1; if(m_drops[i] != null && r < m_drops[i].getProbability()) m_result.add(m_drops[i].getItemNumber()); } return m_result.size() > 0 ? m_result.get(DataService.getBattleMechanics() .getRandom().nextInt(m_result.size())) : -1; } return - 1; } /** * Returns the pokedex number * @return */ public int getSpeciesNumber() { return m_species; } /** * Return the possible genders for this species. */ public int getPossibleGenders() { return m_genders; } /** * Set the possible genders for this species. */ public void setPossibleGenders(int genders) { m_genders = genders; } /** * Return the default species data. */ public static PokemonSpeciesData getDefaultData() { return m_default; } /** * Set the default species data. */ public static void setDefaultData(PokemonSpeciesData data) { m_default = data; } /** * Get a "balanced" level for this species using this formula: * level = 113 - 0.074 * [base stat total] * This formula places the pokemon's level within the interval [60, 100] * based on base stats. */ public int getBalancedLevel() { int total = 0; for (int i = 0; i < m_base.length; ++i) { total += m_base[i]; } int level = (int)Math.round(113.0 - 0.074 * ((double)total)); if (level < 0) { level = 0; } else if (level > 100) { level = 100; } return level; } /** * Return whether a pokemon can have a particular ability. */ public boolean canUseAbility(PokemonSpeciesData data, String ability) { return data.canUseAbility(m_name, ability); } /** * Return a TreeSet of possible abilities. */ public String[] getPossibleAbilities(PokemonSpeciesData data) { return data.getPossibleAbilities(m_name); } /** * Construct a new pokemon species with arbitrary stats. */ public PokemonSpecies(int species, String name, int[] base, int gender) { m_species = species; m_name = name; m_base = base; m_genders = gender; } private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); } /** * Read a PokemonSpecies from a stream, backed by an arbitrary * PokemonSpeciesData object. */ public synchronized static Object readObject(PokemonSpeciesData data, ObjectInputStream in) throws IOException, ClassNotFoundException { PokemonSpeciesData old = m_default; m_default = data; Object o = in.readObject(); m_default = old; return o; } /** * This methods prevents pokemon with arbitrary base stats from being * loaded. Pokemon are unserialised only by id and their stats are loaded * from that id. * * This method creatively throws an IOException if the species id does not * correspond to a valid pokemon species. * * This method works from the default species data. To use this with * arbitrary species data, use the <code>readFromStream</code> method. */ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); PokemonSpecies species; try { species = m_default.getSpecies(m_species); } catch (PokemonException e) { throw new IOException(); } m_name = species.m_name; m_base = species.m_base; m_type = species.m_type; m_genders = species.m_genders; } /** * Creates a new instance of PokemonSpecies */ public PokemonSpecies(PokemonSpeciesData data, int i) throws PokemonException { this(data.getSpecies(i)); } /** * Allows for construction from another PokemonSpecies. */ public PokemonSpecies(PokemonSpecies i) { m_species = i.m_species; m_name = i.m_name; m_base = i.m_base; m_type = i.m_type; m_genders = i.m_genders; } /** Constructor used for serialization */ public PokemonSpecies() {} public PokemonType[] getTypes() { return m_type; } public int getBase(int i) throws StatException { if ((i < 0) || (i > 5)) throw new StatException(); return m_base[i]; } /** * Get the MoveSet associated with this species. */ public MoveSet getMoveSet(MoveSetData data) { return data.getMoveSet(m_species); } /** * Return whether this species can learn a particular move. */ public boolean canLearn(PokemonSpeciesData data, String move) { return data.canLearn(this, move); } public int getSpecies() { return m_species; } public void setSpecies(int mSpecies) { m_species = mSpecies; } public String getName() { return m_name; } public void setName(String mName) { m_name = mName; } public int[] getBase() { return m_base; } public void setBase(int[] mBase) { m_base = mBase; } public PokemonType[] getType() { return m_type; } public void setType(PokemonType[] mType) { m_type = mType; } public int getGenders() { return m_genders; } public void setGenders(int mGenders) { m_genders = mGenders; } public String getInternalName() { return m_internalName; } public void setInternalName(String mInternalName) { m_internalName = mInternalName; } public String getKind() { return m_kind; } public void setKind(String mKind) { m_kind = mKind; } public String getPokedexInfo() { return m_pokedex; } public void setPokedexInfo(String mPokedex) { m_pokedex = mPokedex; } public String getType1() { return m_type1; } public void setType1(String mType1) { m_type1 = mType1; } public String getType2() { return m_type2; } public void setType2(String mType2) { m_type2 = mType2; } public int[] getBaseStats() { return m_baseStats; } public void setBaseStats(int[] mBaseStats) { m_baseStats = mBaseStats; } public int getRareness() { return m_rareness; } public void setRareness(int mRareness) { m_rareness = mRareness; } public int getBaseEXP() { return m_baseEXP; } public void setBaseEXP(int mBaseEXP) { m_baseEXP = mBaseEXP; } public int getHappiness() { return m_happiness; } public void setHappiness(int mHappiness) { m_happiness = mHappiness; } public ExpTypes getGrowthRate() { return m_growthRate; } public void setGrowthRate(ExpTypes mGrowthRate) { m_growthRate = mGrowthRate; } public int getStepsToHatch() { return m_stepsToHatch; } public void setStepsToHatch(int mStepsToHatch) { m_stepsToHatch = mStepsToHatch; } public String getColor() { return m_color; } public void setColor(String mColor) { m_color = mColor; } public String getHabitat() { return m_habitat; } public void setHabitat(String mHabitat) { m_habitat = mHabitat; } public int[] getEffortPoints() { return m_effortPoints; } public void setEffortPoints(int[] mEffortPoints) { m_effortPoints = mEffortPoints; } public String [] getAbilities() { return m_abilities; } public void setAbilities(String [] mAbilities) { m_abilities = mAbilities; } public int[] getCompatibility() { return m_compatibility; } public void setCompatibility(int[] mCompatibility) { m_compatibility = mCompatibility; } public float getHeight() { return m_height; } public void setHeight(float mHeight) { m_height = mHeight; } public float getWeight() { return m_weight; } public void setWeight(float mWeight) { m_weight = mWeight; } public int getFemalePercentage() { return m_femalePercentage; } public void setFemalePercentage(int mFemalePercentage) { m_femalePercentage = mFemalePercentage; } public Map<Integer, String> getLevelMoves() { return m_levelMoves; } public void setLevelMoves(HashMap<Integer, String> mMoves) { m_levelMoves = mMoves; } public void setStarterMoves(String [] m) { m_starterMoves = m; } public String [] getStarterMoves() { return m_starterMoves; } public String [] getEggMoves() { return m_eggMoves; } public void setEggMoves(String [] mEggMoves) { m_eggMoves = mEggMoves; } public PokemonEvolution [] getEvolutions() { return m_evolutions; } public void setEvolutions(PokemonEvolution [] mEvolutions) { m_evolutions = mEvolutions; } public String [] getTMMoves() { return m_tmMoves; } public void setTMMoves(String [] mPossibleMoves) { m_tmMoves = mPossibleMoves; } }