mirror of
https://github.com/yairm210/Unciv.git
synced 2025-02-10 10:58:13 +07:00
Implemented religious pressure (#4863)
* Implemented religious pressure: cities now can have more than one religion in them and religions spread between nearby cities over time. * Implemented proposed changes * Implemented requested changes & minor changes I forgot to include last time * All pantheons not founded by you are now removed when you gain a new city (found this somewhere in the source code of the original, don't know if it's documented anywhere online)
This commit is contained in:
parent
344ff85eea
commit
5d249ee673
BIN
android/Images/StatIcons/ReligiousStrength.png
Normal file
BIN
android/Images/StatIcons/ReligiousStrength.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.7 KiB |
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
@ -1500,8 +1500,10 @@
|
||||
"name": "Great Prophet",
|
||||
"unitType": "Civilian",
|
||||
"uniques": ["Can construct [Holy site] if it hasn't spread religion yet", "Can spread religion [4] times",
|
||||
"May found a religion", "Great Person - [Faith]", "Unbuildable", "Religious Unit", "Hidden when religion is disabled"],
|
||||
"movement": 2
|
||||
"May found a religion", "May enter foreign tiles without open borders", "[-1] Visibility Range",
|
||||
"Great Person - [Faith]", "Unbuildable", "Religious Unit", "Hidden when religion is disabled"],
|
||||
"movement": 2,
|
||||
"religiousStrength": 1000
|
||||
},
|
||||
{
|
||||
"name": "Great General",
|
||||
@ -1525,9 +1527,11 @@
|
||||
{
|
||||
"name": "Missionary",
|
||||
"unitType": "Civilian",
|
||||
"uniques": ["Can spread religion [2] times", "Can be purchased with [Faith] [in all cities in which the majority religion is a major religion]",
|
||||
"Unbuildable", "Religious Unit", "Hidden when religion is disabled"],
|
||||
"movement": 4
|
||||
"uniques": ["Can spread religion [2] times", "May enter foreign tiles without open borders, but loses [250] religious strength each turn it ends there",
|
||||
"Can be purchased with [Faith] [in all cities in which the majority religion is a major religion]",
|
||||
"[-1] Visibility Range", "Unbuildable", "Religious Unit", "Hidden when religion is disabled"],
|
||||
"movement": 4,
|
||||
"religiousStrength": 1000
|
||||
}
|
||||
|
||||
/* Spaceship Parts */
|
||||
|
@ -533,6 +533,7 @@ Our influence with City-States has started dropping faster! =
|
||||
You gained [Stats] as your religion was spread to [cityName] =
|
||||
You gained [Stats] as your religion was spread to an unknown city =
|
||||
Your city [cityName] was converted to [religionName]! =
|
||||
Your [unitName] lost its faith after spending too long inside enemy territory! =
|
||||
|
||||
|
||||
# World Screen UI
|
||||
|
@ -63,6 +63,9 @@ object Constants {
|
||||
const val unitActionParadrop = "Paradrop"
|
||||
|
||||
const val futureTech = "Future Tech"
|
||||
// Easter egg name. Hopefully is to hopefully avoid conflicts when later players can name their own religions.
|
||||
// This religion name should never be displayed.
|
||||
const val noReligionName = "The religion of TheLegend27"
|
||||
|
||||
const val cancelImprovementOrder = "Cancel improvement order"
|
||||
const val tutorialPopupNamePrefix = "Tutorial: "
|
||||
|
@ -91,7 +91,7 @@ class GameInfo {
|
||||
fun getCurrentPlayerCivilization() = currentPlayerCiv
|
||||
fun getBarbarianCivilization() = getCivilization(Constants.barbarians)
|
||||
fun getDifficulty() = difficultyObject
|
||||
fun getCities() = civilizations.flatMap { it.cities }
|
||||
fun getCities() = civilizations.asSequence().flatMap { it.cities }
|
||||
fun getAliveCityStates() = civilizations.filter { it.isAlive() && it.isCityState() }
|
||||
fun getAliveMajorCivs() = civilizations.filter { it.isAlive() && it.isMajorCiv() }
|
||||
//endregion
|
||||
|
@ -485,7 +485,8 @@ class CityInfo {
|
||||
}
|
||||
} else population.nextTurn(foodForNextTurn())
|
||||
|
||||
// if (civInfo.gameInfo.hasReligionEnabled()) religion.getAffectedBySurroundingCities()
|
||||
// This should go after the population change, as that might impact the amount of followers in this city
|
||||
if (civInfo.gameInfo.hasReligionEnabled()) religion.endTurn()
|
||||
|
||||
if (this in civInfo.cities) { // city was not destroyed
|
||||
health = min(health + 20, getMaxHealth())
|
||||
@ -652,7 +653,7 @@ class CityInfo {
|
||||
}
|
||||
|
||||
fun isHolyCity(): Boolean {
|
||||
return civInfo.gameInfo.religions.values.any { it.holyCityId == id }
|
||||
return religion.religionThisIsTheHolyCityOf != null
|
||||
}
|
||||
|
||||
fun canBeDestroyed(): Boolean {
|
||||
|
@ -215,6 +215,8 @@ class CityInfoConquestFunctions(val city: CityInfo){
|
||||
cityConstructions.addBuilding(civEquivalentBuilding.name)
|
||||
}
|
||||
}
|
||||
|
||||
religion.removeUnknownPantheons()
|
||||
|
||||
tryUpdateRoadStatus()
|
||||
}
|
||||
|
@ -1,11 +1,10 @@
|
||||
package com.unciv.logic.city
|
||||
|
||||
import com.unciv.logic.civilization.CivilizationInfo
|
||||
import com.unciv.Constants
|
||||
import com.unciv.logic.civilization.NotificationIcon
|
||||
import com.unciv.models.Counter
|
||||
import com.unciv.models.metadata.GameSpeed
|
||||
import com.unciv.models.ruleset.Unique
|
||||
import com.unciv.models.stats.Stats
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class CityInfoReligionManager {
|
||||
@Transient
|
||||
@ -16,16 +15,41 @@ class CityInfoReligionManager {
|
||||
val religionsAtSomePointAdopted: HashSet<String> = hashSetOf()
|
||||
|
||||
private val pressures: Counter<String> = Counter()
|
||||
// `getNumberOfFollowers()` was called a surprisingly large amount of time, so caching it feels useful
|
||||
@Transient
|
||||
private val followers: Counter<String> = Counter()
|
||||
|
||||
private val pressureFromAdjacentCities: Int by lazy {
|
||||
when (cityInfo.civInfo.gameInfo.gameParameters.gameSpeed) {
|
||||
GameSpeed.Quick -> 9
|
||||
GameSpeed.Standard -> 6
|
||||
GameSpeed.Epic -> 4
|
||||
GameSpeed.Marathon -> 2
|
||||
}
|
||||
}
|
||||
|
||||
var religionThisIsTheHolyCityOf: String? = null
|
||||
|
||||
init {
|
||||
clearAllPressures()
|
||||
}
|
||||
|
||||
fun clone(): CityInfoReligionManager {
|
||||
val toReturn = CityInfoReligionManager()
|
||||
toReturn.religionsAtSomePointAdopted.addAll(religionsAtSomePointAdopted)
|
||||
toReturn.pressures.putAll(pressures)
|
||||
toReturn.followers.putAll(followers)
|
||||
toReturn.religionThisIsTheHolyCityOf = religionThisIsTheHolyCityOf
|
||||
return toReturn
|
||||
}
|
||||
|
||||
fun setTransients(cityInfo: CityInfo) {
|
||||
this.cityInfo = cityInfo
|
||||
updateNumberOfFollowers()
|
||||
}
|
||||
|
||||
fun endTurn() {
|
||||
getAffectedBySurroundingCities()
|
||||
}
|
||||
|
||||
fun getUniques(): Sequence<Unique> {
|
||||
@ -40,14 +64,31 @@ class CityInfoReligionManager {
|
||||
|
||||
fun clearAllPressures() {
|
||||
pressures.clear()
|
||||
// We add pressure for following no religion
|
||||
// Basically used as a failsafe so that there is always some religion,
|
||||
// and we don't suddenly divide by 0 somewhere
|
||||
// Should be removed when updating the followers so it never becomes the majority religion,
|
||||
// `null` is used for that instead.
|
||||
pressures.add(Constants.noReligionName, 100)
|
||||
}
|
||||
|
||||
fun addPressure(religionName: String, amount: Int) {
|
||||
val oldMajorityReligion = getMajorityReligion()
|
||||
fun addPressure(religionName: String, amount: Int, shouldUpdateFollowers: Boolean = true) {
|
||||
pressures.add(religionName, amount)
|
||||
val newMajorityReligion = getMajorityReligion()
|
||||
if (oldMajorityReligion != newMajorityReligion && newMajorityReligion != null) {
|
||||
triggerReligionAdoption(newMajorityReligion)
|
||||
|
||||
if (shouldUpdateFollowers) {
|
||||
updateNumberOfFollowers()
|
||||
}
|
||||
}
|
||||
|
||||
fun updatePressureOnPopulationChange(populationChangeAmount: Int) {
|
||||
val majorityReligion =
|
||||
if (getMajorityReligion() != null) getMajorityReligion()!!
|
||||
else Constants.noReligionName
|
||||
|
||||
if (populationChangeAmount > 0) {
|
||||
addPressure(majorityReligion, 100 * populationChangeAmount)
|
||||
} else {
|
||||
updateNumberOfFollowers()
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,50 +121,94 @@ class CityInfoReligionManager {
|
||||
religionsAtSomePointAdopted.add(newMajorityReligion)
|
||||
}
|
||||
|
||||
private fun updateNumberOfFollowers() {
|
||||
val oldMajorityReligion = getMajorityReligion()
|
||||
|
||||
followers.clear()
|
||||
|
||||
val remainders = HashMap<String, Float>()
|
||||
val pressurePerFollower = pressures.values.sum() / cityInfo.population.population
|
||||
|
||||
// First give each religion an approximate share based on pressure
|
||||
for ((religion, pressure) in pressures) {
|
||||
val followersOfThisReligion = (pressure.toFloat() / pressurePerFollower).toInt()
|
||||
followers.add(religion, followersOfThisReligion)
|
||||
remainders[religion] = pressure.toFloat() - followersOfThisReligion * pressurePerFollower
|
||||
}
|
||||
|
||||
var unallocatedPopulation = cityInfo.population.population - followers.values.sum()
|
||||
|
||||
// Divide up the remaining population
|
||||
while (unallocatedPopulation > 0) {
|
||||
val largestRemainder = remainders.maxByOrNull { it.value }
|
||||
if (largestRemainder == null) {
|
||||
followers.add(Constants.noReligionName, unallocatedPopulation)
|
||||
break
|
||||
}
|
||||
followers.add(largestRemainder.key, 1)
|
||||
remainders[largestRemainder.key] = 0f
|
||||
unallocatedPopulation -= 1
|
||||
}
|
||||
|
||||
followers.remove(Constants.noReligionName)
|
||||
|
||||
val newMajorityReligion = getMajorityReligion()
|
||||
if (oldMajorityReligion != newMajorityReligion && newMajorityReligion != null) {
|
||||
triggerReligionAdoption(newMajorityReligion)
|
||||
}
|
||||
}
|
||||
|
||||
fun getNumberOfFollowers(): Counter<String> {
|
||||
val totalInfluence = pressures.values.sum()
|
||||
val population = cityInfo.population.population
|
||||
if (totalInfluence > 100 * population) {
|
||||
val toReturn = Counter<String>()
|
||||
for ((key, value) in pressures)
|
||||
if (value > 100)
|
||||
toReturn.add(key, value / 100)
|
||||
return toReturn
|
||||
|
||||
// println(followers) // ToDo: remove this when a UI for viewing followers is added
|
||||
|
||||
return followers
|
||||
}
|
||||
|
||||
/** Removes all pantheons except for the one founded by the current owner of the city
|
||||
* Should be called whenever a city changes hands, e.g. conquering and trading
|
||||
*/
|
||||
fun removeUnknownPantheons() {
|
||||
for (pressure in pressures) {
|
||||
val correspondingReligion = cityInfo.civInfo.gameInfo.religions[pressure.key]!!
|
||||
if (correspondingReligion.isPantheon()
|
||||
&& correspondingReligion.foundingCivName != cityInfo.civInfo.civName
|
||||
) {
|
||||
pressures.remove(pressure.key)
|
||||
}
|
||||
}
|
||||
|
||||
val toReturn = Counter<String>()
|
||||
|
||||
for ((key, value) in pressures) {
|
||||
val percentage = value.toFloat() / totalInfluence
|
||||
val relativePopulation = (percentage * population).roundToInt()
|
||||
toReturn.add(key, relativePopulation)
|
||||
}
|
||||
return toReturn
|
||||
updateNumberOfFollowers()
|
||||
}
|
||||
|
||||
fun getMajorityReligion(): String? {
|
||||
val followersPerReligion = getNumberOfFollowers()
|
||||
if (followersPerReligion.isEmpty()) return null
|
||||
val religionWithMaxFollowers = followersPerReligion.maxByOrNull { it.value }!!
|
||||
return if (religionWithMaxFollowers.value >= cityInfo.population.population) religionWithMaxFollowers.key
|
||||
return if (religionWithMaxFollowers.value >= cityInfo.population.population / 2) religionWithMaxFollowers.key
|
||||
else null
|
||||
}
|
||||
|
||||
fun getAffectedBySurroundingCities() {
|
||||
private fun getAffectedBySurroundingCities() {
|
||||
// We don't update the amount of followers yet, as only the end result should matter
|
||||
// If multiple religions would become the majority religion due to pressure,
|
||||
// this will make it so we only receive a notification for the last one.
|
||||
// Also, doing it like this increases performance :D
|
||||
if (cityInfo.isHolyCity()) {
|
||||
addPressure(religionThisIsTheHolyCityOf!!,5 * pressureFromAdjacentCities, false)
|
||||
}
|
||||
|
||||
val allCitiesWithin10Tiles =
|
||||
cityInfo.civInfo.gameInfo.civilizations.asSequence().flatMap { it.cities }
|
||||
cityInfo.civInfo.gameInfo.getCities()
|
||||
.filter {
|
||||
it != cityInfo && it.getCenterTile()
|
||||
.aerialDistanceTo(cityInfo.getCenterTile()) <= 10
|
||||
it != cityInfo
|
||||
&& it.getCenterTile().aerialDistanceTo(cityInfo.getCenterTile()) <= 10
|
||||
}
|
||||
for (city in allCitiesWithin10Tiles) {
|
||||
val majorityReligionOfCity = city.religion.getMajorityReligion()
|
||||
if (majorityReligionOfCity == null) continue
|
||||
else addPressure(
|
||||
majorityReligionOfCity,
|
||||
if (city.isHolyCity()) 30
|
||||
else 6
|
||||
)
|
||||
val majorityReligionOfCity = city.religion.getMajorityReligion() ?: continue
|
||||
if (!cityInfo.civInfo.gameInfo.religions[majorityReligionOfCity]!!.isMajorReligion()) continue
|
||||
addPressure(majorityReligionOfCity, pressureFromAdjacentCities, false)
|
||||
}
|
||||
|
||||
updateNumberOfFollowers()
|
||||
}
|
||||
}
|
@ -56,7 +56,7 @@ class PopulationManager {
|
||||
if (food < 0)
|
||||
cityInfo.civInfo.addNotification("[${cityInfo.name}] is starving!", cityInfo.location, NotificationIcon.Growth, NotificationIcon.Death)
|
||||
if (foodStored < 0) { // starvation!
|
||||
if (population > 1) population--
|
||||
if (population > 1) addPopulation(-1)
|
||||
foodStored = 0
|
||||
}
|
||||
if (foodStored >= getFoodToNextPopulation()) { // growth!
|
||||
@ -68,7 +68,7 @@ class PopulationManager {
|
||||
// Try to avoid runaway food gain in mods, just in case
|
||||
if (percentOfFoodCarriedOver > 95) percentOfFoodCarriedOver = 95
|
||||
foodStored += (getFoodToNextPopulation() * percentOfFoodCarriedOver / 100f).toInt()
|
||||
population++
|
||||
addPopulation(1)
|
||||
autoAssignPopulation()
|
||||
cityInfo.civInfo.addNotification("[${cityInfo.name}] has grown!", cityInfo.location, NotificationIcon.Growth)
|
||||
}
|
||||
@ -77,14 +77,18 @@ class PopulationManager {
|
||||
private fun getStatsOfSpecialist(name: String) = cityInfo.cityStats.getStatsOfSpecialist(name)
|
||||
|
||||
internal fun addPopulation(count: Int) {
|
||||
population += count
|
||||
if (population < 0) population = 0
|
||||
val changedAmount =
|
||||
if (population + count < 0) -population
|
||||
else count
|
||||
population += changedAmount
|
||||
val freePopulation = getFreePopulation()
|
||||
if (freePopulation < 0) {
|
||||
unassignExtraPopulation()
|
||||
} else {
|
||||
autoAssignPopulation()
|
||||
}
|
||||
|
||||
cityInfo.religion.updatePressureOnPopulationChange(changedAmount)
|
||||
}
|
||||
|
||||
internal fun setPopulation(count: Int) {
|
||||
|
@ -32,7 +32,7 @@ class CapitalConnectionsFinder(private val civInfo: CivilizationInfo) {
|
||||
// this is so we know that if we've seen which cities can be connected by port A, and one
|
||||
// of those is city B, then we don't need to check the cities that B can connect to by port,
|
||||
// since we'll get the same cities we got from A, since they're connected to the same sea.
|
||||
while (citiesToCheck.isNotEmpty() && citiesReachedToMediums.size < allCivCities.size) {
|
||||
while (citiesToCheck.isNotEmpty() && citiesReachedToMediums.size < allCivCities.count()) {
|
||||
newCitiesToCheck = mutableListOf()
|
||||
for (cityToConnectFrom in citiesToCheck) {
|
||||
if (cityToConnectFrom.containsHarbor()) {
|
||||
|
@ -87,9 +87,8 @@ class ReligionManager {
|
||||
religion = Religion(belief.name, civInfo.gameInfo, civInfo.civName)
|
||||
religion!!.followerBeliefs.add(belief.name)
|
||||
civInfo.gameInfo.religions[belief.name] = religion!!
|
||||
// ToDo: This should later be changed when religions can have multiple beliefs
|
||||
civInfo.getCapital().religion.clearAllPressures()
|
||||
civInfo.getCapital().religion.addPressure(belief.name, 100) // Capital is religious, other cities are not
|
||||
for (city in civInfo.cities)
|
||||
city.religion.addPressure(belief.name, 200 * city.population.population)
|
||||
religionState = ReligionState.Pantheon
|
||||
}
|
||||
|
||||
@ -114,10 +113,9 @@ class ReligionManager {
|
||||
|
||||
if (Random(civInfo.gameInfo.turns).nextFloat() < prophetSpawnChange) {
|
||||
val birthCity =
|
||||
if (religionState == ReligionState.Pantheon) civInfo.getCapital()
|
||||
else civInfo.cities.firstOrNull { it.id == religion!!.holyCityId }
|
||||
val prophet = civInfo.addUnit("Great Prophet", birthCity)
|
||||
if (prophet == null) return
|
||||
if (religionState <= ReligionState.Pantheon) civInfo.getCapital()
|
||||
else civInfo.cities.firstOrNull { it.religion.religionThisIsTheHolyCityOf == religion!!.name }
|
||||
val prophet = civInfo.addUnit("Great Prophet", birthCity) ?: return
|
||||
prophet.religion = religion!!.name
|
||||
prophet.abilityUsedCount["Religion Spread"] = 0
|
||||
storedFaith -= faithForNextGreatProphet()
|
||||
@ -170,15 +168,14 @@ class ReligionManager {
|
||||
}
|
||||
newReligion.followerBeliefs.addAll(followerBeliefs)
|
||||
newReligion.founderBeliefs.addAll(founderBelief)
|
||||
newReligion.holyCityId = foundingCityId
|
||||
religion = newReligion
|
||||
civInfo.gameInfo.religions[name] = newReligion
|
||||
|
||||
religionState = ReligionState.Religion
|
||||
val holyCity = civInfo.cities.firstOrNull { it.id == newReligion.holyCityId }!!
|
||||
// ToDo: check this when implementing followers
|
||||
holyCity.religion.clearAllPressures()
|
||||
holyCity.religion.addPressure(name, 100)
|
||||
|
||||
val holyCity = civInfo.cities.first { it.id == foundingCityId }
|
||||
holyCity.religion.religionThisIsTheHolyCityOf = newReligion.name
|
||||
holyCity.religion.addPressure(name, holyCity.population.population * 500)
|
||||
|
||||
foundingCityId = null
|
||||
}
|
||||
|
@ -71,6 +71,9 @@ class MapUnit {
|
||||
@Transient
|
||||
var cannotEnterOceanTilesUntilAstronomy = false
|
||||
|
||||
@Transient
|
||||
var canEnterForeignTerrain: Boolean = false
|
||||
|
||||
@Transient
|
||||
var paradropRange = 0
|
||||
|
||||
@ -95,7 +98,7 @@ class MapUnit {
|
||||
fun displayName(): String {
|
||||
val name = if (instanceName == null) name
|
||||
else "$instanceName ({${name}})"
|
||||
return if (religion != null && maxReligionSpreads() > 0) "[$name] ([$religion])"
|
||||
return if (religion != null) "[$name] ([$religion])"
|
||||
else name
|
||||
}
|
||||
|
||||
@ -113,6 +116,7 @@ class MapUnit {
|
||||
|
||||
var abilityUsedCount: HashMap<String, Int> = hashMapOf()
|
||||
var religion: String? = null
|
||||
var religiousStrengthLost = 0
|
||||
|
||||
//region pure functions
|
||||
fun clone(): MapUnit {
|
||||
@ -130,6 +134,7 @@ class MapUnit {
|
||||
toReturn.isTransported = isTransported
|
||||
toReturn.abilityUsedCount.putAll(abilityUsedCount)
|
||||
toReturn.religion = religion
|
||||
toReturn.religiousStrengthLost = religiousStrengthLost
|
||||
return toReturn
|
||||
}
|
||||
|
||||
@ -177,7 +182,7 @@ class MapUnit {
|
||||
val uniques = ArrayList<Unique>()
|
||||
val baseUnit = baseUnit()
|
||||
uniques.addAll(baseUnit.uniqueObjects)
|
||||
if (type != null) uniques.addAll(type!!.uniqueObjects)
|
||||
uniques.addAll(type.uniqueObjects)
|
||||
|
||||
for (promotion in promotions.promotions) {
|
||||
uniques.addAll(currentTile.tileMap.gameInfo.ruleSet.unitPromotions[promotion]!!.uniqueObjects)
|
||||
@ -193,12 +198,14 @@ class MapUnit {
|
||||
ignoresTerrainCost = hasUnique("Ignores terrain cost")
|
||||
roughTerrainPenalty = hasUnique("Rough terrain penalty")
|
||||
doubleMovementInCoast = hasUnique("Double movement in coast")
|
||||
doubleMovementInForestAndJungle =
|
||||
hasUnique("Double movement rate through Forest and Jungle")
|
||||
doubleMovementInForestAndJungle = hasUnique("Double movement rate through Forest and Jungle")
|
||||
doubleMovementInSnowTundraAndHills = hasUnique("Double movement in Snow, Tundra and Hills")
|
||||
canEnterIceTiles = hasUnique("Can enter ice tiles")
|
||||
cannotEnterOceanTiles = hasUnique("Cannot enter ocean tiles")
|
||||
cannotEnterOceanTilesUntilAstronomy = hasUnique("Cannot enter ocean tiles until Astronomy")
|
||||
canEnterForeignTerrain =
|
||||
hasUnique("May enter foreign tiles without open borders, but loses [] religious strength each turn it ends there")
|
||||
|| hasUnique("May enter foreign tiles without open borders")
|
||||
}
|
||||
|
||||
fun hasUnique(unique: String): Boolean {
|
||||
@ -239,7 +246,9 @@ class MapUnit {
|
||||
for (unique in getTile().getAllTerrains().flatMap { it.uniqueObjects })
|
||||
if (unique.placeholderText == "[] Sight for [] units" && matchesFilter(unique.params[1]))
|
||||
visibilityRange += unique.params[0].toInt()
|
||||
|
||||
|
||||
if (visibilityRange < 1) visibilityRange = 1
|
||||
|
||||
return visibilityRange
|
||||
}
|
||||
|
||||
@ -619,6 +628,23 @@ class MapUnit {
|
||||
|
||||
if (action == Constants.unitActionParadrop)
|
||||
action = null
|
||||
|
||||
if (hasUnique("Religious Unit")
|
||||
&& getTile().getOwner() != null
|
||||
&& !getTile().getOwner()!!.isCityState()
|
||||
&& !civInfo.canPassThroughTiles(getTile().getOwner()!!)
|
||||
) {
|
||||
val lostReligiousStrength =
|
||||
getMatchingUniques("May enter foreign tiles without open borders, but loses [] religious strength each turn it ends there")
|
||||
.map { it.params[0].toInt() }
|
||||
.minOrNull()
|
||||
if (lostReligiousStrength != null)
|
||||
religiousStrengthLost += lostReligiousStrength
|
||||
if (religiousStrengthLost >= baseUnit.religiousStrength) {
|
||||
civInfo.addNotification("Your [${name}] lost its faith after spending too long inside enemy territory!", getTile().position, name)
|
||||
destroy()
|
||||
}
|
||||
}
|
||||
|
||||
getCitadelDamage()
|
||||
getTerrainDamage()
|
||||
@ -653,7 +679,7 @@ class MapUnit {
|
||||
action = null
|
||||
|
||||
val tileOwner = getTile().getOwner()
|
||||
if (tileOwner != null && !civInfo.canPassThroughTiles(tileOwner) && !tileOwner.isCityState()) // if an enemy city expanded onto this tile while I was in it
|
||||
if (tileOwner != null && !canEnterForeignTerrain && !civInfo.canPassThroughTiles(tileOwner) && !tileOwner.isCityState()) // if an enemy city expanded onto this tile while I was in it
|
||||
movement.teleportToClosestMoveableTile()
|
||||
}
|
||||
|
||||
@ -914,6 +940,14 @@ class MapUnit {
|
||||
return getMatchingUniques("Can spread religion [] times").sumBy { it.params[0].toInt() }
|
||||
}
|
||||
|
||||
fun canSpreadReligion(): Boolean {
|
||||
return hasUnique("Can spread religion [] times")
|
||||
}
|
||||
|
||||
fun getPressureAddedFromSpread(): Int {
|
||||
return baseUnit.religiousStrength
|
||||
}
|
||||
|
||||
fun getReligionString(): String {
|
||||
val maxSpreads = maxReligionSpreads()
|
||||
if (abilityUsedCount["Religion Spread"] == null) return "" // That is, either the key doesn't exist, or it does exist and the value is null.
|
||||
|
@ -498,8 +498,8 @@ class UnitMovementAlgorithms(val unit:MapUnit) {
|
||||
return false
|
||||
}
|
||||
if (tile.naturalWonder != null) return false
|
||||
|
||||
if (!tile.canCivPassThrough(unit.civInfo)) return false
|
||||
|
||||
if (!unit.canEnterForeignTerrain && !tile.canCivPassThrough(unit.civInfo)) return false
|
||||
|
||||
val firstUnit = tile.getFirstUnit()
|
||||
if (firstUnit != null && firstUnit.civInfo != unit.civInfo && unit.civInfo.isAtWarWith(firstUnit.civInfo))
|
||||
|
@ -12,7 +12,6 @@ class Religion() : INamed {
|
||||
override lateinit var name: String
|
||||
var iconName: String = "Pantheon"
|
||||
lateinit var foundingCivName: String
|
||||
var holyCityId: String? = null
|
||||
|
||||
var founderBeliefs: HashSet<String> = hashSetOf()
|
||||
var followerBeliefs: HashSet<String> = hashSetOf()
|
||||
@ -29,7 +28,6 @@ class Religion() : INamed {
|
||||
fun clone(): Religion {
|
||||
val toReturn = Religion(name, gameInfo, foundingCivName)
|
||||
toReturn.iconName = iconName
|
||||
toReturn.holyCityId = holyCityId
|
||||
toReturn.founderBeliefs.addAll(founderBeliefs)
|
||||
toReturn.followerBeliefs.addAll(followerBeliefs)
|
||||
return toReturn
|
||||
|
@ -32,6 +32,7 @@ class BaseUnit : INamed, INonPerpetualConstruction, ICivilopediaText {
|
||||
var movement: Int = 0
|
||||
var strength: Int = 0
|
||||
var rangedStrength: Int = 0
|
||||
var religiousStrength: Int = 0
|
||||
var range: Int = 2
|
||||
var interceptRange = 0
|
||||
lateinit var unitType: String
|
||||
@ -327,6 +328,8 @@ class BaseUnit : INamed, INonPerpetualConstruction, ICivilopediaText {
|
||||
|
||||
if (unit.hasUnique("Religious Unit")) {
|
||||
unit.religion = cityConstructions.cityInfo.religion.getMajorityReligion()
|
||||
if (unit.canSpreadReligion())
|
||||
unit.abilityUsedCount["Religion Spread"] = 0
|
||||
}
|
||||
|
||||
if (this.isCivilian()) return true // tiny optimization makes save files a few bytes smaller
|
||||
|
@ -466,15 +466,12 @@ object UnitActions {
|
||||
val maxReligionSpreads = unit.maxReligionSpreads()
|
||||
if (!unit.abilityUsedCount.containsKey("Religion Spread")) return // This should be impossible anyways, but just in case
|
||||
if (maxReligionSpreads <= unit.abilityUsedCount["Religion Spread"]!!) return
|
||||
val city = tile.getCity()
|
||||
if (city == null) return
|
||||
val city = tile.getCity() ?: return
|
||||
actionList += UnitAction(UnitActionType.SpreadReligion,
|
||||
title = "Spread [${unit.religion!!}]",
|
||||
action = {
|
||||
unit.abilityUsedCount["Religion Spread"] = unit.abilityUsedCount["Religion Spread"]!! + 1
|
||||
// ToDo: implement followers
|
||||
city.religion.clearAllPressures()
|
||||
city.religion.addPressure(unit.religion!!, 100)
|
||||
city.religion.addPressure(unit.religion!!, unit.getPressureAddedFromSpread())
|
||||
unit.currentMovement = 0f
|
||||
if (unit.abilityUsedCount["Religion Spread"] == maxReligionSpreads) {
|
||||
addGoldPerGreatPersonUsage(unit.civInfo)
|
||||
@ -487,7 +484,7 @@ object UnitActions {
|
||||
fun getImprovementConstructionActions(unit: MapUnit, tile: TileInfo): ArrayList<UnitAction> {
|
||||
val finalActions = ArrayList<UnitAction>()
|
||||
var uniquesToCheck = unit.getMatchingUniques("Can construct []")
|
||||
if (unit.abilityUsedCount.containsKey("Religion Spread") && unit.abilityUsedCount["Religion Spread"]!! == 0 && unit.maxReligionSpreads() > 0)
|
||||
if (unit.abilityUsedCount.containsKey("Religion Spread") && unit.abilityUsedCount["Religion Spread"]!! == 0 && unit.canSpreadReligion())
|
||||
uniquesToCheck += unit.getMatchingUniques("Can construct [] if it hasn't spread religion yet")
|
||||
for (unique in uniquesToCheck) {
|
||||
val improvementName = unique.params[0]
|
||||
|
@ -163,10 +163,15 @@ class UnitTable(val worldScreen: WorldScreen) : Table(){
|
||||
unitDescriptionTable.add(unit.promotions.XP.toString() + "/" + unit.promotions.xpForNextPromotion())
|
||||
}
|
||||
|
||||
if (unit.maxReligionSpreads() > 0) {
|
||||
if (unit.canSpreadReligion()) {
|
||||
unitDescriptionTable.add(ImageGetter.getStatIcon("Faith")).size(20f)
|
||||
unitDescriptionTable.add(unit.getReligionString())
|
||||
}
|
||||
|
||||
if (unit.baseUnit.religiousStrength > 0) {
|
||||
unitDescriptionTable.add(ImageGetter.getStatIcon("ReligiousStrength")).size(20f)
|
||||
unitDescriptionTable.add((unit.baseUnit.religiousStrength - unit.religiousStrengthLost).toString())
|
||||
}
|
||||
|
||||
if (unit.promotions.promotions.size != promotionsTable.children.size) // The unit has been promoted! Reload promotions!
|
||||
selectedUnitHasChanged = true
|
||||
|
@ -613,6 +613,7 @@ Unless otherwise specified, all the following are from [the Noun Project](https:
|
||||
* [Lock](https://thenounproject.com/search/?q=lock&i=3217613) by Vadim Solomakhin for locked tiles
|
||||
* [Hourglass](https://thenounproject.com/search/?q=hourglass&i=142268) by I Create Stuff for the 'Turn' icon
|
||||
* [Dove](https://thenounproject.com/search/?q=dove&i=1344084) by Sandra for Faith
|
||||
* [Shield](https://thenounproject.com/search/?q=shield&i=813568) by Gregor Cresnar for Religious Strength
|
||||
|
||||
## Main menu
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user