Added city filter, and gerenicised several uniques to work with the city filter.

Deleted some deprecated uniques
This commit is contained in:
Yair Morgenstern
2021-01-28 14:26:42 +02:00
parent 6a266a6cac
commit 18f4d4e53e
7 changed files with 72 additions and 39 deletions

View File

@ -209,7 +209,7 @@
"requiredNearbyImprovedResources": ["Horses","Sheep","Cattle"],
"resourceBonusStats": {"production": 1},
"hurryCostModifier": 25,
"uniques": ["+[15]% production when building [mounted units] in this city"],
"uniques": ["+[15]% Production when constructing [Mounted] units [in this city]"]
"requiredTech": "Horseback Riding"
},
{
@ -463,7 +463,8 @@
"requiredNearbyImprovedResources": ["Iron"],
"resourceBonusStats": {"production": 1},
"requiredTech": "Metal Casting",
"uniques": ["+[15]% production when building [land units] in this city", "+[15]% production when building [Spaceship part] in this city"]
"uniques": ["+[15]% Production when constructing [Spaceship part] units [in this city]",
"+[15]% Production when constructing [Land] units [in this city]"]
},
{
"name": "Harbor",
@ -599,7 +600,7 @@
"culture": 1,
"isWonder": true,
"greatPersonPoints": {"culture": 2},
"uniques": ["+[25]% [Culture] in all cities"],
"uniques": ["+[25]% [Culture] [in all cities]"],
"requiredTech": "Acoustics",
"quote": "'I live and love in God's peculiar light.' - Michelangelo Buonarroti"
},
@ -707,7 +708,7 @@
"maintenance": 3,
"requiredBuilding": "Harbor",
"uniques": ["[+1 Production, +1 Gold] from [Water resource] tiles in this city",
"Must be next to [Coast]", "+[15]% production when building [naval units] in this city"],
"Must be next to [Coast]", "+[15]% Production when constructing [Water] units [in this city]"]
"requiredTech": "Navigation"
},
{
@ -735,7 +736,7 @@
"specialistSlots": {"Engineer": 1},
"hurryCostModifier": 25,
"maintenance": 2,
"uniques": ["Must not be on [Hill]", "+[10]% production when building [Buildings] in this city"],
"uniques": ["Must not be on [Hill]", "+[10]% Production when constructing [Buildings] [in this city]"],
"requiredTech": "Economics"
},
@ -996,7 +997,7 @@
"requiredResource": "Aluminum",
"cost": 360,
"requiredBuilding": "Factory",
"uniques": ["+[50]% production when building [Spaceship part] in this city"],
"uniques": ["+[50]% Production when constructing [Spaceship part] units [in this city]"],
"requiredTech": "Robotics"
},
{
@ -1022,7 +1023,7 @@
"greatPersonPoints": {"science": 1},
"providesFreeBuilding": "Spaceship Factory",
"uniques": ["[2] free [Great Scientist] units appear",
"+[25]% production when building [Spaceship part] in this city"],
"+[25]% Production when constructing [Spaceship part] units [in this city]"],
"requiredTech": "Satellites",
"quote": "'The wonder is, not that the field of stars is so vast, but that man has measured it.' - Anatole France"
// will be introduced in G&K expansion pack

View File

