Added German nation - #703

This commit is contained in:
Yair Morgenstern 2019-06-17 11:20:15 +03:00
parent eb711b9a79
commit 853a325876
16 changed files with 140 additions and 100 deletions

View File

@ -508,6 +508,7 @@
specialistSlots:{gold:1}, specialistSlots:{gold:1},
hurryCostModifier:15, hurryCostModifier:15,
percentStatBonus:{gold:25}, percentStatBonus:{gold:25},
uniques:["+5% Production for every Trade Route with a City-State in the empire"]
requiredBuilding:"Market", requiredBuilding:"Market",
requiredTech:"Banking" requiredTech:"Banking"
}, },

View File

@ -430,8 +430,7 @@
"Kolhapur","Prayaga","Ayodhya","Indraprastha","Mathura","Ujjain","Gulbarga","Jaunpur","Rajagriha","Sravasti","Tiruchirapalli","Thanjavur", "Kolhapur","Prayaga","Ayodhya","Indraprastha","Mathura","Ujjain","Gulbarga","Jaunpur","Rajagriha","Sravasti","Tiruchirapalli","Thanjavur",
"Bodhgaya","Kushinagar","Amaravati","Gaur","Gwalior","Jaipur","Karachi"] "Bodhgaya","Kushinagar","Amaravati","Gaur","Gwalior","Jaipur","Karachi"]
}, },
/* {
{ // REQUIRES BARBARIAN CAMPS
name:"Germany", name:"Germany",
leaderName:"Otto von Bismark", leaderName:"Otto von Bismark",
adjective:["German"], adjective:["German"],
@ -440,10 +439,10 @@
startIntroPart1: "Hail mighty Bismark, first canchellor of Germany and her empire! Germany is an upstart nation, fashioned from the ruins of the Holy Roman Empire and finally unified in 1871, a little more than a century ago. The German people have proven themselves to be creative, industrious a ferocious warriors. Despite enduring great catastrophes in the first half of the 20th century, Germany remains a worldwide economic, artistic and technological leader." startIntroPart1: "Hail mighty Bismark, first canchellor of Germany and her empire! Germany is an upstart nation, fashioned from the ruins of the Holy Roman Empire and finally unified in 1871, a little more than a century ago. The German people have proven themselves to be creative, industrious a ferocious warriors. Despite enduring great catastrophes in the first half of the 20th century, Germany remains a worldwide economic, artistic and technological leader."
startIntroPart2: "Great Prince Bismark, the German people look up too you to lead them to greater days of glory. Their determination is strong, and now they turn to you, their beloved iron chancellor, to guide them once more. Will you rile and conquer through blood and iron, or foster the Germanic arts and industry? Can you build a civilization that will stand the test of time?" startIntroPart2: "Great Prince Bismark, the German people look up too you to lead them to greater days of glory. Their determination is strong, and now they turn to you, their beloved iron chancellor, to guide them once more. Will you rile and conquer through blood and iron, or foster the Germanic arts and industry? Can you build a civilization that will stand the test of time?"
declaringWar:"I cannot wait until ye grow even mightier. Therefore, prepare for war!" declaringWar: "I cannot wait until ye grow even mightier. Therefore, prepare for war!"
attacked:"Corrupted villain! We will bring you into the ground!" attacked: "Corrupted villain! We will bring you into the ground!"
defeated:"Germany has been destroyed. I weep for the future generations." defeated: "Germany has been destroyed. I weep for the future generations."
introduction:"Guten tag. In the name of the great German people, I bid you welcome." introduction: "Guten tag. In the name of the great German people, I bid you welcome."
neutralHello:"What now?" neutralHello:"What now?"
neutralLetsHearIt:["What do ye say?","Yes?","Ja?"] neutralLetsHearIt:["What do ye say?","Yes?","Ja?"]
@ -458,8 +457,8 @@
afterPeace:"What do ye think about calling it a draw?" afterPeace:"What do ye think about calling it a draw?"
tradeRequest:"It would be in your best interest, to carefully consider this proposal." tradeRequest:"It would be in your best interest, to carefully consider this proposal."
mainColor:[224,224,224], mainColor:[150,150,150],
secondaryColor:[64,64,64], secondaryColor:[60,60,60],
uniqueName:"Furor Teutonicus" uniqueName:"Furor Teutonicus"
unique:"67% chance to earn 25 Gold and recruit a Barbarian unit from a conquered encampment, -25% land units maintenance.", unique:"67% chance to earn 25 Gold and recruit a Barbarian unit from a conquered encampment, -25% land units maintenance.",
cities:["Berlin","Hamburg","Munich","Cologne","Frankfurt","Essen","Dortmund","Stuttgart","Dusseldorf","Bremen", cities:["Berlin","Hamburg","Munich","Cologne","Frankfurt","Essen","Dortmund","Stuttgart","Dusseldorf","Bremen",
@ -470,6 +469,7 @@
"Recklinghausen","Gצttingen","Wolfsburg","Koblenz","Hildesheim","Erlangen"] "Recklinghausen","Gצttingen","Wolfsburg","Koblenz","Hildesheim","Erlangen"]
}, },
/*
{ // REQUIRES RIVERS { // REQUIRES RIVERS
name:"Aztecs", name:"Aztecs",
leaderName:"Montezuma I", leaderName:"Montezuma I",

View File

@ -133,11 +133,11 @@
Portuguese:"o(a) [construction] foi construirdo em [cityName]" Portuguese:"o(a) [construction] foi construirdo em [cityName]"
Japanese:"[construction]は[cityName]に建てられました" Japanese:"[construction]は[cityName]に建てられました"
} }
"[wonder] has been built in a faraway land":{ "[wonder] has been built in a faraway land":{
Italian:"La Meraviglia [wonder] è stata costruita in una terra lontana" Italian:"La Meraviglia [wonder] è stata costruita in una terra lontana"
French:"[wonder] a été construit(e) dans un lointain pays" French:"[wonder] a été construit(e) dans un lointain pays"
} }
"Work has started on [construction]":{ "Work has started on [construction]":{
Italian:"Sono iniziati i lavori per [construction]" Italian:"Sono iniziati i lavori per [construction]"
@ -159,7 +159,7 @@
"One of our trades with [nation] has ended": { "One of our trades with [nation] has ended": {
Italian:"Un nostro accordo con [nation] è terminato." Italian:"Un nostro accordo con [nation] è terminato."
French:"Un de nos échanges avec [nation] a pris fin" French:"Un de nos échanges avec [nation] a pris fin"
}, },
"[cityname] has expanded its borders!":{ "[cityname] has expanded its borders!":{
@ -229,10 +229,10 @@
Japanese:"敵[unit]が私たちの[ourUnit]を攻撃しました" Japanese:"敵[unit]が私たちの[ourUnit]を攻撃しました"
} }
"Enemy city [cityName] has attacked our [ourUnit]":{ "Enemy city [cityName] has attacked our [ourUnit]":{
Italian:"La città nemica [cityName] ha attaccato [ourUnit]" Italian:"La città nemica [cityName] ha attaccato [ourUnit]"
French:"La cité ennemie [cityName] a attaqué notre [ourUnit]" French:"La cité ennemie [cityName] a attaqué notre [ourUnit]"
} }
"An enemy [unit] has captured [cityname]":{ "An enemy [unit] has captured [cityname]":{
Italian:"Un'unità nemica [unit] ha conquistato [cityname]" Italian:"Un'unità nemica [unit] ha conquistato [cityname]"
@ -273,10 +273,10 @@
Japanese:"敵[unit]が私たちの[ourUnit]を破壊しました" Japanese:"敵[unit]が私たちの[ourUnit]を破壊しました"
} }
"Enemy city [cityName] has destroyed our [ourUnit]":{ "Enemy city [cityName] has destroyed our [ourUnit]":{
Italian:"La città nemica [cityName] ha distrutto [ourUnit]" Italian:"La città nemica [cityName] ha distrutto [ourUnit]"
French:"La cité ennemie [cityName] a détruit notre [ourUnit]" French:"La cité ennemie [cityName] a détruit notre [ourUnit]"
} }
"An enemy [unit] was destroyed while attacking [cityname]":{ "An enemy [unit] was destroyed while attacking [cityname]":{
Italian:"Un'unità nemica [unit] è stata distrutta mentre attaccava [cityname]" Italian:"Un'unità nemica [unit] è stata distrutta mentre attaccava [cityname]"
@ -334,14 +334,14 @@
Italian:"Abbiamo avvistato [amount] unità nemiche vicino ai nostri confini!" Italian:"Abbiamo avvistato [amount] unità nemiche vicino ai nostri confini!"
German:"[amount] feindliche Einheiten wurden nahe unserer Grenzen entdeckt" German:"[amount] feindliche Einheiten wurden nahe unserer Grenzen entdeckt"
Simplified_Chinese:"在我们的领土附近发现了[amount]个敌方单位" Simplified_Chinese:"在我们的领土附近发现了[amount]个敌方单位"
French:"[amount] unités ennemies ont été repérées proche de notre territoire" French:"[amount] unités ennemies ont été repérées proche de notre territoire"
} }
"[amount] enemy units were spotted in our territory": { "[amount] enemy units were spotted in our territory": {
Italian:"Abbiamo avvistato [amount] unità nemiche nel nostro territorio!" Italian:"Abbiamo avvistato [amount] unità nemiche nel nostro territorio!"
German:"[amount] feindliche Einheiten wurden in unseren Grenzen entdeckt" German:"[amount] feindliche Einheiten wurden in unseren Grenzen entdeckt"
Simplified_Chinese:"在我们的领土内发现了[amount]个敌方单位" Simplified_Chinese:"在我们的领土内发现了[amount]个敌方单位"
French:"[amount] unités ennemies ont été repérées sur notre territoire" French:"[amount] unités ennemies ont été repérées sur notre territoire"
} }
"The civilization of [civName] has been destroyed!":{ "The civilization of [civName] has been destroyed!":{
@ -356,11 +356,14 @@
Portuguese:"A civilização de [civName] foi destruida!" Portuguese:"A civilização de [civName] foi destruida!"
Japanese:"[civName]の文明は破壊されました!" Japanese:"[civName]の文明は破壊されました!"
} }
"We have captured a barbarian encampment and recovered [goldAmount] gold!":{ //shouldn't it be "we have destroyed ..." ?
Italian:"Nella cattura di un accampamento barbaro, abbiamo recuperato [goldAmount] Oro!"
French:"Nous avons capturé un campement barbare et pillé [goldAmount] ors"
}
"We have captured a barbarian encampment and recovered [goldAmount] gold!":{ //shouldn't it be "we have destroyed ..." ? "A barbarian [unitType] has joined us!":{
Italian:"Nella cattura di un accampamento barbaro, abbiamo recuperato [goldAmount] Oro!" }
French:"Nous avons capturé un campement barbare et pillé [goldAmount] ors"
}
///////////////// ruins ///////////////// ruins
@ -440,19 +443,19 @@
French:"[unit] n'a rien à faire" French:"[unit] n'a rien à faire"
} }
"You're losing control of [name].":{ //When you're about to lose your friendship with a City-State "You're losing control of [name].":{ //When you're about to lose your friendship with a City-State
Italian:"Stai perdendo il controllo di [name]." Italian:"Stai perdendo il controllo di [name]."
} }
"You and [name] are no longer friends!":{ // When you lose friendship with a City-State (Relationship fall less than 30) "You and [name] are no longer friends!":{ // When you lose friendship with a City-State (Relationship fall less than 30)
Italian:"Non sei più amico di [name]!" Italian:"Non sei più amico di [name]!"
} }
"Your alliance with [name] is faltering.":{ //When you're about to lose your alliance with a City-State "Your alliance with [name] is faltering.":{ //When you're about to lose your alliance with a City-State
Italian:"L'alleanza con [name] si sta sfaldando." Italian:"L'alleanza con [name] si sta sfaldando."
} }
"You and [name] are no longer allies!":{ // When you lose alliance with a City-State (Relationship fall less than 60) "You and [name] are no longer allies!":{ // When you lose alliance with a City-State (Relationship fall less than 60)
Italian:"Non sei più alleato con [name]!" Italian:"Non sei più alleato con [name]!"
} }
} }

View File

@ -516,7 +516,6 @@
attackSound:"metalhit" attackSound:"metalhit"
//Pikeman should upgrade not only to Musketman but also to Lancer //Pikeman should upgrade not only to Musketman but also to Lancer
}, },
/*
{ {
name:"Landsknecht", name:"Landsknecht",
replaces:"Pikeman", replaces:"Pikeman",
@ -532,7 +531,6 @@
hurryCostModifier:20, hurryCostModifier:20,
attackSound:"metalhit" attackSound:"metalhit"
}, },
*/
{ {
name:"Galleass", name:"Galleass",
unitType:"WaterRanged", unitType:"WaterRanged",
@ -1014,7 +1012,6 @@
uniques:["Can move after attacking","No defensive terrain bonus"] uniques:["Can move after attacking","No defensive terrain bonus"]
hurryCostModifier:20, hurryCostModifier:20,
}, },
/*
{ {
name:"Panzer", name:"Panzer",
unitType:"Armor", unitType:"Armor",
@ -1029,7 +1026,6 @@
hurryCostModifier:20, hurryCostModifier:20,
//German unique unit, stronger than Tank //German unique unit, stronger than Tank
}, },
*/
{ {
name:"Anti-Tank Gun", name:"Anti-Tank Gun",
unitType:"Melee", unitType:"Melee",

View File

@ -85,6 +85,16 @@ class Battle(val gameInfo:GameInfo) {
conquerCity(defender.city, attacker) conquerCity(defender.city, attacker)
} }
// German unique - needs to be checked before we try to move to the enemy tile, since the encampment disappears after we move in
if(defender.isDefeated() && defender.getCivInfo().isBarbarianCivilization() && attackedTile.improvement==Constants.barbarianEncampment
&& attacker.getCivInfo().getNation().unique== "67% chance to earn 25 Gold and recruit a Barbarian unit from a conquered encampment, -25% land units maintenance."
&& Random().nextDouble() > 0.67){
attacker.getCivInfo().placeUnitNearTile(attackedTile.position, defender.getName())
attacker.getCivInfo().gold += 25
attacker.getCivInfo().addNotification("A barbarian [${defender.getName()}] has joined us!",attackedTile.position, Color.RED)
}
// we're a melee unit and we destroyed\captured an enemy unit // we're a melee unit and we destroyed\captured an enemy unit
else if (attacker.isMelee() else if (attacker.isMelee()
&& (defender.isDefeated() || defender.getCivInfo()==attacker.getCivInfo()) && (defender.isDefeated() || defender.getCivInfo()==attacker.getCivInfo())
@ -96,6 +106,7 @@ class Battle(val gameInfo:GameInfo) {
attacker.unit.moveToTile(attackedTile) attacker.unit.moveToTile(attackedTile)
} }
if(attacker is MapUnitCombatant) { if(attacker is MapUnitCombatant) {
val unit = attacker.unit val unit = attacker.unit
if (unit.hasUnique("Can move after attacking") if (unit.hasUnique("Can move after attacking")
@ -141,6 +152,7 @@ class Battle(val gameInfo:GameInfo) {
addXp(defender,2,attacker) addXp(defender,2,attacker)
} }
// Add culture when defeating a barbarian when Honor policy is adopted (can be either attacker or defender!) // Add culture when defeating a barbarian when Honor policy is adopted (can be either attacker or defender!)
fun tryGetCultureFromHonor(civUnit:ICombatant, barbarianUnit:ICombatant){ fun tryGetCultureFromHonor(civUnit:ICombatant, barbarianUnit:ICombatant){
if(barbarianUnit.isDefeated() && barbarianUnit is MapUnitCombatant if(barbarianUnit.isDefeated() && barbarianUnit is MapUnitCombatant

View File

@ -49,8 +49,8 @@ class CityConstructions {
fun getStatPercentBonuses(): Stats { fun getStatPercentBonuses(): Stats {
val stats = Stats() val stats = Stats()
for (building in getBuiltBuildings().filter { it.percentStatBonus != null }) for (building in getBuiltBuildings())
stats.add(building.percentStatBonus!!) stats.add(building.getStatPercentageBonuses(cityInfo.civInfo))
return stats return stats
} }

View File

@ -17,7 +17,6 @@ import kotlin.math.min
class CityInfo { class CityInfo {
@Transient lateinit var civInfo: CivilizationInfo @Transient lateinit var civInfo: CivilizationInfo
@Transient var isConnectedToCapital = false
@Transient lateinit var ccenterTile:TileInfo // cached for better performance @Transient lateinit var ccenterTile:TileInfo // cached for better performance
@Transient val range = 2 @Transient val range = 2
@Transient lateinit var tileMap: TileMap @Transient lateinit var tileMap: TileMap
@ -95,7 +94,6 @@ class CityInfo {
toReturn.tiles = tiles toReturn.tiles = tiles
toReturn.workedTiles = workedTiles toReturn.workedTiles = workedTiles
toReturn.isBeingRazed=isBeingRazed toReturn.isBeingRazed=isBeingRazed
toReturn.isConnectedToCapital = isConnectedToCapital
toReturn.attackedThisTurn = attackedThisTurn toReturn.attackedThisTurn = attackedThisTurn
toReturn.resistanceCounter = resistanceCounter toReturn.resistanceCounter = resistanceCounter
return toReturn return toReturn
@ -178,6 +176,7 @@ class CityInfo {
} }
fun isCapital() = cityConstructions.isBuilt("Palace") fun isCapital() = cityConstructions.isBuilt("Palace")
fun isConnectedToCapital() = civInfo.citiesConnectedToCapital.contains(this)
internal fun getMaxHealth(): Int { internal fun getMaxHealth(): Int {
return 200 + cityConstructions.getBuiltBuildings().sumBy { it.cityHealth } return 200 + cityConstructions.getBuiltBuildings().sumBy { it.cityHealth }

View File

@ -34,7 +34,7 @@ class CityStats {
private fun getStatsFromTradeRoute(): Stats { private fun getStatsFromTradeRoute(): Stats {
val stats = Stats() val stats = Stats()
if (!cityInfo.isCapital() && isConnectedToCapital(RoadStatus.Road)) { if (!cityInfo.isCapital() && cityInfo.isConnectedToCapital()) {
val civInfo = cityInfo.civInfo val civInfo = cityInfo.civInfo
var goldFromTradeRoute = civInfo.getCapital().population.population * 0.15 + cityInfo.population.population * 1.1 - 1 // Calculated by http://civilization.wikia.com/wiki/Trade_route_(Civ5) var goldFromTradeRoute = civInfo.getCapital().population.population * 0.15 + cityInfo.population.population * 1.1 - 1 // Calculated by http://civilization.wikia.com/wiki/Trade_route_(Civ5)
if(civInfo.getNation().unique=="+1 Gold from each Trade Route, Oil resources provide double quantity") goldFromTradeRoute += 1 if(civInfo.getNation().unique=="+1 Gold from each Trade Route, Oil resources provide double quantity") goldFromTradeRoute += 1
@ -196,7 +196,7 @@ class CityStats {
happinessFromPolicies += (cityInfo.population.population / 10).toFloat() happinessFromPolicies += (cityInfo.population.population / 10).toFloat()
if (civInfo.policies.isAdopted("Monarchy") && cityInfo.isCapital()) if (civInfo.policies.isAdopted("Monarchy") && cityInfo.isCapital())
happinessFromPolicies += (cityInfo.population.population / 2).toFloat() happinessFromPolicies += (cityInfo.population.population / 2).toFloat()
if (civInfo.policies.isAdopted("Meritocracy") && isConnectedToCapital(RoadStatus.Road)) if (civInfo.policies.isAdopted("Meritocracy") && cityInfo.isConnectedToCapital())
happinessFromPolicies += 1f happinessFromPolicies += 1f
if(civInfo.policies.isAdopted("Military Caste") && cityInfo.getCenterTile().militaryUnit!=null) if(civInfo.policies.isAdopted("Military Caste") && cityInfo.getCenterTile().militaryUnit!=null)
happinessFromPolicies+=1 happinessFromPolicies+=1
@ -320,7 +320,7 @@ class CityStats {
fun isConnectedToCapital(roadType: RoadStatus): Boolean { fun isConnectedToCapital(roadType: RoadStatus): Boolean {
if (cityInfo.civInfo.cities.count() < 2) return false// first city! if (cityInfo.civInfo.cities.count() < 2) return false// first city!
if(roadType==RoadStatus.Road) return cityInfo.isConnectedToCapital // this transient is not applicable to connection via railroad. if(roadType==RoadStatus.Road) return cityInfo.isConnectedToCapital() // this transient is not applicable to connection via railroad.
val capitalTile = cityInfo.civInfo.getCapital().getCenterTile() val capitalTile = cityInfo.civInfo.getCapital().getCenterTile()
val bfs = BFS(capitalTile){it.roadStatus == roadType} val bfs = BFS(capitalTile){it.roadStatus == roadType}

View File

@ -0,0 +1,7 @@
package com.unciv.logic.civilization
enum class CityStateType{
Cultured,
Maritime,
Mercantile
}

View File

@ -14,7 +14,7 @@ import com.unciv.logic.map.BFS
import com.unciv.logic.map.MapUnit import com.unciv.logic.map.MapUnit
import com.unciv.logic.map.RoadStatus import com.unciv.logic.map.RoadStatus
import com.unciv.logic.map.TileInfo import com.unciv.logic.map.TileInfo
import com.unciv.logic.trade.Trade import com.unciv.logic.trade.TradeRequest
import com.unciv.models.gamebasics.* import com.unciv.models.gamebasics.*
import com.unciv.models.gamebasics.tech.TechEra import com.unciv.models.gamebasics.tech.TechEra
import com.unciv.models.gamebasics.tile.ResourceSupplyList import com.unciv.models.gamebasics.tile.ResourceSupplyList
@ -25,24 +25,10 @@ import java.util.*
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
import kotlin.collections.HashMap import kotlin.collections.HashMap
import kotlin.math.max import kotlin.math.max
import kotlin.math.min
import kotlin.math.pow import kotlin.math.pow
import kotlin.math.roundToInt import kotlin.math.roundToInt
enum class PlayerType{
AI,
Human
}
enum class CityStateType{
Cultured,
Maritime,
Mercantile
}
class TradeRequest(val requestingCiv:String,
/** Their offers are what they offer us, and our offers are what they want in return */
val trade: Trade)
class CivilizationInfo { class CivilizationInfo {
@Transient lateinit var gameInfo: GameInfo @Transient lateinit var gameInfo: GameInfo
/** /**
@ -53,6 +39,8 @@ class CivilizationInfo {
@Transient private var units=listOf<MapUnit>() @Transient private var units=listOf<MapUnit>()
@Transient var viewableTiles = setOf<TileInfo>() @Transient var viewableTiles = setOf<TileInfo>()
@Transient var viewableInvisibleUnitsTiles = setOf<TileInfo>() @Transient var viewableInvisibleUnitsTiles = setOf<TileInfo>()
/** Contains cities from ALL civilizations connected by trade routes to the capital */
@Transient var citiesConnectedToCapital = listOf<CityInfo>()
/** This is for performance since every movement calculation depends on this, see MapUnit comment */ /** This is for performance since every movement calculation depends on this, see MapUnit comment */
@Transient var hasActiveGreatWall = false @Transient var hasActiveGreatWall = false
@ -203,9 +191,16 @@ class CivilizationInfo {
val freeUnits = 3 val freeUnits = 3
var unitsToPayFor = getCivUnits() var unitsToPayFor = getCivUnits()
if(policies.isAdopted("Oligarchy")) unitsToPayFor = unitsToPayFor.filterNot { it.getTile().isCityCenter() } if(policies.isAdopted("Oligarchy")) unitsToPayFor = unitsToPayFor.filterNot { it.getTile().isCityCenter() }
val totalPaidUnits = max(0,unitsToPayFor.count()-freeUnits)
var numberOfUnitsToPayFor = max(0f, unitsToPayFor.count().toFloat() - freeUnits)
if(getNation().unique=="67% chance to earn 25 Gold and recruit a Barbarian unit from a conquered encampment, -25% land units maintenance."){
val numberOfUnitsWithDiscount = min(numberOfUnitsToPayFor, unitsToPayFor.count { it.type.isLandUnit() }.toFloat())
numberOfUnitsToPayFor -= 0.25f * numberOfUnitsWithDiscount
}
val gameProgress = gameInfo.turns/400f // as game progresses Maintenance cost rises val gameProgress = gameInfo.turns/400f // as game progresses Maintenance cost rises
var cost = baseUnitCost*totalPaidUnits*(1+gameProgress) var cost = baseUnitCost*numberOfUnitsToPayFor*(1+gameProgress)
cost = cost.pow(1+gameProgress/3) // Why 3? To spread 1 to 1.33 cost = cost.pow(1+gameProgress/3) // Why 3? To spread 1 to 1.33
if(!isPlayerCivilization()) if(!isPlayerCivilization())
cost *= gameInfo.getDifficulty().aiUnitMaintenanceModifier cost *= gameInfo.getDifficulty().aiUnitMaintenanceModifier
@ -544,6 +539,7 @@ class CivilizationInfo {
val citiesReachedToMediums = HashMap<CityInfo,ArrayList<String>>() val citiesReachedToMediums = HashMap<CityInfo,ArrayList<String>>()
var citiesToCheck = mutableListOf(getCapital()) var citiesToCheck = mutableListOf(getCapital())
citiesReachedToMediums[getCapital()] = arrayListOf("Start") citiesReachedToMediums[getCapital()] = arrayListOf("Start")
while(citiesToCheck.isNotEmpty() && citiesReachedToMediums.size<cities.size){ while(citiesToCheck.isNotEmpty() && citiesReachedToMediums.size<cities.size){
val newCitiesToCheck = mutableListOf<CityInfo>() val newCitiesToCheck = mutableListOf<CityInfo>()
for(cityToConnectFrom in citiesToCheck){ for(cityToConnectFrom in citiesToCheck){
@ -551,6 +547,7 @@ class CivilizationInfo {
// This is copypasta and can be cleaned up // This is copypasta and can be cleaned up
if(!reachedMediums.contains("Road")){ if(!reachedMediums.contains("Road")){
val roadBfs = BFS(cityToConnectFrom.getCenterTile()){it.roadStatus!=RoadStatus.None} val roadBfs = BFS(cityToConnectFrom.getCenterTile()){it.roadStatus!=RoadStatus.None}
roadBfs.stepToEnd() roadBfs.stepToEnd()
val reachedCities = cities.filter { roadBfs.tilesReached.containsKey(it.getCenterTile())} val reachedCities = cities.filter { roadBfs.tilesReached.containsKey(it.getCenterTile())}
@ -586,9 +583,7 @@ class CivilizationInfo {
citiesToCheck = newCitiesToCheck citiesToCheck = newCitiesToCheck
} }
for(city in cities){ citiesConnectedToCapital = citiesReachedToMediums.keys.toList()
city.isConnectedToCapital = citiesReachedToMediums.containsKey(city)
}
} }
fun destroy(){ fun destroy(){

View File

@ -0,0 +1,6 @@
package com.unciv.logic.civilization
enum class PlayerType{
AI,
Human
}

View File

@ -38,4 +38,9 @@ class Trade{
theirOffers.clear() theirOffers.clear()
theirOffers.addAll(trade.theirOffers) theirOffers.addAll(trade.theirOffers)
} }
} }
class TradeRequest(val requestingCiv:String,
/** Their offers are what they offer us, and our offers are what they want in return */
val trade: Trade)

View File

@ -55,10 +55,9 @@ class Building : NamedStats(), IConstruction{
val infoList= mutableListOf<String>() val infoList= mutableListOf<String>()
val str = getStats(null).toString() val str = getStats(null).toString()
if(str.isNotEmpty()) infoList += str if(str.isNotEmpty()) infoList += str
if(percentStatBonus!=null){ for(stat in getStatPercentageBonuses(null).toHashMap())
for(stat in percentStatBonus!!.toHashMap()) if(stat.value!=0f) infoList+="+${stat.value.toInt()}% ${stat.key.toString().tr()}"
if(stat.value!=0f) infoList+="+${stat.value.toInt()}% ${stat.key.toString().tr()}"
}
val improvedResources = GameBasics.TileResources.values.filter { it.building==name }.map { it.name.tr() } val improvedResources = GameBasics.TileResources.values.filter { it.building==name }.map { it.name.tr() }
if(improvedResources.isNotEmpty()){ if(improvedResources.isNotEmpty()){
// buildings that improve resources // buildings that improve resources
@ -93,13 +92,14 @@ class Building : NamedStats(), IConstruction{
if(uniques.isNotEmpty()) stringBuilder.appendln(uniques.asSequence().map { it.tr() }.joinToString("\n")) if(uniques.isNotEmpty()) stringBuilder.appendln(uniques.asSequence().map { it.tr() }.joinToString("\n"))
if (stats.toString() != "") if (stats.toString() != "")
stringBuilder.appendln(stats) stringBuilder.appendln(stats)
if (this.percentStatBonus != null) {
if (this.percentStatBonus!!.production != 0f) stringBuilder.append("+" + this.percentStatBonus!!.production.toInt() + "% {Production}\n".tr()) val percentStats = getStatPercentageBonuses(civInfo)
if (this.percentStatBonus!!.gold != 0f) stringBuilder.append("+" + this.percentStatBonus!!.gold.toInt() + "% {Gold}\n".tr()) if (percentStats.production != 0f) stringBuilder.append("+" + percentStats.production.toInt() + "% {Production}\n".tr())
if (this.percentStatBonus!!.science != 0f) stringBuilder.append("+" + this.percentStatBonus!!.science.toInt() + "% {Science}\r\n".tr()) if (percentStats.gold != 0f) stringBuilder.append("+" + percentStats.gold.toInt() + "% {Gold}\n".tr())
if (this.percentStatBonus!!.food != 0f) stringBuilder.append("+" + this.percentStatBonus!!.food.toInt() + "% {Food}\n".tr()) if (percentStats.science != 0f) stringBuilder.append("+" + percentStats.science.toInt() + "% {Science}\r\n".tr())
if (this.percentStatBonus!!.culture != 0f) stringBuilder.append("+" + this.percentStatBonus!!.culture.toInt() + "% {Culture}\r\n".tr()) if (percentStats.food != 0f) stringBuilder.append("+" + percentStats.food.toInt() + "% {Food}\n".tr())
} if (percentStats.culture != 0f) stringBuilder.append("+" + percentStats.culture.toInt() + "% {Culture}\r\n".tr())
if (this.greatPersonPoints != null) { if (this.greatPersonPoints != null) {
val gpp = this.greatPersonPoints!! val gpp = this.greatPersonPoints!!
if (gpp.production != 0f) stringBuilder.appendln("+" + gpp.production.toInt()+" " + "[Great Engineer] points".tr()) if (gpp.production != 0f) stringBuilder.appendln("+" + gpp.production.toInt()+" " + "[Great Engineer] points".tr())
@ -143,12 +143,6 @@ class Building : NamedStats(), IConstruction{
if (adoptedPolicies.contains("Humanism") && hashSetOf("University", "Observatory", "Public School").contains(baseBuildingName )) if (adoptedPolicies.contains("Humanism") && hashSetOf("University", "Observatory", "Public School").contains(baseBuildingName ))
stats.happiness += 1f stats.happiness += 1f
if (adoptedPolicies.contains("Theocracy") && baseBuildingName == "Temple")
percentStatBonus = Stats().apply { gold = 10f }
if (adoptedPolicies.contains("Free Thought") && baseBuildingName == "University")
percentStatBonus!!.science = 50f
if (adoptedPolicies.contains("Rationalism Complete") && !isWonder && stats.science > 0) if (adoptedPolicies.contains("Rationalism Complete") && !isWonder && stats.science > 0)
stats.gold += 1f stats.gold += 1f
@ -168,6 +162,26 @@ class Building : NamedStats(), IConstruction{
return stats return stats
} }
fun getStatPercentageBonuses(civInfo: CivilizationInfo?): Stats {
val stats = percentStatBonus
if(stats==null) return Stats() // empty
if(civInfo==null) return stats // initial stats
val adoptedPolicies = civInfo.policies.adoptedPolicies
val baseBuildingName = getBaseBuilding().name
if (adoptedPolicies.contains("Theocracy") && baseBuildingName == "Temple")
stats.gold = 10f
if (adoptedPolicies.contains("Free Thought") && baseBuildingName == "University")
stats.science = 50f
if(uniques.contains("+5% Production for every Trade Route with a City-State in the empire"))
stats.production += 5*civInfo.citiesConnectedToCapital.count { it.civInfo.isCityState() }
return stats
}
override fun canBePurchased(): Boolean { override fun canBePurchased(): Boolean {
return !isWonder && !isNationalWonder return !isWonder && !isNationalWonder
} }
@ -331,7 +345,7 @@ class Building : NamedStats(), IConstruction{
fun isStatRelated(stat: Stat): Boolean { fun isStatRelated(stat: Stat): Boolean {
if (get(stat) > 0) return true if (get(stat) > 0) return true
if (percentStatBonus!=null && percentStatBonus!!.get(stat)>0) return true if (getStatPercentageBonuses(null).get(stat)>0) return true
if (specialistSlots!=null && specialistSlots!!.get(stat)>0) return true if (specialistSlots!=null && specialistSlots!!.get(stat)>0) return true
return false return false
} }

View File

@ -56,6 +56,7 @@ class NationTable(val nation: Nation, val newGameParameters: GameParameters, ski
for (stat in building.toHashMap()) for (stat in building.toHashMap())
if (stat.value != originalBuildingStatMap[stat.key]) if (stat.value != originalBuildingStatMap[stat.key])
textList += " "+stat.key.toString().tr() +" "+stat.value.toInt() + " vs " + originalBuildingStatMap[stat.key]!!.toInt() textList += " "+stat.key.toString().tr() +" "+stat.value.toInt() + " vs " + originalBuildingStatMap[stat.key]!!.toInt()
for(unique in building.uniques.filter { it !in originalBuilding.uniques }) for(unique in building.uniques.filter { it !in originalBuilding.uniques })
textList += " "+unique.tr() textList += " "+unique.tr()
if (building.maintenance != originalBuilding.maintenance) if (building.maintenance != originalBuilding.maintenance)
@ -74,6 +75,8 @@ class NationTable(val nation: Nation, val newGameParameters: GameParameters, ski
val originalUnit = GameBasics.Units[unit.replaces!!]!! val originalUnit = GameBasics.Units[unit.replaces!!]!!
textList += unit.name.tr() + " - {replaces} " + originalUnit.name.tr() textList += unit.name.tr() + " - {replaces} " + originalUnit.name.tr()
if(unit.cost != originalUnit.cost)
textList += " {Cost} " + unit.cost + " vs " + originalUnit.cost
if (unit.strength != originalUnit.strength) if (unit.strength != originalUnit.strength)
textList += " {Strength} " + unit.strength + " vs " + originalUnit.strength textList += " {Strength} " + unit.strength + " vs " + originalUnit.strength
if (unit.rangedStrength!= originalUnit.rangedStrength) if (unit.rangedStrength!= originalUnit.rangedStrength)

View File

@ -234,17 +234,17 @@ class NewGameScreen: PickerScreen(){
newGameOptionsTable.add("{Victory conditions}:".tr()).colspan(2).row() newGameOptionsTable.add("{Victory conditions}:".tr()).colspan(2).row()
// Create a checkbox for each VictoryType existing // Create a checkbox for each VictoryType existing
var i=0 var i = 0
val victoryConditionsTable = Table().apply { defaults().pad(10f) } val victoryConditionsTable = Table().apply { defaults().pad(10f) }
for (victoryType in VictoryType.values()) { for (victoryType in VictoryType.values()) {
if(victoryType==VictoryType.Neutral) continue if (victoryType == VictoryType.Neutral) continue
val victoryCheckbox = CheckBox(victoryType.name.tr(),skin) val victoryCheckbox = CheckBox(victoryType.name.tr(), skin)
victoryCheckbox.name=victoryType.name victoryCheckbox.name = victoryType.name
victoryCheckbox.isChecked=newGameParameters.victoryTypes.contains(victoryType) victoryCheckbox.isChecked = newGameParameters.victoryTypes.contains(victoryType)
victoryCheckbox.addListener(object : ChangeListener() { victoryCheckbox.addListener(object : ChangeListener() {
override fun changed(event: ChangeEvent?, actor: Actor?) { override fun changed(event: ChangeEvent?, actor: Actor?) {
// If the checkbox is checked, adds the victoryTypes else remove it // If the checkbox is checked, adds the victoryTypes else remove it
if(victoryCheckbox.isChecked){ if (victoryCheckbox.isChecked) {
newGameParameters.victoryTypes.add(victoryType) newGameParameters.victoryTypes.add(victoryType)
} else { } else {
newGameParameters.victoryTypes.remove(victoryType) newGameParameters.victoryTypes.remove(victoryType)
@ -252,7 +252,7 @@ class NewGameScreen: PickerScreen(){
} }
}) })
victoryConditionsTable.add(victoryCheckbox) victoryConditionsTable.add(victoryCheckbox)
if(++i%2==0) victoryConditionsTable.row() if (++i % 2 == 0) victoryConditionsTable.row()
} }
newGameOptionsTable.add(victoryConditionsTable).colspan(2).row() newGameOptionsTable.add(victoryConditionsTable).colspan(2).row()
} }

View File

@ -12,7 +12,6 @@ import com.unciv.UnCivGame
import com.unciv.logic.city.CityConstructions import com.unciv.logic.city.CityConstructions
import com.unciv.logic.city.CityInfo import com.unciv.logic.city.CityInfo
import com.unciv.logic.city.SpecialConstruction import com.unciv.logic.city.SpecialConstruction
import com.unciv.logic.map.RoadStatus
import com.unciv.ui.cityscreen.CityScreen import com.unciv.ui.cityscreen.CityScreen
import com.unciv.ui.utils.* import com.unciv.ui.utils.*
@ -87,7 +86,7 @@ class CityButton(val city: CityInfo, internal val tileGroup: WorldTileGroup, ski
val starImage = ImageGetter.getImage("OtherIcons/Star.png").apply { color = Color.LIGHT_GRAY } val starImage = ImageGetter.getImage("OtherIcons/Star.png").apply { color = Color.LIGHT_GRAY }
iconTable.add(starImage).size(20f).pad(2f).padLeft(10f) iconTable.add(starImage).size(20f).pad(2f).padLeft(10f)
} }
} else if (city.civInfo.isCurrentPlayer() && city.cityStats.isConnectedToCapital(RoadStatus.Road)) { } else if (city.civInfo.isCurrentPlayer() && city.isConnectedToCapital()) {
val connectionImage = ImageGetter.getStatIcon("CityConnection") val connectionImage = ImageGetter.getStatIcon("CityConnection")
iconTable.add(connectionImage).size(20f).pad(2f).padLeft(10f) iconTable.add(connectionImage).size(20f).pad(2f).padLeft(10f)
} }