CS bonuses graded according to relationship level (#4664)

* city-state bonuses graded depending on friend or ally

* siam militaristic UP, cleaned up presentation

* fix strings

* move city state modifiers to json

* city-state bonuses graded depending on friend or ally

* siam militaristic UP, cleaned up presentation

* fix strings

* move city state modifiers to json

* Restructure eras.json

* reduce indentation in DiplomacyManager.kt

* Add fallback values in cas of missing json definitions

* review edits

* fix conflicts???

Co-authored-by: Yair Morgenstern <yairm210@hotmail.com>
This commit is contained in:
SimonCeder 2021-08-17 12:55:02 +02:00 committed by GitHub
parent 076128a37e
commit 74a1da8e17
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 260 additions and 29 deletions

View File

@ -11,6 +11,18 @@
"startingMilitaryUnit": "Warrior",
"settlerPopulation": 1,
"baseUnitBuyCost": 200,
"friendBonus": {
"Cultured": ["Provides [3] [Culture] per turn"],
"Maritime": ["Provides [2] [Food] [in capital]"],
"Mercantile": ["Provides [2] Happiness"],
"Militaristic": ["Provides military units every [20] turns"]
},
"allyBonus": {
"Cultured": ["Provides [6] [Culture] per turn"],
"Maritime": ["Provides [2] [Food] [in capital]", "Provides [1] [Food] [in all cities]"],
"Mercantile": ["Provides [2] Happiness", "Provides a unique luxury"],
"Militaristic": ["Provides military units every [17] turns"]
},
"iconRGB": [255, 87, 35]
},
{
@ -24,6 +36,18 @@
"startingCulture": 100,
"settlerPopulation": 1,
"baseUnitBuyCost": 200,
"friendBonus": {
"Cultured": ["Provides [3] [Culture] per turn"],
"Maritime": ["Provides [2] [Food] [in capital]"],
"Mercantile": ["Provides [2] Happiness"],
"Militaristic": ["Provides military units every [20] turns"]
},
"allyBonus": {
"Cultured": ["Provides [6] [Culture] per turn"],
"Maritime": ["Provides [2] [Food] [in capital]", "Provides [1] [Food] [in all cities]"],
"Mercantile": ["Provides [2] Happiness", "Provides a unique luxury"],
"Militaristic": ["Provides military units every [17] turns"]
},
"iconRGB": [233, 31, 99]
},
{
@ -39,6 +63,18 @@
"settlerBuildings": ["Shrine","Monument"],
"startingObsoleteWonders": ["Temple of Artemis", "Stonehenge", "The Great Library", "Mausoleum of Halicarnassus", "The Pyramids", "Statue of Zeus"],
"baseUnitBuyCost": 200,
"friendBonus": {
"Cultured": ["Provides [6] [Culture] per turn"],
"Maritime": ["Provides [2] [Food] [in capital]"],
"Mercantile": ["Provides [3] Happiness"],
"Militaristic": ["Provides military units every [20] turns"]
},
"allyBonus": {
"Cultured": ["Provides [12] [Culture] per turn"],
"Maritime": ["Provides [2] [Food] [in capital]", "Provides [1] [Food] [in all cities]"],
"Mercantile": ["Provides [3] Happiness", "Provides a unique luxury"],
"Militaristic": ["Provides military units every [17] turns"]
},
"iconRGB": [157, 39, 176]
},
{
@ -55,6 +91,18 @@
"startingObsoleteWonders": ["Temple of Artemis", "Stonehenge", "The Great Library", "Mausoleum of Halicarnassus", "The Pyramids", "Statue of Zeus",
"The Great Lighthouse", "Hanging Gardens", "Terracotta Army", "The Oracle", "Petra", "Great Wall", "Colossus"],
"baseUnitBuyCost": 300,
"friendBonus": {
"Cultured": ["Provides [6] [Culture] per turn"],
"Maritime": ["Provides [2] [Food] [in capital]"],
"Mercantile": ["Provides [3] Happiness"],
"Militaristic": ["Provides military units every [20] turns"]
},
"allyBonus": {
"Cultured": ["Provides [12] [Culture] per turn"],
"Maritime": ["Provides [2] [Food] [in capital]", "Provides [1] [Food] [in all cities]"],
"Mercantile": ["Provides [3] Happiness", "Provides a unique luxury"],
"Militaristic": ["Provides military units every [17] turns"]
},
"iconRGB": [104, 58, 183]
},
{
@ -72,6 +120,18 @@
"The Great Lighthouse", "Hanging Gardens", "Terracotta Army", "The Oracle", "Petra", "Great Wall", "Colossus",
"Hagia Sophia", "Chichen Itza", "Machu Picchu", "Angkor Wat", "Alhambra", "Notre Dame"],
"baseUnitBuyCost": 400,
"friendBonus": {
"Cultured": ["Provides [13] [Culture] per turn"],
"Maritime": ["Provides [2] [Food] [in capital]"],
"Mercantile": ["Provides [3] Happiness"],
"Militaristic": ["Provides military units every [20] turns"]
},
"allyBonus": {
"Cultured": ["Provides [26] [Culture] per turn"],
"Maritime": ["Provides [2] [Food] [in capital]", "Provides [1] [Food] [in all cities]"],
"Mercantile": ["Provides [3] Happiness", "Provides a unique luxury"],
"Militaristic": ["Provides military units every [17] turns"]
},
"iconRGB": [63, 81, 182]
},
{
@ -90,6 +150,18 @@
"Hagia Sophia", "Chichen Itza", "Machu Picchu", "Angkor Wat", "Alhambra", "Notre Dame",
"Sistine Chapel", "Forbidden Palace", "Leaning Tower of Pisa", "Himeji Castle", "Taj Mahal", "Porcelain Tower", "Kremlin"],
"baseUnitBuyCost": 600,
"friendBonus": {
"Cultured": ["Provides [13] [Culture] per turn"],
"Maritime": ["Provides [2] [Food] [in capital]"],
"Mercantile": ["Provides [3] Happiness"],
"Militaristic": ["Provides military units every [20] turns"]
},
"allyBonus": {
"Cultured": ["Provides [26] [Culture] per turn"],
"Maritime": ["Provides [2] [Food] [in capital]", "Provides [1] [Food] [in all cities]"],
"Mercantile": ["Provides [3] Happiness", "Provides a unique luxury"],
"Militaristic": ["Provides military units every [17] turns"]
},
"iconRGB": [33, 150, 243]
},
{
@ -109,6 +181,18 @@
"Sistine Chapel", "Forbidden Palace", "Leaning Tower of Pisa", "Himeji Castle", "Taj Mahal", "Porcelain Tower", "Kremlin",
"The Louvre", "Big Ben", "Brandenburg Gate"],
"baseUnitBuyCost": 800,
"friendBonus": {
"Cultured": ["Provides [13] [Culture] per turn"],
"Maritime": ["Provides [2] [Food] [in capital]"],
"Mercantile": ["Provides [3] Happiness"],
"Militaristic": ["Provides military units every [20] turns"]
},
"allyBonus": {
"Cultured": ["Provides [26] [Culture] per turn"],
"Maritime": ["Provides [2] [Food] [in capital]", "Provides [1] [Food] [in all cities]"],
"Mercantile": ["Provides [3] Happiness", "Provides a unique luxury"],
"Militaristic": ["Provides military units every [17] turns"]
},
"iconRGB": [0, 150, 136]
},
{
@ -132,6 +216,18 @@
// So theoretically this is always just all the wonders at least 2 eras old. So we could just use that.
// But where is the modularity? The excluding of very specific wonders? That is no fun.
// So we just write down the entire long list (sorted by era!) instead.
"friendBonus": {
"Cultured": ["Provides [13] [Culture] per turn"],
"Maritime": ["Provides [2] [Food] [in capital]"],
"Mercantile": ["Provides [3] Happiness"],
"Militaristic": ["Provides military units every [20] turns"]
},
"allyBonus": {
"Cultured": ["Provides [26] [Culture] per turn"],
"Maritime": ["Provides [2] [Food] [in capital]", "Provides [1] [Food] [in all cities]"],
"Mercantile": ["Provides [3] Happiness", "Provides a unique luxury"],
"Militaristic": ["Provides military units every [17] turns"]
},
"iconRGB": [76, 176, 81]
},
{ // Technically, this Era doesn't exist in the original game.
@ -154,6 +250,18 @@
"The Louvre", "Big Ben", "Brandenburg Gate",
"Eiffel Tower", "Statue of Liberty", "Neuschwanstein", "Cristo Redentor"],
"baseUnitBuyCost": 1000,
"friendBonus": {
"Cultured": ["Provides [13] [Culture] per turn"],
"Maritime": ["Provides [2] [Food] [in capital]"],
"Mercantile": ["Provides [3] Happiness"],
"Militaristic": ["Provides military units every [20] turns"]
},
"allyBonus": {
"Cultured": ["Provides [26] [Culture] per turn"],
"Maritime": ["Provides [2] [Food] [in capital]", "Provides [1] [Food] [in all cities]"],
"Mercantile": ["Provides [3] Happiness", "Provides a unique luxury"],
"Militaristic": ["Provides military units every [17] turns"]
},
"iconRGB": [76, 176, 81]
}
]