@ -49,7 +49,7 @@
"policies": [
{
"name": "Collective Rule",
"uniques": ["Training of settlers increased +50% in capital", "Free [Settler] appears"],
"uniques": ["+[50]% Production when constructing [Settler] units [in capital]", "Free [Settler] appears"],
"row": 1,
"column": 1
},
@ -156,7 +156,7 @@
},
{
"name": "Reformation",
"uniques": ["+33% culture in all cities with a world wonder", "Empire enters golden age"],
"uniques": ["+[33]% [Culture] [in all cities with a world wonder]", "Empire enters golden age"],
"requires": ["Organized Religion"],
"row": 2,
"column": 3
@ -213,7 +213,7 @@
},*/
{
"name": "Commerce",
"uniques": ["+25% gold in capital"],
"uniques": ["+[25]% [Gold] [in capital]"],
"era": "Medieval era",
"policies": [
{

View File

@ -99,8 +99,7 @@ class CityInfo {
for (unique in civInfo.getMatchingUniques("Gain a free [] []")) {
val freeBuildingName = unique.params[0]
val cityFilter = unique.params[1]
if (cityFilter == "in every city" || (cityFilter == "in every coastal city" && getCenterTile().isCoastalTile())) {
if (matchesFilter(unique.params[1])) {
if (!cityConstructions.isBuilt(freeBuildingName))
cityConstructions.addBuilding(freeBuildingName)
}
@ -648,5 +647,17 @@ class CityInfo {
}
return true
}
fun matchesFilter(filter: String): Boolean {
return when {
filter == "in this city" -> true
filter == "in all cities" -> true
filter == "in all coastal cities" && getCenterTile().isCoastalTile() -> true
filter == "in capital" && isCapital() -> true
filter == "in all cities with a world wonder" && cityConstructions.getBuiltBuildings().any { it.isWonder } -> true
else -> false
}
}
//endregion
}

View File

@ -89,7 +89,7 @@ class CityStats {
return stats
}
private fun getStatPercentBonusesFromMarble(construction: IConstruction): Stats {
private fun getStatPercentBonusesFromResources(construction: IConstruction): Stats {
val stats = Stats()
if (construction is Building
@ -101,17 +101,6 @@ class CityStats {
return stats
}
private fun getStatPercentBonusesFromComputers(): Stats {
val stats = Stats()
if (cityInfo.civInfo.hasUnique("+10% science and production in all cities")) {
stats.production += 10f
stats.science += 10f
}
return stats
}
private fun getStatsFromNationUnique(): Stats {
val stats = Stats()
@ -224,7 +213,7 @@ class CityStats {
newHappinessList["National ability"] = getStatsFromUniques(cityInfo.civInfo.nation.uniqueObjects.asSequence()).happiness
newHappinessList["Wonders"] = getStatsFromUniques(civInfo.getBuildingUniques()).happiness
newHappinessList["Wonders"] = getStatsFromUniques(civInfo.getCivWideBuildingUniques()).happiness
newHappinessList["Tile yields"] = getStatsFromTiles().happiness
@ -289,6 +278,7 @@ class CityStats {
private fun getStatPercentBonusesFromBuildings(currentConstruction: IConstruction): Stats {
val stats = cityInfo.cityConstructions.getStatPercentBonuses()
// Deprecated as of 3.12.11 - replaces with "+[amount]% Production when constructing [unitFilter] units [in this city]"
for (unique in cityInfo.cityConstructions.builtBuildingUniqueMap.getUniques("+[]% production when building [] in this city")) {
if (constructionMatchesFilter(currentConstruction, unique.params[1]))
stats.production += unique.params[0].toInt()
@ -303,6 +293,7 @@ class CityStats {
// Since this is sometimes run from a different thread (getConstructionButtonDTOs),
// this helps mitigate concurrency problems.
// Deprecated as of 3.12.10 - changed to "+[50]% Production when constructing [Settler] units [in capital]"
if (currentConstruction.name == Constants.settler && cityInfo.isCapital()
&& uniques.any { it.text == "Training of settlers increased +50% in capital" })
stats.production += 50f
@ -314,30 +305,54 @@ class CityStats {
stats.production += unique.params[0].toInt()
}
// For instance "+[50]% [Production]
for (unique in uniques.filter { it.placeholderText == "+[]% [] in all cities"})
stats.add(Stat.valueOf(unique.params[1]), unique.params[0].toFloat())
// Params: "+[amount]% [Stat] [cityFilter]", pretty crazy amirite
// For instance "+[50]% [Production] [in all cities]
for (unique in uniques.filter { it.placeholderText == "+[]% [] []"})
if (cityInfo.matchesFilter(unique.params[2]))
stats.add(Stat.valueOf(unique.params[1]), unique.params[0].toFloat())
for (unique in uniques.filter { it.placeholderText == "+[]% Production when constructing []" }) {
if (constructionMatchesFilter(currentConstruction, unique.params[1]))
stats.production += unique.params[0].toInt()
}
// "+[amount]% Production when constructing [constructionFilter] [cityFilter]"
for (unique in uniques.filter { it.placeholderText == "+[]% Production when constructing [] []" }) {
if (constructionMatchesFilter(currentConstruction, unique.params[1]) && cityInfo.matchesFilter(unique.params[2]))
stats.production += unique.params[0].toInt()
}
// Deprecated as of 3.12.10 - changed to "+[amount]% Production when constructing [unitFilter] units [in all cities]"
for (unique in uniques.filter { it.placeholderText == "+[]% Production when constructing [] units" }) {
if (currentConstruction is BaseUnit && currentConstruction.matchesFilter(unique.params[1]))
stats.production += unique.params[0].toInt()
}
// "+[amount]% Production when constructing [unitFilter] units [cityFilter]"
for (unique in uniques.filter { it.placeholderText == "+[]% Production when constructing [] units []" }) {
if (currentConstruction is BaseUnit && currentConstruction.matchesFilter(unique.params[1])
&& cityInfo.matchesFilter(unique.params[2]))
stats.production += unique.params[0].toInt()
}
// Deprecated as of 3.12.10 - changed to "+[33]% [Culture] [in all cities with a world wonder]"
if (cityInfo.cityConstructions.getBuiltBuildings().any { it.isWonder }
&& uniques.any { it.text == "+33% culture in all cities with a world wonder" })
stats.culture += 33f
// Deprecated as of 3.12.10 - changed to "+[25]% [Gold] [in capital]" (Commerce policy)
if (uniques.any { it.text == "+25% gold in capital" } && cityInfo.isCapital())
stats.gold += 25f
if (cityInfo.civInfo.getHappiness() >= 0 && uniques.any { it.text == "+15% science while empire is happy" })
stats.science += 15f
// Deprecated as of 3.12.10 - changed to "+[25]% [Culture] [in all cities]" (Sistine Chapel)
if (uniques.any { it.text == "Culture in all cities increased by 25%" })
stats.culture += 25f
@ -389,15 +404,15 @@ class CityStats {
}
fun updateStatPercentBonusList(currentConstruction:IConstruction) {
fun updateStatPercentBonusList(currentConstruction: IConstruction, citySpecificUniques: Sequence<Unique>) {
val newStatPercentBonusList = LinkedHashMap<String, Stats>()
newStatPercentBonusList["Golden Age"] = getStatPercentBonusesFromGoldenAge(cityInfo.civInfo.goldenAges.isGoldenAge())
newStatPercentBonusList["Policies"] = getStatPercentBonusesFromUniques(currentConstruction, cityInfo.civInfo.policies.policyUniques.getAllUniques())
newStatPercentBonusList["Buildings"] = getStatPercentBonusesFromBuildings(currentConstruction)
newStatPercentBonusList["Wonders"] = getStatPercentBonusesFromUniques(currentConstruction, cityInfo.civInfo.getBuildingUniques())
newStatPercentBonusList["Buildings"] = getStatPercentBonusesFromUniques(currentConstruction, citySpecificUniques)
.plus(getStatPercentBonusesFromBuildings(currentConstruction)) // This function is to be deprecated but it'll take a while.
newStatPercentBonusList["Wonders"] = getStatPercentBonusesFromUniques(currentConstruction, cityInfo.civInfo.getCivWideBuildingUniques())
newStatPercentBonusList["Railroad"] = getStatPercentBonusesFromRailroad()
newStatPercentBonusList["Marble"] = getStatPercentBonusesFromMarble(currentConstruction)
newStatPercentBonusList["Computers"] = getStatPercentBonusesFromComputers()
newStatPercentBonusList["Resources"] = getStatPercentBonusesFromResources(currentConstruction)
newStatPercentBonusList["National ability"] = getStatPercentBonusesFromNationUnique(currentConstruction)
newStatPercentBonusList["Puppet City"] = getStatPercentBonusesFromPuppetCity()
@ -411,10 +426,13 @@ class CityStats {
}
fun update(currentConstruction: IConstruction = cityInfo.cityConstructions.getCurrentConstruction()) {
val citySpecificUniques: Sequence<Unique> = cityInfo.cityConstructions.builtBuildingUniqueMap.getAllUniques()
.filter { it.params.size>0 && it.params.last()=="in this city" }
// We need to compute Tile yields before happiness
updateBaseStatList()
updateCityHappiness()
updateStatPercentBonusList(currentConstruction)
updateStatPercentBonusList(currentConstruction, citySpecificUniques)
updateFinalStatList(currentConstruction) // again, we don't edit the existing currentCityStats directly, in order to avoid concurrency exceptions

View File

@ -218,13 +218,20 @@ class CivilizationInfo {
fun hasResource(resourceName: String): Boolean = getCivResourcesByName()[resourceName]!! > 0
fun getBuildingUniques(): Sequence<Unique> = cities.asSequence().flatMap { it.cityConstructions.builtBuildingUniqueMap.getAllUniques() }
fun getCivWideBuildingUniques(): Sequence<Unique> = cities.asSequence().flatMap {
it.cityConstructions.builtBuildingUniqueMap.getAllUniques()
.filter { it.params.isEmpty() || it.params.last() != "in this city" }
}
fun hasUnique(unique: String) = getMatchingUniques(unique).any()
// Does not return local uniques, only global ones.
fun getMatchingUniques(uniqueTemplate: String): Sequence<Unique> {
return nation.uniqueObjects.asSequence().filter { it.placeholderText == uniqueTemplate } +
cities.asSequence().flatMap { it.cityConstructions.builtBuildingUniqueMap.getUniques(uniqueTemplate).asSequence() } +
cities.asSequence().flatMap {
it.cityConstructions.builtBuildingUniqueMap.getUniques(uniqueTemplate).asSequence()
.filter { it.params.isEmpty() || it.params.last() != "in this city" }
} +
policies.policyUniques.getUniques(uniqueTemplate) +
tech.getTechUniques().filter { it.placeholderText == uniqueTemplate }
}

View File

@ -26,11 +26,6 @@ class GoldenAgeManager{
fun enterGoldenAge(unmodifiedNumberOfTurns: Int = 10) {
var turnsToGoldenAge = unmodifiedNumberOfTurns.toFloat()
// as of 3.10.7 This is to be deprecated and converted to "Golden Age length increased by []%" - keeping it here to that mods with this can still work for now
for(unique in civInfo.getMatchingUniques("Golden Age length increases +50%"))
turnsToGoldenAge *= 1.5f
for(unique in civInfo.getMatchingUniques("Golden Age length increased by []%"))
turnsToGoldenAge *= (unique.params[0].toFloat()/100 + 1)
turnsToGoldenAge *= civInfo.gameInfo.gameParameters.gameSpeed.modifier

View File

@ -191,7 +191,8 @@ class BaseUnit : INamed, IConstruction {
val filter = unique.params[0]
val promotion = unique.params[1]
if (unit.matchesFilter(filter) || (filter == "relevant" && civInfo.gameInfo.ruleSet.unitPromotions.values.any { unit.type.toString() in it.unitTypes && it.name == promotion }))
if (unit.matchesFilter(filter) || (filter == "relevant" && civInfo.gameInfo.ruleSet.unitPromotions.values
.any { unit.type.name in it.unitTypes && it.name == promotion }))
unit.promotions.addPromotion(promotion, isFree = true)
}