/**
* 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;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import com.godsandtowers.core.PlayerStats;
import com.godsandtowers.core.grid.Grid;
import com.godsandtowers.messaging.ViewMessageProcessor;
import com.gundogstudios.gl.Sprite;
import com.gundogstudios.modules.Modules;
import com.gundogstudios.util.FastMath;
public class Player implements Externalizable {
private static final int AUTO_BUY_DELAY = 1000;// ms
protected static final float COST_VS_INCOME_UPGRADE_FACTOR = 4f;
protected int id;
protected PlayerStats playerStats;
protected float income;
protected float gold;
protected float life;
protected float costUpgradeThreshold;
protected int creatureLevel;
protected boolean attacking;
protected Race race;
protected Grid grid;
protected BaseTower[] sortedTowers;
protected BaseCreature[] sortedCreatures;
protected HashMap<Integer, HashMap<String, BaseTower>> towers;
protected HashMap<String, BaseCreature> creatures;
protected HashMap<String, BaseSpecial> specials;
protected String autoBuyCreatureName;
private int autoBuyCooldown;
public Player() {
}
public Player(int id, PlayerStats playerStats, int races, Grid grid) {
this.playerStats = playerStats;
this.id = id;
this.grid = grid;
this.race = new Race(playerStats.getBaseRace(), races);
this.attacking = false;
this.creatureLevel = 1;
this.autoBuyCreatureName = null;
autoBuyCooldown = 0;
this.income = playerStats.getBasePlayer().getStartingIncome();
this.gold = playerStats.getBasePlayer().getStartingGold();
this.life = playerStats.getBasePlayer().getStartingLife();
float maxCost = 0;
this.creatures = new HashMap<String, BaseCreature>();
for (BaseCreature creature : playerStats.getBaseCreatures()) {
if (!Races.isRaces(race.getRaces(), creature.getRaces())) {
continue;
}
float cost = creature.getCost();
if (creature.isUnlocked() && cost > maxCost)
maxCost = cost;
creatures.put(creature.getName(), creature);
}
costUpgradeThreshold = maxCost * COST_VS_INCOME_UPGRADE_FACTOR;
this.towers = new HashMap<Integer, HashMap<String, BaseTower>>();
HashMap<String, BaseTower> towerMap = new HashMap<String, BaseTower>();
for (BaseTower tower : playerStats.getBaseTowers()) {
if (!race.isRaces(tower.getRaces())) {
continue;
}
towerMap.put(tower.getName(), tower);
}
towers.put(1, towerMap);
specials = new HashMap<String, BaseSpecial>();
for (BaseSpecial baseSpecial : playerStats.getSpecials()) {
specials.put(baseSpecial.getName(), baseSpecial);
}
}
public BaseSpecial getSpecial(String name) {
return specials.get(name);
}
public boolean timeToAutoBuy(int timePassed) {
autoBuyCooldown -= timePassed;
if (autoBuyCooldown <= 0) {
autoBuyCooldown += AUTO_BUY_DELAY;
return true;
} else {
return false;
}
}
public String getAutoBuyCreatureName() {
return autoBuyCreatureName;
}
public void cancelAutoBuyCreature() {
this.autoBuyCreatureName = null;
}
public void setAutoBuyCreature(String name) {
this.autoBuyCreatureName = name;
}
public void setIncome(float income) {
this.income = income;
}
public void setGold(float gold) {
this.gold = gold;
}
public void setLife(float life) {
this.life = life;
}
public void setCreatureLevel(int creatureLevel) {
this.creatureLevel = creatureLevel;
}
public int getCreatureLevel() {
return creatureLevel;
}
public float getCostUpgradeThreshold() {
return costUpgradeThreshold;
}
public boolean isAttacking() {
return attacking;
}
public void setAttacking(boolean attacking) {
this.attacking = attacking;
}
public int getID() {
return id;
}
public void nextTurn(int timePassed, int timeBetweenWaves) {
if (income > costUpgradeThreshold)
upgradeCreatures();
if (attacking) {
float temp = timePassed;
temp /= timeBetweenWaves;
temp *= income;
gold -= temp;
if (gold <= 0) {
attacking = false;
gold = 0;
Modules.MESSENGER.submit(ViewMessageProcessor.ID, ViewMessageProcessor.TURN_OFF_ATTACKING);
}
}
}
public Race getRace() {
return race;
}
public Grid getGrid() {
return grid;
}
public float getIncome() {
return income;
}
public float getGold() {
return gold;
}
public float getLife() {
return life;
}
public ArrayList<Creature> moveCreatures(int timePassed) {
ArrayList<Creature> remove = grid.moveCreatures(timePassed);
life -= remove.size();
if (life < 0.0f)
life = 0.0f;
return remove;
}
public ArrayList<Sprite> updateDyingSprites(int timePassed) {
return grid.updateDyingSprites(timePassed);
}
private void addGoldFromKills(ArrayList<Creature> creaturesKilled) {
for (Creature creature : creaturesKilled) {
gold += creature.getIncome();
}
}
public ArrayList<Creature> attackCreatures(int timePassed, ArrayList<Projectile> newProjectiles) {
ArrayList<Creature> creaturesKilled = grid.attackCreatures(timePassed, newProjectiles);
addGoldFromKills(creaturesKilled);
return creaturesKilled;
}
public ArrayList<Tower> attackTowers(int timePassed) {
return grid.attackTowers(timePassed);
}
public ArrayList<Creature> moveProjectiles(int timePassed, ArrayList<MovingProjectile> uselessProjectiles) {
ArrayList<Creature> creaturesKilled = grid.moveProjectiles(timePassed, uselessProjectiles);
addGoldFromKills(creaturesKilled);
return creaturesKilled;
}
public void addIncome(int currentWave) {
gold += income;
}
public void increaseIncome(float amount) {
float sum = income + amount;
if (sum < playerStats.getBasePlayer().getStartingIncome())
income = playerStats.getBasePlayer().getStartingIncome();
else
income = sum;
}
public void decreaseGold(float amount) {
gold -= amount;
}
public void increaseGold(float amount) {
gold += amount;
}
public PlayerStats getPlayerStats() {
return playerStats;
}
public BasePlayer getBasePlayer() {
return playerStats.getBasePlayer();
}
public BaseCreature getCreature(String name) {
return creatures.get(name);
}
public BaseTower getTower(String name) {
return towers.get(1).get(name);
}
public Collection<BaseCreature> getBaseCreatures() {
return creatures.values();
}
public BaseCreature[] getSortedBaseCreatures() {
if (sortedCreatures == null) {
Collection<BaseCreature> collection = creatures.values();
sortedCreatures = collection.toArray(new BaseCreature[collection.size()]);
Arrays.sort(sortedCreatures, new Comparator<BaseCreature>() {
@Override
public int compare(BaseCreature o1, BaseCreature o2) {
int cost = FastMath.floor(o1.getCost() - o2.getCost());
if (cost != 0) {
return cost;
}
cost = o1.getRaces() - o2.getRaces();
if (cost != 0) {
return cost;
}
return o1.getName().compareTo(o2.getName());
}
});
}
return sortedCreatures;
}
public Collection<BaseTower> getBaseTowers() {
return towers.get(1).values();
}
public BaseTower[] getSortedBaseTowers() {
if (sortedTowers == null) {
Collection<BaseTower> collection = towers.get(1).values();
sortedTowers = collection.toArray(new BaseTower[collection.size()]);
Arrays.sort(sortedTowers, new Comparator<BaseTower>() {
@Override
public int compare(BaseTower o1, BaseTower o2) {
int cost = FastMath.floor(o1.getCost() - o2.getCost());
if (cost != 0) {
return cost;
}
cost = o1.getRaces() - o2.getRaces();
if (cost != 0) {
return cost;
}
return o1.getName().compareTo(o2.getName());
}
});
}
return sortedTowers;
}
public void upgradeCreatures() {
Collection<BaseCreature> upgraded = BaseCreature.getUpgradedCreatures(creatures.values());
float maxCost = 0;
for (BaseCreature creature : upgraded) {
float cost = creature.getCost();
if (creature.isUnlocked() && cost > maxCost)
maxCost = cost;
creatures.put(creature.getName(), creature);
}
costUpgradeThreshold = maxCost * COST_VS_INCOME_UPGRADE_FACTOR;
creatureLevel++;
sortedCreatures = null;
}
public BaseTower getUpgrade(BaseTower tower) {
int level = tower.getLevel() + 1;
HashMap<String, BaseTower> towerMap = towers.get(level);
if (towerMap == null) {
towerMap = new HashMap<String, BaseTower>();
towers.put(level, towerMap);
}
String name = tower.getName();
BaseTower upgraded = towerMap.get(name);
if (upgraded == null) {
upgraded = BaseTower.createUpgrade(tower);
towerMap.put(name, upgraded);
}
return upgraded;
}
@Override
public String toString() {
return "Player [id=" + id + ", income=" + income + ", gold=" + gold + ", life=" + life + ", creatureLevel="
+ creatureLevel + "]";
}
@SuppressWarnings("unchecked")
@Override
public void readExternal(ObjectInput input) throws IOException, ClassNotFoundException {
id = input.readInt();
playerStats = (PlayerStats) input.readObject();
income = input.readFloat();
gold = input.readFloat();
life = input.readFloat();
costUpgradeThreshold = input.readFloat();
creatureLevel = input.readInt();
race = (Race) input.readObject();
grid = (Grid) input.readObject();
towers = (HashMap<Integer, HashMap<String, BaseTower>>) input.readObject();
creatures = (HashMap<String, BaseCreature>) input.readObject();
specials = (HashMap<String, BaseSpecial>) input.readObject();
}
@Override
public void writeExternal(ObjectOutput output) throws IOException {
output.writeInt(id);
output.writeObject(playerStats);
output.writeFloat(income);
output.writeFloat(gold);
output.writeFloat(life);
output.writeFloat(costUpgradeThreshold);
output.writeInt(creatureLevel);
output.writeObject(race);
output.writeObject(grid);
output.writeObject(towers);
output.writeObject(creatures);
output.writeObject(specials);
}
}