Normalized city strength according to original civ game

Added Walls and Castle buildings
This commit is contained in:
Yair Morgenstern 2018-06-17 19:47:01 +03:00
parent 80963e7eac
commit 5fa9ad0640
6 changed files with 63 additions and 35 deletions

View File

@ -69,6 +69,13 @@
hurryCostModifier:25,
requiredTech:"Trapping"
},
{
name:"Walls",
cityStrength:5,
cityHealth:50,
hurryCostModifier:25,
requiredTech:"Masonry"
},
{
name:"The Pyramids",
baseDescription: "Worker construction increased 25%, provides 2 free workers",
@ -243,6 +250,14 @@
requiredBuildingInAllCities:"University",
requiredTech:"Education"
},
{
name:"Castle",
cityStrength:7,
cityHealth:25,
hurryCostModifier:25,
requiredBuilding:"Walls",
requiredTech:"Chivalry"
},
{
name:"Angkor Wat",
baseDescription: "Cost of acquiring new tiles reduced by 25%",

View File

@ -76,33 +76,32 @@ class BattleDamage{
return modifiers
}
fun getDefenceModifiers(attacker: ICombatant, defender: ICombatant): HashMap<String, Float> {
fun getDefenceModifiers(attacker: ICombatant, defender: MapUnitCombatant): HashMap<String, Float> {
val modifiers = getGeneralModifiers(defender, attacker)
if (!(defender is MapUnitCombatant && defender.unit.hasUnique("No defensive terrain bonus"))) {
if (!(defender.unit.hasUnique("No defensive terrain bonus"))) {
val tileDefenceBonus = defender.getTile().getDefensiveBonus()
if (tileDefenceBonus > 0) modifiers["Terrain"] = tileDefenceBonus
}
if(defender is MapUnitCombatant) {
val defenderTile = defender.getTile()
val isDefenderInRoughTerrain = defenderTile.baseTerrain=="Hill" || defenderTile.terrainFeature == "Forest" || defenderTile.terrainFeature == "Jungle"
for (BDM in getBattleDamageModifiersOfUnit(defender.unit)) {
val text = BDM.getText()
if (BDM.vs == "units in open terrain" && !isDefenderInRoughTerrain) {
if(modifiers.containsKey(text))
modifiers[text] =modifiers[text]!! + BDM.modificationAmount
else modifiers[text] = BDM.modificationAmount
}
if (BDM.vs == "units in rough terrain" && isDefenderInRoughTerrain) {
if (modifiers.containsKey(text))
modifiers[text] = modifiers[text]!! + BDM.modificationAmount
else modifiers[text] = BDM.modificationAmount
}
val defenderTile = defender.getTile()
val isDefenderInRoughTerrain = defenderTile.baseTerrain == "Hill" || defenderTile.terrainFeature == "Forest" || defenderTile.terrainFeature == "Jungle"
for (BDM in getBattleDamageModifiersOfUnit(defender.unit)) {
val text = BDM.getText()
if (BDM.vs == "units in open terrain" && !isDefenderInRoughTerrain) {
if (modifiers.containsKey(text))
modifiers[text] = modifiers[text]!! + BDM.modificationAmount
else modifiers[text] = BDM.modificationAmount
}
if (BDM.vs == "units in rough terrain" && isDefenderInRoughTerrain) {
if (modifiers.containsKey(text))
modifiers[text] = modifiers[text]!! + BDM.modificationAmount
else modifiers[text] = BDM.modificationAmount
}
}
if(defender is MapUnitCombatant && defender.unit.isFortified())
modifiers["Fortification"]=0.2f*defender.unit.getFortificationTurns()
if (defender.unit.isFortified())
modifiers["Fortification"] = 0.2f * defender.unit.getFortificationTurns()
return modifiers
}
@ -133,7 +132,8 @@ class BattleDamage{
* Includes defence modifiers
*/
fun getDefendingStrength(attacker: ICombatant, defender: ICombatant): Float {
val defenceModifier = modifiersToMultiplicationBonus(getDefenceModifiers(attacker,defender))
var defenceModifier = 1f
if(defender is MapUnitCombatant) defenceModifier = modifiersToMultiplicationBonus(getDefenceModifiers(attacker,defender))
return defender.getDefendingStrength(attacker) * defenceModifier
}

View File

@ -3,8 +3,8 @@ package com.unciv.logic.battle
import com.unciv.logic.city.CityInfo
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.map.TileInfo
import com.unciv.models.gamebasics.unit.UnitType
import com.unciv.models.gamebasics.GameBasics
import com.unciv.models.gamebasics.unit.UnitType
class CityCombatant(val city: CityInfo) : ICombatant {
override fun getHealth(): Int = city.health
@ -25,24 +25,29 @@ class CityCombatant(val city: CityInfo) : ICombatant {
return getCityStrength()
}
private fun
getCityStrength(): Int {
val baseStrength = 10
private fun getCityStrength(): Int { // Civ fanatics forum, from a modder who went through the original code
var strength = 8f
if(city.isCapital()) strength+=2.5f
strength += (city.population.population/5) * 2 // Each 5 pop gives 2 defence
val cityTile = city.getCenterTile()
if(cityTile.baseTerrain=="Hill") strength+=5
// as tech progresses so does city strength
val techsPercentKnown: Float = city.civInfo.tech.techsResearched.count().toFloat() /
GameBasics.Technologies.count()
val strengthFromTechs = Math.pow(techsPercentKnown*3.0,2.0) *5
strength += Math.pow(techsPercentKnown*5.5, 2.8).toFloat()
// The way all of this adds up...
// 25% of the way through the game provides an extra 3.12
// 50% of the way through the game provides an extra 12.50
// 75% of the way through the game provides an extra 28.12
// All ancient techs - 0.5 extra, Classical - 2.7, Medieval - 8, Renaissance - 17.5,
// Industrial - 32.4, Modern - 51, Atomic - 72.5, All - 118.3
// 100% of the way through the game provides an extra 50.00
// 10% bonus foreach pop
val strengthWithPop = (baseStrength + strengthFromTechs) * (1 + 0.1*city.population.population)
// Garrisoned unit gives up to 20% of strength to city, health-dependant
if(cityTile.militaryUnit!=null)
strength += cityTile.militaryUnit!!.getBaseUnit().strength * cityTile.militaryUnit!!.health/100f
return strengthWithPop.toInt()
strength += city.cityConstructions.getBuiltBuildings().sumBy{ it.cityStrength }
return strength.toInt()
}
override fun toString(): String {return city.name} // for debug

View File

@ -142,15 +142,14 @@ class CityInfo {
}
}
val maxHealth =getMaxHealth()
health = min(health+maxHealth/10, maxHealth)
health = min(health+20, getMaxHealth())
population.unassignExtraPopulation()
}
fun isCapital() = cityConstructions.isBuilt("Palace")
internal fun getMaxHealth(): Int {
return 200 // add more later when walls citadel etc.
return 200 + cityConstructions.getBuiltBuildings().sumBy { it.cityHealth }
}
override fun toString(): String {return name} // for debug

View File

@ -28,6 +28,8 @@ class Building : NamedStats(), IConstruction{
/** City can only be built if one of these resources is nearby - it must be improved! */
var requiredNearbyImprovedResources: List<String>? = null
var cannotBeBuiltWith: String? = null
var cityStrength=0
var cityHealth=0
// Uniques
var providesFreeBuilding: String? = null
@ -52,6 +54,8 @@ class Building : NamedStats(), IConstruction{
infoList += resourceBonusStats.toString() +" from "+improvedResources.joinToString()
}
if(unique!=null) infoList += unique!!
if(cityStrength!=0) infoList+="city strength +"+cityStrength
if(cityHealth!=0) infoList+="city health +"+cityHealth
return infoList.joinToString()
}
@ -123,6 +127,9 @@ class Building : NamedStats(), IConstruction{
val resources = GameBasics.TileResources.values.filter { name == it.building }.joinToString { it.name }
stringBuilder.appendln("$resources provide $resourceBonusStats")
}
if(cityStrength!=0) stringBuilder.appendln("City strength +"+cityStrength)
if(cityHealth!=0) stringBuilder.appendln("City health +"+cityHealth)
if (maintenance != 0)
stringBuilder.appendln("Maintenance cost: $maintenance "+"Gold".tr())
return stringBuilder.toString().trim()

View File

@ -68,7 +68,9 @@ class BattleTable(val worldScreen: WorldScreen): Table() {
row().pad(5f)
val attackerModifiers = BattleDamage().getAttackModifiers(attacker,defender) .map { it.key+": "+(if(it.value>0)"+" else "")+(it.value*100).toInt()+"%" }
val defenderModifiers = BattleDamage().getDefenceModifiers(attacker, defender).map { it.key+": "+(if(it.value>0)"+" else "")+(it.value*100).toInt()+"%" }
val defenderModifiers = if (defender is MapUnitCombatant)
BattleDamage().getDefenceModifiers(attacker, defender).map { it.key+": "+(if(it.value>0)"+" else "")+(it.value*100).toInt()+"%" }
else listOf()
for(i in 0..max(attackerModifiers.size,defenderModifiers.size)){
if (attackerModifiers.size > i) add(attackerModifiers[i]).actor.setFont(14) else add()