Founding Religions (#4505)
* Fixed crashes on loading save games with religion * Added missing credit * Religious cities now show religion icons in the city button * Add icons for religions * You can now found beliefs, with snazzy icons! * Fixed bug which made prophets impossible to generate * Added missing translatable strings * Fixed translation tests properly * Implemented requested changes * Implemented part of the requested changes * Removed SplitPane in favor of Table * Removed unused code * Capped the amount of foundable religions to the amount of religions
BIN
android/Images/ReligionIcons/Buddhism.png
Normal file
After Width: | Height: | Size: 4.6 KiB |
BIN
android/Images/ReligionIcons/Christianity.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
android/Images/ReligionIcons/Hinduism.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
BIN
android/Images/ReligionIcons/Islam.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
android/Images/ReligionIcons/Pantheon.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
android/Images/ReligionIcons/Taoism.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 1.0 MiB |
7
android/assets/jsons/Civ V - Vanilla/Religions.json
Normal file
@ -0,0 +1,7 @@
|
||||
[
|
||||
"Buddhism",
|
||||
"Christianity",
|
||||
"Hinduism",
|
||||
"Islam",
|
||||
"Taoism"
|
||||
]
|
@ -1477,7 +1477,8 @@
|
||||
{
|
||||
"name": "Great Prophet",
|
||||
"unitType": "Civilian",
|
||||
"uniques": ["Can construct [Holy site] if it hasn't spread religion yet", "Can spread religion [4] times","Great Person - [Faith]", "Unbuildable"],
|
||||
"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"],
|
||||
"movement": 2
|
||||
},
|
||||
{
|
||||
|
@ -723,6 +723,7 @@ Your trade mission to [civName] has earned you [goldAmount] gold and [influenceA
|
||||
Hurry Wonder = Versnel Wonder
|
||||
Spread Religion = Verkondig Religie
|
||||
Spread [religionName] = Verkondig [religionName]
|
||||
Found a Religion = Begin een religie
|
||||
Your citizens have been happy with your rule for so long that the empire enters a Golden Age! = Jouw dorpelingen zijn voor zo een lange tijd blij met jouw leiderschap dat jouw rijk de Gulden Eeuw binnen gaat.
|
||||
You have entered the [newEra]! = Jij bent in het/de [newEra] aangekomen!
|
||||
[civName] has entered the [eraName]! = [civName] is aangekomen in de [eraName]!
|
||||
|
@ -679,6 +679,7 @@ Your trade mission to [civName] has earned you [goldAmount] gold and [influenceA
|
||||
Hurry Wonder =
|
||||
Spread Religion =
|
||||
Spread [religionName] =
|
||||
Found a Religion =
|
||||
Your citizens have been happy with your rule for so long that the empire enters a Golden Age! =
|
||||
You have entered the [newEra]! =
|
||||
[civName] has entered the [eraName]! =
|
||||
@ -904,6 +905,11 @@ Unlocked at =
|
||||
Gain 2 free technologies =
|
||||
All policies adopted =
|
||||
|
||||
# Religions
|
||||
|
||||
Choose an Icon and name for your Religion =
|
||||
Found [religionName] =
|
||||
|
||||
# Terrains
|
||||
|
||||
Impassable =
|
||||
|
@ -395,7 +395,7 @@ object Battle {
|
||||
UncivGame.Current.settings.addCompletedTutorialTask("Conquer a city")
|
||||
} else {
|
||||
city.puppetCity(attackerCiv)
|
||||
if (city.population.population < 4 && !city.isOriginalCapital) {
|
||||
if (city.population.population < 4 && city.canBeDestroyed()) {
|
||||
city.annexCity()
|
||||
city.isBeingRazed = true
|
||||
}
|
||||
|
@ -433,7 +433,7 @@ class CityInfo {
|
||||
}
|
||||
} else population.nextTurn(foodForNextTurn())
|
||||
|
||||
if (civInfo.gameInfo.hasReligionEnabled()) religion.getAffectedBySurroundingCities()
|
||||
// if (civInfo.gameInfo.hasReligionEnabled()) religion.getAffectedBySurroundingCities()
|
||||
|
||||
if (this in civInfo.cities) { // city was not destroyed
|
||||
health = min(health + 20, getMaxHealth())
|
||||
@ -442,10 +442,9 @@ class CityInfo {
|
||||
}
|
||||
|
||||
fun destroyCity(overrideSafeties: Boolean = false) {
|
||||
// Original capitals can't be destroyed.
|
||||
// Unless they are captured by a one-city-challenger for some reason.
|
||||
// This was tested in the original.
|
||||
if (isOriginalCapital && !overrideSafeties) return
|
||||
// Original capitals and holy cities cannot be destroyed,
|
||||
// unless, of course, they are captured by a one-city-challenger.
|
||||
if (!canBeDestroyed() && !overrideSafeties) return
|
||||
|
||||
for (airUnit in getCenterTile().airUnits.toList()) airUnit.destroy() //Destroy planes stationed in city
|
||||
|
||||
@ -594,6 +593,14 @@ class CityInfo {
|
||||
.filter { it.params.none { param -> param == "in this city" } }
|
||||
// Note that we don't query religion here, as those only have local effects (for now at least)
|
||||
}
|
||||
|
||||
fun isHolyCity(): Boolean {
|
||||
return civInfo.gameInfo.religions.values.any { it.holyCityId == id }
|
||||
}
|
||||
|
||||
fun canBeDestroyed(): Boolean {
|
||||
return !isCapital() && !isHolyCity()
|
||||
}
|
||||
|
||||
//endregion
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.unciv.logic.civilization
|
||||
|
||||
import com.unciv.logic.city.CityInfo
|
||||
import com.unciv.logic.map.MapUnit
|
||||
import com.unciv.models.Religion
|
||||
import com.unciv.models.ruleset.Belief
|
||||
@ -15,7 +16,7 @@ class ReligionManager {
|
||||
var religion: Religion? = null
|
||||
// You might ask why this is the transient variable, and not the one in GameInfo.
|
||||
// After all, filling a hashmap is much easier than later distributing its contents over multiple classes.
|
||||
// I would agree that that is better. However, there is, of course, a problem.
|
||||
// There is, however, a problem.
|
||||
// When founding a religion, the religion of your pantheon doesn't immediately disappear.
|
||||
// It just stops growing. Your new religion will then have to spread out from your holy city
|
||||
// and convert these cities. This means, that civilizations can have multiple active religions
|
||||
@ -25,9 +26,18 @@ class ReligionManager {
|
||||
|
||||
private var greatProphetsEarned = 0
|
||||
|
||||
var religionState = ReligionState.None
|
||||
private set
|
||||
|
||||
private var foundingCityId: String? = null
|
||||
// Only used for keeping track of the city a prophet was used when founding a religion
|
||||
|
||||
fun clone(): ReligionManager {
|
||||
val clone = ReligionManager()
|
||||
clone.foundingCityId = foundingCityId
|
||||
clone.storedFaith = storedFaith
|
||||
clone.religionState = religionState
|
||||
clone.greatProphetsEarned = greatProphetsEarned
|
||||
return clone
|
||||
}
|
||||
|
||||
@ -45,17 +55,7 @@ class ReligionManager {
|
||||
}
|
||||
|
||||
fun startTurn() {
|
||||
if (canGenerateProphet()) {
|
||||
val prophetSpawnChange = (5f + storedFaith - faithForNextGreatProphet()) / 100f
|
||||
if (Random(civInfo.gameInfo.turns).nextFloat() < prophetSpawnChange) {
|
||||
val birthCity = civInfo.cities.filter { it.religion.getMajorityReligion() == religion!!.name }.random()
|
||||
val prophet = civInfo.addUnit("Great Prophet", birthCity)
|
||||
if (prophet == null) return
|
||||
prophet.religion = religion!!.name
|
||||
prophet.abilityUsedCount["Religion Spread"] = 0
|
||||
storedFaith -= faithForNextGreatProphet()
|
||||
}
|
||||
}
|
||||
if (canGenerateProphet()) generateProphet()
|
||||
}
|
||||
|
||||
fun endTurn(faithFromNewTurn: Int) {
|
||||
@ -65,8 +65,8 @@ class ReligionManager {
|
||||
private fun faithForPantheon() = 10 + civInfo.gameInfo.civilizations.count { it.isMajorCiv() && it.religionManager.religion != null } * 5
|
||||
|
||||
fun canFoundPantheon(): Boolean {
|
||||
if (religion != null) return false
|
||||
if (!civInfo.gameInfo.hasReligionEnabled()) return false
|
||||
if (religionState != ReligionState.None) return false
|
||||
if (!civInfo.isMajorCiv()) return false
|
||||
if (civInfo.gameInfo.ruleSet.beliefs.values.none { isPickablePantheonBelief(it) })
|
||||
return false
|
||||
@ -75,7 +75,7 @@ class ReligionManager {
|
||||
|
||||
fun isPickablePantheonBelief(belief: Belief): Boolean {
|
||||
if (belief.type != "Pantheon") return false
|
||||
if (civInfo.gameInfo.civilizations.any { it.religionManager.religion != null && it.religionManager.religion!!.pantheonBeliefs.contains(belief.name)})
|
||||
if (civInfo.gameInfo.civilizations.any { it.religionManager.religion != null && it.religionManager.religion!!.followerBeliefs.contains(belief.name)})
|
||||
return false
|
||||
return true
|
||||
}
|
||||
@ -83,23 +83,101 @@ class ReligionManager {
|
||||
fun choosePantheonBelief(belief: Belief) {
|
||||
storedFaith -= faithForPantheon()
|
||||
religion = Religion(belief.name, civInfo.gameInfo, civInfo.civName)
|
||||
religion!!.pantheonBeliefs.add(belief.name)
|
||||
religion!!.followerBeliefs.add(belief.name)
|
||||
civInfo.gameInfo.religions[belief.name] = religion!!
|
||||
// This should later be changed when religions can have multiple beliefs
|
||||
civInfo.getCapital().religion[belief.name] = 100 // Capital is religious, other cities are not
|
||||
religionState = ReligionState.Pantheon
|
||||
}
|
||||
|
||||
|
||||
// https://www.reddit.com/r/civ/comments/2m82wu/can_anyone_detail_the_finer_points_of_great/
|
||||
// Game files (globaldefines.xml)
|
||||
fun faithForNextGreatProphet() = ((200 + 100 * greatProphetsEarned * (greatProphetsEarned + 1)/2) * civInfo.gameInfo.gameParameters.gameSpeed.modifier).toInt()
|
||||
private fun faithForNextGreatProphet() = (
|
||||
(200 + 100 * greatProphetsEarned * (greatProphetsEarned + 1) / 2) *
|
||||
civInfo.gameInfo.gameParameters.gameSpeed.modifier
|
||||
).toInt()
|
||||
|
||||
fun canGenerateProphet(): Boolean {
|
||||
if (religion == null || !religion!!.hasPantheon()) return false // First get a pantheon, then we'll talk about a real religion
|
||||
private fun canGenerateProphet(): Boolean {
|
||||
if (religion == null || religionState == ReligionState.None) return false // First get a pantheon, then we'll talk about a real religion
|
||||
if (storedFaith < faithForNextGreatProphet()) return false
|
||||
// In the base game, great prophets shouldn't generate anymore starting from the industrial era
|
||||
// This is difficult to implement in the current codebase, probably requires an additional variable in eras.json
|
||||
// Also only if you either [have founded a religion] or [the max amount of religions (players/2 + 1) has not been reached].
|
||||
// As this is yet to be implemented, this function does almost nothing
|
||||
return true
|
||||
}
|
||||
|
||||
private fun generateProphet() {
|
||||
val prophetSpawnChange = (5f + storedFaith - faithForNextGreatProphet()) / 100f
|
||||
|
||||
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
|
||||
prophet.religion = religion!!.name
|
||||
prophet.abilityUsedCount["Religion Spread"] = 0
|
||||
storedFaith -= faithForNextGreatProphet()
|
||||
}
|
||||
}
|
||||
|
||||
fun mayUseGreatProphetAtAll(prophet: MapUnit): Boolean {
|
||||
if (religion == null) return false // First found a pantheon
|
||||
if (religion!!.isMajorReligion()) return false // Already created a major religion
|
||||
if (prophet.abilityUsedCount["Religion Spread"] != 0) return false // Already used its power for other things
|
||||
|
||||
val foundedReligionsCount = civInfo.gameInfo.civilizations.count {
|
||||
it.religionManager.religion != null && it.religionManager.religion!!.isMajorReligion()
|
||||
}
|
||||
|
||||
if (foundedReligionsCount >= civInfo.gameInfo.civilizations.count { it.isMajorCiv() } / 2 + 1)
|
||||
return false // Too bad, too many religions have already been founded.
|
||||
|
||||
if (foundedReligionsCount >= civInfo.gameInfo.ruleSet.religions.count())
|
||||
return false
|
||||
// Mod maker did not provide enough religions for the amount of civs present
|
||||
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
fun mayUseGreatProphetNow(prophet: MapUnit): Boolean {
|
||||
if (!mayUseGreatProphetAtAll(prophet)) return false
|
||||
if (!prophet.getTile().isCityCenter()) return false
|
||||
return true
|
||||
}
|
||||
|
||||
fun useGreatProphet(prophet: MapUnit) {
|
||||
if (!mayUseGreatProphetNow(prophet)) return // How did you do this?
|
||||
religionState = ReligionState.FoundingReligion
|
||||
foundingCityId = prophet.getTile().getCity()!!.id
|
||||
}
|
||||
|
||||
fun foundReligion(iconName: String, name: String, founderBelief: String, followerBelief: String) {
|
||||
val newReligion = Religion(name, civInfo.gameInfo, civInfo.civName)
|
||||
newReligion.iconName = iconName
|
||||
if (religion != null) {
|
||||
newReligion.followerBeliefs.addAll(religion!!.followerBeliefs)
|
||||
}
|
||||
newReligion.followerBeliefs.add(followerBelief)
|
||||
newReligion.founderBeliefs.add(founderBelief)
|
||||
newReligion.holyCityId = foundingCityId
|
||||
religion = newReligion
|
||||
civInfo.gameInfo.religions[name] = newReligion
|
||||
|
||||
religionState = ReligionState.Religion
|
||||
val holyCity = civInfo.cities.firstOrNull { it.id == newReligion.holyCityId }!!
|
||||
holyCity.religion.clear()
|
||||
holyCity.religion[name] = 100
|
||||
|
||||
foundingCityId = null
|
||||
}
|
||||
}
|
||||
|
||||
enum class ReligionState {
|
||||
None,
|
||||
Pantheon,
|
||||
FoundingReligion, // Great prophet used, but religion has not yet been founded
|
||||
Religion,
|
||||
EnhancingReligion, // Great prophet used, but religion has not yet been enhanced
|
||||
EnhancedReligion
|
||||
}
|
@ -7,34 +7,39 @@ import com.unciv.models.stats.INamed
|
||||
|
||||
/** Data object for Religions */
|
||||
class Religion() : INamed {
|
||||
|
||||
var pantheonBeliefs: HashSet<String> = hashSetOf()
|
||||
|
||||
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()
|
||||
override lateinit var name: String
|
||||
lateinit var foundingCivName: String
|
||||
|
||||
|
||||
|
||||
@Transient
|
||||
lateinit var gameInfo: GameInfo
|
||||
|
||||
|
||||
constructor(name: String, gameInfo: GameInfo, foundingCivName: String) : this() {
|
||||
this.name = name
|
||||
this.foundingCivName = foundingCivName
|
||||
this.gameInfo = gameInfo
|
||||
}
|
||||
|
||||
|
||||
fun clone(): Religion {
|
||||
val toReturn = Religion(name, gameInfo, foundingCivName)
|
||||
toReturn.pantheonBeliefs.addAll(pantheonBeliefs)
|
||||
toReturn.iconName = iconName
|
||||
toReturn.holyCityId = holyCityId
|
||||
toReturn.founderBeliefs.addAll(founderBeliefs)
|
||||
toReturn.followerBeliefs.addAll(followerBeliefs)
|
||||
return toReturn
|
||||
}
|
||||
|
||||
|
||||
fun setTransients(gameInfo: GameInfo) {
|
||||
this.gameInfo = gameInfo
|
||||
}
|
||||
|
||||
|
||||
private fun getUniquesOfBeliefs(beliefs: HashSet<String>): Sequence<Unique> {
|
||||
val rulesetBeliefs = gameInfo.ruleSet.beliefs
|
||||
return beliefs.mapNotNull {
|
||||
@ -42,24 +47,26 @@ class Religion() : INamed {
|
||||
else rulesetBeliefs[it]!!.uniqueObjects
|
||||
}.flatten().asSequence()
|
||||
}
|
||||
|
||||
|
||||
fun getFollowerUniques(): Sequence<Unique> {
|
||||
return getUniquesOfBeliefs((followerBeliefs + pantheonBeliefs).toHashSet())
|
||||
return getUniquesOfBeliefs(followerBeliefs)
|
||||
}
|
||||
|
||||
|
||||
fun getFounderUniques(): Sequence<Unique> {
|
||||
return getUniquesOfBeliefs(founderBeliefs)
|
||||
}
|
||||
|
||||
|
||||
fun isPantheon(): Boolean {
|
||||
return hasPantheon() && !isMajorReligion()
|
||||
}
|
||||
|
||||
|
||||
fun isMajorReligion(): Boolean {
|
||||
return founderBeliefs.isNotEmpty() && followerBeliefs.isNotEmpty()
|
||||
if ("" in followerBeliefs) return true // Temporary as a result of follower beliefs not yet being implemented
|
||||
return founderBeliefs.isNotEmpty() && followerBeliefs.any { gameInfo.ruleSet.beliefs[it]!!.type == "Follower"}
|
||||
}
|
||||
|
||||
|
||||
fun hasPantheon(): Boolean {
|
||||
return pantheonBeliefs.isNotEmpty()
|
||||
// Temporary as a result of follower beliefs not yet being implemented
|
||||
return followerBeliefs.any { it != "" && gameInfo.ruleSet.beliefs[it]!!.type == "Pantheon" }
|
||||
}
|
||||
}
|
@ -35,5 +35,6 @@ enum class UnitActionType(val value: String) {
|
||||
StartGoldenAge("Start Golden Age"),
|
||||
HurryWonder("Hurry Wonder"),
|
||||
ConductTradeMission("Conduct Trade Mission"),
|
||||
FoundReligion("Found a Religion"),
|
||||
DisbandUnit("Disband unit")
|
||||
}
|
@ -45,21 +45,23 @@ class Ruleset {
|
||||
var modWithReligionLoaded = false
|
||||
|
||||
var name = ""
|
||||
val beliefs = LinkedHashMap<String, Belief>()
|
||||
val religions = ArrayList<String>()
|
||||
val buildings = LinkedHashMap<String, Building>()
|
||||
val terrains = LinkedHashMap<String, Terrain>()
|
||||
val tileResources = LinkedHashMap<String, TileResource>()
|
||||
val tileImprovements = LinkedHashMap<String, TileImprovement>()
|
||||
val technologies = LinkedHashMap<String, Technology>()
|
||||
val difficulties = LinkedHashMap<String, Difficulty>()
|
||||
val eras = LinkedHashMap<String, Era>()
|
||||
val units = LinkedHashMap<String, BaseUnit>()
|
||||
val unitPromotions = LinkedHashMap<String, Promotion>()
|
||||
val nations = LinkedHashMap<String, Nation>()
|
||||
val policies = LinkedHashMap<String, Policy>()
|
||||
val policyBranches = LinkedHashMap<String, PolicyBranch>()
|
||||
val quests = LinkedHashMap<String, Quest>()
|
||||
val specialists = LinkedHashMap<String, Specialist>()
|
||||
val policyBranches = LinkedHashMap<String, PolicyBranch>()
|
||||
val policies = LinkedHashMap<String, Policy>()
|
||||
val beliefs = LinkedHashMap<String, Belief>()
|
||||
val difficulties = LinkedHashMap<String, Difficulty>()
|
||||
val technologies = LinkedHashMap<String, Technology>()
|
||||
val terrains = LinkedHashMap<String, Terrain>()
|
||||
val tileImprovements = LinkedHashMap<String, TileImprovement>()
|
||||
val tileResources = LinkedHashMap<String, TileResource>()
|
||||
val units = LinkedHashMap<String, BaseUnit>()
|
||||
val unitPromotions = LinkedHashMap<String, Promotion>()
|
||||
|
||||
val mods = LinkedHashSet<String>()
|
||||
var modOptions = ModOptions()
|
||||
|
||||
@ -82,10 +84,12 @@ class Ruleset {
|
||||
difficulties.putAll(ruleset.difficulties)
|
||||
eras.putAll(ruleset.eras)
|
||||
nations.putAll(ruleset.nations)
|
||||
for (nationToRemove in ruleset.modOptions.nationsToRemove) nations.remove(nationToRemove)
|
||||
policyBranches.putAll(ruleset.policyBranches)
|
||||
policies.putAll(ruleset.policies)
|
||||
beliefs.putAll(ruleset.beliefs)
|
||||
quests.putAll(ruleset.quests)
|
||||
religions.addAll(ruleset.religions)
|
||||
specialists.putAll(ruleset.specialists)
|
||||
technologies.putAll(ruleset.technologies)
|
||||
for (techToRemove in ruleset.modOptions.techsToRemove) technologies.remove(techToRemove)
|
||||
@ -95,7 +99,6 @@ class Ruleset {
|
||||
unitPromotions.putAll(ruleset.unitPromotions)
|
||||
units.putAll(ruleset.units)
|
||||
for (unitToRemove in ruleset.modOptions.unitsToRemove) units.remove(unitToRemove)
|
||||
for (nationToRemove in ruleset.modOptions.nationsToRemove) nations.remove(nationToRemove)
|
||||
mods += ruleset.mods
|
||||
modWithReligionLoaded = modWithReligionLoaded || ruleset.modWithReligionLoaded
|
||||
}
|
||||
@ -110,6 +113,7 @@ class Ruleset {
|
||||
mods.clear()
|
||||
nations.clear()
|
||||
policies.clear()
|
||||
religions.clear()
|
||||
quests.clear()
|
||||
technologies.clear()
|
||||
terrains.clear()
|
||||
@ -157,6 +161,7 @@ class Ruleset {
|
||||
|
||||
val erasFile = folderHandle.child("Eras.json")
|
||||
if (erasFile.exists()) eras += createHashmap(jsonParser.getFromJson(Array<Era>::class.java, erasFile))
|
||||
|
||||
val unitsFile = folderHandle.child("Units.json")
|
||||
if (unitsFile.exists()) units += createHashmap(jsonParser.getFromJson(Array<BaseUnit>::class.java, unitsFile))
|
||||
|
||||
@ -189,6 +194,9 @@ class Ruleset {
|
||||
if (beliefsFile.exists())
|
||||
beliefs += createHashmap(jsonParser.getFromJson(Array<Belief>::class.java, beliefsFile))
|
||||
|
||||
val religionsFile = folderHandle.child("Religions.json")
|
||||
if (religionsFile.exists())
|
||||
religions += jsonParser.getFromJson(Array<String>::class.java, religionsFile).toList()
|
||||
|
||||
val nationsFile = folderHandle.child("Nations.json")
|
||||
if (nationsFile.exists()) {
|
||||
|
@ -147,7 +147,7 @@ class CityScreen(internal val city: CityInfo): CameraStageBaseScreen() {
|
||||
val razeCityButton = "Raze city".toTextButton()
|
||||
razeCityButton.labelCell.pad(10f)
|
||||
razeCityButton.onClick { city.isBeingRazed = true; update() }
|
||||
if (!canChangeState || city.isOriginalCapital)
|
||||
if (!canChangeState || !city.canBeDestroyed())
|
||||
razeCityButton.disable()
|
||||
|
||||
razeCityButtonHolder.add(razeCityButton).colspan(cityPickerTable.columns)
|
||||
|
@ -0,0 +1,99 @@
|
||||
package com.unciv.ui.pickerscreens
|
||||
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.*
|
||||
import com.badlogic.gdx.utils.Align
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.logic.GameInfo
|
||||
import com.unciv.logic.civilization.CivilizationInfo
|
||||
import com.unciv.models.UncivSound
|
||||
import com.unciv.models.ruleset.Belief
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.utils.*
|
||||
import kotlin.math.max
|
||||
|
||||
class FoundReligionPickerScreen (
|
||||
private val choosingCiv: CivilizationInfo,
|
||||
private val gameInfo: GameInfo
|
||||
): PickerScreen() {
|
||||
|
||||
// Roughly follows the layout of the original (although I suck at UI designing, so please improve this)
|
||||
private val topReligionIcons = Table() // Top of the layout, contains icons for religions
|
||||
private val leftChosenBeliefs: ScrollPane // Left middle part, contains buttons to select the types of beliefs to choose
|
||||
private val rightBeliefsToChoose: ScrollPane // Right middle part, contains the beliefs to choose
|
||||
|
||||
private val middlePanes = Table()
|
||||
|
||||
private var previouslySelectedIcon: Button? = null
|
||||
private var iconName: String? = null
|
||||
private var religionName: String? = null
|
||||
private var chosenFounderBelief: Belief? = null
|
||||
private var chosenFollowerBelief: Belief? = null
|
||||
|
||||
init {
|
||||
closeButton.isVisible = true
|
||||
setDefaultCloseAction()
|
||||
|
||||
setupReligionIcons()
|
||||
|
||||
leftChosenBeliefs = ScrollPane(Table())
|
||||
rightBeliefsToChoose = ScrollPane(Table())
|
||||
|
||||
middlePanes.add(leftChosenBeliefs)
|
||||
middlePanes.addSeparatorVertical()
|
||||
middlePanes.add(rightBeliefsToChoose)
|
||||
|
||||
topTable.add(topReligionIcons).row()
|
||||
// commented out, as the middle panes will always be empty for now, and this will create a random line otherwise
|
||||
// topTable.addSeparator()
|
||||
topTable.add(middlePanes)
|
||||
|
||||
rightSideButton.label = "Choose a religion".toLabel()
|
||||
rightSideButton.onClick(UncivSound.Choir) {
|
||||
choosingCiv.religionManager.foundReligion(iconName!!, religionName!!, "", "", /**chosenFollowerBelief!!.name, chosenFounderBelief!!.name*/)
|
||||
UncivGame.Current.setWorldScreen()
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkAndEnableRightSideButton() {
|
||||
if (religionName == null) return
|
||||
// check if founder belief chosen
|
||||
// check if follower belief chosen
|
||||
rightSideButton.enable()
|
||||
}
|
||||
|
||||
private fun setupReligionIcons() {
|
||||
topReligionIcons.clear()
|
||||
|
||||
// This should later be replaced with a user-modifiable text field, but not in this PR
|
||||
val descriptionLabel = "Choose an Icon and name for your Religion".toLabel()
|
||||
|
||||
val iconsTable = Table()
|
||||
iconsTable.align(Align.center)
|
||||
for (religionName in gameInfo.ruleSet.religions) {
|
||||
if (gameInfo.religions.keys.any { it == religionName }) continue
|
||||
val image = ImageGetter.getReligionIcon(religionName)
|
||||
image.color = Color.BLACK
|
||||
val icon = image.surroundWithCircle(60f)
|
||||
val button = Button(icon, skin)
|
||||
val translatedReligionName = religionName.tr()
|
||||
button.onClick {
|
||||
if (previouslySelectedIcon != null) {
|
||||
previouslySelectedIcon!!.enable()
|
||||
}
|
||||
iconName = religionName
|
||||
this.religionName = religionName
|
||||
previouslySelectedIcon = button
|
||||
button.disable()
|
||||
descriptionLabel.setText(translatedReligionName)
|
||||
rightSideButton.label = "Found [$translatedReligionName]".toLabel()
|
||||
checkAndEnableRightSideButton()
|
||||
}
|
||||
if (religionName == this.religionName) button.disable()
|
||||
iconsTable.add(button).pad(5f)
|
||||
}
|
||||
iconsTable.row()
|
||||
topReligionIcons.add(iconsTable).padBottom(10f).row()
|
||||
topReligionIcons.add(descriptionLabel).center()
|
||||
}
|
||||
}
|
@ -12,7 +12,7 @@ open class PickerScreen(val disableScroll: Boolean = false) : CameraStageBaseScr
|
||||
protected var descriptionLabel: Label
|
||||
protected var rightSideGroup = VerticalGroup()
|
||||
protected var rightSideButton: TextButton
|
||||
private var screenSplit = 0.85f
|
||||
protected var screenSplit = 0.85f
|
||||
|
||||
/**
|
||||
* The table displaying the choices from which to pick (usually).
|
||||
|
@ -251,6 +251,13 @@ class CityButton(val city: CityInfo, private val tileGroup: WorldTileGroup): Tab
|
||||
nationIcon.color = secondaryColor
|
||||
iconTable.add(nationIcon).size(20f)
|
||||
}
|
||||
|
||||
val cityReligionName = city.religion.getMajorityReligion()
|
||||
if (cityReligionName != null) {
|
||||
val cityReligion = city.civInfo.gameInfo.religions[cityReligionName]!!
|
||||
val religionImage = ImageGetter.getReligionIcon(cityReligion.iconName)
|
||||
iconTable.add(religionImage).size(20f).padLeft(5f).fillY()
|
||||
}
|
||||
|
||||
iconTable.pack()
|
||||
cityStrengthLabel.x = label.x // so it'll be aligned right above the city name
|
||||
|
@ -56,8 +56,7 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() {
|
||||
private fun updateLeftSideTable() {
|
||||
leftSideTable.clear()
|
||||
for (civ in viewingCiv.gameInfo.civilizations
|
||||
.filterNot { it.isDefeated() || it == viewingCiv || it.isBarbarian() || it.isSpectator() }) {
|
||||
if (!viewingCiv.knows(civ)) continue
|
||||
.filterNot { it.isDefeated() || it == viewingCiv || it.isBarbarian() || it.isSpectator() || viewingCiv.knows(it) }) {
|
||||
|
||||
val civIndicator = ImageGetter.getNationIndicator(civ.nation, 100f)
|
||||
|
||||
|
@ -287,6 +287,10 @@ object ImageGetter {
|
||||
}
|
||||
return circle
|
||||
}
|
||||
|
||||
fun getReligionIcon(iconName: String): Image {
|
||||
return getImage("ReligionIcons/$iconName")
|
||||
}
|
||||
|
||||
fun getBlue() = Color(0x004085bf)
|
||||
|
||||
|
@ -142,7 +142,7 @@ class AlertPopup(val worldScreen: WorldScreen, val popupAlert: PopupAlert): Popu
|
||||
close()
|
||||
}
|
||||
add("Raze".toTextButton().apply {
|
||||
if (city.isOriginalCapital) disable()
|
||||
if (!city.canBeDestroyed()) disable()
|
||||
else {
|
||||
onClick(function = razeAction)
|
||||
keyPressDispatcher['r'] = razeAction
|
||||
|
@ -19,6 +19,7 @@ import com.unciv.UncivGame
|
||||
import com.unciv.logic.GameInfo
|
||||
import com.unciv.logic.GameSaver
|
||||
import com.unciv.logic.civilization.CivilizationInfo
|
||||
import com.unciv.logic.civilization.ReligionState
|
||||
import com.unciv.logic.civilization.diplomacy.DiplomaticStatus
|
||||
import com.unciv.models.Tutorial
|
||||
import com.unciv.models.UncivSound
|
||||
@ -697,6 +698,11 @@ class WorldScreen(val gameInfo: GameInfo, val viewingCiv:CivilizationInfo) : Cam
|
||||
NextTurnAction("Found Pantheon", Color.WHITE) {
|
||||
game.setScreen(PantheonPickerScreen(viewingCiv, gameInfo))
|
||||
}
|
||||
|
||||
viewingCiv.religionManager.religionState == ReligionState.FoundingReligion ->
|
||||
NextTurnAction("Found Religion", Color.WHITE) {
|
||||
game.setScreen(FoundReligionPickerScreen(viewingCiv, gameInfo))
|
||||
}
|
||||
|
||||
else ->
|
||||
NextTurnAction("${Fonts.turn}{Next turn}", Color.WHITE) {
|
||||
|
@ -63,6 +63,7 @@ object UnitActions {
|
||||
//
|
||||
addCreateWaterImprovements(unit, actionList)
|
||||
addGreatPersonActions(unit, actionList, tile)
|
||||
addFoundReligionAction(unit, actionList, tile)
|
||||
addSpreadReligionActions(unit, actionList, tile)
|
||||
actionList += getImprovementConstructionActions(unit, tile)
|
||||
addDisbandAction(actionList, unit, worldScreen)
|
||||
@ -372,7 +373,8 @@ object UnitActions {
|
||||
unit.civInfo.tech.addScience(unit.civInfo.tech.getScienceFromGreatScientist())
|
||||
addGoldPerGreatPersonUsage(unit.civInfo)
|
||||
unit.destroy()
|
||||
}.takeIf { unit.civInfo.tech.currentTechnologyName() != null })
|
||||
}.takeIf { unit.civInfo.tech.currentTechnologyName() != null }
|
||||
)
|
||||
}
|
||||
"Can start an []-turn golden age" -> {
|
||||
val turnsToGoldenAge = unique.params[0].toInt()
|
||||
@ -382,7 +384,8 @@ object UnitActions {
|
||||
unit.civInfo.goldenAges.enterGoldenAge(turnsToGoldenAge)
|
||||
addGoldPerGreatPersonUsage(unit.civInfo)
|
||||
unit.destroy()
|
||||
}.takeIf { unit.currentTile.getOwner() != null && unit.currentTile.getOwner() == unit.civInfo })
|
||||
}.takeIf { unit.currentTile.getOwner() != null && unit.currentTile.getOwner() == unit.civInfo }
|
||||
)
|
||||
}
|
||||
"Can speed up construction of a wonder" -> {
|
||||
val canHurryWonder = if (!tile.isCityCenter()) false
|
||||
@ -400,7 +403,8 @@ object UnitActions {
|
||||
}
|
||||
addGoldPerGreatPersonUsage(unit.civInfo)
|
||||
unit.destroy()
|
||||
}.takeIf { canHurryWonder })
|
||||
}.takeIf { canHurryWonder }
|
||||
)
|
||||
}
|
||||
"Can undertake a trade mission with City-State, giving a large sum of gold and [] Influence" -> {
|
||||
val canConductTradeMission = tile.owningCity?.civInfo?.isCityState() == true
|
||||
@ -419,16 +423,30 @@ object UnitActions {
|
||||
tile.owningCity!!.civInfo.civName, NotificationIcon.Gold, NotificationIcon.Culture)
|
||||
addGoldPerGreatPersonUsage(unit.civInfo)
|
||||
unit.destroy()
|
||||
}.takeIf { canConductTradeMission })
|
||||
}.takeIf { canConductTradeMission }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun addFoundReligionAction(unit: MapUnit, actionList: ArrayList<UnitAction>, tile: TileInfo) {
|
||||
if (!unit.hasUnique("May found a religion")) return // should later also include enhance religion
|
||||
if (!unit.civInfo.religionManager.mayUseGreatProphetAtAll(unit)) return
|
||||
actionList += UnitAction(UnitActionType.FoundReligion,
|
||||
uncivSound = UncivSound.Choir,
|
||||
action = {
|
||||
addGoldPerGreatPersonUsage(unit.civInfo)
|
||||
unit.civInfo.religionManager.useGreatProphet(unit)
|
||||
unit.destroy()
|
||||
}.takeIf { unit.civInfo.religionManager.mayUseGreatProphetNow(unit) }
|
||||
)
|
||||
}
|
||||
|
||||
private fun addSpreadReligionActions(unit: MapUnit, actionList: ArrayList<UnitAction>, tile: TileInfo) {
|
||||
if (!unit.hasUnique("Can spread religion [] times")) return
|
||||
if (unit.religion == null) return
|
||||
val maxReligionSpreads = unit.maxReligionSpreads()
|
||||
if (!unit.abilityUsedCount.containsKey("Religion Spread")) return // This should be impossible anways, but just in case
|
||||
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()
|
||||
actionList += UnitAction(UnitActionType.SpreadReligion,
|
||||
|
@ -178,6 +178,7 @@ Unless otherwise specified, all the following are from [the Noun Project](https:
|
||||
* [Fort](https://thenounproject.com/term/fort/1697645/) By Adrien Coquet
|
||||
* [Citadel](https://thenounproject.com/term/fort/1697646/) By Adrien Coquet
|
||||
* [Village](https://thenounproject.com/search/?q=city+center&i=476338) by Andrey Vasiliev
|
||||
* [pumping station](https://thenounproject.com/search/?q=dike&i=555172) by Peter van Driel for Polder
|
||||
|
||||
## Buildings
|
||||
|
||||
@ -551,6 +552,14 @@ Unless otherwise specified, all the following are from [the Noun Project](https:
|
||||
* [Anchor](https://thenounproject.com/term/anchor/676586) by Gregor Cresnar for Amphibious
|
||||
* [survival knife](https://thenounproject.com/search/?q=survival&i=2663392) by b faris for Survivalism
|
||||
|
||||
## Religions
|
||||
* [Lightning Bolt](https://thenounproject.com/search/?q=lightning+bolt&i=154820) by sian huxtable for Pantheon
|
||||
* [Christianity](https://thenounproject.com/search/?q=christianity&i=181) by Public Domain Nouns for Christianity
|
||||
* [Islam](https://thenounproject.com/search/?q=Islam&i=2431350) by Muhammed Riza for Islam
|
||||
* [taoism](https://thenounproject.com/search/?q=Taoism&i=740812) by parkjisun for Taosim
|
||||
* [Buddhism](https://thenounproject.com/search/?q=buddhism&i=38764) by Julio Yanes for Buddhism
|
||||
* [Hinduism](https://thenounproject.com/search/?q=hinduism&i=20383) by Mugda Damle for Hinduism
|
||||
|
||||
## Others
|
||||
|
||||
* [Circle](https://thenounproject.com/term/circle/1841891/) By Aybige
|
||||
|