mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-29 15:01:09 -04: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:
parent
da991b5f66
commit
0d79326869
@ -52,7 +52,7 @@
|
|||||||
"name": "Library",
|
"name": "Library",
|
||||||
"hurryCostModifier": 25,
|
"hurryCostModifier": 25,
|
||||||
"maintenance": 1,
|
"maintenance": 1,
|
||||||
"uniques": ["[+1 Science] Per [2] Population in this city"],
|
"uniques": ["[+1 Science] Per [2] Population [in this city]"],
|
||||||
"requiredTech": "Writing"
|
"requiredTech": "Writing"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -72,7 +72,7 @@
|
|||||||
"uniqueTo": "China",
|
"uniqueTo": "China",
|
||||||
"hurryCostModifier": 25,
|
"hurryCostModifier": 25,
|
||||||
"gold": 2,
|
"gold": 2,
|
||||||
"uniques": ["[+1 Science] Per [2] Population in this city"],
|
"uniques": ["[+1 Science] Per [2] Population [in this city]"],
|
||||||
"requiredTech": "Writing"
|
"requiredTech": "Writing"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -752,7 +752,7 @@
|
|||||||
"requiredBuilding": "University",
|
"requiredBuilding": "University",
|
||||||
"maintenance": 3,
|
"maintenance": 3,
|
||||||
"hurryCostModifier": 0,
|
"hurryCostModifier": 0,
|
||||||
"uniques": ["[+1 Science] Per [2] Population in this city"],
|
"uniques": ["[+1 Science] Per [2] Population [in this city]"],
|
||||||
"requiredTech": "Scientific Theory"
|
"requiredTech": "Scientific Theory"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -6,19 +6,19 @@
|
|||||||
"policies": [
|
"policies": [
|
||||||
{
|
{
|
||||||
"name": "Aristocracy",
|
"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,
|
"row": 1,
|
||||||
"column": 1
|
"column": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Legalism",
|
"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,
|
"row": 1,
|
||||||
"column": 3
|
"column": 3
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Oligarchy",
|
"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,
|
"row": 1,
|
||||||
"column": 5
|
"column": 5
|
||||||
},
|
},
|
||||||
@ -38,7 +38,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Tradition Complete",
|
"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
|
modifiers["Statue of Zeus"] = 15
|
||||||
} else if (attacker is CityCombatant) {
|
} else if (attacker is CityCombatant) {
|
||||||
if (attacker.getCivInfo()
|
if (attacker.city.getCenterTile().militaryUnit != null) {
|
||||||
.hasUnique("+50% attacking strength for cities with garrisoned units")
|
val garrisonBonus = attacker.getCivInfo().getMatchingUniques("+[]% attacking strength for cities with garrisoned units")
|
||||||
&& attacker.city.getCenterTile().militaryUnit != null
|
.sumBy { it.params[0].toInt() }
|
||||||
)
|
if (garrisonBonus != 0)
|
||||||
modifiers["Oligarchy"] = 50
|
modifiers["Garrisoned unit"] = garrisonBonus
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return modifiers
|
return modifiers
|
||||||
|
@ -81,8 +81,12 @@ class CityConstructions {
|
|||||||
stats.add(building.getStats(cityInfo.civInfo))
|
stats.add(building.getStats(cityInfo.civInfo))
|
||||||
|
|
||||||
for (unique in builtBuildingUniqueMap.getAllUniques()) when (unique.placeholderText) {
|
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)
|
"[] 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
|
return stats
|
||||||
@ -92,13 +96,14 @@ class CityConstructions {
|
|||||||
* @return Maintenance cost of all built buildings
|
* @return Maintenance cost of all built buildings
|
||||||
*/
|
*/
|
||||||
fun getMaintenanceCosts(): Int {
|
fun getMaintenanceCosts(): Int {
|
||||||
var maintenanceCost = getBuiltBuildings().sumBy { it.maintenance }
|
var maintenanceCost = 0
|
||||||
val policyManager = cityInfo.civInfo.policies
|
// We cache this to increase performance
|
||||||
if (cityInfo.id in policyManager.legalismState) {
|
val freeBuildings = cityInfo.civInfo.policies.getListOfFreeBuildings(cityInfo.id)
|
||||||
val buildingName = policyManager.legalismState[cityInfo.id]
|
for (building in getBuiltBuildings()) {
|
||||||
maintenanceCost -= cityInfo.getRuleset().buildings[buildingName]!!.maintenance
|
if (building.name !in freeBuildings) {
|
||||||
|
maintenanceCost += building.maintenance
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return maintenanceCost
|
return maintenanceCost
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ class CityInfo {
|
|||||||
|
|
||||||
if (civInfo.cities.size == 1) cityConstructions.addBuilding(capitalCityIndicator())
|
if (civInfo.cities.size == 1) cityConstructions.addBuilding(capitalCityIndicator())
|
||||||
|
|
||||||
civInfo.policies.tryAddLegalismBuildings()
|
civInfo.policies.tryToAddPolicyBuildings()
|
||||||
|
|
||||||
for (unique in civInfo.getMatchingUniques("Gain a free [] []")) {
|
for (unique in civInfo.getMatchingUniques("Gain a free [] []")) {
|
||||||
val freeBuildingName = unique.params[0]
|
val freeBuildingName = unique.params[0]
|
||||||
|
@ -158,13 +158,9 @@ class CityStats {
|
|||||||
|
|
||||||
fun getGrowthBonusFromPoliciesAndWonders(): Float {
|
fun getGrowthBonusFromPoliciesAndWonders(): Float {
|
||||||
var bonus = 0f
|
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]"
|
// "+[amount]% growth [cityFilter]"
|
||||||
for (unique in cityInfo.civInfo.getMatchingUniques("+[]% growth []"))
|
for (unique in cityInfo.civInfo.getMatchingUniques("+[]% growth []"))
|
||||||
if (cityInfo.matchesFilter(unique.params[0]))
|
if (cityInfo.matchesFilter(unique.params[1]))
|
||||||
bonus += unique.params[0].toFloat()
|
bonus += unique.params[0].toFloat()
|
||||||
return bonus / 100
|
return bonus / 100
|
||||||
}
|
}
|
||||||
@ -444,7 +440,7 @@ class CityStats {
|
|||||||
First we see how much food we generate. Then we apply production bonuses to it.
|
First we see how much food we generate. Then we apply production bonuses to it.
|
||||||
Up till here, business as usual.
|
Up till here, business as usual.
|
||||||
Then, we deduct food eaten (from the total produced).
|
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.
|
Some policies have bonuses for excess food only, not general food production.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -24,8 +24,14 @@ class PolicyManager {
|
|||||||
var numberOfAdoptedPolicies = 0
|
var numberOfAdoptedPolicies = 0
|
||||||
var shouldOpenPolicyPicker = false
|
var shouldOpenPolicyPicker = false
|
||||||
get() = field && canAdoptPolicy()
|
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
|
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 {
|
fun clone(): PolicyManager {
|
||||||
val toReturn = PolicyManager()
|
val toReturn = PolicyManager()
|
||||||
@ -34,8 +40,13 @@ class PolicyManager {
|
|||||||
toReturn.freePolicies = freePolicies
|
toReturn.freePolicies = freePolicies
|
||||||
toReturn.shouldOpenPolicyPicker = shouldOpenPolicyPicker
|
toReturn.shouldOpenPolicyPicker = shouldOpenPolicyPicker
|
||||||
toReturn.storedCulture = storedCulture
|
toReturn.storedCulture = storedCulture
|
||||||
toReturn.legalismState.putAll(legalismState)
|
toReturn.cultureBuildingsAdded.putAll(cultureBuildingsAdded)
|
||||||
|
toReturn.specificBuildingsAdded.putAll(specificBuildingsAdded)
|
||||||
toReturn.autocracyCompletedTurns = autocracyCompletedTurns
|
toReturn.autocracyCompletedTurns = autocracyCompletedTurns
|
||||||
|
|
||||||
|
// Deprecated since 3.14.17, left for backwards compatibility
|
||||||
|
toReturn.legalismState.putAll(cultureBuildingsAdded)
|
||||||
|
|
||||||
return toReturn
|
return toReturn
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,6 +55,10 @@ class PolicyManager {
|
|||||||
fun setTransients() {
|
fun setTransients() {
|
||||||
for (policyName in adoptedPolicies)
|
for (policyName in adoptedPolicies)
|
||||||
addPolicyToTransients(getPolicyByName(policyName))
|
addPolicyToTransients(getPolicyByName(policyName))
|
||||||
|
// Deprecated since 3.14.17, left for backwards compatibility
|
||||||
|
if (cultureBuildingsAdded.isEmpty() && legalismState.isNotEmpty()) {
|
||||||
|
cultureBuildingsAdded.putAll(legalismState)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addPolicyToTransients(policy: Policy) {
|
fun addPolicyToTransients(policy: Policy) {
|
||||||
@ -52,7 +67,7 @@ class PolicyManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun startTurn() {
|
fun startTurn() {
|
||||||
tryAddLegalismBuildings()
|
tryToAddPolicyBuildings()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addCulture(culture: Int) {
|
fun addCulture(culture: Int) {
|
||||||
@ -133,7 +148,7 @@ class PolicyManager {
|
|||||||
for (unique in policy.uniqueObjects)
|
for (unique in policy.uniqueObjects)
|
||||||
UniqueTriggerActivation.triggerCivwideUnique(unique, civInfo)
|
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
|
// 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)
|
for (cityInfo in civInfo.cities)
|
||||||
@ -141,22 +156,63 @@ class PolicyManager {
|
|||||||
|
|
||||||
if (!canAdoptPolicy()) shouldOpenPolicyPicker = false
|
if (!canAdoptPolicy()) shouldOpenPolicyPicker = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun tryToAddPolicyBuildings() {
|
||||||
|
tryAddCultureBuildings()
|
||||||
|
tryAddFreeBuildings()
|
||||||
|
}
|
||||||
|
|
||||||
fun tryAddLegalismBuildings() {
|
private fun tryAddCultureBuildings() {
|
||||||
if (!civInfo.hasUnique("Immediately creates a cheapest available cultural building in each of your first 4 cities for free"))
|
val cultureBuildingUniques = civInfo.getMatchingUniques("Immediately creates the cheapest available cultural building in each of your first [] cities for free")
|
||||||
return
|
val citiesToReceiveCultureBuilding = cultureBuildingUniques.sumOf { it.params[0].toInt() }
|
||||||
if (legalismState.size >= 4) return
|
if (!cultureBuildingUniques.any()) return
|
||||||
|
if (cultureBuildingsAdded.size >= citiesToReceiveCultureBuilding) return
|
||||||
|
|
||||||
val candidateCities = civInfo.cities
|
val candidateCities = civInfo.cities
|
||||||
.sortedBy { it.turnAcquired }
|
.sortedBy { it.turnAcquired }
|
||||||
.subList(0, min(4, civInfo.cities.size))
|
.subList(0, min(citiesToReceiveCultureBuilding, civInfo.cities.size))
|
||||||
.filter {
|
.filter {
|
||||||
it.id !in legalismState
|
it.id !in cultureBuildingsAdded
|
||||||
&& it.cityConstructions.hasBuildableCultureBuilding()
|
&& it.cityConstructions.hasBuildableCultureBuilding()
|
||||||
}
|
}
|
||||||
for (city in candidateCities) {
|
for (city in candidateCities) {
|
||||||
val builtBuilding = city.cityConstructions.addCultureBuilding()
|
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 {
|
fun isStatRelated(stat: Stat): Boolean {
|
||||||
if (get(stat) > 0) return true
|
if (get(stat) > 0) return true
|
||||||
if (getStatPercentageBonuses(null).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
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user