View File

@ -494,7 +494,7 @@
"outerColor": [228,208,43],
"innerColor": [193,21,17],
"uniqueName": "Father Governs Children",
"uniques": ["Food and Culture from Friendly City-States are increased by 50%"],
"uniques": ["Food and Culture from Friendly City-States are increased by 50%","Military Units gifted from City-States start with [+10] XP"],
"cities": ["Sukhothai","Si Satchanalai","Muang Saluang","Lampang","Phitsanulok","Kamphaeng Pet","Nakhom Chum","Vientiane",
"Nakhon Si Thammarat","Martaban","Nakhon Sawan","Chainat","Luang Prabang","Uttaradit","Chiang Thong","Phrae",
"Nan","Tak","Suphanburi","Hongsawadee","Thawaii","Ayutthaya","Taphan Hin","Uthai Thani","Lap Buri","Ratchasima",

View File

@ -11,6 +11,8 @@ import com.unciv.models.ruleset.Unique
import com.unciv.models.ruleset.unit.BaseUnit
import com.unciv.models.stats.Stat
import com.unciv.models.stats.Stats
import com.unciv.models.translations.getPlaceholderParameters
import com.unciv.models.translations.getPlaceholderText
class CityStats {
@ -122,13 +124,32 @@ class CityStats {
val stats = Stats()
for (otherCiv in cityInfo.civInfo.getKnownCivs()) {
if (otherCiv.isCityState() && otherCiv.cityStateType == CityStateType.Maritime
&& otherCiv.getDiplomacyManager(cityInfo.civInfo).relationshipLevel() >= RelationshipLevel.Friend) {
if (cityInfo.isCapital()) stats.food += 3
else stats.food += 1
if (otherCiv.isCityState() && otherCiv.getDiplomacyManager(cityInfo.civInfo).relationshipLevel() >= RelationshipLevel.Friend) {
val eraInfo = cityInfo.civInfo.getEraObject()
if (cityInfo.civInfo.hasUnique("Food and Culture from Friendly City-States are increased by 50%"))
if (eraInfo.friendBonus[otherCiv.cityStateType.name] == null || eraInfo.allyBonus[otherCiv.cityStateType.name] == null) {
// Deprecated, assume Civ V values for compatibility
if (otherCiv.cityStateType == CityStateType.Maritime && otherCiv.getDiplomacyManager(cityInfo.civInfo).relationshipLevel() == RelationshipLevel.Ally)
stats.food += 1
if (otherCiv.cityStateType == CityStateType.Maritime && cityInfo.isCapital())
stats.food += 2
if (cityInfo.civInfo.hasUnique("Food and Culture from Friendly City-States are increased by 50%"))
stats.food *= 1.5f
return stats
}
for (bonus in if (otherCiv.getDiplomacyManager(cityInfo.civInfo).relationshipLevel() == RelationshipLevel.Friend)
eraInfo.friendBonus[otherCiv.cityStateType.name]!! else eraInfo.allyBonus[otherCiv.cityStateType.name]!!) {
if (bonus.getPlaceholderText() == "Provides [] [] []" && cityInfo.matchesFilter(bonus.getPlaceholderParameters()[2])) {
stats.add(Stat.valueOf(bonus.getPlaceholderParameters()[1]), bonus.getPlaceholderParameters()[0].toFloat())
}
}
if (cityInfo.civInfo.hasUnique("Food and Culture from Friendly City-States are increased by 50%")) {
stats.food *= 1.5f
stats.culture *= 1.5f
}
}
}

View File

@ -6,6 +6,8 @@ import com.unciv.models.ruleset.tile.ResourceType
import com.unciv.models.stats.Stat
import com.unciv.models.stats.StatMap
import com.unciv.models.stats.Stats
import com.unciv.models.translations.getPlaceholderParameters
import com.unciv.models.translations.getPlaceholderText
import kotlin.math.max
import kotlin.math.min
import kotlin.math.pow
@ -80,16 +82,35 @@ class CivInfoStats(val civInfo: CivilizationInfo) {
statMap.add(entry.key, entry.value)
}
//City-States culture bonus
//City-States bonuses
for (otherCiv in civInfo.getKnownCivs()) {
if (otherCiv.isCityState() && otherCiv.cityStateType == CityStateType.Cultured
&& otherCiv.getDiplomacyManager(civInfo.civName).relationshipLevel() >= RelationshipLevel.Friend) {
val cultureBonus = Stats()
var culture = 3f * (civInfo.getEraNumber() + 1)
if (otherCiv.isCityState() && otherCiv.getDiplomacyManager(civInfo.civName).relationshipLevel() >= RelationshipLevel.Friend) {
val cityStateBonus = Stats()
val relevantBonuses = if (otherCiv.getDiplomacyManager(civInfo.civName).relationshipLevel() == RelationshipLevel.Friend)
civInfo.getEraObject().friendBonus[otherCiv.cityStateType.name]
else
civInfo.getEraObject().allyBonus[otherCiv.cityStateType.name]
if (relevantBonuses != null) {
for (bonus in relevantBonuses) {
if (bonus.getPlaceholderText() == "Provides [] [] per turn") {
cityStateBonus.add(Stat.valueOf(bonus.getPlaceholderParameters()[1]), bonus.getPlaceholderParameters()[0].toFloat())
}
}
} else {
// Deprecated, assume Civ V values for compatibility
if (otherCiv.cityStateType == CityStateType.Cultured) {
cityStateBonus.culture = if(civInfo.getEraNumber() in 0..1) 3f else if (civInfo.getEraNumber() in 2..3) 6f else 13f
if (otherCiv.getDiplomacyManager(civInfo.civName).relationshipLevel() == RelationshipLevel.Ally)
cityStateBonus.culture *= 2f
}
}
if (civInfo.hasUnique("Food and Culture from Friendly City-States are increased by 50%"))
culture *= 1.5f
cultureBonus.add(Stat.Culture, culture)
statMap.add("City-States", cultureBonus)
cityStateBonus.culture *= 1.5f
statMap.add("City-States", cityStateBonus)
}
if (otherCiv.isCityState())
@ -213,12 +234,31 @@ class CivInfoStats(val civInfo: CivilizationInfo) {
//From city-states
for (otherCiv in civInfo.getKnownCivs()) {
if (otherCiv.isCityState() && otherCiv.cityStateType == CityStateType.Mercantile
&& otherCiv.getDiplomacyManager(civInfo).relationshipLevel() >= RelationshipLevel.Friend) {
if (statMap.containsKey("City-States"))
statMap["City-States"] = statMap["City-States"]!! + 3f
else
statMap["City-States"] = 3f
if (otherCiv.isCityState() && otherCiv.getDiplomacyManager(civInfo).relationshipLevel() >= RelationshipLevel.Friend) {
val relevantbonuses = if (otherCiv.getDiplomacyManager(civInfo).relationshipLevel() == RelationshipLevel.Friend)
civInfo.getEraObject().friendBonus[otherCiv.cityStateType.name]
else
civInfo.getEraObject().allyBonus[otherCiv.cityStateType.name]
if (relevantbonuses != null) {
for (bonus in relevantbonuses) {
if (bonus.getPlaceholderText() == "Provides [] Happiness") {
if (statMap.containsKey("City-States"))
statMap["City-States"] = statMap["City-States"]!! + bonus.getPlaceholderParameters()[0].toFloat()
else
statMap["City-States"] = bonus.getPlaceholderParameters()[0].toFloat()
}
}
} else {
// Deprecated, assume Civ V values for compatibility
if (otherCiv.cityStateType == CityStateType.Mercantile) {
val happinessBonus = if(civInfo.getEraNumber() in 0..1) 2f else 3f
if (statMap.containsKey("City-States"))
statMap["City-States"] = statMap["City-States"]!! + happinessBonus
else
statMap["City-States"] = happinessBonus
}
}
}
}

View File

@ -408,6 +408,8 @@ class CivilizationInfo {
fun getEraNumber(): Int = gameInfo.ruleSet.getEraNumber(getEra())
fun getEraObject(): Era = gameInfo.ruleSet.eras[getEra()]!!
fun isAtWarWith(otherCiv: CivilizationInfo): Boolean {
if (otherCiv.civName == civName) return false // never at war with itself
if (otherCiv.isBarbarian() || isBarbarian()) return true
@ -854,6 +856,10 @@ class CivilizationInfo {
.toList().random()
// placing the unit may fail - in that case stay quiet
val placedUnit = placeUnitNearTile(city.location, militaryUnit.name) ?: return
// Siam gets +10 XP for all CS units
for (unique in getMatchingUniques("Military Units gifted from City-States start with [] XP")) {
placedUnit.promotions.XP += unique.params[0].toInt()
}
// Point to the places mentioned in the message _in that order_ (debatable)
val placedLocation = placedUnit.getTile().position
val locations = LocationAction(listOf(placedLocation, cities.city2.location, city.location))

View File

@ -6,6 +6,9 @@ import com.unciv.logic.trade.Trade
import com.unciv.logic.trade.TradeOffer
import com.unciv.logic.trade.TradeType
import com.unciv.models.ruleset.tile.ResourceSupplyList
import com.unciv.models.translations.getPlaceholderParameters
import com.unciv.models.translations.getPlaceholderText
import javax.management.relation.Relation
import kotlin.math.ceil
import kotlin.math.max
import kotlin.math.min
@ -501,11 +504,31 @@ class DiplomacyManager() {
if (!hasFlag(DiplomacyFlags.DeclarationOfFriendship))
revertToZero(DiplomaticModifiers.DeclarationOfFriendship, 1 / 2f) //decreases slowly and will revert to full if it is declared later
if (otherCiv().isCityState() && otherCiv().cityStateType == CityStateType.Militaristic) {
if (otherCiv().isCityState()) {
val eraInfo = civInfo.getEraObject()
if (relationshipLevel() < RelationshipLevel.Friend) {
if (hasFlag(DiplomacyFlags.ProvideMilitaryUnit)) removeFlag(DiplomacyFlags.ProvideMilitaryUnit)
} else {
if (!hasFlag(DiplomacyFlags.ProvideMilitaryUnit)) setFlag(DiplomacyFlags.ProvideMilitaryUnit, 20)
val relevantBonuses = if (relationshipLevel() == RelationshipLevel.Friend) eraInfo.friendBonus[otherCiv().cityStateType.name]
else eraInfo.allyBonus[otherCiv().cityStateType.name]
if (relevantBonuses == null && otherCiv().cityStateType == CityStateType.Militaristic) {
// Deprecated, assume Civ V values for compatibility
if (!hasFlag(DiplomacyFlags.ProvideMilitaryUnit) && relationshipLevel() == RelationshipLevel.Friend)
setFlag(DiplomacyFlags.ProvideMilitaryUnit, 20)
if ((!hasFlag(DiplomacyFlags.ProvideMilitaryUnit) || getFlag(DiplomacyFlags.ProvideMilitaryUnit) > 17)
&& relationshipLevel() == RelationshipLevel.Ally)
setFlag(DiplomacyFlags.ProvideMilitaryUnit, 17)
}
if (relevantBonuses == null) return
for (bonus in relevantBonuses) {
// Reset the countdown if it has ended, or if we have longer to go than the current maximum (can happen when going from friend to ally)
if (bonus.getPlaceholderText() == "Provides military units every [] turns" &&
(!hasFlag(DiplomacyFlags.ProvideMilitaryUnit) || getFlag(DiplomacyFlags.ProvideMilitaryUnit) > bonus.getPlaceholderParameters()[0].toInt()))
setFlag(DiplomacyFlags.ProvideMilitaryUnit, bonus.getPlaceholderParameters()[0].toInt())
}
}
}
}

View File

@ -1,6 +1,7 @@
package com.unciv.models.ruleset
import com.badlogic.gdx.graphics.Color
import com.unciv.logic.civilization.CityStateType
import com.unciv.models.stats.INamed
import com.unciv.ui.utils.colorFromRGB
@ -19,6 +20,8 @@ class Era : INamed {
var settlerBuildings = ArrayList<String>()
var startingObsoleteWonders = ArrayList<String>()
var baseUnitBuyCost = 200
var friendBonus = HashMap<String, ArrayList<String>>()
var allyBonus = HashMap<String, ArrayList<String>>()
var iconRGB: List<Int>? = null
fun getStartingUnits(): List<String> {

View File

@ -162,11 +162,37 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() {
diplomacyTable.add(nextLevelString.toLabel()).row()
}
val friendBonusText = when (otherCiv.cityStateType) {
CityStateType.Cultured -> ("Provides [" + (3 * (viewingCiv.getEraNumber() + 1)).toString() + "] culture at 30 Influence").tr()
CityStateType.Maritime -> "Provides 3 food in capital and 1 food in other cities at 30 Influence".tr()
CityStateType.Mercantile -> "Provides 3 happiness at 30 Influence".tr()
CityStateType.Militaristic -> "Provides land units every 20 turns at 30 Influence".tr()
var friendBonusText = "When Friends: ".tr()
val friendBonuses = viewingCiv.getEraObject().friendBonus[otherCiv.cityStateType.name]
if (friendBonuses != null) {
friendBonusText += friendBonuses.joinToString(separator = ", ") { it.tr() }
} else {
// Deprecated, assume Civ V values for compatibility
val cultureBonus = if(viewingCiv.getEraNumber() in 0..1) "3" else if (viewingCiv.getEraNumber() in 2..3) "6" else "13"
val happinessBonus = if(viewingCiv.getEraNumber() in 0..1) "2" else "3"
friendBonusText += when (otherCiv.cityStateType) {
CityStateType.Militaristic -> "Provides military units every [20] turns".tr()
CityStateType.Cultured -> ("Provides [" + cultureBonus + "] [Culture] per turn").tr()
CityStateType.Mercantile -> ("Provides [" + happinessBonus + "] Happiness").tr()
CityStateType.Maritime -> "Provides [2] [Food] [in capital]".tr()
}
}
var allyBonusText = "When Allies: "
val allyBonuses = viewingCiv.getEraObject().allyBonus[otherCiv.cityStateType.name]
if (allyBonuses != null) {
allyBonusText += allyBonuses.joinToString(separator = ", ") { it.tr() }
} else {
// Deprecated, assume Civ V values for compatibility
val cultureBonus = if(viewingCiv.getEraNumber() in 0..1) "6" else if (viewingCiv.getEraNumber() in 2..3) "12" else "26"
val happinessBonus = if(viewingCiv.getEraNumber() in 0..1) "2" else "3"
allyBonusText += when (otherCiv.cityStateType) {
CityStateType.Militaristic -> "Provides military units every [20] turns".tr()
CityStateType.Cultured -> ("Provides [" + cultureBonus + "] [Culture] per turn").tr()
CityStateType.Mercantile -> ("Provides [" + happinessBonus + "] Happiness").tr() + ", " + "Provides a unique luxury".tr()
CityStateType.Maritime -> "Provides [2] [Food] [in capital]".tr() + ", " + "Provides [1] [Food] [in all cities]".tr()
}
}
val friendBonusLabelColor: Color
@ -182,6 +208,10 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() {
val friendBonusLabel = friendBonusText.toLabel(friendBonusLabelColor)
.apply { setAlignment(Align.center) }
diplomacyTable.add(friendBonusLabel).row()
val allyBonusLabelColor = if (otherCivDiplomacyManager.relationshipLevel() == RelationshipLevel.Ally) Color.GREEN else Color.GRAY
val allyBonusLabel = allyBonusText.toLabel(allyBonusLabelColor)
.apply { setAlignment(Align.center) }
diplomacyTable.add(allyBonusLabel).row()
return diplomacyTable
}