Updated Autocracy branch to G&K (#4149)

* Updated Autocracy branch to G&K

* Fxied a typo

* Implemented potentially requested changes

* Implemented requested changes

Co-authored-by: Yair Morgenstern <yairm210@hotmail.com>
This commit is contained in:
Xander Lenstra 2021-06-18 08:46:30 +02:00 committed by GitHub
parent 1d18c418e7
commit d1c10c6d47
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 100 additions and 44 deletions

View File

@ -101,7 +101,7 @@
{ {
"name": "Discipline", "name": "Discipline",
"uniques":["+[15]% Strength for [Melee] units which have another [Military] unit in an adjacent tile"], "uniques":["+[15]% Strength for [Melee] units which have another [Military] unit in an adjacent tile"],
"row": 1, "row": 1,
"column": 4 "column": 4
}, },
{ {
@ -393,7 +393,7 @@
{ {
"name": "Autocracy", "name": "Autocracy",
"era": "Industrial era", "era": "Industrial era",
"uniques": ["-33% unit upkeep costs"], "uniques": ["-[33]% unit upkeep costs", "Upon capturing a city, receive [10] times its [Culture] production as [Culture] immediately"],
"policies": [ "policies": [
{ {
"name": "Populism", "name": "Populism",
@ -403,13 +403,13 @@
}, },
{ {
"name": "Militarism", "name": "Militarism",
"uniques": ["Gold cost of purchasing units -33%"], "uniques": ["Gold cost of purchasing [All] units -[33]%"],
"row": 1, "row": 1,
"column": 5 "column": 5
}, },
{ {
"name": "Fascism", "name": "Fascism",
"uniques": ["Quantity of strategic resources produced by the empire increased by 100%"], "uniques": ["Quantity of strategic resources produced by the empire +[100]%", "+[2] Movement for all [Great General] units"],
"requires": ["Populism","Militarism"], "requires": ["Populism","Militarism"],
"row": 2, "row": 2,
"column": 3 "column": 3
@ -417,20 +417,21 @@
{ {
"name": "Police State", "name": "Police State",
"uniques": ["[+3 Happiness] from every [Courthouse]", "+[100]% Production when constructing [Courthouse]"], "uniques": ["[+3 Happiness] from every [Courthouse]", "+[100]% Production when constructing [Courthouse]"],
// There are also some uniques regarding espoinage, which as of this writing is not yet implemented
"requires": ["Militarism"], "requires": ["Militarism"],
"row": 2, "row": 2,
"column": 5 "column": 5
}, },
{ {
"name": "Total War", "name": "Total War",
"uniques": ["+[15]% Production when constructing [Military] units [in all cities]", "New [Military] units start with [15] Experience"], "uniques": ["+[25]% Production when constructing [Military] units [in all cities]", "New [Military] units start with [15] Experience"],
"requires": ["Police State","Fascism"], "requires": ["Police State","Fascism"],
"row": 3, "row": 3,
"column": 4 "column": 4
}, },
{ {
"name": "Autocracy Complete", "name": "Autocracy Complete",
"uniques": ["+20% attack bonus to all Military Units for 30 turns"] "uniques": ["+[25]% attack strength to all [Military] units for [50] turns"]
} }
] ]
} }

View File

@ -10,6 +10,7 @@ import com.unciv.logic.map.TileInfo
import com.unciv.models.AttackableTile import com.unciv.models.AttackableTile
import com.unciv.models.ruleset.Unique import com.unciv.models.ruleset.Unique
import com.unciv.models.ruleset.unit.UnitType import com.unciv.models.ruleset.unit.UnitType
import com.unciv.models.stats.Stat
import java.util.* import java.util.*
import kotlin.math.max import kotlin.math.max
@ -317,6 +318,13 @@ object Battle {
return return
} }
for (unique in attackerCiv.getMatchingUniques("Upon capturing a city, receive [] times its [] production as [] immediately")) {
attackerCiv.addStat(
Stat.valueOf(unique.params[2]),
unique.params[0].toInt() * city.cityStats.currentCityStats.get(Stat.valueOf(unique.params[1])).toInt()
)
}
if (attackerCiv.isPlayerCivilization()) { if (attackerCiv.isPlayerCivilization()) {
attackerCiv.popupAlerts.add(PopupAlert(AlertType.CityConquered, city.id)) attackerCiv.popupAlerts.add(PopupAlert(AlertType.CityConquered, city.id))
UncivGame.Current.settings.addCompletedTutorialTask("Conquer a city") UncivGame.Current.settings.addCompletedTutorialTask("Conquer a city")

View File

@ -147,8 +147,11 @@ object BattleDamage {
} }
} }
if (attacker.getCivInfo().policies.autocracyCompletedTurns > 0) for (unique in attacker.getCivInfo().getMatchingUniques("+[]% attack strength to all [] units for [] turns")) {
modifiers["Autocracy Complete"] = 20 if (attacker.matchesCategory(unique.params[1])) {
modifiers.add("Temporary Bonus", unique.params[0].toInt())
}
}
if (defender is CityCombatant && if (defender is CityCombatant &&
attacker.getCivInfo() attacker.getCivInfo()

View File

@ -34,7 +34,7 @@ class CivInfoStats(val civInfo: CivilizationInfo) {
for (unique in civInfo.getMatchingUniques("-[]% [] unit maintenance costs")) { for (unique in civInfo.getMatchingUniques("-[]% [] unit maintenance costs")) {
val numberOfUnitsWithDiscount = min(numberOfUnitsToPayFor, unitsToPayFor.count { it.matchesFilter(unique.params[1]) }.toFloat()) val numberOfUnitsWithDiscount = min(numberOfUnitsToPayFor, unitsToPayFor.count { it.matchesFilter(unique.params[1]) }.toFloat())
numberOfUnitsToPayFor -= numberOfUnitsWithDiscount * unique.params[0].toFloat() / 100 numberOfUnitsToPayFor -= numberOfUnitsWithDiscount * unique.params[0].toFloat() / 100f
} }
val turnLimit = BASE_GAME_DURATION_TURNS * civInfo.gameInfo.gameParameters.gameSpeed.modifier val turnLimit = BASE_GAME_DURATION_TURNS * civInfo.gameInfo.gameParameters.gameSpeed.modifier
@ -43,11 +43,11 @@ class CivInfoStats(val civInfo: CivilizationInfo) {
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 (!civInfo.isPlayerCivilization()) if (!civInfo.isPlayerCivilization())
cost *= civInfo.gameInfo.getDifficulty().aiUnitMaintenanceModifier cost *= civInfo.gameInfo.getDifficulty().aiUnitMaintenanceModifier
for (unique in civInfo.getMatchingUniques("-[]% unit upkeep costs")) { for (unique in civInfo.getMatchingUniques("-[]% unit upkeep costs")) {
cost *= 1f - unique.params[0].toFloat() / 100f cost *= 1f - unique.params[0].toFloat() / 100f
} }
// Deprecated since 3.15 // Deprecated since 3.15
if (civInfo.hasUnique("-33% unit upkeep costs")) cost *= 0.67f if (civInfo.hasUnique("-33% unit upkeep costs")) cost *= 0.67f
// //

View File

@ -19,6 +19,7 @@ import com.unciv.models.ruleset.tile.ResourceSupplyList
import com.unciv.models.ruleset.tile.ResourceType import com.unciv.models.ruleset.tile.ResourceType
import com.unciv.models.ruleset.tile.TileResource import com.unciv.models.ruleset.tile.TileResource
import com.unciv.models.ruleset.unit.BaseUnit import com.unciv.models.ruleset.unit.BaseUnit
import com.unciv.models.stats.Stat
import com.unciv.models.stats.Stats import com.unciv.models.stats.Stats
import com.unciv.models.translations.tr import com.unciv.models.translations.tr
import com.unciv.ui.victoryscreen.RankingType import com.unciv.ui.victoryscreen.RankingType
@ -92,6 +93,11 @@ class CivilizationInfo {
/** See DiplomacyManager.flagsCountdown to why not eEnum */ /** See DiplomacyManager.flagsCountdown to why not eEnum */
private var flagsCountdown = HashMap<String, Int>() private var flagsCountdown = HashMap<String, Int>()
/** Arraylist instead of HashMap as there might be doubles
* Pairs of Uniques and the amount of turns they are still active
* If the counter reaches 0 at the end of a turn, it is removed immediately
*/
var temporaryUniques = ArrayList<Pair<Unique, Int>>()
// if we only use lists, and change the list each time the cities are changed, // if we only use lists, and change the list each time the cities are changed,
// we won't get concurrent modification exceptions. // we won't get concurrent modification exceptions.
@ -135,6 +141,7 @@ class CivilizationInfo {
toReturn.naturalWonders.addAll(naturalWonders) toReturn.naturalWonders.addAll(naturalWonders)
toReturn.cityStatePersonality = cityStatePersonality toReturn.cityStatePersonality = cityStatePersonality
toReturn.flagsCountdown.putAll(flagsCountdown) toReturn.flagsCountdown.putAll(flagsCountdown)
toReturn.temporaryUniques.addAll(temporaryUniques)
return toReturn return toReturn
} }
@ -213,15 +220,21 @@ class CivilizationInfo {
} }
fun getResourceModifier(resource: TileResource): Int { fun getResourceModifier(resource: TileResource): Int {
var resourceModifier = 1 var resourceModifier = 1f
for (unique in getMatchingUniques("Double quantity of [] produced")) for (unique in getMatchingUniques("Double quantity of [] produced"))
if (unique.params[0] == resource.name) if (unique.params[0] == resource.name)
resourceModifier *= 2 resourceModifier *= 2f
if (resource.resourceType == ResourceType.Strategic) { if (resource.resourceType == ResourceType.Strategic) {
if (hasUnique("Quantity of strategic resources produced by the empire increased by 100%")) resourceModifier *= 1f + getMatchingUniques("Quantity of strategic resources produced by the empire +[]%")
resourceModifier *= 2 .map { it.params[0].toFloat() / 100f }.sum()
// Deprecated since 3.15
if (hasUnique("Quantity of strategic resources produced by the empire increased by 100%")) {
resourceModifier *= 2f
}
//
} }
return resourceModifier return resourceModifier.toInt()
} }
fun hasResource(resourceName: String): Boolean = getCivResourcesByName()[resourceName]!! > 0 fun hasResource(resourceName: String): Boolean = getCivResourcesByName()[resourceName]!! > 0
@ -242,7 +255,8 @@ class CivilizationInfo {
} + } +
policies.policyUniques.getUniques(uniqueTemplate) + policies.policyUniques.getUniques(uniqueTemplate) +
tech.getTechUniques().filter { it.placeholderText == uniqueTemplate } + tech.getTechUniques().filter { it.placeholderText == uniqueTemplate } +
religionManager.getUniques().filter { it.placeholderText == uniqueTemplate } religionManager.getUniques().filter { it.placeholderText == uniqueTemplate } +
temporaryUniques.filter { it.first.placeholderText == uniqueTemplate }.map { it.first }
} }
//region Units //region Units
@ -547,6 +561,12 @@ class CivilizationInfo {
for (city in cities.toList()) { // a city can be removed while iterating (if it's being razed) so we need to iterate over a copy for (city in cities.toList()) { // a city can be removed while iterating (if it's being razed) so we need to iterate over a copy
city.endTurn() city.endTurn()
} }
// Update turn counter for temporary uniques
for (unique in temporaryUniques.toList()) {
temporaryUniques.remove(unique)
if (unique.second > 1) temporaryUniques.add(Pair(unique.first, unique.second - 1))
}
goldenAges.endTurn(getHappiness()) goldenAges.endTurn(getHappiness())
getCivUnits().forEach { it.endTurn() } getCivUnits().forEach { it.endTurn() }
@ -566,6 +586,18 @@ class CivilizationInfo {
else -> gold + delta else -> gold + delta
} }
} }
fun addStat(stat: Stat, amount: Int) {
when (stat) {
Stat.Culture -> policies.addCulture(amount)
Stat.Science -> tech.addScience(amount)
Stat.Gold -> addGold(amount)
Stat.Faith -> religionManager.storedFaith += amount
else -> {}
// Food and Production wouldn't make sense to be added nationwide
// Happiness cannot be added as it is recalculated again, use a unique instead
}
}
fun getGreatPersonPointsForNextTurn(): Stats { fun getGreatPersonPointsForNextTurn(): Stats {
val stats = Stats() val stats = Stats()

View File

@ -27,11 +27,13 @@ class PolicyManager {
private var cultureBuildingsAdded = HashMap<String, String>() // Maps cities to buildings private var cultureBuildingsAdded = HashMap<String, String>() // Maps cities to buildings
private var specificBuildingsAdded = HashMap<String, MutableSet<String>>() // Maps buildings to cities private var specificBuildingsAdded = HashMap<String, MutableSet<String>>() // Maps buildings to cities
@Deprecated("Deprecated since 3.15")
var autocracyCompletedTurns = 0 var autocracyCompletedTurns = 0
@Deprecated("Deprecated since 3.14.17") // Replaced with cultureBuildingsAdded @Deprecated("Deprecated since 3.14.17") // Replaced with cultureBuildingsAdded
var legalismState = HashMap<String, String>() // Maps cities to buildings 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()
@ -42,11 +44,11 @@ class PolicyManager {
toReturn.storedCulture = storedCulture toReturn.storedCulture = storedCulture
toReturn.cultureBuildingsAdded.putAll(cultureBuildingsAdded) toReturn.cultureBuildingsAdded.putAll(cultureBuildingsAdded)
toReturn.specificBuildingsAdded.putAll(specificBuildingsAdded) toReturn.specificBuildingsAdded.putAll(specificBuildingsAdded)
toReturn.autocracyCompletedTurns = autocracyCompletedTurns
// Deprecated since 3.15 left for backwards compatibility
// Deprecated since 3.14.17, left for backwards compatibility toReturn.legalismState.putAll(cultureBuildingsAdded)
toReturn.legalismState.putAll(cultureBuildingsAdded) toReturn.autocracyCompletedTurns = autocracyCompletedTurns
//
return toReturn return toReturn
} }
@ -89,8 +91,6 @@ class PolicyManager {
fun endTurn(culture: Int) { fun endTurn(culture: Int) {
addCulture(culture) addCulture(culture)
if (autocracyCompletedTurns > 0)
autocracyCompletedTurns -= 1
} }
// from https://forums.civfanatics.com/threads/the-number-crunching-thread.389702/ // from https://forums.civfanatics.com/threads/the-number-crunching-thread.389702/
@ -166,7 +166,7 @@ class PolicyManager {
if (!canAdoptPolicy()) shouldOpenPolicyPicker = false if (!canAdoptPolicy()) shouldOpenPolicyPicker = false
} }
fun tryToAddPolicyBuildings() { fun tryToAddPolicyBuildings() {
tryAddCultureBuildings() tryAddCultureBuildings()
tryAddFreeBuildings() tryAddFreeBuildings()
@ -188,10 +188,10 @@ class PolicyManager {
for (city in candidateCities) { for (city in candidateCities) {
val builtBuilding = city.cityConstructions.addCultureBuilding() val builtBuilding = city.cityConstructions.addCultureBuilding()
if (builtBuilding != null) cultureBuildingsAdded[city.id] = builtBuilding!! if (builtBuilding != null) cultureBuildingsAdded[city.id] = builtBuilding!!
} }
} }
private fun tryAddFreeBuildings() { private fun tryAddFreeBuildings() {
val matchingUniques = civInfo.getMatchingUniques("Immediately creates a [] in each of your first [] cities for free") 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" // 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"
@ -200,7 +200,7 @@ class PolicyManager {
tryAddSpecificBuilding(unique.key, unique.value.sumBy {it.params[1].toInt()}) tryAddSpecificBuilding(unique.key, unique.value.sumBy {it.params[1].toInt()})
} }
} }
private fun tryAddSpecificBuilding(building: String, cityCount: Int) { private fun tryAddSpecificBuilding(building: String, cityCount: Int) {
if (specificBuildingsAdded[building] == null) specificBuildingsAdded[building] = mutableSetOf() if (specificBuildingsAdded[building] == null) specificBuildingsAdded[building] = mutableSetOf()
val citiesAlreadyGivenBuilding = specificBuildingsAdded[building] val citiesAlreadyGivenBuilding = specificBuildingsAdded[building]
@ -211,13 +211,13 @@ class PolicyManager {
.filter { .filter {
it.id !in citiesAlreadyGivenBuilding && !it.cityConstructions.containsBuildingOrEquivalent(building) it.id !in citiesAlreadyGivenBuilding && !it.cityConstructions.containsBuildingOrEquivalent(building)
} }
for (city in candidateCities) { for (city in candidateCities) {
city.cityConstructions.getConstruction(building).postBuildEvent(city.cityConstructions, false) city.cityConstructions.getConstruction(building).postBuildEvent(city.cityConstructions, false)
citiesAlreadyGivenBuilding.add(city.id) citiesAlreadyGivenBuilding.add(city.id)
} }
} }
fun getListOfFreeBuildings(cityId: String): MutableSet<String> { fun getListOfFreeBuildings(cityId: String): MutableSet<String> {
val freeBuildings = cultureBuildingsAdded.filter { it.key == cityId }.values.toMutableSet() val freeBuildings = cultureBuildingsAdded.filter { it.key == cityId }.values.toMutableSet()
for (building in specificBuildingsAdded.filter { it.value.contains(cityId) }) { for (building in specificBuildingsAdded.filter { it.value.contains(cityId) }) {
@ -225,4 +225,4 @@ class PolicyManager {
} }
return freeBuildings return freeBuildings
} }
} }

View File

@ -329,7 +329,7 @@ class MapUnit {
val unitToUpgradeTo = getUnitToUpgradeTo() val unitToUpgradeTo = getUnitToUpgradeTo()
var goldCostOfUpgrade = (unitToUpgradeTo.cost - baseUnit().cost) * 2f + 10f var goldCostOfUpgrade = (unitToUpgradeTo.cost - baseUnit().cost) * 2f + 10f
for (unique in civInfo.getMatchingUniques("Gold cost of upgrading [] units reduced by []%")) { for (unique in civInfo.getMatchingUniques("Gold cost of upgrading [] units reduced by []%")) {
if (matchesFilter(unique.params[0])) if (matchesFilter(unique.params[0]))
goldCostOfUpgrade *= (1 - unique.params[1].toFloat() / 100f) goldCostOfUpgrade *= (1 - unique.params[1].toFloat() / 100f)
} }
// Deprecated since 3.14.17 // Deprecated since 3.14.17
@ -337,7 +337,7 @@ class MapUnit {
goldCostOfUpgrade *= 0.67f goldCostOfUpgrade *= 0.67f
} }
// //
if (goldCostOfUpgrade < 0) return 0 // For instance, Landsknecht costs less than Spearman, so upgrading would cost negative gold if (goldCostOfUpgrade < 0) return 0 // For instance, Landsknecht costs less than Spearman, so upgrading would cost negative gold
return goldCostOfUpgrade.toInt() return goldCostOfUpgrade.toInt()
} }

