/**
* Copyright (C) 2013 Gundog Studios LLC.
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
package com.godsandtowers.sprites;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
public class BaseTower implements Upgradeable, Externalizable {
// ICE
public static final String WATER_CANNON = "water_cannon";
public static final String WATER_CATAPULT = "water_catapult";
public static final String WATER_PILLAR = "water_pillar";
public static final String WATER_EMITTER = "water_emitter";
// WIND
public static final String LIGHTNING_CANNON = "lightning_cannon";
public static final String GRIFFIN_STATUE = "griffin_statue";
public static final String LIGHTNING_PILLAR = "lightning_pillar";
public static final String LIGHTNING_EMITTER = "lightning_emitter";
// EARTH
public static final String ROCK_CANNON = "rock_cannon";
public static final String STONE_CATAPULT = "stone_catapult";
public static final String EARTH_PILLAR = "earth_pillar";
public static final String DIRT_EMITTER = "dirt_emitter";
// FIRE
public static final String FLAME_CANNON = "flame_cannon";
public static final String FLAME_CATAPULT = "flame_catapult";
public static final String FIRE_PILLAR = "fire_pillar";
public static final String FIRE_EMITTER = "fire_emitter";
// LIFE
public static final String ENERGY_CANNON = "energy_cannon";
public static final String ANGEL_STATUE = "angel_statue";
public static final String LIFE_PILLAR = "life_pillar";
public static final String HOLY_WATER_EMITTER = "holy_water_emitter";
// DEATH
public static final String POISON_CANNON = "poison_cannon";
public static final String GARGOYLE_STATUE = "gargoyle_statue";
public static final String UNDEAD_PILLAR = "undead_pillar";
public static final String TOXIC_GAS_EMITTER = "toxic_gas_emitter";
// COMBO
public static final String FLAME_WHIP = "flame_whip";
public static final String WATER_WHIP = "water_whip";
public static final String TENTICAL_WHIP = "tentical_whip";
public static final String FLAME_CRYSTALLIZER = "flame_crystallizer";
public static final String ICE_CRYSTALLIZER = "ice_crystallizer";
public static final String EARTH_CRYSTALLIZER = "earth_crystallizer";
public static final String LIGHTNING_BLADE = "lightning_blade";
public static final String ICE_BLADE = "ice_blade";
public static final String FLAME_BLADE = "flame_blade";
public static final String EARTH_BALLISTA = "earth_ballista";
public static final String ICE_BALLISTA = "ice_ballista";
public static final String FLAME_BALLISTA = "flame_ballista";
private static final BaseTower[] BASE_TOWERS = {
new BaseTower(WATER_CANNON, 1, 5.0f, 6.0f, 20.0f, 1.0f, 3000.0f, 3f, true, true, false, false, true),
new BaseTower(ENERGY_CANNON, 16, 6.0f, 6.0f, 20.0f, 1.0f, 3000.0f, 3f, true, true, false, false, true),
new BaseTower(POISON_CANNON, 32, 7.0f, 6.0f, 20.0f, 1.0f, 3000.0f, 3f, true, true, false, false, true),
new BaseTower(LIGHTNING_CANNON, 2, 8.0f, 6.0f, 20.0f, 1.0f, 3000.0f, 3f, true, true, false, false, true),
new BaseTower(ROCK_CANNON, 4, 9.0f, 5.0f, 20.0f, 1.0f, 4000.0f, 3f, true, true, false, false, true),
new BaseTower(FLAME_CANNON, 8, 10.0f, 3.0f, 20.0f, 1.0f, 4000.0f, 3f, true, true, false, false, true),
new BaseTower(DIRT_EMITTER, 4, 11.0f, 2.0f, 40.0f, 1.0f, 4000.0f, 1.5f, true, false, true, true, true),
new BaseTower(FIRE_EMITTER, 8, 12.0f, 3.0f, 40.0f, 1.0f, 4000.0f, 1.5f, true, false, true, true, true),
new BaseTower(HOLY_WATER_EMITTER, 16, 13.0f, 6.0f, 40.0f, 1.0f, 4000.0f, 1.5f, true, false, true, true,
true),
new BaseTower(TOXIC_GAS_EMITTER, 32, 14.0f, 6.0f, 40.0f, 1.0f, 4000.0f, 1.5f, true, false, true, true, true),
new BaseTower(WATER_EMITTER, 1, 15.0f, 6.0f, 40.0f, 1.0f, 4000.0f, 1.5f, true, false, true, true, true),
new BaseTower(LIGHTNING_EMITTER, 2, 16.0f, 6.0f, 40.0f, 1.0f, 8000.0f, 1.5f, true, false, true, true, true),
new BaseTower(TENTICAL_WHIP, 34, 17.0f, 50.0f, 60.0f, 2.0f, 2000.0f, 1.5f, true, false, false, true, true),
new BaseTower(WATER_WHIP, 3, 18.0f, 50.0f, 60.0f, 2.0f, 2000.0f, 1.5f, true, false, false, true, true),
new BaseTower(FLAME_WHIP, 10, 19.0f, 50.0f, 60.0f, 2.0f, 2000.0f, 1.5f, true, false, false, true, true),
new BaseTower(ICE_CRYSTALLIZER, 17, 20.0f, 40.0f, 60.0f, 2.0f, 3000.0f, 3.0f, true, true, false, false,
true),
new BaseTower(EARTH_CRYSTALLIZER, 20, 21.0f, 55.0f, 60.0f, 2.0f, 3000.0f, 3.0f, true, true, false, false,
true),
new BaseTower(FLAME_CRYSTALLIZER, 24, 22.0f, 25.0f, 60.0f, 2.0f, 3000.0f, 3.0f, true, true, false, false,
true),
new BaseTower(GRIFFIN_STATUE, 2, 23.0f, 24.0f, 80.0f, 2.0f, 3000.0f, 1.5f, true, false, false, true, true),
new BaseTower(ANGEL_STATUE, 16, 24.0f, 24.0f, 80.0f, 2.0f, 2000.0f, 1.5f, true, false, false, true, true),
new BaseTower(GARGOYLE_STATUE, 32, 25.0f, 25.0f, 80.0f, 2.0f, 2000.0f, 1.5f, true, false, false, true, true),
new BaseTower(WATER_CATAPULT, 1, 26.0f, 52.0f, 80.0f, 1.0f, 3000.0f, 5f, true, false, false, false, true),
new BaseTower(STONE_CATAPULT, 4, 27.0f, 20.0f, 80.0f, 1.0f, 4000.0f, 5f, true, false, false, false, true),
new BaseTower(FLAME_CATAPULT, 8, 28.0f, 14.0f, 80.0f, 1.0f, 4000.0f, 5f, true, false, false, false, true),
new BaseTower(ICE_BLADE, 5, 29.0f, 90.0f, 100.0f, 2.0f, 2000.0f, 1.5f, true, false, false, true, true),
new BaseTower(FLAME_BLADE, 12, 30.0f, 60.0f, 100.0f, 2.0f, 2000.0f, 1.5f, true, false, false, true, true),
new BaseTower(LIGHTNING_BLADE, 18, 31.0f, 70.0f, 100.0f, 2.0f, 2000.0f, 1.5f, true, false, false, true,
true),
new BaseTower(EARTH_BALLISTA, 36, 32.0f, 150.0f, 100.0f, 1.0f, 4000.0f, 5.0f, true, false, false, false,
true),
new BaseTower(ICE_BALLISTA, 33, 33.0f, 90.0f, 100.0f, 1.0f, 4000.0f, 5.0f, true, false, false, false, true),
new BaseTower(FLAME_BALLISTA, 40, 34.0f, 70.0f, 100.0f, 1.0f, 4000.0f, 5.0f, true, false, false, false,
true),
new BaseTower(WATER_PILLAR, 1, 35.0f, 60.0f, 120.0f, 2.0f, 3000.0f, 3.0f, true, true, false, false, true),
new BaseTower(LIGHTNING_PILLAR, 2, 36.0f, 30.0f, 120.0f, 2.0f, 3000.0f, 3.0f, true, true, false, false,
true),
new BaseTower(LIFE_PILLAR, 16, 37.0f, 30.0f, 120.0f, 2.0f, 3000.0f, 3.0f, true, true, false, false, true),
new BaseTower(UNDEAD_PILLAR, 32, 38.0f, 30.0f, 120.0f, 2.0f, 3000.0f, 3.0f, true, true, false, false, true),
new BaseTower(EARTH_PILLAR, 4, 39.0f, 25.0f, 120.0f, 2.0f, 3000.0f, 3.0f, true, true, false, false, true),
new BaseTower(FIRE_PILLAR, 8, 40.0f, 10.0f, 120.0f, 2.0f, 3000.0f, 3.0f, true, true, false, false, true), };
public static BaseTower createUpgrade(BaseTower tower) {
BaseTower upgrade = new BaseTower(tower);
upgrade.cost *= 2;
upgrade.damage *= 2;
upgrade.health *= 2;
upgrade.defense *= 1.25;
upgrade.level += 1;
upgrade.calculatePower();
return upgrade;
}
public static BaseTower[] getBaseTowers() {
BaseTower[] newList = new BaseTower[BASE_TOWERS.length];
for (int j = 0; j < BASE_TOWERS.length; j++) {
newList[j] = new BaseTower(BASE_TOWERS[j]);
}
return newList;
};
public static BaseTower getBaseTower(BaseTower[] towers, String name) {
for (BaseTower tower : towers) {
if (tower.getName().equals(name))
return tower;
}
return null;
}
// upgradeable stats
private static final float HEALTH_UPGRADE_RATE = 2f;
private static final float DEFENSE_UPGRADE_RATE = 1.25f;
private static final float DAMAGE_UPGRADE_RATE = 2f;
private static final float ATTACK_RATE_UPGRADE_RATE = .9f;
private float damage;
private float health;
private float attackRate;
private float defense;
private int healthUpgradeCount = 1;
private int defenseUpgradeCount = 1;
private int damageUpgradeCount = 1;
private int attackRateUpgradeCount = 1;
private int totalUpgradeCount = 1;
private int level = 1;
// other stats
private boolean unlocked;
private String name;
private int races;
private float attackRange;
private boolean attacksGround;
private boolean attacksAir;
private boolean attacksAllInRange;
private boolean attacksInstantly;
private float cost;
private float power;
public BaseTower() {
}
public BaseTower(BaseTower tower) {
this(tower.name, tower.races, tower.cost, tower.damage, tower.health, tower.defense, tower.attackRate,
tower.attackRange, tower.attacksGround, tower.attacksAir, tower.attacksAllInRange,
tower.attacksInstantly, tower.unlocked);
this.level = tower.level;
this.totalUpgradeCount = tower.totalUpgradeCount;
this.power = tower.power;
}
public BaseTower(String name, int races, float cost, float damage, float health, float defense, float attackRate,
float attackRange, boolean attacksGround, boolean attacksAir, boolean attacksAllInRange,
boolean attacksInstantly, boolean unlocked) {
this.name = name;
this.races = races;
this.cost = cost;
this.damage = damage;
this.health = health;
this.attackRate = attackRate;
this.attackRange = attackRange;
this.defense = defense;
this.attacksGround = attacksGround;
this.attacksAir = attacksAir;
this.attacksAllInRange = attacksAllInRange;
this.attacksInstantly = attacksInstantly;
this.unlocked = unlocked;
calculatePower();
}
private void calculatePower() {
power = totalUpgradeCount * cost / 100f;
}
public float getPower() {
return power;
}
public int getTotalUpgradeCount() {
return totalUpgradeCount;
}
public int getLevel() {
return level;
}
public boolean attacksAllInRange() {
return attacksAllInRange;
}
public boolean attacksInstantly() {
return attacksInstantly;
}
public int getRaces() {
return races;
}
public boolean isUnlocked() {
return true;// unlocked;
}
public void setUnlocked(boolean unlocked) {
this.unlocked = unlocked;
}
public float getDamage() {
return damage;
}
public float getHealth() {
return health;
}
public float getAttackRate() {
return attackRate;
}
public float getAttackRange() {
return attackRange;
}
public float getDefense() {
return defense;
}
public boolean attacksGround() {
return attacksGround;
}
public boolean attacksAir() {
return attacksAir;
}
public float getCost() {
return cost;
}
public void setDamage(float damage) {
this.damage = damage;
}
public void setAttackRate(float attackRate) {
this.attackRate = attackRate;
}
public void setAttackRange(float attackRange) {
this.attackRange = attackRange;
}
@Override
public String toString() {
return name.toUpperCase() + "," + races + "," + cost + "f," + damage + "f," + health + "f," + defense + "f,"
+ attackRate + "f," + attackRange + "f," + attacksGround + "," + attacksAir + "," + attacksAllInRange
+ "," + attacksInstantly + "," + unlocked + "," + power;
}
private static final int HEALTH_ID = 1;
private static final int DEFENSE_ID = 2;
private static final int DAMAGE_ID = 3;
private static final int ATTACK_RATE_ID = 4;
private static final String HEALTH = "stat_health";
private static final String DEFENSE = "stat_defense";
private static final String DAMAGE = "stat_damage";
private static final String ATTACK_RATE = "stat_attack_rate";
@Override
public String getName() {
return name;
}
@Override
public String getUpgradeName(int id) {
switch (id) {
case HEALTH_ID:
return HEALTH;
case DEFENSE_ID:
return DEFENSE;
case DAMAGE_ID:
return DAMAGE;
case ATTACK_RATE_ID:
return ATTACK_RATE;
default:
throw new RuntimeException("Unknown getUpgradeCost ID: " + id);
}
}
@Override
public int[] getUpgradeIDs() {
return new int[] { HEALTH_ID, DEFENSE_ID, DAMAGE_ID, ATTACK_RATE_ID };
}
@Override
public long getUpgradeCost(int id) {
switch (id) {
case HEALTH_ID:
return (long) Math.pow(5, healthUpgradeCount);
case DEFENSE_ID:
return (long) Math.pow(5, defenseUpgradeCount);
case DAMAGE_ID:
return (long) Math.pow(5, damageUpgradeCount);
case ATTACK_RATE_ID:
return (long) Math.pow(5, attackRateUpgradeCount);
default:
throw new RuntimeException("Unknown getUpgradeCost ID: " + id);
}
}
@Override
public float getBaseValue(int id) {
switch (id) {
case HEALTH_ID:
return health;
case DEFENSE_ID:
return defense;
case DAMAGE_ID:
return damage;
case ATTACK_RATE_ID:
return attackRate;
default:
throw new RuntimeException("Unknown getBaseValue ID: " + id);
}
}
@Override
public float getUpgradedValue(int id) {
switch (id) {
case HEALTH_ID:
return health * HEALTH_UPGRADE_RATE;
case DEFENSE_ID:
return defense * DEFENSE_UPGRADE_RATE;
case DAMAGE_ID:
return damage * DAMAGE_UPGRADE_RATE;
case ATTACK_RATE_ID:
return attackRate * ATTACK_RATE_UPGRADE_RATE;
default:
throw new RuntimeException("Unknown getUpgradedValue ID: " + id);
}
}
@Override
public void upgrade(int id) {
switch (id) {
case HEALTH_ID:
health *= HEALTH_UPGRADE_RATE;
healthUpgradeCount++;
break;
case DEFENSE_ID:
defense *= DEFENSE_UPGRADE_RATE;
defenseUpgradeCount++;
break;
case DAMAGE_ID:
damage *= DAMAGE_UPGRADE_RATE;
damageUpgradeCount++;
break;
case ATTACK_RATE_ID:
attackRate *= ATTACK_RATE_UPGRADE_RATE;
attackRateUpgradeCount++;
break;
default:
throw new RuntimeException("Unknown upgrade ID: " + id);
}
totalUpgradeCount++;
}
@Override
public int getUpgradeCount(int id) {
switch (id) {
case HEALTH_ID:
return healthUpgradeCount;
case DEFENSE_ID:
return defenseUpgradeCount;
case DAMAGE_ID:
return damageUpgradeCount;
case ATTACK_RATE_ID:
return attackRateUpgradeCount;
default:
throw new RuntimeException("Unknown getBaseValue ID: " + id);
}
}
@Override
public void readExternal(ObjectInput input) throws IOException, ClassNotFoundException {
name = (String) input.readObject();
unlocked = input.readBoolean();
races = input.readInt();
damage = input.readFloat();
health = input.readFloat();
attackRate = input.readFloat();
defense = input.readFloat();
attackRange = input.readFloat();
attacksGround = input.readBoolean();
attacksAir = input.readBoolean();
attacksAllInRange = input.readBoolean();
attacksInstantly = input.readBoolean();
cost = input.readFloat();
power = input.readFloat();
level = input.readInt();
healthUpgradeCount = input.readInt();
defenseUpgradeCount = input.readInt();
damageUpgradeCount = input.readInt();
attackRateUpgradeCount = input.readInt();
totalUpgradeCount = input.readInt();
}
@Override
public void writeExternal(ObjectOutput output) throws IOException {
output.writeObject(name);
output.writeBoolean(unlocked);
output.writeInt(races);
output.writeFloat(damage);
output.writeFloat(health);
output.writeFloat(attackRate);
output.writeFloat(defense);
output.writeFloat(attackRange);
output.writeBoolean(attacksGround);
output.writeBoolean(attacksAir);
output.writeBoolean(attacksAllInRange);
output.writeBoolean(attacksInstantly);
output.writeFloat(cost);
output.writeFloat(power);
output.writeInt(level);
output.writeInt(healthUpgradeCount);
output.writeInt(defenseUpgradeCount);
output.writeInt(damageUpgradeCount);
output.writeInt(attackRateUpgradeCount);
output.writeInt(totalUpgradeCount);
}
}