/** * 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.core; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.util.Arrays; import java.util.HashMap; import com.godsandtowers.achievements.Achievement; import com.godsandtowers.achievements.Achievements; import com.godsandtowers.campaigns.Campaign; import com.godsandtowers.campaigns.CampaignLevel; import com.godsandtowers.sprites.BaseCreature; import com.godsandtowers.sprites.BasePlayer; import com.godsandtowers.sprites.BaseRace; import com.godsandtowers.sprites.BaseSpecial; import com.godsandtowers.sprites.BaseTower; import com.godsandtowers.sprites.Races; import com.gundogstudios.modules.Modules; public class PlayerStats implements Externalizable { public static final int VERSION = 4; private int currentLevel; private long totalXP; private long longestGame; private long shortestGame; private long highestScore; private long highestLevelBeaten; private long wins; private long losses; private boolean multipleRacesUnlocked; private HashMap<Integer, Long> raceXP; private HashMap<Integer, Integer> defensiveGamesWon; private HashMap<Integer, Integer> battleGamesWon; private HashMap<Integer, Campaign> campaigns; private BasePlayer basePlayer; private BaseRace baseRace; private BaseCreature[] baseCreatures; private BaseTower[] baseTowers; private BaseSpecial[] specials; private Achievement[] achievements; public PlayerStats() { } public PlayerStats(int level) { reset(); totalXP = getLevelXP(level); currentLevel = level; } public PlayerStats(int level, PlayerStats stats) { this(level, stats.basePlayer, stats.baseRace, stats.baseTowers, stats.baseCreatures); } public PlayerStats(int level, BasePlayer basePlayer, BaseRace baseRace, BaseTower[] baseTowers, BaseCreature[] baseCreatures) { this(level); this.basePlayer = new BasePlayer(basePlayer); this.baseRace = new BaseRace(baseRace); for (int i = 0; i < baseTowers.length; i++) { this.baseTowers[i] = new BaseTower(baseTowers[i]); } for (int i = 0; i < baseCreatures.length; i++) { this.baseCreatures[i] = new BaseCreature(baseCreatures[i]); } } protected PlayerStats(long totalXP, long longestGame, long shortestGame, long highestScore, long highestLevelBeaten, int currentLevel, long wins, long losses, boolean multipleRacesUnlocked) { reset(); this.totalXP = totalXP; this.longestGame = longestGame; this.shortestGame = shortestGame; this.highestScore = highestScore; this.highestLevelBeaten = highestLevelBeaten; this.currentLevel = currentLevel; this.wins = wins; this.losses = losses; this.multipleRacesUnlocked = multipleRacesUnlocked; } public void reset() { totalXP = 0; longestGame = 0; shortestGame = Long.MAX_VALUE; highestScore = 0; highestLevelBeaten = 0; currentLevel = 0; wins = 0; losses = 0; multipleRacesUnlocked = false; raceXP = new HashMap<Integer, Long>(); defensiveGamesWon = new HashMap<Integer, Integer>(); battleGamesWon = new HashMap<Integer, Integer>(); for (int race : Races.ALL_RACES) { raceXP.put(race, 0l); defensiveGamesWon.put(race, 0); battleGamesWon.put(race, 0); } campaigns = Campaign.generateCampaigns(); basePlayer = BasePlayer.getBasePlayer(); baseRace = BaseRace.getBaseRace(); baseCreatures = BaseCreature.getBaseCreatures(); baseTowers = BaseTower.getBaseTowers(); specials = BaseSpecial.getSpecials(); achievements = Achievements.getAchievements(); } public long getRaceXP(int race) { return raceXP.get(race); } public void decreaseXP(int race, long amount) { long xp = raceXP.get(race) - amount; raceXP.put(race, xp); } public int getDefensiveGamesWon(int race) { return defensiveGamesWon.get(race); } public int getBattleGamesWon(int race) { return battleGamesWon.get(race); } public static long getLevelXP(long level) { return (level * (level + 1) / 2); } private void processRace(GameInfo gameInfo, int race, long xp) { xp = raceXP.get(race) + xp; raceXP.put(race, xp); if (gameInfo.won()) { switch (gameInfo.getGameType()) { case GameInfo.DEFENSE: int defenseWon = defensiveGamesWon.get(race); defensiveGamesWon.put(race, defenseWon + 1); break; case GameInfo.BATTLE: int battleWon = battleGamesWon.get(race); battleGamesWon.put(race, battleWon + 1); break; default: Modules.LOG.error("PlayerStats", "Unknown game type in player stats " + gameInfo.getGameType()); } } } public void update(GameInfo gameInfo) { int races = gameInfo.getLocalPlayerRaces(); CampaignLevel campaignLevel = gameInfo.getCampaignLevel(); if (campaignLevel != null && gameInfo.won()) { int stars = gameInfo.getStarCount(); campaignLevel.update(stars, gameInfo.getComputerLevel()); } long xp = increaseXP(gameInfo); for (int race : Races.asArray(races)) { processRace(gameInfo, race, xp); } if (gameInfo.won()) wins++; else losses++; if (longestGame < gameInfo.getLength()) longestGame = gameInfo.getLength(); if (shortestGame > gameInfo.getLength()) shortestGame = gameInfo.getLength(); if (highestLevelBeaten < gameInfo.getComputerLevel()) highestLevelBeaten = gameInfo.getComputerLevel(); if (highestScore < xp) highestScore = xp; for (Achievement achievement : achievements) { if (achievement.executeIfNotCompleted(this)) { // add achievement to list if it was executed for the first time gameInfo.addAchievement(achievement); } } } public long increaseXP(GameInfo info) { long xp = info.getXP(); long xpToNextLevel = getLevelXP(currentLevel + 1) - totalXP; totalXP += xp; long temp = xp - xpToNextLevel; if (xp >= 0) { currentLevel++; long nextLevel = currentLevel + 1; while ((temp -= nextLevel) >= 0) { currentLevel++; nextLevel++; } } return xp; } public void doubleExperience() { for (int race : Races.ALL_RACES) { long xp = raceXP.get(race) * 2; raceXP.put(race, xp); } } public void unlockMultipleRaces() { multipleRacesUnlocked = true; } public void setMultipleRaces(boolean unlocked) { multipleRacesUnlocked = unlocked; } public long getTotalXP() { return totalXP; } public long getLongestGame() { return longestGame; } public long getShortestGame() { return shortestGame; } public long getHighestScore() { return highestScore; } public long getHighestLevelBeaten() { return highestLevelBeaten; } public int getCurrentLevel() { return currentLevel; } public long getWins() { return wins; } public long getLosses() { return losses; } public boolean areMultipleRacesUnlocked() { return multipleRacesUnlocked; } public boolean areAllRacesUnlocked() { return true; } public HashMap<Integer, Long> getRaceXP() { return raceXP; } public HashMap<Integer, Integer> getDefensiveGamesWon() { return defensiveGamesWon; } public HashMap<Integer, Integer> getBattleGamesWon() { return battleGamesWon; } public HashMap<Integer, Campaign> getCampaigns() { return campaigns; } public BasePlayer getBasePlayer() { return basePlayer; } public BaseRace getBaseRace() { return baseRace; } public BaseCreature[] getBaseCreatures() { return baseCreatures; } public BaseTower[] getBaseTowers() { return baseTowers; } public BaseSpecial[] getSpecials() { return specials; } public Achievement[] getAchievements() { return achievements; } @Override public String toString() { return "PlayerStats [totalXP=" + totalXP + ", longestGame=" + longestGame + ", shortestGame=" + shortestGame + ", highestScore=" + highestScore + ", highestLevelBeaten=" + highestLevelBeaten + ", currentLevel=" + currentLevel + ", wins=" + wins + ", losses=" + losses + ", multipleRacesUnlocked=" + multipleRacesUnlocked + ", raceXP=" + raceXP + ", defensiveGamesWon=" + defensiveGamesWon + ", battleGamesWon=" + battleGamesWon + ", campaigns=" + campaigns + ", basePlayer=" + basePlayer + ", baseRace=" + baseRace + ", baseCreatures=" + Arrays.toString(baseCreatures) + ", baseTowers=" + Arrays.toString(baseTowers) + ", specials=" + Arrays.toString(specials) + ", achievements=" + Arrays.toString(achievements) + "]"; } @SuppressWarnings("unchecked") @Override public void readExternal(ObjectInput input) throws IOException, ClassNotFoundException { currentLevel = input.readInt(); totalXP = input.readLong(); longestGame = input.readLong(); shortestGame = input.readLong(); highestScore = input.readLong(); highestLevelBeaten = input.readLong(); wins = input.readLong(); losses = input.readLong(); multipleRacesUnlocked = input.readBoolean(); raceXP = (HashMap<Integer, Long>) input.readObject(); defensiveGamesWon = (HashMap<Integer, Integer>) input.readObject(); battleGamesWon = (HashMap<Integer, Integer>) input.readObject(); campaigns = (HashMap<Integer, Campaign>) input.readObject(); basePlayer = (BasePlayer) input.readObject(); baseRace = (BaseRace) input.readObject(); baseCreatures = (BaseCreature[]) input.readObject(); baseTowers = (BaseTower[]) input.readObject(); specials = (BaseSpecial[]) input.readObject(); achievements = (Achievement[]) input.readObject(); } @Override public void writeExternal(ObjectOutput output) throws IOException { output.writeInt(currentLevel); output.writeLong(totalXP); output.writeLong(longestGame); output.writeLong(shortestGame); output.writeLong(highestScore); output.writeLong(highestLevelBeaten); output.writeLong(wins); output.writeLong(losses); output.writeBoolean(multipleRacesUnlocked); output.writeObject(raceXP); output.writeObject(defensiveGamesWon); output.writeObject(battleGamesWon); output.writeObject(campaigns); output.writeObject(basePlayer); output.writeObject(baseRace); output.writeObject(baseCreatures); output.writeObject(baseTowers); output.writeObject(specials); output.writeObject(achievements); } }