View File

@ -85,7 +85,10 @@ object UniqueTriggerActivation {
"[] Free Technologies" -> if (!civInfo.isSpectator()) civInfo.tech.freeTechs += unique.params[0].toInt() "[] Free Technologies" -> if (!civInfo.isSpectator()) civInfo.tech.freeTechs += unique.params[0].toInt()
"Quantity of strategic resources produced by the empire increased by 100%" -> civInfo.updateDetailedCivResources() "Quantity of strategic resources produced by the empire increased by 100%" -> civInfo.updateDetailedCivResources()
"+20% attack bonus to all Military Units for 30 turns" -> civInfo.policies.autocracyCompletedTurns = 30 // Deprecated since 3.15
"+20% attack bonus to all Military Units for 30 turns" -> civInfo.temporaryUniques.add(Pair(unique, 30))
//
"+[]% attack strength to all [] Units for [] turns" -> civInfo.temporaryUniques.add(Pair(unique, unique.params[2].toInt()))
"Reveals the entire map" -> civInfo.exploredTiles.addAll(civInfo.gameInfo.tileMap.values.asSequence().map { it.position }) "Reveals the entire map" -> civInfo.exploredTiles.addAll(civInfo.gameInfo.tileMap.values.asSequence().map { it.position })
@ -94,12 +97,13 @@ object UniqueTriggerActivation {
val promotion = unique.params[1] val promotion = unique.params[1]
for (unit in civInfo.getCivUnits()) for (unit in civInfo.getCivUnits())
if (unit.matchesFilter(filter) if (unit.matchesFilter(filter)
|| civInfo.gameInfo.ruleSet.unitPromotions.values.any { || civInfo.gameInfo.ruleSet.unitPromotions.values.any {
it.name == promotion && unit.type.name in it.unitTypes it.name == promotion && unit.type.name in it.unitTypes
}) }
) {
unit.promotions.addPromotion(promotion, isFree = true) unit.promotions.addPromotion(promotion, isFree = true)
}
} }
} }
} }
} }

