diff --git a/android/build.gradle b/android/build.gradle index 4006d7fdcd..9847328b61 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -21,7 +21,7 @@ android { applicationId "com.unciv.game" minSdkVersion 9 targetSdkVersion 25 - versionCode 10 + versionCode 11 versionName "0.9" } buildTypes { diff --git a/core/src/com/unciv/civinfo/CityBuildings.java b/core/src/com/unciv/civinfo/CityBuildings.java deleted file mode 100644 index 21deb65b28..0000000000 --- a/core/src/com/unciv/civinfo/CityBuildings.java +++ /dev/null @@ -1,241 +0,0 @@ -package com.unciv.civinfo; - -import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.utils.Predicate; -import com.unciv.game.UnCivGame; -import com.unciv.game.VictoryScreen; -import com.unciv.models.LinqCollection; -import com.unciv.models.gamebasics.Building; -import com.unciv.models.gamebasics.GameBasics; -import com.unciv.models.stats.FullStats; - -import java.util.HashMap; - - -public class CityBuildings -{ - static final String Worker="Worker"; - static final String Settler="Settler"; - - public Vector2 cityLocation; - - public CityBuildings(){} // for json parsing, we need to have a default constructor - - public CityBuildings(CityInfo cityInfo) - { - cityLocation = cityInfo.cityLocation; - } - - public LinqCollection builtBuildings = new LinqCollection(); - public HashMap inProgressBuildings = new HashMap(); - public String currentBuilding = Worker; // default starting building! - public Building getCurrentBuilding(){return getGameBuilding(currentBuilding);} - - public CityInfo getCity(){return UnCivGame.Current.civInfo.tileMap.get(cityLocation).getCity(); } - public boolean isBuilt(String buildingName) { return builtBuildings.contains(buildingName); } - public boolean isBuilding(String buildingName) { return currentBuilding!=null && currentBuilding.equals(buildingName); } - - Building getGameBuilding(String buildingName) { return GameBasics.Buildings.get(buildingName); } - public LinqCollection getBuiltBuildings(){ return builtBuildings.select(new LinqCollection.Func() { - @Override - public Building GetBy(String arg0) { - return getGameBuilding(arg0); - } - }); } - - public void nextTurn(FullStats cityStats) - { - if (getCurrentBuilding()==null) return; - - Building gameBuilding = getGameBuilding(currentBuilding); - - // Let's try to remove the building from the city, and seee if we can still build it (weneed to remove because of wonders etc. - String saveCurrentBuilding = currentBuilding; - currentBuilding = null; - if(!canBuild(gameBuilding)){ - // We can't build this building anymore! (Wonder has been built / resource is gone / etc.) - CivilizationInfo.current().notifications.add("Cannot continue work on "+saveCurrentBuilding); - chooseNextBuilding(); - gameBuilding = getGameBuilding(currentBuilding); - } - else currentBuilding = saveCurrentBuilding; - - if (!inProgressBuildings.containsKey(currentBuilding)) inProgressBuildings.put(currentBuilding, 0); - inProgressBuildings.put(currentBuilding, inProgressBuildings.get(currentBuilding) + Math.round(cityStats.production)); - - if (inProgressBuildings.get(currentBuilding) >= gameBuilding.cost) - { - if (currentBuilding.equals(Worker) || currentBuilding.equals(Settler)) - UnCivGame.Current.civInfo.tileMap.get(cityLocation).unit = new Unit(currentBuilding,2); - else if("SpaceshipPart".equals(gameBuilding.unique)) { - CivilizationInfo.current().scienceVictory.currentParts.add(currentBuilding, 1); - if(CivilizationInfo.current().scienceVictory.unconstructedParts().isEmpty()) - UnCivGame.Current.setScreen(new VictoryScreen(UnCivGame.Current)); - } - - else - { - builtBuildings.add(currentBuilding); - if (gameBuilding.providesFreeBuilding != null && !builtBuildings.contains(gameBuilding.providesFreeBuilding)) - builtBuildings.add(gameBuilding.providesFreeBuilding); - if (gameBuilding.freeTechs != 0) UnCivGame.Current.civInfo.tech.freeTechs += gameBuilding.freeTechs; - if("EmpireEntersGoldenAge".equals(gameBuilding.unique)) CivilizationInfo.current().enterGoldenAge(); - } - - inProgressBuildings.remove(currentBuilding); - - CivilizationInfo.current().notifications.add(currentBuilding+" has been built in "+getCity().name); - - chooseNextBuilding(); - } - - } - - private void chooseNextBuilding() { - currentBuilding = getBuildableBuildings().first(new Predicate() { - @Override - public boolean evaluate(String arg0) { - if(arg0.equals(Settler) || arg0.equals(Worker) || getGameBuilding(arg0).isWonder) return false; - return !builtBuildings.contains(arg0); - } - }); - if (currentBuilding == null) currentBuilding = Worker; - - CivilizationInfo.current().notifications.add("Work has started on "+currentBuilding); - } - - public boolean canBuild(final Building building) - { - CivilizationInfo civInfo = UnCivGame.Current.civInfo; - if(isBuilt(building.name)) return false; - if(building.requiredNearbyImprovedResources!=null) { - boolean containsResourceWithImprovement = getCity().getTilesInRange() - .any(new Predicate() { - @Override - public boolean evaluate(TileInfo tile) { - return tile.resource != null - && building.requiredNearbyImprovedResources.contains(tile.resource) - && tile.getTileResource().improvement.equals(tile.improvement); - } - }); - if(!containsResourceWithImprovement) return false; - } - - if (building.requiredTech != null && !civInfo.tech.isResearched(building.requiredTech)) return false; - if (building.isWonder && civInfo.cities - .any(new Predicate() { - @Override - public boolean evaluate(CityInfo arg0) { - CityBuildings CB = arg0.cityBuildings; - return CB.isBuilding(building.name) || CB.isBuilt(building.name); - } - }) ) return false; - if (building.requiredBuilding != null && !isBuilt(building.requiredBuilding)) return false; - if (building.requiredBuildingInAllCities != null || - civInfo.cities.any(new Predicate() { - @Override - public boolean evaluate(CityInfo arg0) { - return arg0.cityBuildings.isBuilt(building.requiredBuildingInAllCities); - } - }) ) return false; - if(building.cannotBeBuiltWith != null && isBuilt(building.cannotBeBuiltWith)) return false; - if("MustBeNextToDesert".equals(building.unique) && - !civInfo.tileMap.getTilesInDistance(cityLocation,1).any(new Predicate() { - @Override - public boolean evaluate(TileInfo arg0) { - return arg0.baseTerrain.equals("Desert"); - } - })) - return false; - if(building.requiredResource!=null && - !civInfo.getCivResources().keySet().contains(GameBasics.TileResources.get(building.requiredResource))) - return false; // Only checks if exists, doesn't check amount - todo - - if("SpaceshipPart".equals(building.unique)){ - if(!civInfo.getBuildingUniques().contains("ApolloProgram")) return false; - if(civInfo.scienceVictory.requiredParts.get(building.name)==0) return false; // Don't need to build any more of these! - } - - return true; - } - - public LinqCollection getBuildableBuildings() - { - return new LinqCollection(GameBasics.Buildings.values()) - .where(new Predicate() { - @Override - public boolean evaluate(Building arg0) { return canBuild(arg0); } - }) - .select(new LinqCollection.Func() { - @Override - public String GetBy(Building arg0) { - return arg0.name; - } - }); - } - - public FullStats getStats() - { - FullStats stats = new FullStats(); - for(Building building : getBuiltBuildings()) stats.add(building); - stats.science += getCity().getBuildingUniques().count(new Predicate() { - @Override - public boolean evaluate(String arg0) { - return "SciencePer2Pop".equals(arg0); - } - }) * getCity().population/2; // Library and public school unique (not actualy unique, though...hmm) - return stats; - } - - public int getMaintainanceCosts(){ - int maintainanceTotal = 0; - for( Building building : getBuiltBuildings()) maintainanceTotal+=building.maintainance; - return maintainanceTotal; - } - - public FullStats getStatPercentBonuses(){ - - FullStats stats = new FullStats(); - for(Building building : getBuiltBuildings()) - if(building.percentStatBonus != null) - stats.add(building.percentStatBonus); - - return stats; - } - - public int workDone(String buildingName) { - if (inProgressBuildings.containsKey(buildingName)) - return inProgressBuildings.get(buildingName); - return 0; - } - - public int turnsToBuilding(String buildingName) - { - float workLeft = getGameBuilding(buildingName).cost - workDone(buildingName); // needs to be float so that we get the cieling properly ;) - - FullStats cityStats = getCity().cityStats; - int production = Math.round(cityStats.production); - if (buildingName.equals(Settler)) production += cityStats.food; - - return (int) Math.ceil(workLeft / production); - } - - public void purchaseBuilding(String buildingName) { - CivilizationInfo.current().civStats.gold -= getGameBuilding(buildingName).getGoldCost(); - builtBuildings.add(buildingName); - if(currentBuilding.equals(buildingName)) chooseNextBuilding(); - } - - public String getCityProductionText(){ - String result = currentBuilding; - if(!result.equals("Science") && !result.equals("Gold")) - result+="\r\n"+turnsToBuilding(currentBuilding)+" turns"; - return result; - } - - - public String getAmountConstructedText(){ - if(currentBuilding.equals("Science") || currentBuilding.equals("Gold")) return ""; - return " ("+ workDone(currentBuilding) + "/"+getCurrentBuilding().cost+")"; - } -} \ No newline at end of file diff --git a/core/src/com/unciv/civinfo/CityConstructions.java b/core/src/com/unciv/civinfo/CityConstructions.java new file mode 100644 index 0000000000..fdb6f97d34 --- /dev/null +++ b/core/src/com/unciv/civinfo/CityConstructions.java @@ -0,0 +1,185 @@ +package com.unciv.civinfo; + +import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.utils.Predicate; +import com.unciv.game.UnCivGame; +import com.unciv.models.LinqCollection; +import com.unciv.models.gamebasics.Building; +import com.unciv.models.gamebasics.GameBasics; +import com.unciv.models.stats.FullStats; + +import java.util.HashMap; + + +public class CityConstructions +{ + static final String Worker="Worker"; + static final String Settler="Settler"; + + public Vector2 cityLocation; + + public CityConstructions(){} // for json parsing, we need to have a default constructor + + public CityConstructions(CityInfo cityInfo) + { + cityLocation = cityInfo.cityLocation; + } + + public LinqCollection builtBuildings = new LinqCollection(); + public HashMap inProgressConstructions = new HashMap(); + public String currentConstruction = Worker; // default starting building! + public IConstruction getCurrentConstruction(){return getConstruction(currentConstruction);} + + public CityInfo getCity(){return UnCivGame.Current.civInfo.tileMap.get(cityLocation).getCity(); } + public boolean isBuilt(String buildingName) { return builtBuildings.contains(buildingName); } + public boolean isBuilding(String buildingName) { return currentConstruction !=null && currentConstruction.equals(buildingName); } + + IConstruction getConstruction(String constructionName) { + if(GameBasics.Buildings.containsKey(constructionName)) + return GameBasics.Buildings.get(constructionName); + else if(GameBasics.Units.containsKey(constructionName)) + return GameBasics.Units.get(constructionName); + return null; + } + + public LinqCollection getBuiltBuildings(){ return builtBuildings.select(new LinqCollection.Func() { + @Override + public Building GetBy(String arg0) { + return GameBasics.Buildings.get(arg0); + } + }); } + + public void nextTurn(FullStats cityStats) + { + if (getCurrentConstruction()==null) return; + + IConstruction construction = getConstruction(currentConstruction); + + // Let's try to remove the building from the city, and see if we can still build it (weneed to remove because of wonders etc. + String saveCurrentConstruction = currentConstruction; + currentConstruction = null; + if(!construction.isBuildable(this)){ + // We can't build this building anymore! (Wonder has been built / resource is gone / etc.) + CivilizationInfo.current().notifications.add("Cannot continue work on "+saveCurrentConstruction); + chooseNextConstruction(); + construction = getConstruction(currentConstruction); + } + else currentConstruction = saveCurrentConstruction; + + if (!inProgressConstructions.containsKey(currentConstruction)) inProgressConstructions.put(currentConstruction, 0); + inProgressConstructions.put(currentConstruction, inProgressConstructions.get(currentConstruction) + Math.round(cityStats.production)); + + if (inProgressConstructions.get(currentConstruction) >= construction.getProductionCost()) + { + construction.postBuildEvent(this); + + inProgressConstructions.remove(currentConstruction); + CivilizationInfo.current().notifications.add(currentConstruction +" has been built in "+getCity().name); + + chooseNextConstruction(); + } + + } + + private void chooseNextConstruction() { + currentConstruction = getBuildableBuildings().first(new Predicate() { + @Override + public boolean evaluate(String arg0) { + if(((Building)getConstruction(arg0)).isWonder) return false; + return !builtBuildings.contains(arg0); + } + }); + if (currentConstruction == null) currentConstruction = Worker; + + CivilizationInfo.current().notifications.add("Work has started on "+ currentConstruction); + } + + + public LinqCollection getBuildableBuildings() + { + final CityConstructions self=this; + return new LinqCollection(GameBasics.Buildings.values()) + .where(new Predicate() { + @Override + public boolean evaluate(Building arg0) { return (arg0.isBuildable(self)); } + }) + .select(new LinqCollection.Func() { + @Override + public String GetBy(Building arg0) { + return arg0.name; + } + }); + } + + public FullStats getStats() + { + FullStats stats = new FullStats(); + for(Building building : getBuiltBuildings()) stats.add(building); + stats.science += getCity().getBuildingUniques().count(new Predicate() { + @Override + public boolean evaluate(String arg0) { + return "SciencePer2Pop".equals(arg0); + } + }) * getCity().population/2; // Library and public school unique (not actualy unique, though...hmm) + return stats; + } + + public int getMaintainanceCosts(){ + int maintainanceTotal = 0; + for( Building building : getBuiltBuildings()) maintainanceTotal+=building.maintainance; + return maintainanceTotal; + } + + public FullStats getStatPercentBonuses(){ + + FullStats stats = new FullStats(); + for(Building building : getBuiltBuildings()) + if(building.percentStatBonus != null) + stats.add(building.percentStatBonus); + + return stats; + } + + public int workDone(String constructionName) { + if (inProgressConstructions.containsKey(constructionName)) + return inProgressConstructions.get(constructionName); + return 0; + } + + public int turnsToConstruction(String constructionName){ + int cost = getConstruction(constructionName).getProductionCost(); + + float workLeft = cost - workDone(constructionName); // needs to be float so that we get the cieling properly ;) + + FullStats cityStats = getCity().cityStats; + int production = Math.round(cityStats.production); + if (constructionName.equals(Settler)) production += cityStats.food; + + return (int) Math.ceil(workLeft / production); + } + + public void purchaseBuilding(String buildingName) { + CivilizationInfo.current().civStats.gold -= getConstruction(buildingName).getGoldCost(); + builtBuildings.add(buildingName); + if(currentConstruction.equals(buildingName)) chooseNextConstruction(); + } + + public String getCityProductionTextForCityButton(){ + String result = currentConstruction; + if(!result.equals("Science") && !result.equals("Gold")) + result+="\r\n"+ turnsToConstruction(currentConstruction)+" turns"; + return result; + } + + public String getProductionForTileInfo(){ + String result = currentConstruction; + if(!result.equals("Science") && !result.equals("Gold")) + result+="\r\nin "+ turnsToConstruction(currentConstruction)+" turns,\r\n"; + return result; + } + + public String getAmountConstructedText(){ + if(currentConstruction.equals("Science") || currentConstruction.equals("Gold")) return ""; + return " ("+ workDone(currentConstruction) + "/"+ getCurrentConstruction().getProductionCost()+")"; + } +} \ No newline at end of file diff --git a/core/src/com/unciv/civinfo/CityInfo.java b/core/src/com/unciv/civinfo/CityInfo.java index 86a5e93e04..a8af969574 100644 --- a/core/src/com/unciv/civinfo/CityInfo.java +++ b/core/src/com/unciv/civinfo/CityInfo.java @@ -5,7 +5,6 @@ import com.badlogic.gdx.utils.Predicate; import com.unciv.game.UnCivGame; import com.unciv.models.LinqCollection; import com.unciv.models.LinqCounter; -import com.unciv.models.LinqHashMap; import com.unciv.models.gamebasics.Building; import com.unciv.models.gamebasics.GameBasics; import com.unciv.models.gamebasics.TileResource; @@ -15,7 +14,7 @@ public class CityInfo { public final Vector2 cityLocation; public String name; - public CityBuildings cityBuildings; + public CityConstructions cityConstructions; public int cultureStored; private int tilesClaimed; public int population = 1; @@ -35,7 +34,9 @@ public class CityInfo { }); } - private String[] CityNames = new String[]{"Assur", "Ninveh", "Nimrud", "Kar-Tukuli-Ninurta", "Dur-Sharrukin"}; + private String[] CityNames = new String[]{ + "New Bark","Cherrygrove","Violet","Azalea","Goldenrod","Ecruteak","Olivine","Cianwood","Mahogany","Blackthorn", + "Pallet","Viridian","Pewter","Cerulean","Vermillion","Lavender","Celadon","Fuchsia","Saffron","Cinnibar"}; public CityInfo(){ cityLocation = Vector2.Zero; @@ -55,8 +56,8 @@ public class CityInfo { CityInfo(CivilizationInfo civInfo, Vector2 cityLocation) { name = CityNames[civInfo.cities.size()]; this.cityLocation = cityLocation; - cityBuildings = new CityBuildings(this); - if(civInfo.cities.size()==0) cityBuildings.builtBuildings.add("Palace"); + cityConstructions = new CityConstructions(this); + if(civInfo.cities.size()==0) cityConstructions.builtBuildings.add("Palace"); civInfo.cities.add(this); for(TileInfo tileInfo : civInfo.tileMap.getTilesInDistance(cityLocation,1)) { @@ -82,7 +83,7 @@ public class CityInfo { cityResources.add(resource,1); } // Remove resources required by buildings - for(Building building : cityBuildings.getBuiltBuildings()){ + for(Building building : cityConstructions.getBuiltBuildings()){ if(building.requiredResource!=null){ TileResource resource = GameBasics.TileResources.get(building.requiredResource); cityResources.add(resource,-1); @@ -119,7 +120,6 @@ public class CityInfo { //idle ppl stats.production += getFreePopulation(); - stats.food -= population * 2; if(!isCapital() && isConnectedToCapital(RoadStatus.Road)) { // Calculated by http://civilization.wikia.com/wiki/Trade_route_(Civ5) @@ -129,35 +129,47 @@ public class CityInfo { stats.gold += goldFromTradeRoute; } - stats.add(cityBuildings.getStats()); + stats.add(cityConstructions.getStats()); - FullStats statPercentBonuses = cityBuildings.getStatPercentBonuses(); + FullStats statPercentBonuses = cityConstructions.getStatPercentBonuses(); if(isCapital() || isConnectedToCapital(RoadStatus.Railroad)) statPercentBonuses.production += 25; if(CivilizationInfo.current().isGoldenAge()) statPercentBonuses.production+=20; + IConstruction currentConstruction = cityConstructions.getCurrentConstruction(); + if(currentConstruction instanceof Building && ((Building)currentConstruction).isWonder && + CivilizationInfo.current().getCivResources().containsKey(GameBasics.TileResources.get("Marble"))) + statPercentBonuses.production+=15; + stats.production*=1+statPercentBonuses.production/100; // So they get bonuses for production and gold/science - if(cityBuildings.currentBuilding.equals("Gold")) stats.gold+=stats.production/4; - if(cityBuildings.currentBuilding.equals("Science")) stats.science+=stats.production/4; - stats.food*=1+statPercentBonuses.food/100; + if(cityConstructions.currentConstruction.equals("Gold")) stats.gold+=stats.production/4; + if(cityConstructions.currentConstruction.equals("Science")) stats.science+=stats.production/4; + stats.gold*=1+statPercentBonuses.gold/100; stats.science*=1+statPercentBonuses.science/100; stats.culture*=1+statPercentBonuses.culture/100; - stats.gold-=cityBuildings.getMaintainanceCosts(); // this is AFTER the bonus calculation! - if(CivilizationInfo.current().getHappinessForNextTurn() < 0) - stats.food /= 4; // Reduce excess food to 1/4 + boolean isUnhappy =CivilizationInfo.current().getHappinessForNextTurn() < 0; + if (!isUnhappy) stats.food*=1+statPercentBonuses.food/100; // Regular food bonus revoked when unhappy per https://forums.civfanatics.com/resources/complete-guide-to-happiness-vanilla.25584/ + stats.food -= population * 2; // Food reduced after the bonus + if(isUnhappy) stats.food /= 4; // Reduce excess food to 1/4 per the same + + + stats.gold-= cityConstructions.getMaintainanceCosts(); // this is AFTER the bonus calculation! this.cityStats = stats; } - public int getCityHappiness(){ // needs to be a separate function because we need to know the global happiness state + public float getCityHappiness(){ // needs to be a separate function because we need to know the global happiness state // in order to determine how much food is produced in a city! - int happiness = -3 - population; // -3 happiness per city and -1 per population - return happiness + (int)cityBuildings.getStats().happiness; + float happiness = -3; // -3 happiness per city + if(CivilizationInfo.current().getBuildingUniques().contains("CitizenUnhappinessDecreased")) + happiness-=population*0.9; + else happiness-=population; //and -1 per population + return happiness + (int) cityConstructions.getStats().happiness; } void nextTurn() { FullStats stats = cityStats; - if (cityBuildings.currentBuilding.equals(CityBuildings.Settler) && stats.food > 0) { + if (cityConstructions.currentConstruction.equals(CityConstructions.Settler) && stats.food > 0) { stats.production += stats.food; stats.food = 0; } @@ -178,7 +190,7 @@ public class CityInfo { CivilizationInfo.current().notifications.add(name+" has grown!"); } - cityBuildings.nextTurn(stats); + cityConstructions.nextTurn(stats); cultureStored+=stats.culture; if(cultureStored>=getCultureToNextTile()){ @@ -275,7 +287,7 @@ public class CityInfo { } public LinqCollection getBuildingUniques(){ - return cityBuildings.getBuiltBuildings().select(new LinqCollection.Func() { + return cityConstructions.getBuiltBuildings().select(new LinqCollection.Func() { @Override public String GetBy(Building arg0) { return arg0.unique; diff --git a/core/src/com/unciv/civinfo/CivilizationInfo.java b/core/src/com/unciv/civinfo/CivilizationInfo.java index 2090770ef3..6001e7f946 100644 --- a/core/src/com/unciv/civinfo/CivilizationInfo.java +++ b/core/src/com/unciv/civinfo/CivilizationInfo.java @@ -5,12 +5,12 @@ import com.badlogic.gdx.utils.Predicate; import com.unciv.game.UnCivGame; import com.unciv.models.LinqCollection; import com.unciv.models.LinqCounter; -import com.unciv.models.LinqHashMap; import com.unciv.models.gamebasics.Building; import com.unciv.models.gamebasics.GameBasics; import com.unciv.models.gamebasics.ResourceType; import com.unciv.models.gamebasics.TileResource; import com.unciv.models.stats.CivStats; +import com.unciv.models.stats.FullStats; import java.util.Collection; @@ -26,6 +26,8 @@ public class CivilizationInfo { public int turnsLeftForCurrentGoldenAge=0; public String civName = "Babylon"; + public FullStats greatPersonPoints = new FullStats(); + public CivilizationTech tech = new CivilizationTech(); public int turns = 1; public LinqCollection notifications = new LinqCollection(); @@ -55,7 +57,7 @@ public class CivilizationInfo { return cities.first(new Predicate() { @Override public boolean evaluate(CityInfo arg0) { - return arg0.cityBuildings.isBuilt("Palace"); + return arg0.cityConstructions.isBuilt("Palace"); } }); } @@ -71,8 +73,9 @@ public class CivilizationInfo { CivStats nextTurnStats = getStatsForNextTurn(); civStats.add(nextTurnStats); - if(!isGoldenAge()) - civStats.happiness += getHappinessForNextTurn(); + int happiness = getHappinessForNextTurn(); + if(!isGoldenAge() && happiness>0) + civStats.happiness += happiness; if(cities.size() > 0) tech.nextTurn((int)nextTurnStats.science); @@ -102,6 +105,10 @@ public class CivilizationInfo { statsForTurn.add(city.cityStats); } statsForTurn.happiness=0; + for(TileInfo tile : tileMap.values()) { + if (tile.roadStatus == RoadStatus.Road) statsForTurn.gold += 1; + else if(tile.roadStatus == RoadStatus.Railroad) statsForTurn.gold +=2; + } return statsForTurn; } @@ -130,7 +137,7 @@ public class CivilizationInfo { return cities.selectMany(new LinqCollection.Func>() { @Override public Collection GetBy(CityInfo arg0) { - return arg0.cityBuildings.getBuiltBuildings().select(new LinqCollection.Func() { + return arg0.cityConstructions.getBuiltBuildings().select(new LinqCollection.Func() { @Override public String GetBy(Building arg0) { return arg0.unique; diff --git a/core/src/com/unciv/civinfo/IConstruction.java b/core/src/com/unciv/civinfo/IConstruction.java new file mode 100644 index 0000000000..7177f462df --- /dev/null +++ b/core/src/com/unciv/civinfo/IConstruction.java @@ -0,0 +1,10 @@ +package com.unciv.civinfo; + +import com.unciv.models.stats.INamed; + +public interface IConstruction extends INamed { + public int getProductionCost(); + public int getGoldCost(); + public boolean isBuildable(CityConstructions construction); + public void postBuildEvent(CityConstructions construction); // Yes I'm hilarious. +} diff --git a/core/src/com/unciv/civinfo/TileInfo.java b/core/src/com/unciv/civinfo/TileInfo.java index e60b2838ab..f1f5c74ea5 100644 --- a/core/src/com/unciv/civinfo/TileInfo.java +++ b/core/src/com/unciv/civinfo/TileInfo.java @@ -67,7 +67,7 @@ public class TileInfo if (hasViewableResource()) { stats.add(resource); // resource base - if(resource.building !=null && city!=null && city.cityBuildings.isBuilt(resource.building)) + if(resource.building !=null && city!=null && city.cityConstructions.isBuilt(resource.building)) { stats.add(resource.GetBuilding().resourceBonusStats); // resource-specific building (eg forge, stable) bonus } @@ -124,7 +124,7 @@ public class TileInfo public void nextTurn() { - if(unit !=null) unit.currentMovement = unit.maxMovement; + if(unit !=null) unit.currentMovement = unit.movement; if (improvementInProgress == null || unit ==null || !unit.name.equals("Worker")) return; turnsToImprovement -= 1; @@ -158,14 +158,14 @@ public class TileInfo public String toString() { StringBuilder SB = new StringBuilder(); - if (isCityCenter()) SB.append(workingCity+",\r\n"); + if (isCityCenter()){SB.append(workingCity+",\r\n"+getCity().cityConstructions.getProductionForTileInfo());} SB.append(this.baseTerrain); if (terrainFeature != null) SB.append(",\r\n" + terrainFeature); if (hasViewableResource()) SB.append(",\r\n" + resource); if (roadStatus!= RoadStatus.None && !isCityCenter()) SB.append(",\r\n" + roadStatus); if (improvement != null) SB.append(",\r\n" + improvement); if (improvementInProgress != null) SB.append(",\r\n" + improvementInProgress +" in "+this.turnsToImprovement +" turns"); - if (unit !=null) SB.append(",\r\n" + unit.name + "("+ new DecimalFormat("0.#").format(unit.currentMovement)+"/"+ unit.maxMovement +")"); + if (unit !=null) SB.append(",\r\n" + unit.name + "("+ new DecimalFormat("0.#").format(unit.currentMovement)+"/"+ unit.movement +")"); return SB.toString(); } diff --git a/core/src/com/unciv/civinfo/TileMap.java b/core/src/com/unciv/civinfo/TileMap.java index d9098adea4..bd0c867fdf 100644 --- a/core/src/com/unciv/civinfo/TileMap.java +++ b/core/src/com/unciv/civinfo/TileMap.java @@ -125,5 +125,13 @@ public class TileMap{ }).getRandom(); } + void placeUnitNearTile(Vector2 position, Unit unit){ + getTilesInDistance(position,1).first(new Predicate() { + @Override + public boolean evaluate(TileInfo arg0) { + return arg0.unit==null; + } + }).unit = unit; // And if there's none, then kill me. + } } diff --git a/core/src/com/unciv/civinfo/Unit.java b/core/src/com/unciv/civinfo/Unit.java index 3312d084db..b6a8f879c2 100644 --- a/core/src/com/unciv/civinfo/Unit.java +++ b/core/src/com/unciv/civinfo/Unit.java @@ -1,15 +1,52 @@ package com.unciv.civinfo; -public class Unit{ +import com.unciv.game.UnCivGame; +import com.unciv.models.stats.INamed; + +public class Unit implements INamed, IConstruction{ public String name; - public int maxMovement; + public String description; + public int cost; + public int hurryCostModifier; + public int movement; public float currentMovement; + boolean unbuildable; // for special units likee great people public Unit(){} // for json parsing, we need to have a default constructor public Unit(String name, int maxMovement) { this.name = name; - this.maxMovement = maxMovement; + this.movement = maxMovement; currentMovement = maxMovement; } + + @Override + public String getName() { + return name; + } + + public boolean isConstructable() { + if(unbuildable) return false; + return true; + } + + @Override + public int getProductionCost() { + return cost; + } + + @Override + public int getGoldCost() { + return (int)( Math.pow(30 * cost,0.75) * (1 + hurryCostModifier/100) / 10 ) * 10; + } + + @Override + public boolean isBuildable(CityConstructions construction) { + return !unbuildable; + } + + @Override + public void postBuildEvent(CityConstructions construction) { + UnCivGame.Current.civInfo.tileMap.placeUnitNearTile(construction.cityLocation,new Unit(name,movement)); + } } diff --git a/core/src/com/unciv/game/CityScreen.java b/core/src/com/unciv/game/CityScreen.java index 89743c2c9a..744ceca11f 100644 --- a/core/src/com/unciv/game/CityScreen.java +++ b/core/src/com/unciv/game/CityScreen.java @@ -20,6 +20,7 @@ import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; import com.badlogic.gdx.utils.Align; import com.unciv.civinfo.CityInfo; +import com.unciv.civinfo.IConstruction; import com.unciv.civinfo.TileInfo; import com.unciv.game.pickerscreens.BuildingPickerScreen; import com.unciv.models.gamebasics.Building; @@ -202,7 +203,7 @@ public class CityScreen extends com.unciv.game.utils.CameraStageBaseScreen { HashMap CityStatsValues = new LinkedHashMap(); CityStatsValues.put("Production",Math.round(stats.production) - +cityInfo.cityBuildings.getAmountConstructedText()); + +cityInfo.cityConstructions.getAmountConstructedText()); CityStatsValues.put("Food",Math.round(stats.food) +" ("+cityInfo.foodStored+"/"+cityInfo.foodToNextPopulation()+")"); CityStatsValues.put("Gold",Math.round(stats.gold) +""); @@ -217,10 +218,10 @@ public class CityScreen extends com.unciv.game.utils.CameraStageBaseScreen { CityStatsTable.row(); } - String CurrentBuilding = game.civInfo.getCurrentCity().cityBuildings.currentBuilding; + String CurrentBuilding = game.civInfo.getCurrentCity().cityConstructions.currentConstruction; String BuildingText = "Pick building"; - if(CurrentBuilding != null) BuildingText = cityInfo.cityBuildings.getCityProductionText(); + if(CurrentBuilding != null) BuildingText = cityInfo.cityConstructions.getCityProductionTextForCityButton(); TextButton buildingPickButton = new TextButton(BuildingText,skin); buildingPickButton.addListener(new ClickListener(){ @Override @@ -236,15 +237,15 @@ public class CityScreen extends com.unciv.game.utils.CameraStageBaseScreen { // https://forums.civfanatics.com/threads/rush-buying-formula.393892/ - Building building = cityInfo.cityBuildings.getCurrentBuilding(); - if(building != null && !building.isWonder) { + IConstruction construction = cityInfo.cityConstructions.getCurrentConstruction(); + if(construction != null && !(construction instanceof Building && ((Building)construction).isWonder)) { CityStatsTable.row(); - int buildingGoldCost = building.getGoldCost(); + int buildingGoldCost = construction.getGoldCost(); TextButton buildingBuyButton = new TextButton("Buy for \r\n"+buildingGoldCost+" gold", skin); buildingBuyButton.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { - cityInfo.cityBuildings.purchaseBuilding(cityInfo.cityBuildings.currentBuilding); + cityInfo.cityConstructions.purchaseBuilding(cityInfo.cityConstructions.currentConstruction); updateCityTable(); } }); diff --git a/core/src/com/unciv/game/TileGroup.java b/core/src/com/unciv/game/TileGroup.java index 6bf095ca7e..0032b5b828 100644 --- a/core/src/com/unciv/game/TileGroup.java +++ b/core/src/com/unciv/game/TileGroup.java @@ -10,6 +10,7 @@ import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; import com.unciv.civinfo.CivilizationInfo; import com.unciv.civinfo.RoadStatus; import com.unciv.civinfo.TileInfo; +import com.unciv.game.utils.ImageGetter; import com.unciv.models.LinqHashMap; public class TileGroup extends Group { @@ -18,6 +19,7 @@ public class TileGroup extends Group { Image resourceImage; Image unitImage; Image improvementImage; + String improvementType; Image populationImage; LinqHashMap roadImages = new LinqHashMap(); Image hexagon; @@ -30,14 +32,14 @@ public class TileGroup extends Group { terrainType = tileInfo.getLastTerrain().name; String terrainFileName = "TerrainIcons/" + terrainType.replace(' ','_') + "_(Civ5).png"; - terrainImage = com.unciv.game.utils.ImageGetter.getImageByFilename(terrainFileName); + terrainImage = ImageGetter.getImageByFilename(terrainFileName); terrainImage.setSize(50,50); addActor(terrainImage); } void addPopulationIcon(){ - populationImage = com.unciv.game.utils.ImageGetter.getStatIcon("Population"); + populationImage = ImageGetter.getStatIcon("Population"); populationImage.moveBy(0, terrainImage.getHeight()-populationImage.getHeight()); // top left addActor(populationImage); } @@ -52,12 +54,12 @@ public class TileGroup extends Group { if(!terrainType.equals(tileInfo.getLastTerrain().name)) { terrainType = tileInfo.getLastTerrain().name; String terrainFileName = "TerrainIcons/" + terrainType.replace(' ', '_') + "_(Civ5).png"; - terrainImage.setDrawable(new TextureRegionDrawable(com.unciv.game.utils.ImageGetter.textureRegionByFileName.get(terrainFileName))); // In case we e.g. removed a jungle + terrainImage.setDrawable(new TextureRegionDrawable(ImageGetter.textureRegionByFileName.get(terrainFileName))); // In case we e.g. removed a jungle } if (tileInfo.hasViewableResource() && resourceImage == null) { // Need to add the resource image! String fileName = "ResourceIcons/" + tileInfo.resource + "_(Civ5).png"; - Image image = com.unciv.game.utils.ImageGetter.getImageByFilename(fileName); + Image image = ImageGetter.getImageByFilename(fileName); image.setSize(20,20); image.moveBy(terrainImage.getWidth()-image.getWidth(), 0); // bottom right resourceImage = image; @@ -65,7 +67,7 @@ public class TileGroup extends Group { } if (tileInfo.unit != null && unitImage == null) { - unitImage = com.unciv.game.utils.ImageGetter.getImageByFilename("StatIcons/" + tileInfo.unit.name + "_(Civ5).png"); + unitImage = ImageGetter.getImageByFilename("StatIcons/" + tileInfo.unit.name + "_(Civ5).png"); addActor(unitImage); unitImage.setSize(20, 20); // not moved - is at bottom left } @@ -83,12 +85,13 @@ public class TileGroup extends Group { } - if (tileInfo.improvement != null && improvementImage == null) { - improvementImage = com.unciv.game.utils.ImageGetter.getImageByFilename("ImprovementIcons/" + tileInfo.improvement.replace(' ','_') + "_(Civ5).png"); + if (tileInfo.improvement != null &&!tileInfo.improvement.equals(improvementType)) { + improvementImage = ImageGetter.getImageByFilename("ImprovementIcons/" + tileInfo.improvement.replace(' ','_') + "_(Civ5).png"); addActor(improvementImage); improvementImage.setSize(20, 20); improvementImage.moveBy(terrainImage.getWidth()-improvementImage.getWidth(), terrainImage.getHeight() - improvementImage.getHeight()); // top right + improvementType = tileInfo.improvement; } if(populationImage!=null){ @@ -101,7 +104,7 @@ public class TileGroup extends Group { if (neighbor == tileInfo || neighbor.roadStatus == RoadStatus.None) continue; if (roadImages.containsKey(neighbor.position.toString())) continue; - Image image = com.unciv.game.utils.ImageGetter.getImageByFilename("TerrainIcons/road.png"); + Image image = ImageGetter.getImageByFilename("TerrainIcons/road.png"); roadImages.put(neighbor.position.toString(), image); Vector2 relativeHexPosition = tileInfo.position.cpy().sub(neighbor.position); diff --git a/core/src/com/unciv/game/UnCivGame.java b/core/src/com/unciv/game/UnCivGame.java index 69c00cfc24..37e045127f 100644 --- a/core/src/com/unciv/game/UnCivGame.java +++ b/core/src/com/unciv/game/UnCivGame.java @@ -17,6 +17,8 @@ import com.unciv.models.gamebasics.TechColumn; import com.unciv.models.gamebasics.Terrain; import com.unciv.models.gamebasics.TileImprovement; import com.unciv.models.gamebasics.TileResource; +import com.unciv.models.stats.INamed; +import com.unciv.models.stats.NamedStats; public class UnCivGame extends Game { @@ -64,9 +66,9 @@ public class UnCivGame extends Game { return new Json().fromJson(tClass,jsonText); } - private LinqHashMap CreateHashmap(Class tClass, T[] items){ + private LinqHashMap CreateHashmap(Class tClass, T[] items){ LinqHashMap hashMap = new LinqHashMap(); - for(T item:items) hashMap.put(item.GetName(),item); + for(T item:items) hashMap.put(item.getName(),item); return hashMap; } @@ -76,6 +78,7 @@ public class UnCivGame extends Game { GameBasics.TileResources = CreateHashmap(TileResource.class,GetFromJson(TileResource[].class,"TileResources")); GameBasics.TileImprovements = CreateHashmap(TileImprovement.class,GetFromJson(TileImprovement[].class,"TileImprovements")); GameBasics.Helps = CreateHashmap(BasicHelp.class,GetFromJson(BasicHelp[].class,"BasicHelp")); + GameBasics.Units = CreateHashmap(Unit.class,GetFromJson(Unit[].class,"Units")); TechColumn[] TechColumns = GetFromJson(TechColumn[].class, "Techs"); GameBasics.Technologies = new LinqHashMap(); diff --git a/core/src/com/unciv/game/VictoryScreen.java b/core/src/com/unciv/game/VictoryScreen.java index d94a877af4..8c7bf00097 100644 --- a/core/src/com/unciv/game/VictoryScreen.java +++ b/core/src/com/unciv/game/VictoryScreen.java @@ -6,8 +6,6 @@ import com.badlogic.gdx.scenes.scene2d.ui.TextButton; import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; import com.unciv.game.utils.CameraStageBaseScreen; -import javax.xml.soap.Text; - public class VictoryScreen extends CameraStageBaseScreen{ public VictoryScreen(final UnCivGame game) { diff --git a/core/src/com/unciv/game/WorldTileGroup.java b/core/src/com/unciv/game/WorldTileGroup.java index 7cbbb10946..15af6e225a 100644 --- a/core/src/com/unciv/game/WorldTileGroup.java +++ b/core/src/com/unciv/game/WorldTileGroup.java @@ -62,7 +62,7 @@ public class WorldTileGroup extends TileGroup { } String cityButtonText = city.name +" ("+city.population+")"; -// +" ("+city.population+")" + "\r\n" + city.cityBuildings.getCityProductionText(); +// +" ("+city.population+")" + "\r\n" + city.cityConstructions.getCityProductionTextForCityButton(); TextButton button = cityButton.getActor(); button.setText(cityButtonText); button.setSize(button.getPrefWidth(), button.getPrefHeight()); diff --git a/core/src/com/unciv/game/pickerscreens/BuildingPickerScreen.java b/core/src/com/unciv/game/pickerscreens/BuildingPickerScreen.java index 0d2f827143..e8c2325e99 100644 --- a/core/src/com/unciv/game/pickerscreens/BuildingPickerScreen.java +++ b/core/src/com/unciv/game/pickerscreens/BuildingPickerScreen.java @@ -6,7 +6,8 @@ import com.badlogic.gdx.scenes.scene2d.Touchable; import com.badlogic.gdx.scenes.scene2d.ui.TextButton; import com.badlogic.gdx.scenes.scene2d.ui.VerticalGroup; import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; -import com.unciv.civinfo.CityBuildings; +import com.unciv.civinfo.CityConstructions; +import com.unciv.civinfo.Unit; import com.unciv.game.CityScreen; import com.unciv.game.UnCivGame; import com.unciv.models.gamebasics.Building; @@ -47,7 +48,7 @@ public class BuildingPickerScreen extends PickerScreen { rightSideButton.addListener(new ClickListener(){ @Override public void clicked(InputEvent event, float x, float y) { - game.civInfo.getCurrentCity().cityBuildings.currentBuilding = selectedProduction; + game.civInfo.getCurrentCity().cityConstructions.currentConstruction = selectedProduction; game.civInfo.getCurrentCity().updateCityStats(); // Because maybe we set/removed the science or gold production options. game.setScreen(new CityScreen(game)); dispose(); @@ -56,21 +57,29 @@ public class BuildingPickerScreen extends PickerScreen { rightSideButton.setTouchable(Touchable.disabled); rightSideButton.setColor(Color.GRAY); - CityBuildings cityBuildings = game.civInfo.getCurrentCity().cityBuildings; + CityConstructions cityBuildings = game.civInfo.getCurrentCity().cityConstructions; VerticalGroup regularBuildings = new VerticalGroup().space(10), wonders = new VerticalGroup().space(10), + units = new VerticalGroup().space(10), specials = new VerticalGroup().space(10); for(final Building building : GameBasics.Buildings.values()) { - if(!cityBuildings.canBuild(building)) continue; + if(!building.isBuildable(cityBuildings)) continue; TextButton TB = getProductionButton(building.name, - building.name +"\r\n"+cityBuildings.turnsToBuilding(building.name)+" turns", + building.name +"\r\n"+cityBuildings.turnsToConstruction(building.name)+" turns", building.getDescription(true), "Build "+building.name); if(building.isWonder) wonders.addActor(TB); else regularBuildings.addActor(TB); } + for(Unit unit : GameBasics.Units.values()){ + if(!unit.isConstructable()) continue; + units.addActor(getProductionButton(unit.name, + unit.name+"\r\n"+cityBuildings.turnsToConstruction(unit.name)+" turns", + unit.description, "Train "+unit.name)); + } + if(game.civInfo.tech.isResearched("Education")) specials.addActor(getProductionButton("Science","Produce Science", "Convert production to science at a rate of 4 to 1", "Produce Science")); @@ -79,6 +88,7 @@ public class BuildingPickerScreen extends PickerScreen { specials.addActor(getProductionButton("Gold","Produce Gold", "Convert production to gold at a rate of 4 to 1", "Produce Gold")); + topTable.add(units); topTable.add(regularBuildings); topTable.add(wonders); topTable.add(specials); diff --git a/core/src/com/unciv/game/pickerscreens/ImprovementPickerScreen.java b/core/src/com/unciv/game/pickerscreens/ImprovementPickerScreen.java index b8be2047de..d1a8937b20 100644 --- a/core/src/com/unciv/game/pickerscreens/ImprovementPickerScreen.java +++ b/core/src/com/unciv/game/pickerscreens/ImprovementPickerScreen.java @@ -37,12 +37,15 @@ public class ImprovementPickerScreen extends PickerScreen { regularImprovements.space(10); for(final TileImprovement improvement : GameBasics.TileImprovements.values()) { if(!tileInfo.canBuildImprovement(improvement) || improvement.name.equals(tileInfo.improvement)) continue; - TextButton TB = new TextButton(improvement.name +"\r\n"+improvement.turnsToBuild +" turns", skin); + int turnsToBuild = improvement.turnsToBuild; + if(CivilizationInfo.current().getBuildingUniques().contains("WorkerConstruction")) turnsToBuild= (int) Math.round(0.75*turnsToBuild); + TextButton TB = new TextButton(improvement.name +"\r\n"+turnsToBuild +" turns", skin); + final int finalTurnsToBuild = turnsToBuild; TB.addListener(new ClickListener(){ @Override public void clicked(InputEvent event, float x, float y) { SelectedImprovement = improvement.name; - TurnsToImprovement = improvement.turnsToBuild; + TurnsToImprovement = finalTurnsToBuild; rightSideButton.setTouchable(Touchable.enabled); rightSideButton.setText(improvement.name); rightSideButton.setColor(Color.WHITE); diff --git a/core/src/com/unciv/models/gamebasics/BasicHelp.java b/core/src/com/unciv/models/gamebasics/BasicHelp.java index 383e526503..4caf3e2bb9 100644 --- a/core/src/com/unciv/models/gamebasics/BasicHelp.java +++ b/core/src/com/unciv/models/gamebasics/BasicHelp.java @@ -1,9 +1,15 @@ package com.unciv.models.gamebasics; +import com.unciv.models.stats.INamed; import com.unciv.models.stats.NamedStats; -public class BasicHelp extends NamedStats implements ICivilopedia { +public class BasicHelp implements ICivilopedia, INamed { public String description; + public String name; + + public String getName() { + return name; + } @Override public String getDescription() { diff --git a/core/src/com/unciv/models/gamebasics/Building.java b/core/src/com/unciv/models/gamebasics/Building.java index 27cbe84220..28dbb52d07 100644 --- a/core/src/com/unciv/models/gamebasics/Building.java +++ b/core/src/com/unciv/models/gamebasics/Building.java @@ -1,10 +1,18 @@ package com.unciv.models.gamebasics; +import com.badlogic.gdx.utils.Predicate; +import com.unciv.civinfo.CityInfo; +import com.unciv.civinfo.CivilizationInfo; +import com.unciv.civinfo.CityConstructions; +import com.unciv.civinfo.IConstruction; +import com.unciv.civinfo.TileInfo; +import com.unciv.game.UnCivGame; +import com.unciv.game.VictoryScreen; import com.unciv.models.LinqCollection; import com.unciv.models.stats.FullStats; import com.unciv.models.stats.NamedStats; -public class Building extends NamedStats implements ICivilopedia { +public class Building extends NamedStats implements IConstruction, ICivilopedia { public String description; public String requiredTech; @@ -14,7 +22,9 @@ public class Building extends NamedStats implements ICivilopedia { public int cost; public int maintainance = 0; - public FullStats percentStatBonus = new FullStats(); + public FullStats percentStatBonus; + public FullStats specialistSlots; + public FullStats greatPersonPoints; public int hurryCostModifier; // Extra cost percentage when purchasing public boolean isWonder = false; public String requiredBuilding; @@ -54,12 +64,92 @@ public class Building extends NamedStats implements ICivilopedia { if (maintainance != 0) stringBuilder.append("Maintainance cost: " + maintainance + " gold\r\n"); stringBuilder.append(description + "\r\n" + stats); + if(this.percentStatBonus!=null){ + if(this.percentStatBonus.production!=0) stringBuilder.append("\r\n+"+this.percentStatBonus.production+" production"); + if(this.percentStatBonus.gold!=0) stringBuilder.append("\r\n+"+this.percentStatBonus.gold+" gold"); + if(this.percentStatBonus.science!=0) stringBuilder.append("\r\n+"+this.percentStatBonus.science+" science"); + if(this.percentStatBonus.food!=0) stringBuilder.append("\r\n+"+this.percentStatBonus.food+" food"); + if(this.percentStatBonus.culture!=0) stringBuilder.append("\r\n+"+this.percentStatBonus.culture+" culture"); + } return stringBuilder.toString(); } + @Override + public int getProductionCost() { + return cost; + } + public int getGoldCost(){ return (int)( Math.pow(30 * cost,0.75) * (1 + hurryCostModifier/100) / 10 ) * 10; } + + public boolean isBuildable(CityConstructions construction){ + CivilizationInfo civInfo = UnCivGame.Current.civInfo; + if(construction.isBuilt(name)) return false; + if(requiredNearbyImprovedResources!=null) { + boolean containsResourceWithImprovement = construction.getCity().getTilesInRange() + .any(new Predicate() { + @Override + public boolean evaluate(TileInfo tile) { + return tile.resource != null + && requiredNearbyImprovedResources.contains(tile.resource) + && tile.getTileResource().improvement.equals(tile.improvement); + } + }); + if(!containsResourceWithImprovement) return false; + } + + if (requiredTech != null && !civInfo.tech.isResearched(requiredTech)) return false; + if (isWonder && civInfo.cities + .any(new Predicate() { + @Override + public boolean evaluate(CityInfo arg0) { + CityConstructions CB = arg0.cityConstructions; + return CB.isBuilding(name) || CB.isBuilt(name); + } + }) ) return false; + if (requiredBuilding != null && !construction.isBuilt(requiredBuilding)) return false; + if (requiredBuildingInAllCities != null || + civInfo.cities.any(new Predicate() { + @Override + public boolean evaluate(CityInfo arg0) { + return arg0.cityConstructions.isBuilt(requiredBuildingInAllCities); + } + }) ) return false; + if(cannotBeBuiltWith != null && construction.isBuilt(cannotBeBuiltWith)) return false; + if("MustBeNextToDesert".equals(unique) && + !civInfo.tileMap.getTilesInDistance(construction.cityLocation,1).any(new Predicate() { + @Override + public boolean evaluate(TileInfo arg0) { + return arg0.baseTerrain.equals("Desert"); + } + })) + return false; + if(requiredResource!=null && + !civInfo.getCivResources().keySet().contains(GameBasics.TileResources.get(requiredResource))) + return false; // Only checks if exists, doesn't check amount - todo + + if("SpaceshipPart".equals(unique)){ + if(!civInfo.getBuildingUniques().contains("ApolloProgram")) return false; + if(civInfo.scienceVictory.requiredParts.get(name)==0) return false; // Don't need to build any more of these! + } + return true; + } + + @Override + public void postBuildEvent(CityConstructions constructions) { + if("SpaceshipPart".equals(unique)) { + CivilizationInfo.current().scienceVictory.currentParts.add(name, 1); + if(CivilizationInfo.current().scienceVictory.unconstructedParts().isEmpty()) + UnCivGame.Current.setScreen(new VictoryScreen(UnCivGame.Current)); + return; + } + constructions.builtBuildings.add(name); + if (providesFreeBuilding != null && !constructions.builtBuildings.contains(providesFreeBuilding)) + constructions.builtBuildings.add(providesFreeBuilding); + if (freeTechs != 0) UnCivGame.Current.civInfo.tech.freeTechs += freeTechs; + if("EmpireEntersGoldenAge".equals(unique)) CivilizationInfo.current().enterGoldenAge(); + } } diff --git a/core/src/com/unciv/models/gamebasics/GameBasics.java b/core/src/com/unciv/models/gamebasics/GameBasics.java index 494f219701..2f02a285d3 100644 --- a/core/src/com/unciv/models/gamebasics/GameBasics.java +++ b/core/src/com/unciv/models/gamebasics/GameBasics.java @@ -1,7 +1,10 @@ package com.unciv.models.gamebasics; +import com.unciv.civinfo.Unit; import com.unciv.models.LinqHashMap; +import java.util.LinkedHashMap; + public class GameBasics{ public static LinqHashMap Buildings; public static LinqHashMap Terrains; @@ -9,4 +12,5 @@ public class GameBasics{ public static LinqHashMap TileImprovements; public static LinqHashMap Technologies; public static LinqHashMap Helps; + public static LinkedHashMap Units; } \ No newline at end of file diff --git a/core/src/com/unciv/models/stats/INamed.java b/core/src/com/unciv/models/stats/INamed.java new file mode 100644 index 0000000000..26d4021f3a --- /dev/null +++ b/core/src/com/unciv/models/stats/INamed.java @@ -0,0 +1,3 @@ +package com.unciv.models.stats; + +public interface INamed{public String getName();} diff --git a/core/src/com/unciv/models/stats/NamedStats.java b/core/src/com/unciv/models/stats/NamedStats.java index 31c1bf34db..4493d23662 100644 --- a/core/src/com/unciv/models/stats/NamedStats.java +++ b/core/src/com/unciv/models/stats/NamedStats.java @@ -1,9 +1,10 @@ package com.unciv.models.stats; -public class NamedStats extends FullStats { + +public class NamedStats extends FullStats implements INamed { public String name; - public String GetName() { + public String getName() { return name; }