mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-04 23:40:01 +07:00
Updated Tradition branch to G&K (#4106)
* Updated Tradition branch to G&K * Small performance boost for calcualting maintenance; fix crash on next turn * Fixed a bug where maintenance-free buildings would still cost maintenance * Simplified some code * I am unable to read * Fixed a few broken uniques, including #4109 * Implemented requested changes
This commit is contained in:
@ -52,7 +52,7 @@
|
||||
"name": "Library",
|
||||
"hurryCostModifier": 25,
|
||||
"maintenance": 1,
|
||||
"uniques": ["[+1 Science] Per [2] Population in this city"],
|
||||
"uniques": ["[+1 Science] Per [2] Population [in this city]"],
|
||||
"requiredTech": "Writing"
|
||||
},
|
||||
{
|
||||
@ -72,7 +72,7 @@
|
||||
"uniqueTo": "China",
|
||||
"hurryCostModifier": 25,
|
||||
"gold": 2,
|
||||
"uniques": ["[+1 Science] Per [2] Population in this city"],
|
||||
"uniques": ["[+1 Science] Per [2] Population [in this city]"],
|
||||
"requiredTech": "Writing"
|
||||
},
|
||||
{
|
||||
@ -752,7 +752,7 @@
|
||||
"requiredBuilding": "University",
|
||||
"maintenance": 3,
|
||||
"hurryCostModifier": 0,
|
||||
"uniques": ["[+1 Science] Per [2] Population in this city"],
|
||||
"uniques": ["[+1 Science] Per [2] Population [in this city]"],
|
||||
"requiredTech": "Scientific Theory"
|
||||
},
|
||||
{
|
||||
|
@ -6,19 +6,19 @@
|
||||
"policies": [
|
||||
{
|
||||
"name": "Aristocracy",
|
||||
"uniques": ["+[15]% Production when constructing [Wonders]", "[+1 Happiness] per [10] population in all cities"],
|
||||
"uniques": ["+[15]% Production when constructing [Wonders]", "[+1 Happiness] per [10] population [in all cities]"],
|
||||
"row": 1,
|
||||
"column": 1
|
||||
},
|
||||
{
|
||||
"name": "Legalism",
|
||||
"uniques":["Immediately creates a cheapest available cultural building in each of your first 4 cities for free"],
|
||||
"uniques":["Immediately creates the cheapest available cultural building in each of your first [4] cities for free"],
|
||||
"row": 1,
|
||||
"column": 3
|
||||
},
|
||||
{
|
||||
"name": "Oligarchy",
|
||||
"uniques": ["Units in cities cost no Maintenance", "+50% attacking strength for cities with garrisoned units"],
|
||||
"uniques": ["Units in cities cost no Maintenance", "+[50]% attacking strength for cities with garrisoned units"],
|
||||
"row": 1,
|
||||
"column": 5
|
||||
},
|
||||
@ -38,7 +38,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Tradition Complete",
|
||||
"uniques": ["+[15]% growth [in all cities]","[+2 Food] [in all cities]"]
|
||||
"uniques": ["+[15]% growth [in all cities]","Immediately creates a [Aqueduct] in each of your first [4] cities for free"]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -181,11 +181,12 @@ object BattleDamage {
|
||||
)
|
||||
modifiers["Statue of Zeus"] = 15
|
||||
} else if (attacker is CityCombatant) {
|
||||
if (attacker.getCivInfo()
|
||||
.hasUnique("+50% attacking strength for cities with garrisoned units")
|
||||
&& attacker.city.getCenterTile().militaryUnit != null
|
||||
)
|
||||
modifiers["Oligarchy"] = 50
|
||||
if (attacker.city.getCenterTile().militaryUnit != null) {
|
||||
val garrisonBonus = attacker.getCivInfo().getMatchingUniques("+[]% attacking strength for cities with garrisoned units")
|
||||
.sumBy { it.params[0].toInt() }
|
||||
if (garrisonBonus != 0)
|
||||
modifiers["Garrisoned unit"] = garrisonBonus
|
||||
}
|
||||
}
|
||||
|
||||
return modifiers
|
||||
|
@ -81,8 +81,12 @@ class CityConstructions {
|
||||
stats.add(building.getStats(cityInfo.civInfo))
|
||||
|
||||
for (unique in builtBuildingUniqueMap.getAllUniques()) when (unique.placeholderText) {
|
||||
"[] Per [] Population in this city" -> stats.add(unique.stats.times(cityInfo.population.population / unique.params[1].toFloat()))
|
||||
"[] per [] population []" -> if (cityInfo.matchesFilter(unique.params[2]))
|
||||
stats.add(unique.stats.times(cityInfo.population.population / unique.params[1].toFloat()))
|
||||
"[] once [] is discovered" -> if (cityInfo.civInfo.tech.isResearched(unique.params[1])) stats.add(unique.stats)
|
||||
// Deprecated since 3.14.17, left for modding compatibility
|
||||
"[] Per [] Population in this city" ->
|
||||
stats.add(unique.stats.times(cityInfo.population.population / unique.params[1].toFloat()))
|
||||
}
|
||||
|
||||
return stats
|
||||
@ -92,13 +96,14 @@ class CityConstructions {
|
||||
* @return Maintenance cost of all built buildings
|
||||
*/
|
||||
fun getMaintenanceCosts(): Int {
|
||||
var maintenanceCost = getBuiltBuildings().sumBy { it.maintenance }
|
||||
val policyManager = cityInfo.civInfo.policies
|
||||
if (cityInfo.id in policyManager.legalismState) {
|
||||
val buildingName = policyManager.legalismState[cityInfo.id]
|
||||
maintenanceCost -= cityInfo.getRuleset().buildings[buildingName]!!.maintenance
|
||||
var maintenanceCost = 0
|
||||
// We cache this to increase performance
|
||||
val freeBuildings = cityInfo.civInfo.policies.getListOfFreeBuildings(cityInfo.id)
|
||||
for (building in getBuiltBuildings()) {
|
||||
if (building.name !in freeBuildings) {
|
||||
maintenanceCost += building.maintenance
|
||||
}
|
||||
}
|
||||
|
||||
return maintenanceCost
|
||||
}
|
||||
|
||||
|
@ -88,7 +88,7 @@ class CityInfo {
|
||||
|
||||
if (civInfo.cities.size == 1) cityConstructions.addBuilding(capitalCityIndicator())
|
||||
|
||||
civInfo.policies.tryAddLegalismBuildings()
|
||||
civInfo.policies.tryToAddPolicyBuildings()
|
||||
|
||||
for (unique in civInfo.getMatchingUniques("Gain a free [] []")) {
|
||||
val freeBuildingName = unique.params[0]
|
||||
|
@ -158,13 +158,9 @@ class CityStats {
|
||||
|
||||
fun getGrowthBonusFromPoliciesAndWonders(): Float {
|
||||
var bonus = 0f
|
||||
// This requires more... complex navigation of the local uniques to merge into "+[amount]% growth [cityFilter]"
|
||||
for (unique in cityInfo.civInfo.getMatchingUniques("+[]% growth in all cities"))
|
||||
bonus += unique.params[0].toFloat()
|
||||
|
||||
// "+[amount]% growth [cityFilter]"
|
||||
for (unique in cityInfo.civInfo.getMatchingUniques("+[]% growth []"))
|
||||
if (cityInfo.matchesFilter(unique.params[0]))
|
||||
if (cityInfo.matchesFilter(unique.params[1]))
|
||||
bonus += unique.params[0].toFloat()
|
||||
return bonus / 100
|
||||
}
|
||||
@ -444,7 +440,7 @@ class CityStats {
|
||||
First we see how much food we generate. Then we apply production bonuses to it.
|
||||
Up till here, business as usual.
|
||||
Then, we deduct food eaten (from the total produced).
|
||||
Now we have the excess food, whih has its own things. If we're unhappy, cut it by 1/4.
|
||||
Now we have the excess food, which has its own things. If we're unhappy, cut it by 1/4.
|
||||
Some policies have bonuses for excess food only, not general food production.
|
||||
*/
|
||||
|
||||
|
@ -24,8 +24,14 @@ class PolicyManager {
|
||||
var numberOfAdoptedPolicies = 0
|
||||
var shouldOpenPolicyPicker = false
|
||||
get() = field && canAdoptPolicy()
|
||||
var legalismState = HashMap<String, String>()
|
||||
|
||||
private var cultureBuildingsAdded = HashMap<String, String>() // Maps cities to buildings
|
||||
private var specificBuildingsAdded = HashMap<String, MutableSet<String>>() // Maps buildings to cities
|
||||
var autocracyCompletedTurns = 0
|
||||
|
||||
@Deprecated("Deprecated since 3.14.17") // Replaced with cultureBuildingsAdded
|
||||
var legalismState = HashMap<String, String>() // Maps cities to buildings
|
||||
// We make it a reference copy of the original variable. This way, it can still works in older versions
|
||||
|
||||
fun clone(): PolicyManager {
|
||||
val toReturn = PolicyManager()
|
||||
@ -34,8 +40,13 @@ class PolicyManager {
|
||||
toReturn.freePolicies = freePolicies
|
||||
toReturn.shouldOpenPolicyPicker = shouldOpenPolicyPicker
|
||||
toReturn.storedCulture = storedCulture
|
||||
toReturn.legalismState.putAll(legalismState)
|
||||
toReturn.cultureBuildingsAdded.putAll(cultureBuildingsAdded)
|
||||
toReturn.specificBuildingsAdded.putAll(specificBuildingsAdded)
|
||||
toReturn.autocracyCompletedTurns = autocracyCompletedTurns
|
||||
|
||||
// Deprecated since 3.14.17, left for backwards compatibility
|
||||
toReturn.legalismState.putAll(cultureBuildingsAdded)
|
||||
|
||||
return toReturn
|
||||
}
|
||||
|
||||
@ -44,6 +55,10 @@ class PolicyManager {
|
||||
fun setTransients() {
|
||||
for (policyName in adoptedPolicies)
|
||||
addPolicyToTransients(getPolicyByName(policyName))
|
||||
// Deprecated since 3.14.17, left for backwards compatibility
|
||||
if (cultureBuildingsAdded.isEmpty() && legalismState.isNotEmpty()) {
|
||||
cultureBuildingsAdded.putAll(legalismState)
|
||||
}
|
||||
}
|
||||
|
||||
fun addPolicyToTransients(policy: Policy) {
|
||||
@ -52,7 +67,7 @@ class PolicyManager {
|
||||
}
|
||||
|
||||
fun startTurn() {
|
||||
tryAddLegalismBuildings()
|
||||
tryToAddPolicyBuildings()
|
||||
}
|
||||
|
||||
fun addCulture(culture: Int) {
|
||||
@ -133,7 +148,7 @@ class PolicyManager {
|
||||
for (unique in policy.uniqueObjects)
|
||||
UniqueTriggerActivation.triggerCivwideUnique(unique, civInfo)
|
||||
|
||||
tryAddLegalismBuildings()
|
||||
tryToAddPolicyBuildings()
|
||||
|
||||
// This ALSO has the side-effect of updating the CivInfo statForNextTurn so we don't need to call it explicitly
|
||||
for (cityInfo in civInfo.cities)
|
||||
@ -141,22 +156,63 @@ class PolicyManager {
|
||||
|
||||
if (!canAdoptPolicy()) shouldOpenPolicyPicker = false
|
||||
}
|
||||
|
||||
fun tryToAddPolicyBuildings() {
|
||||
tryAddCultureBuildings()
|
||||
tryAddFreeBuildings()
|
||||
}
|
||||
|
||||
fun tryAddLegalismBuildings() {
|
||||
if (!civInfo.hasUnique("Immediately creates a cheapest available cultural building in each of your first 4 cities for free"))
|
||||
return
|
||||
if (legalismState.size >= 4) return
|
||||
private fun tryAddCultureBuildings() {
|
||||
val cultureBuildingUniques = civInfo.getMatchingUniques("Immediately creates the cheapest available cultural building in each of your first [] cities for free")
|
||||
val citiesToReceiveCultureBuilding = cultureBuildingUniques.sumOf { it.params[0].toInt() }
|
||||
if (!cultureBuildingUniques.any()) return
|
||||
if (cultureBuildingsAdded.size >= citiesToReceiveCultureBuilding) return
|
||||
|
||||
val candidateCities = civInfo.cities
|
||||
.sortedBy { it.turnAcquired }
|
||||
.subList(0, min(4, civInfo.cities.size))
|
||||
.subList(0, min(citiesToReceiveCultureBuilding, civInfo.cities.size))
|
||||
.filter {
|
||||
it.id !in legalismState
|
||||
it.id !in cultureBuildingsAdded
|
||||
&& it.cityConstructions.hasBuildableCultureBuilding()
|
||||
}
|
||||
for (city in candidateCities) {
|
||||
val builtBuilding = city.cityConstructions.addCultureBuilding()
|
||||
if (builtBuilding != null) legalismState[city.id] = builtBuilding!!
|
||||
if (builtBuilding != null) cultureBuildingsAdded[city.id] = builtBuilding!!
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryAddFreeBuildings() {
|
||||
val matchingUniques = civInfo.getMatchingUniques("Immediately creates a [] in each of your first [] cities for free")
|
||||
// If we have "create a free aqueduct in first 3 cities" and "create free aqueduct in first 4 cities", we do: "create free aqueduct in first 3+4=7 cities"
|
||||
val sortedUniques = matchingUniques.groupBy {it.params[0]}
|
||||
for (unique in sortedUniques) {
|
||||
tryAddSpecificBuilding(unique.key, unique.value.sumBy {it.params[1].toInt()})
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryAddSpecificBuilding(building: String, cityCount: Int) {
|
||||
if (specificBuildingsAdded[building] == null) specificBuildingsAdded[building] = mutableSetOf()
|
||||
val citiesAlreadyGivenBuilding = specificBuildingsAdded[building]
|
||||
if (citiesAlreadyGivenBuilding!!.size >= cityCount) return
|
||||
val candidateCities = civInfo.cities
|
||||
.sortedBy { it.turnAcquired }
|
||||
.subList(0, min(cityCount, civInfo.cities.size))
|
||||
.filter {
|
||||
it.id !in citiesAlreadyGivenBuilding && !it.cityConstructions.containsBuildingOrEquivalent(building)
|
||||
}
|
||||
|
||||
for (city in candidateCities) {
|
||||
city.cityConstructions.getConstruction(building).postBuildEvent(city.cityConstructions, false)
|
||||
citiesAlreadyGivenBuilding.add(city.id)
|
||||
}
|
||||
}
|
||||
|
||||
fun getListOfFreeBuildings(cityId: String): MutableSet<String> {
|
||||
val freeBuildings = cultureBuildingsAdded.filter { it.key == cityId }.values.toMutableSet()
|
||||
for (building in specificBuildingsAdded.filter { it.value.contains(cityId) }) {
|
||||
freeBuildings.add(building.key)
|
||||
}
|
||||
return freeBuildings
|
||||
}
|
||||
}
|
@ -441,7 +441,9 @@ class Building : NamedStats(), IConstruction {
|
||||
fun isStatRelated(stat: Stat): Boolean {
|
||||
if (get(stat) > 0) return true
|
||||
if (getStatPercentageBonuses(null).get(stat) > 0) return true
|
||||
if (uniqueObjects.any { it.placeholderText == "[] Per [] Population in this city" && it.stats.get(stat) > 0 }) return true
|
||||
if (uniqueObjects.any { it.placeholderText == "[] per [] population []" && it.stats.get(stat) > 0 }) return true
|
||||
// Deprecated since 3.14.17, left for modding compatibility
|
||||
if (uniqueObjects.any { it.placeholderText == "[] Per [] Population in this city"}) return true
|
||||
return false
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user