mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-14 09:48:12 +07:00
Finishing the later five policy trees now allows you to buy great people with faith (#5038)
This commit is contained in:
@ -275,7 +275,9 @@
|
||||
},
|
||||
{
|
||||
"name": "Commerce Complete",
|
||||
"uniques": ["[+1 Gold] from every [Trading post]", "Double gold from Great Merchant trade missions"]
|
||||
"uniques": ["[+1 Gold] from every [Trading post]", "Double gold from Great Merchant trade missions",
|
||||
"May buy [Great Merchant] units for [1000] [Faith] [in all cities in which the majority religion is a major religion] starting from the [Industrial era] at an increasing price ([500])"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -320,7 +322,9 @@
|
||||
},
|
||||
{
|
||||
"name": "Rationalism Complete",
|
||||
"uniques": ["[2] Free Technologies"]
|
||||
"uniques": ["[2] Free Technologies",
|
||||
"May buy [Great Scientist] units for [1000] [Faith] [in all cities in which the majority religion is a major religion] starting from the [Industrial era] at an increasing price ([500])"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -363,7 +367,9 @@
|
||||
},
|
||||
{
|
||||
"name": "Freedom Complete",
|
||||
"uniques": ["+[100]% yield from every [Great Improvement]", "Golden Age length increased by [50]%"]
|
||||
"uniques": ["+[100]% yield from every [Great Improvement]", "Golden Age length increased by [50]%",
|
||||
"May buy [Great Artist] units for [1000] [Faith] [in all cities in which the majority religion is a major religion] starting from the [Industrial era] at an increasing price ([500])"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -409,7 +415,10 @@
|
||||
},
|
||||
{
|
||||
"name": "Autocracy Complete",
|
||||
"uniques": ["+[25]% attack strength to all [Military] units for [50] turns"]
|
||||
"uniques": ["+[25]% attack strength to all [Military] units for [50] turns",
|
||||
"May buy [Great General] units for [1000] [Faith] [in all cities in which the majority religion is a major religion] starting from the [Industrial era] at an increasing price ([500])",
|
||||
"May buy [Great Admiral] units for [1000] [Faith] [in all cities in which the majority religion is a major religion] starting from the [Industrial era] at an increasing price ([500])"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -452,7 +461,9 @@
|
||||
},
|
||||
{
|
||||
"name": "Order Complete",
|
||||
"uniques": ["[+2 Food, +2 Production, +2 Science, +2 Gold, +2 Culture] [in all cities]"]
|
||||
"uniques": ["[+2 Food, +2 Production, +2 Science, +2 Gold, +2 Culture] [in all cities]",
|
||||
"May buy [Great Engineer] units for [1000] [Faith] [in all cities in which the majority religion is a major religion] starting from the [Industrial era] at an increasing price ([500])"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -328,16 +328,12 @@ object NextTurnAutomation {
|
||||
}
|
||||
|
||||
private fun foundReligion(civInfo: CivilizationInfo) {
|
||||
println("Founding check?")
|
||||
if (civInfo.religionManager.religionState != ReligionState.FoundingReligion) return
|
||||
println("Founding check!!")
|
||||
val religionIcon = civInfo.gameInfo.ruleSet.religions
|
||||
.filterNot { civInfo.gameInfo.religions.values.map { religion -> religion.iconName }.contains(it) }
|
||||
.randomOrNull()
|
||||
?: return // Wait what? How did we pass the checking when using a great prophet but not this?
|
||||
println("Icon has been chosen")
|
||||
val chosenBeliefs = chooseBeliefs(civInfo, civInfo.religionManager.getBeliefsToChooseAtFounding()).toList()
|
||||
println("Beliefs have been chosen")
|
||||
civInfo.religionManager.chooseBeliefs(religionIcon, religionIcon, chosenBeliefs)
|
||||
}
|
||||
|
||||
|
@ -251,8 +251,8 @@ class CityConstructions {
|
||||
isBuilt(building) || getBuiltBuildings().any { it.replaces == building }
|
||||
|
||||
fun getWorkDone(constructionName: String): Int {
|
||||
if (inProgressConstructions.containsKey(constructionName)) return inProgressConstructions[constructionName]!!
|
||||
else return 0
|
||||
return if (inProgressConstructions.containsKey(constructionName)) inProgressConstructions[constructionName]!!
|
||||
else 0
|
||||
}
|
||||
|
||||
fun getRemainingWork(constructionName: String, useStoredProduction: Boolean = true): Int {
|
||||
@ -425,7 +425,7 @@ class CityConstructions {
|
||||
}
|
||||
}
|
||||
|
||||
private fun constructionComplete(construction: IConstruction) {
|
||||
private fun constructionComplete(construction: INonPerpetualConstruction) {
|
||||
construction.postBuildEvent(this)
|
||||
if (construction.name in inProgressConstructions)
|
||||
inProgressConstructions.remove(construction.name)
|
||||
@ -501,7 +501,7 @@ class CityConstructions {
|
||||
automatic: Boolean,
|
||||
stat: Stat = Stat.Gold
|
||||
): Boolean {
|
||||
if (!getConstruction(constructionName).postBuildEvent(this, true))
|
||||
if (!(getConstruction(constructionName) as INonPerpetualConstruction).postBuildEvent(this, stat))
|
||||
return false // nothing built - no pay
|
||||
|
||||
if (!cityInfo.civInfo.gameInfo.gameParameters.godMode) {
|
||||
@ -535,7 +535,7 @@ class CityConstructions {
|
||||
return null
|
||||
|
||||
val cultureBuildingToBuild = buildableCultureBuildings.minByOrNull { it.cost }!!.name
|
||||
constructionComplete(getConstruction(cultureBuildingToBuild))
|
||||
constructionComplete(getConstruction(cultureBuildingToBuild) as INonPerpetualConstruction)
|
||||
|
||||
return cultureBuildingToBuild
|
||||
}
|
||||
|
@ -13,7 +13,6 @@ import kotlin.math.roundToInt
|
||||
interface IConstruction : INamed {
|
||||
fun isBuildable(cityConstructions: CityConstructions): Boolean
|
||||
fun shouldBeDisplayed(cityConstructions: CityConstructions): Boolean
|
||||
fun postBuildEvent(cityConstructions: CityConstructions, wasBought: Boolean = false): Boolean // Yes I'm hilarious.
|
||||
fun getResourceRequirements(): HashMap<String,Int>
|
||||
}
|
||||
|
||||
@ -23,6 +22,7 @@ interface INonPerpetualConstruction : IConstruction, INamed, IHasUniques {
|
||||
fun getProductionCost(civInfo: CivilizationInfo): Int
|
||||
fun getStatBuyCost(cityInfo: CityInfo, stat: Stat): Int?
|
||||
fun getRejectionReason(cityConstructions: CityConstructions): String
|
||||
fun postBuildEvent(cityConstructions: CityConstructions, boughtWith: Stat? = null): Boolean // Yes I'm hilarious.
|
||||
|
||||
fun getMatchingUniques(uniqueTemplate: String): Sequence<Unique> {
|
||||
return uniqueObjects.asSequence().filter { it.placeholderText == uniqueTemplate }
|
||||
@ -118,9 +118,6 @@ open class PerpetualConstruction(override var name: String, val description: Str
|
||||
override fun isBuildable(cityConstructions: CityConstructions): Boolean =
|
||||
throw Exception("Impossible!")
|
||||
|
||||
override fun postBuildEvent(cityConstructions: CityConstructions, wasBought: Boolean) =
|
||||
throw Exception("Impossible!")
|
||||
|
||||
override fun getResourceRequirements(): HashMap<String, Int> = hashMapOf()
|
||||
|
||||
}
|
@ -122,7 +122,10 @@ class CivilizationInfo {
|
||||
* 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>>()
|
||||
val temporaryUniques = ArrayList<Pair<Unique, Int>>()
|
||||
|
||||
/** Maps the name of the construction to the amount of times bouhgt */
|
||||
val boughtConstructionsWithGloballyIncreasingPrice = HashMap<String, Int>()
|
||||
|
||||
// if we only use lists, and change the list each time the cities are changed,
|
||||
// we won't get concurrent modification exceptions.
|
||||
@ -174,6 +177,7 @@ class CivilizationInfo {
|
||||
toReturn.cityStateResource = cityStateResource
|
||||
toReturn.flagsCountdown.putAll(flagsCountdown)
|
||||
toReturn.temporaryUniques.addAll(temporaryUniques)
|
||||
toReturn.boughtConstructionsWithGloballyIncreasingPrice.putAll(boughtConstructionsWithGloballyIncreasingPrice)
|
||||
toReturn.hasEverOwnedOriginalCapital = hasEverOwnedOriginalCapital
|
||||
return toReturn
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.unciv.logic.civilization
|
||||
|
||||
import com.unciv.logic.city.INonPerpetualConstruction
|
||||
import com.unciv.logic.map.MapSize
|
||||
import com.unciv.models.ruleset.Policy
|
||||
import com.unciv.models.ruleset.Policy.PolicyBranchType
|
||||
@ -214,7 +215,7 @@ class PolicyManager {
|
||||
}
|
||||
|
||||
for (city in candidateCities) {
|
||||
city.cityConstructions.getConstruction(building).postBuildEvent(city.cityConstructions, false)
|
||||
(city.cityConstructions.getConstruction(building) as INonPerpetualConstruction).postBuildEvent(city.cityConstructions)
|
||||
citiesAlreadyGivenBuilding.add(city.id)
|
||||
}
|
||||
}
|
||||
|
@ -205,38 +205,6 @@ class Building : NamedStats(), INonPerpetualConstruction, ICivilopediaText {
|
||||
return stats
|
||||
}
|
||||
|
||||
override fun canBePurchasedWithStat(cityInfo: CityInfo, stat: Stat, ignoreCityRequirements: Boolean): Boolean {
|
||||
if (stat == Stat.Gold && isAnyWonder()) return false
|
||||
// May buy [buildingFilter] buildings for [amount] [Stat] [cityFilter]
|
||||
if (!ignoreCityRequirements && cityInfo.getMatchingUniques("May buy [] buildings for [] [] []")
|
||||
.any { it.params[2] == stat.name && matchesFilter(it.params[0]) && cityInfo.matchesFilter(it.params[3]) }
|
||||
) return true
|
||||
return super.canBePurchasedWithStat(cityInfo, stat, ignoreCityRequirements)
|
||||
}
|
||||
|
||||
override fun getBaseBuyCost(cityInfo: CityInfo, stat: Stat): Int? {
|
||||
if (stat == Stat.Gold) return getBaseGoldCost(cityInfo.civInfo).toInt()
|
||||
|
||||
val lowestCostFromUnique =
|
||||
(
|
||||
// Can be purchased for [amount] [Stat] [cityFilter]
|
||||
getMatchingUniques("Can be purchased for [] [] []")
|
||||
.filter { it.params[1] == stat.name && cityInfo.matchesFilter(it.params[2]) }
|
||||
.map { it.params[0].toInt() }
|
||||
// May buy [buildingFilter] buildings for [amount] [Stat] [cityFilter]
|
||||
+ cityInfo.getMatchingUniques("May buy [] buildings for [] [] []")
|
||||
.filter { it.params[2] == stat.name && matchesFilter(it.params[0]) && cityInfo.matchesFilter(it.params[3])}
|
||||
.map { it.params[1].toInt() }
|
||||
).minOrNull()
|
||||
if (lowestCostFromUnique != null) return lowestCostFromUnique
|
||||
|
||||
// Can be purchased with [Stat] [cityFilter]
|
||||
if (getMatchingUniques("Can be purchased with [] []")
|
||||
.any { it.params[0] == stat.name && cityInfo.matchesFilter(it.params[1])}
|
||||
) return cityInfo.civInfo.gameInfo.ruleSet.eras[cityInfo.civInfo.getEra()]!!.baseUnitBuyCost
|
||||
return null
|
||||
}
|
||||
|
||||
override fun getCivilopediaTextHeader() = FormattedLine(name, header=2, icon=makeLink())
|
||||
override fun makeLink() = if (isAnyWonder()) "Wonder/$name" else "Building/$name"
|
||||
override fun hasCivilopediaTextLines() = true
|
||||
@ -385,6 +353,32 @@ class Building : NamedStats(), INonPerpetualConstruction, ICivilopediaText {
|
||||
return productionCost.toInt()
|
||||
}
|
||||
|
||||
|
||||
override fun canBePurchasedWithStat(cityInfo: CityInfo, stat: Stat, ignoreCityRequirements: Boolean): Boolean {
|
||||
if (stat == Stat.Gold && isAnyWonder()) return false
|
||||
// May buy [buildingFilter] buildings for [amount] [Stat] [cityFilter]
|
||||
if (!ignoreCityRequirements && cityInfo.getMatchingUniques("May buy [] buildings for [] [] []")
|
||||
.any { it.params[2] == stat.name && matchesFilter(it.params[0]) && cityInfo.matchesFilter(it.params[3]) }
|
||||
) return true
|
||||
return super.canBePurchasedWithStat(cityInfo, stat, ignoreCityRequirements)
|
||||
}
|
||||
|
||||
override fun getBaseBuyCost(cityInfo: CityInfo, stat: Stat): Int? {
|
||||
if (stat == Stat.Gold) return getBaseGoldCost(cityInfo.civInfo).toInt()
|
||||
|
||||
return (
|
||||
sequenceOf(super.getBaseBuyCost(cityInfo, stat)).filterNotNull()
|
||||
// May buy [buildingFilter] buildings for [amount] [Stat] [cityFilter]
|
||||
+ cityInfo.getMatchingUniques("May buy [] buildings for [] [] []")
|
||||
.filter {
|
||||
it.params[2] == stat.name && matchesFilter(it.params[0]) && cityInfo.matchesFilter(
|
||||
it.params[3]
|
||||
)
|
||||
}
|
||||
.map { it.params[1].toInt() }
|
||||
).minOrNull()
|
||||
}
|
||||
|
||||
override fun getStatBuyCost(cityInfo: CityInfo, stat: Stat): Int? {
|
||||
var cost = getBaseBuyCost(cityInfo, stat)?.toDouble()
|
||||
if (cost == null) return null
|
||||
@ -603,7 +597,7 @@ class Building : NamedStats(), INonPerpetualConstruction, ICivilopediaText {
|
||||
override fun isBuildable(cityConstructions: CityConstructions): Boolean =
|
||||
getRejectionReason(cityConstructions) == ""
|
||||
|
||||
override fun postBuildEvent(cityConstructions: CityConstructions, wasBought: Boolean): Boolean {
|
||||
override fun postBuildEvent(cityConstructions: CityConstructions, boughtWith: Stat?): Boolean {
|
||||
val civInfo = cityConstructions.cityInfo.civInfo
|
||||
|
||||
if ("Spaceship part" in uniques) {
|
||||
@ -627,7 +621,7 @@ class Building : NamedStats(), INonPerpetualConstruction, ICivilopediaText {
|
||||
var freeBuildingUniques = uniqueObjects.asSequence().filter { it.placeholderText=="Provides a free [] []" }
|
||||
if (providesFreeBuilding!=null) freeBuildingUniques += sequenceOf(Unique("Provides a free [$providesFreeBuilding] [in this city]"))
|
||||
|
||||
for(unique in freeBuildingUniques) {
|
||||
for (unique in freeBuildingUniques) {
|
||||
val affectedCities =
|
||||
if (unique.params[1] == "in this city") sequenceOf(cityConstructions.cityInfo)
|
||||
else civInfo.cities.asSequence().filter { it.matchesFilter(unique.params[1]) }
|
||||
|
@ -15,6 +15,7 @@ import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.civilopedia.FormattedLine
|
||||
import com.unciv.ui.civilopedia.ICivilopediaText
|
||||
import com.unciv.ui.utils.Fonts
|
||||
import com.unciv.ui.utils.toPercent
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.collections.HashMap
|
||||
@ -212,6 +213,49 @@ class BaseUnit : INamed, INonPerpetualConstruction, ICivilopediaText {
|
||||
return productionCost.toInt()
|
||||
}
|
||||
|
||||
override fun canBePurchasedWithStat(
|
||||
cityInfo: CityInfo,
|
||||
stat: Stat,
|
||||
ignoreCityRequirements: Boolean
|
||||
): Boolean {
|
||||
// May buy [unitFilter] units for [amount] [Stat] starting from the [eraName] at an increasing price ([amount])
|
||||
if (cityInfo.civInfo.getMatchingUniques("May buy [] units for [] [] [] starting from the [] at an increasing price ([])")
|
||||
.any {
|
||||
matchesFilter(it.params[0])
|
||||
&& cityInfo.matchesFilter(it.params[3])
|
||||
&& cityInfo.civInfo.getEraNumber() >= ruleset.getEraNumber(it.params[4])
|
||||
&& it.params[2] == stat.name
|
||||
}
|
||||
) return true
|
||||
|
||||
return super.canBePurchasedWithStat(cityInfo, stat, ignoreCityRequirements)
|
||||
}
|
||||
|
||||
private fun getCostForConstructionsIncreasingInPrice(baseCost: Int, increaseCost: Int, previouslyBought: Int): Int {
|
||||
return (baseCost + increaseCost / 2f * ( previouslyBought * previouslyBought + previouslyBought )).toInt()
|
||||
}
|
||||
|
||||
override fun getBaseBuyCost(cityInfo: CityInfo, stat: Stat): Int? {
|
||||
if (stat == Stat.Gold) return getBaseGoldCost(cityInfo.civInfo).toInt()
|
||||
return (
|
||||
sequenceOf(super.getBaseBuyCost(cityInfo, stat)).filterNotNull()
|
||||
// May buy [unitFilter] units for [amount] [Stat] starting from the [eraName] at an increasing price ([amount])
|
||||
+ cityInfo.civInfo.getMatchingUniques("May buy [] units for [] [] [] starting from the [] at an increasing price ([])")
|
||||
.filter {
|
||||
matchesFilter(it.params[0])
|
||||
&& cityInfo.matchesFilter(it.params[3])
|
||||
&& cityInfo.civInfo.getEraNumber() >= ruleset.getEraNumber(it.params[4])
|
||||
&& it.params[2] == stat.name
|
||||
}.map {
|
||||
getCostForConstructionsIncreasingInPrice(
|
||||
it.params[1].toInt(),
|
||||
it.params[5].toInt(),
|
||||
cityInfo.civInfo.boughtConstructionsWithGloballyIncreasingPrice[name] ?: 0
|
||||
)
|
||||
}
|
||||
).minOrNull()
|
||||
}
|
||||
|
||||
override fun getStatBuyCost(cityInfo: CityInfo, stat: Stat): Int? {
|
||||
var cost = getBaseBuyCost(cityInfo, stat)?.toDouble()
|
||||
if (cost == null) return null
|
||||
@ -226,11 +270,11 @@ class BaseUnit : INamed, INonPerpetualConstruction, ICivilopediaText {
|
||||
|
||||
for (unique in cityInfo.getMatchingUniques("[] cost of purchasing [] units []%")) {
|
||||
if (stat.name == unique.params[0] && matchesFilter(unique.params[1]))
|
||||
cost *= 1f + unique.params[2].toFloat() / 100f
|
||||
cost *= unique.params[2].toPercent()
|
||||
}
|
||||
for (unique in cityInfo.getMatchingUniques("[] cost of purchasing items in cities []%"))
|
||||
if (stat.name == unique.params[0])
|
||||
cost *= 1f + (unique.params[1].toFloat() / 100f)
|
||||
cost *= unique.params[1].toPercent()
|
||||
|
||||
return (cost / 10f).toInt() * 10
|
||||
}
|
||||
@ -316,13 +360,13 @@ class BaseUnit : INamed, INonPerpetualConstruction, ICivilopediaText {
|
||||
fun isBuildableIgnoringTechs(civInfo: CivilizationInfo) =
|
||||
getRejectionReason(civInfo, true) == ""
|
||||
|
||||
override fun postBuildEvent(cityConstructions: CityConstructions, wasBought: Boolean): Boolean {
|
||||
override fun postBuildEvent(cityConstructions: CityConstructions, boughtWith: Stat?): Boolean {
|
||||
val civInfo = cityConstructions.cityInfo.civInfo
|
||||
val unit = civInfo.placeUnitNearTile(cityConstructions.cityInfo.location, name)
|
||||
?: return false // couldn't place the unit, so there's actually no unit =(
|
||||
|
||||
//movement penalty
|
||||
if (wasBought && !civInfo.gameInfo.gameParameters.godMode && !unit.hasUnique("Can move immediately once bought"))
|
||||
if (boughtWith != null && !civInfo.gameInfo.gameParameters.godMode && !unit.hasUnique("Can move immediately once bought"))
|
||||
unit.currentMovement = 0f
|
||||
|
||||
// If this unit has special abilities that need to be kept track of, start doing so here
|
||||
@ -331,6 +375,18 @@ class BaseUnit : INamed, INonPerpetualConstruction, ICivilopediaText {
|
||||
unit.setupAbilityUses(cityConstructions.cityInfo)
|
||||
}
|
||||
|
||||
if (boughtWith != null && cityConstructions.cityInfo.civInfo.getMatchingUniques("May buy [] units for [] [] [] starting from the [] at an increasing price ([])")
|
||||
.filter {
|
||||
matchesFilter(it.params[0])
|
||||
&& cityConstructions.cityInfo.matchesFilter(it.params[3])
|
||||
&& cityConstructions.cityInfo.civInfo.getEraNumber() >= ruleset.getEraNumber(it.params[4])
|
||||
&& it.params[2] == boughtWith.name
|
||||
}.any()
|
||||
) {
|
||||
cityConstructions.cityInfo.civInfo.boughtConstructionsWithGloballyIncreasingPrice[name] =
|
||||
(cityConstructions.cityInfo.civInfo.boughtConstructionsWithGloballyIncreasingPrice[name] ?: 0) + 1
|
||||
}
|
||||
|
||||
if (this.isCivilian()) return true // tiny optimization makes save files a few bytes smaller
|
||||
|
||||
addConstructionBonuses(unit, cityConstructions)
|
||||
@ -340,6 +396,7 @@ class BaseUnit : INamed, INonPerpetualConstruction, ICivilopediaText {
|
||||
|
||||
fun addConstructionBonuses(unit: MapUnit, cityConstructions: CityConstructions) {
|
||||
val civInfo = cityConstructions.cityInfo.civInfo
|
||||
@Suppress("LocalVariableName")
|
||||
var XP = 0
|
||||
|
||||
for (unique in
|
||||
@ -361,10 +418,10 @@ class BaseUnit : INamed, INonPerpetualConstruction, ICivilopediaText {
|
||||
val filter = unique.params[0]
|
||||
val promotion = unique.params.last()
|
||||
|
||||
if (unit.matchesFilter(filter) ||
|
||||
(
|
||||
filter == "relevant" &&
|
||||
civInfo.gameInfo.ruleSet.unitPromotions.values
|
||||
if (unit.matchesFilter(filter)
|
||||
|| (
|
||||
filter == "relevant"
|
||||
&& civInfo.gameInfo.ruleSet.unitPromotions.values
|
||||
.any {
|
||||
it.name == promotion
|
||||
&& unit.type.name in it.unitTypes
|
||||
|
Reference in New Issue
Block a user