Merge branch 'master' into master
BIN
android/Images/UnitPromotionIcons/Accuracy.png
Normal file
After Width: | Height: | Size: 862 B |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.7 KiB |
BIN
android/Images/UnitPromotionIcons/Barrage.png
Normal file
After Width: | Height: | Size: 869 B |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.8 KiB |
BIN
android/Images/UnitPromotionIcons/Bombardment.png
Normal file
After Width: | Height: | Size: 704 B |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.8 KiB |
BIN
android/Images/UnitPromotionIcons/Coastal_Raider.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.7 KiB |
BIN
android/Images/UnitPromotionIcons/Cover.png
Normal file
After Width: | Height: | Size: 825 B |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.9 KiB |
BIN
android/Images/UnitPromotionIcons/Drill.png
Normal file
After Width: | Height: | Size: 614 B |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.9 KiB |
BIN
android/Images/UnitPromotionIcons/Formation.png
Normal file
After Width: | Height: | Size: 468 B |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.7 KiB |
BIN
android/Images/UnitPromotionIcons/Medic.png
Normal file
After Width: | Height: | Size: 273 B |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.8 KiB |
BIN
android/Images/UnitPromotionIcons/Shock.png
Normal file
After Width: | Height: | Size: 562 B |
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.8 KiB |
BIN
android/Images/UnitPromotionIcons/Siege.png
Normal file
After Width: | Height: | Size: 537 B |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 1.0 MiB |
@ -48,7 +48,7 @@
|
||||
{
|
||||
name:"Lakes",
|
||||
type:"Water",
|
||||
food:1,
|
||||
food:2,
|
||||
gold:1,
|
||||
RGB: [ 200, 200, 255],
|
||||
canHaveOverlay:false
|
||||
|
@ -20,6 +20,11 @@ class CityStats {
|
||||
var baseStatList = LinkedHashMap<String, Stats>()
|
||||
@Transient
|
||||
var statPercentBonusList = LinkedHashMap<String, Stats>()
|
||||
|
||||
// Computed from baseStatList and statPercentBonusList - this is so the players can see a breakdown
|
||||
@Transient
|
||||
var finalStatList = LinkedHashMap<String, Stats>()
|
||||
|
||||
@Transient
|
||||
var happinessList = LinkedHashMap<String, Float>()
|
||||
@Transient
|
||||
@ -383,26 +388,38 @@ class CityStats {
|
||||
updateBaseStatList()
|
||||
updateStatPercentBonusList()
|
||||
|
||||
val newCurrentCityStats = Stats() // again, we don't edit the existing currentCityStats directly, in order to avoid concurrency exceptions
|
||||
for(stat in baseStatList.values) newCurrentCityStats.add(stat)
|
||||
updateFinalStatList() // again, we don't edit the existing currentCityStats directly, in order to avoid concurrency exceptions
|
||||
|
||||
val newCurrentCityStats = Stats()
|
||||
for(stat in finalStatList.values) newCurrentCityStats.add(stat)
|
||||
currentCityStats = newCurrentCityStats
|
||||
|
||||
cityInfo.civInfo.updateStatsForNextTurn()
|
||||
}
|
||||
|
||||
private fun updateFinalStatList(){
|
||||
val newFinalStatList = LinkedHashMap<String, Stats>() // again, we don't edit the existing currentCityStats directly, in order to avoid concurrency exceptions
|
||||
|
||||
for (entry in baseStatList)
|
||||
newFinalStatList[entry.key] = entry.value
|
||||
|
||||
val statPercentBonusesSum = Stats()
|
||||
for(bonus in statPercentBonusList.values) statPercentBonusesSum.add(bonus)
|
||||
for (bonus in statPercentBonusList.values) statPercentBonusesSum.add(bonus)
|
||||
|
||||
for (entry in newFinalStatList.values)
|
||||
entry.production *= 1 + statPercentBonusesSum.production / 100
|
||||
|
||||
newCurrentCityStats.production *= 1 + statPercentBonusesSum.production / 100
|
||||
|
||||
val statsFromProduction = getStatsFromProduction(newCurrentCityStats.production)
|
||||
newCurrentCityStats.add(statsFromProduction)
|
||||
baseStatList = LinkedHashMap(baseStatList).apply { put("Construction",statsFromProduction) } // concurrency-safe addition
|
||||
|
||||
newCurrentCityStats.gold *= 1 + statPercentBonusesSum.gold / 100
|
||||
newCurrentCityStats.science *= 1 + statPercentBonusesSum.science / 100
|
||||
newCurrentCityStats.culture *= 1 + statPercentBonusesSum.culture / 100
|
||||
val statsFromProduction = getStatsFromProduction(newFinalStatList.values.map { it.production }.sum())
|
||||
baseStatList = LinkedHashMap(baseStatList).apply { put("Construction", statsFromProduction) } // concurrency-safe addition
|
||||
newFinalStatList["Construction"] = statsFromProduction
|
||||
|
||||
val isUnhappy = cityInfo.civInfo.getHappiness() < 0
|
||||
if (!isUnhappy) // Regular food bonus revoked when unhappy per https://forums.civfanatics.com/resources/complete-guide-to-happiness-vanilla.25584/
|
||||
newCurrentCityStats.food *= 1 + statPercentBonusesSum.food / 100
|
||||
for (entry in newFinalStatList.values) {
|
||||
entry.gold *= 1 + statPercentBonusesSum.gold / 100
|
||||
entry.science *= 1 + statPercentBonusesSum.science / 100
|
||||
entry.culture *= 1 + statPercentBonusesSum.culture / 100
|
||||
if (!isUnhappy) entry.food *= 1 + statPercentBonusesSum.food / 100 // Regular food bonus revoked when unhappy per https://forums.civfanatics.com/resources/complete-guide-to-happiness-vanilla.25584/
|
||||
}
|
||||
|
||||
//
|
||||
/* Okay, food calculation is complicated.
|
||||
@ -414,29 +431,32 @@ class CityStats {
|
||||
*/
|
||||
|
||||
updateFoodEaten()
|
||||
newCurrentCityStats.food -= foodEaten
|
||||
newFinalStatList["Population"]!!.food -= foodEaten
|
||||
|
||||
if (isUnhappy && newCurrentCityStats.food > 0) { // Reduce excess food to 1/4 per the same
|
||||
val foodReducedByUnhappiness = Stats().add(Stat.Food,newCurrentCityStats.food * (-3/4f))
|
||||
var totalFood = newFinalStatList.values.map { it.food }.sum()
|
||||
|
||||
if (isUnhappy && totalFood > 0) { // Reduce excess food to 1/4 per the same
|
||||
val foodReducedByUnhappiness = Stats().apply { food = totalFood * (-3 / 4f) }
|
||||
baseStatList = LinkedHashMap(baseStatList).apply { put("Unhappiness", foodReducedByUnhappiness) } // concurrency-safe addition
|
||||
newCurrentCityStats.add(foodReducedByUnhappiness)
|
||||
newFinalStatList["Unhappiness"] = foodReducedByUnhappiness
|
||||
}
|
||||
|
||||
totalFood = newFinalStatList.values.map { it.food }.sum() // recalculate because of previous change
|
||||
|
||||
// Since growth bonuses are special, (applied afterwards) they will be displayed separately in the user interface as well.
|
||||
val foodFromGrowthBonuses = getGrowthBonusFromPolicies() * newCurrentCityStats.food
|
||||
newCurrentCityStats.food += foodFromGrowthBonuses
|
||||
val foodFromGrowthBonuses = getGrowthBonusFromPolicies() * totalFood
|
||||
newFinalStatList["Policies"]!!.food += foodFromGrowthBonuses
|
||||
|
||||
// Same here - will have a different UI display.
|
||||
val buildingsMaintenance = cityInfo.cityConstructions.getMaintenanceCosts() // this is AFTER the bonus calculation!
|
||||
newCurrentCityStats.gold -= buildingsMaintenance
|
||||
|
||||
if(newCurrentCityStats.production<1) newCurrentCityStats.production=1f
|
||||
newFinalStatList["Maintenance"] = Stats().apply { gold -= buildingsMaintenance }
|
||||
|
||||
if (cityInfo.resistanceCounter > 0)
|
||||
currentCityStats = Stats().add(Stat.Production,1f) // You get nothing, Jon Snow
|
||||
else currentCityStats = newCurrentCityStats
|
||||
newFinalStatList.clear() // NOPE
|
||||
|
||||
cityInfo.civInfo.updateStatsForNextTurn()
|
||||
if (newFinalStatList.values.map { it.production }.sum() < 1) // Minimum production for things to progress
|
||||
newFinalStatList["Production"] = Stats().apply { production += 1 }
|
||||
finalStatList = newFinalStatList
|
||||
}
|
||||
|
||||
private fun updateFoodEaten() {
|
||||
|
@ -54,8 +54,9 @@ class CivInfoStats(val civInfo: CivilizationInfo){
|
||||
|
||||
fun getStatMapForNextTurn(): HashMap<String, Stats> {
|
||||
val statMap = StatMap()
|
||||
for (city in civInfo.cities){
|
||||
statMap.add("Cities",city.cityStats.currentCityStats)
|
||||
for (city in civInfo.cities) {
|
||||
for (entry in city.cityStats.finalStatList)
|
||||
statMap.add(entry.key, entry.value)
|
||||
}
|
||||
|
||||
//City states culture bonus
|
||||
|
@ -114,8 +114,8 @@ class EmpireOverviewScreen : CameraStageBaseScreen(){
|
||||
|
||||
private fun createTradeTable(trade: Trade, otherCiv:CivilizationInfo): Table {
|
||||
val generalTable = Table(skin)
|
||||
generalTable.add(createOffersTable(currentPlayerCivInfo,trade.ourOffers, trade.theirOffers.size))
|
||||
generalTable.add(createOffersTable(otherCiv, trade.theirOffers, trade.ourOffers.size))
|
||||
generalTable.add(createOffersTable(currentPlayerCivInfo,trade.ourOffers, trade.theirOffers.size)).top()
|
||||
generalTable.add(createOffersTable(otherCiv, trade.theirOffers, trade.ourOffers.size)).top()
|
||||
return generalTable
|
||||
}
|
||||
|
||||
|
@ -451,7 +451,10 @@ open class TileGroup(var tileInfo: TileInfo, var tileSetStrings:TileSetStrings)
|
||||
newImage.center(this)
|
||||
newImage.y += yFromCenter
|
||||
|
||||
if (!unit.isIdle() && unit.civInfo.isPlayerCivilization()) newImage.color.a = 0.5f
|
||||
// Instead of fading out the entire unit with its background, we just fade out its central icon,
|
||||
// that way it remains much more visible on the map
|
||||
if (!unit.isIdle() && unit.civInfo.isPlayerCivilization())
|
||||
newImage.unitBaseImage.color.a = 0.5f
|
||||
}
|
||||
return newImage
|
||||
}
|
||||
|
@ -116,7 +116,34 @@ object ImageGetter {
|
||||
return getStatIcon(construction)
|
||||
}
|
||||
|
||||
fun getPromotionIcon(promotionName:String):Image{
|
||||
fun getPromotionIcon(promotionName:String): Actor {
|
||||
var level = 0
|
||||
|
||||
when {
|
||||
promotionName.endsWith(" I") -> level=1
|
||||
promotionName.endsWith(" II") -> level=2
|
||||
promotionName.endsWith(" III") -> level=3
|
||||
}
|
||||
|
||||
val basePromotionName = if(level==0) promotionName
|
||||
else promotionName.substring(0, promotionName.length-level-1)
|
||||
|
||||
if(imageExists("UnitPromotionIcons/$basePromotionName")) {
|
||||
val icon = getImage("UnitPromotionIcons/$basePromotionName")
|
||||
icon.color = colorFromRGB(255,226,0)
|
||||
var circle = icon.surroundWithCircle(30f)
|
||||
circle.circle.color = colorFromRGB(0,12,49)
|
||||
// circle = circle.surroundWithCircle(40f)
|
||||
// circle.circle.color = colorFromRGB(255,226,0)
|
||||
if(level!=0){
|
||||
val starTable = Table().apply { defaults().pad(2f) }
|
||||
for(i in 1..level) starTable.add(getImage("OtherIcons/Star")).size(8f)
|
||||
starTable.centerX(circle)
|
||||
starTable.y=5f
|
||||
circle.addActor(starTable)
|
||||
}
|
||||
return circle
|
||||
}
|
||||
return getImage("UnitPromotionIcons/" + promotionName.replace(' ', '_') + "_(Civ5)")
|
||||
}
|
||||
|
||||
|
@ -9,10 +9,10 @@ import com.unciv.logic.map.MapUnit
|
||||
|
||||
class UnitGroup(val unit: MapUnit, val size: Float): Group() {
|
||||
var blackSpinningCircle:Image?=null
|
||||
val unitBaseImage = ImageGetter.getUnitIcon(unit.name, unit.civInfo.nation.getInnerColor())
|
||||
.apply { setSize(size * 0.75f, size * 0.75f) }
|
||||
|
||||
init {
|
||||
val unitBaseImage = ImageGetter.getUnitIcon(unit.name, unit.civInfo.nation.getInnerColor())
|
||||
.apply { setSize(size * 0.75f, size * 0.75f) }
|
||||
|
||||
val background = getBackgroundImageForUnit(unit)
|
||||
background.apply {
|
||||
|
@ -253,7 +253,7 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
|
||||
val buttonPic = Table()
|
||||
buttonPic.background = ImageGetter.getDrawable("OtherIcons/civTableBackground")
|
||||
.tint(colorFromRGB(7, 46, 43))
|
||||
buttonPic.defaults().pad(10f)
|
||||
buttonPic.defaults().pad(20f)
|
||||
buttonPic.add("{Pick a tech}!".toLabel().setFontColor(Color.WHITE).setFontSize(30))
|
||||
techButtonHolder.add(buttonPic)
|
||||
}
|
||||
|
@ -184,7 +184,7 @@ class UnitTable(val worldScreen: WorldScreen) : Table(){
|
||||
if(selectedUnit!=null) {
|
||||
unitIconHolder.add(UnitGroup(selectedUnit!!,30f)).pad(5f)
|
||||
for(promotion in selectedUnit!!.promotions.promotions)
|
||||
promotionsTable.add(ImageGetter.getPromotionIcon(promotion)).size(20f)
|
||||
promotionsTable.add(ImageGetter.getPromotionIcon(promotion))//.size(20f)
|
||||
|
||||
}
|
||||
|
||||
|
@ -440,6 +440,18 @@ Unless otherwise specified, all the following are from [the Noun Project](https:
|
||||
* Variation on [crecent moon](https://thenounproject.com/search/?q=crescents&i=1438333) by Estu Suhartono for The Ottomans
|
||||
* [Korea](https://thenounproject.com/search/?q=korea&i=1689701) by CJS for Korea
|
||||
|
||||
## Promotions
|
||||
|
||||
* [Sight](https://thenounproject.com/search/?q=sight&i=2631027) By Jejen Juliansyah Nur Agung for Accuracy
|
||||
* [skill bow rain arrow](https://thenounproject.com/search/?q=rain%20of%20arrows&i=2360192) by Maxicons for Barrage
|
||||
* [Bomb](https://thenounproject.com/search/?q=bombardment&i=1705276) By Angelo Troiano for Bombardment
|
||||
* [Private E2](https://thenounproject.com/yeongrong.kim.5/collection/miltary-rank/?i=833152) By Yeong Rong Kim for Shock
|
||||
* [Private First Class](https://thenounproject.com/yeongrong.kim.5/collection/miltary-rank/?i=833161) By Yeong Rong Kim for Drill
|
||||
* [Medic](https://thenounproject.com/search/?q=medic&i=48740) By Yohann Berger for Medic
|
||||
* [City](https://thenounproject.com/search/?q=city&i=2402817) By iconcheese for Siege
|
||||
* [Skull and Crossbones](https://thenounproject.com/search/?q=skull%20and%20cross%20bones&i=15526) By Anton Outkine for Coastal Raider
|
||||
* [Spear](https://thenounproject.com/search/?q=spear&i=1754184) By Deemak Daksina for Formation
|
||||
|
||||
## Others
|
||||
|
||||
* [Circle](https://thenounproject.com/term/circle/1841891/) By Aybige
|
||||
|