View File

@ -112,10 +112,18 @@ class BaseUnit : INamed, IConstruction {
override fun getGoldCost(civInfo: CivilizationInfo): Int { override fun getGoldCost(civInfo: CivilizationInfo): Int {
var cost = getBaseGoldCost(civInfo) var cost = getBaseGoldCost(civInfo)
if (civInfo.hasUnique("Gold cost of purchasing units -33%")) cost *= 0.66f for (unique in civInfo.getMatchingUniques("Gold cost of purchasing [] units -[]%")) {
if (matchesFilter(unique.params[0]))
cost *= 1f - unique.params[1].toFloat() / 100f
}
// Deprecated since 3.15
if (civInfo.hasUnique("Gold cost of purchasing units -33%")) cost *= 0.67f
//
for (unique in civInfo.getMatchingUniques("Cost of purchasing items in cities reduced by []%")) for (unique in civInfo.getMatchingUniques("Cost of purchasing items in cities reduced by []%"))
cost *= 1 - (unique.params[0].toFloat() / 100) cost *= 1f - (unique.params[0].toFloat() / 100f)
return (cost / 10).toInt() * 10 // rounded down o nearest ten return (cost / 10).toInt() * 10 // rounded down to nearest ten
} }
fun getDisbandGold(civInfo: CivilizationInfo) = getBaseGoldCost(civInfo).toInt() / 20 fun getDisbandGold(civInfo: CivilizationInfo) = getBaseGoldCost(civInfo).toInt() / 20