diff --git a/android/assets/jsons/Civ V - Vanilla/Beliefs.json b/android/assets/jsons/Civ V - Vanilla/Beliefs.json index 67028b6ef6..868417346a 100644 --- a/android/assets/jsons/Civ V - Vanilla/Beliefs.json +++ b/android/assets/jsons/Civ V - Vanilla/Beliefs.json @@ -117,6 +117,47 @@ "name": "Stone Circles", "type": "Pantheon", "uniques": ["[+2 Faith] from every [Quarry]"] + }, +///////////////////////////////////////// Follower beliefs ///////////////////////////////////////// + + // Missing: asceticism (requires followers) + // Missing: cathedrals (requires purchasing with faith) + // Missing: choral music (requires followers) + { + "name": "Divine inspiration", + "type": "Follower", + "uniques": ["[+2 Faith] from every Wonder"] + }, + { + "name": "Feed the World", + "type": "Follower", + "uniques": ["[+1 Food] from every [Shrine]", "[+1 Food] from every [Temple]"] + }, + { + "name": "Guruship", + "type": "Follower", + "uniques": ["[+2 Production] if this city has at least [1] specialists"] + }, + // Missing: Holy Warriors (requires purchasing with faith) + // Missing: Liturgical drama (requires followers) + // Missing: Monasteries (requires purchasing with faith) + // Missing: Mosques (requires purchasing with faith) + // Missing: Pagodas (requires purchasing with faith) + { + "name": "Peace Gardens", + "type": "Follower", + "uniques": ["[+2 Happiness] from every [Garden]"] + }, + { + "name": "Religious Art", + "type": "Follower", + "uniques": ["[+8 Culture] from every [Hermitage]"] + }, + // Missing: Religious center (requires followers) + // Missing: Religious community (requires followers) + { + "name": "Swords into Ploughshares", + "type": "Follower", + "uniques": ["[+15]% growth [in this city] when not at war"] } - ] diff --git a/android/assets/jsons/translations/template.properties b/android/assets/jsons/translations/template.properties index 7f9ccd8902..6d18e1f488 100644 --- a/android/assets/jsons/translations/template.properties +++ b/android/assets/jsons/translations/template.properties @@ -931,6 +931,7 @@ All policies adopted = # Religions Choose an Icon and name for your Religion = +Choose a [$beliefType] belief! = Found [religionName] = # Terrains diff --git a/core/src/com/unciv/logic/city/CityStats.kt b/core/src/com/unciv/logic/city/CityStats.kt index 0345639b75..7e2d764983 100644 --- a/core/src/com/unciv/logic/city/CityStats.kt +++ b/core/src/com/unciv/logic/city/CityStats.kt @@ -159,9 +159,12 @@ class CityStats { fun getGrowthBonusFromPoliciesAndWonders(): Float { var bonus = 0f // "+[amount]% growth [cityFilter]" - for (unique in cityInfo.civInfo.getMatchingUniques("+[]% growth []")) + for (unique in cityInfo.getMatchingUniques("+[]% growth []")) if (cityInfo.matchesFilter(unique.params[1])) bonus += unique.params[0].toFloat() + for (unique in cityInfo.getMatchingUniques("+[]% growth [] when not at war")) + if (cityInfo.matchesFilter(unique.params[1]) && !cityInfo.civInfo.isAtWar()) + bonus += unique.params[0].toFloat() return bonus / 100 } @@ -277,7 +280,11 @@ class CityStats { // "[stats] in cities on [tileFilter] tiles" if (unique.placeholderText == "[] in cities on [] tiles" && cityInfo.getCenterTile().matchesTerrainFilter(unique.params[1])) - {stats.add(unique.stats); println(unique.text)} + stats.add(unique.stats) + + // "[stats] if this city has at least [amount] specialists" + if (unique.placeholderText == "[] if this city has at least [] specialists" && cityInfo.population.getNumberOfSpecialists() >= unique.params[1].toInt()) + stats.add(unique.stats) } return stats diff --git a/core/src/com/unciv/logic/civilization/ReligionManager.kt b/core/src/com/unciv/logic/civilization/ReligionManager.kt index 14ab1331b2..e255609e60 100644 --- a/core/src/com/unciv/logic/civilization/ReligionManager.kt +++ b/core/src/com/unciv/logic/civilization/ReligionManager.kt @@ -151,13 +151,13 @@ class ReligionManager { foundingCityId = prophet.getTile().getCity()!!.id } - fun foundReligion(iconName: String, name: String, founderBelief: String, followerBelief: String) { + fun foundReligion(iconName: String, name: String, founderBelief: String, followerBeliefs: List) { val newReligion = Religion(name, civInfo.gameInfo, civInfo.civName) newReligion.iconName = iconName if (religion != null) { newReligion.followerBeliefs.addAll(religion!!.followerBeliefs) } - newReligion.followerBeliefs.add(followerBelief) + newReligion.followerBeliefs.addAll(followerBeliefs) newReligion.founderBeliefs.add(founderBelief) newReligion.holyCityId = foundingCityId religion = newReligion diff --git a/core/src/com/unciv/models/Religion.kt b/core/src/com/unciv/models/Religion.kt index 52b86a06b7..99864f73bd 100644 --- a/core/src/com/unciv/models/Religion.kt +++ b/core/src/com/unciv/models/Religion.kt @@ -1,7 +1,7 @@ package com.unciv.models import com.unciv.logic.GameInfo -import com.unciv.logic.civilization.CivilizationInfo +import com.unciv.models.ruleset.Belief import com.unciv.models.ruleset.Unique import com.unciv.models.stats.INamed @@ -13,7 +13,6 @@ class Religion() : INamed { lateinit var foundingCivName: String var holyCityId: String? = null - var founderBeliefs: HashSet = hashSetOf() var followerBeliefs: HashSet = hashSetOf() @@ -39,13 +38,32 @@ class Religion() : INamed { fun setTransients(gameInfo: GameInfo) { this.gameInfo = gameInfo } - - private fun getUniquesOfBeliefs(beliefs: HashSet): Sequence { + + private fun mapToExistingBeliefs(beliefs: HashSet): List { val rulesetBeliefs = gameInfo.ruleSet.beliefs return beliefs.mapNotNull { if (it !in rulesetBeliefs) null - else rulesetBeliefs[it]!!.uniqueObjects - }.flatten().asSequence() + else rulesetBeliefs[it]!! + } + } + + fun getPantheonBeliefs(): Sequence { + return mapToExistingBeliefs(followerBeliefs) + .filter { it.type == "Pantheon" } + .asSequence() + } + + fun getFollowerBeliefs(): Sequence { + return mapToExistingBeliefs(followerBeliefs) + .filter { it.type == "Follower" } + .asSequence() + } + + private fun getUniquesOfBeliefs(beliefs: HashSet): Sequence { + return mapToExistingBeliefs(beliefs) + .map { it.uniqueObjects } + .flatten() + .asSequence() } fun getFollowerUniques(): Sequence { @@ -56,7 +74,7 @@ class Religion() : INamed { return getUniquesOfBeliefs(founderBeliefs) } - fun isPantheon(): Boolean { + fun isPantheon(): Boolean { // Currently unused return hasPantheon() && !isMajorReligion() } @@ -65,8 +83,12 @@ class Religion() : INamed { return founderBeliefs.isNotEmpty() && followerBeliefs.any { gameInfo.ruleSet.beliefs[it]!!.type == "Follower"} } - fun hasPantheon(): Boolean { + fun hasPantheon(): Boolean { // Currently unused // Temporary as a result of follower beliefs not yet being implemented return followerBeliefs.any { it != "" && gameInfo.ruleSet.beliefs[it]!!.type == "Pantheon" } } + + fun hasBelief(belief: String): Boolean { + return followerBeliefs.contains(belief) || founderBeliefs.contains(belief) + } } \ No newline at end of file diff --git a/core/src/com/unciv/models/ruleset/Belief.kt b/core/src/com/unciv/models/ruleset/Belief.kt index b52b512fc3..f6cfe4a98e 100644 --- a/core/src/com/unciv/models/ruleset/Belief.kt +++ b/core/src/com/unciv/models/ruleset/Belief.kt @@ -3,9 +3,9 @@ package com.unciv.models.ruleset import com.unciv.models.stats.INamed import java.util.ArrayList -class Belief:INamed { - override var name:String="" - var type:String="" +class Belief: INamed { + override var name: String = "" + var type: String = "" var uniques = ArrayList() val uniqueObjects: List by lazy { uniques.map { Unique(it) } } } diff --git a/core/src/com/unciv/ui/pickerscreens/FoundReligionPickerScreen.kt b/core/src/com/unciv/ui/pickerscreens/FoundReligionPickerScreen.kt index 7832738e56..4329ffc980 100644 --- a/core/src/com/unciv/ui/pickerscreens/FoundReligionPickerScreen.kt +++ b/core/src/com/unciv/ui/pickerscreens/FoundReligionPickerScreen.kt @@ -6,59 +6,63 @@ 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.Religion 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() { + private val gameInfo: GameInfo, + followerBeliefsToChoose: Int = 1, + founderBeliefsToChoose: Int = 1, +): PickerScreen(disableScroll = true) { - // Roughly follows the layout of the original (although I suck at UI designing, so please improve this) + // Roughly follows the layout of the original (although I am not very good 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 leftChosenBeliefs = Table() // Left middle part, contains buttons to select the types of beliefs to choose + private val rightBeliefsToChoose = Table() // 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 + private val chosenFollowerBeliefs: MutableList = MutableList(followerBeliefsToChoose) { null } + private val chosenFounderBeliefs: MutableList = MutableList(founderBeliefsToChoose) { null } init { closeButton.isVisible = true setDefaultCloseAction() setupReligionIcons() - - leftChosenBeliefs = ScrollPane(Table()) - rightBeliefsToChoose = ScrollPane(Table()) - middlePanes.add(leftChosenBeliefs) + updateLeftTable() + + middlePanes.add(ScrollPane(leftChosenBeliefs)) middlePanes.addSeparatorVertical() - middlePanes.add(rightBeliefsToChoose) + middlePanes.add(ScrollPane(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.addSeparator() topTable.add(middlePanes) rightSideButton.label = "Choose a religion".toLabel() rightSideButton.onClick(UncivSound.Choir) { - choosingCiv.religionManager.foundReligion(iconName!!, religionName!!, "", "", /**chosenFollowerBelief!!.name, chosenFounderBelief!!.name*/) + choosingCiv.religionManager.foundReligion( + iconName!!, religionName!!, "" /**chosenFollowerBeliefs.map {it!!.name} */, chosenFollowerBeliefs.map { it!!.name} + ) UncivGame.Current.setWorldScreen() } } - + private fun checkAndEnableRightSideButton() { if (religionName == null) return + println(chosenFollowerBeliefs) + if (chosenFollowerBeliefs.any { it == null }) return // check if founder belief chosen - // check if follower belief chosen rightSideButton.enable() } @@ -71,7 +75,6 @@ class FoundReligionPickerScreen ( 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) @@ -89,11 +92,69 @@ class FoundReligionPickerScreen ( rightSideButton.label = "Found [$translatedReligionName]".toLabel() checkAndEnableRightSideButton() } - if (religionName == this.religionName) button.disable() + if (religionName == this.religionName || gameInfo.religions.keys.any { it == religionName }) button.disable() iconsTable.add(button).pad(5f) } iconsTable.row() topReligionIcons.add(iconsTable).padBottom(10f).row() - topReligionIcons.add(descriptionLabel).center() + topReligionIcons.add(descriptionLabel).center().padBottom(5f) + } + + private fun updateLeftTable() { + leftChosenBeliefs.clear() + val currentReligion = choosingCiv.religionManager.religion ?: Religion("Unknown", gameInfo, choosingCiv.civName) + + for (pantheon in currentReligion.getPantheonBeliefs() + currentReligion.getFollowerBeliefs()) { + val beliefButton = convertBeliefToButton(pantheon) + leftChosenBeliefs.add(beliefButton).pad(10f).row() + beliefButton.disable() + } + + for (newFollowerBelief in chosenFollowerBeliefs.withIndex()) { + val newFollowerBeliefButton = + if (newFollowerBelief.value == null) emptyBeliefButton("Follower") + else convertBeliefToButton(newFollowerBelief.value!!) + + leftChosenBeliefs.add(newFollowerBeliefButton).pad(10f).row() + newFollowerBeliefButton.onClick { + loadRightTable("Follower", newFollowerBelief.index) + } + } + } + + private fun loadRightTable(beliefType: String, leftButtonIndex: Int) { + rightBeliefsToChoose.clear() + val availableBeliefs = gameInfo.ruleSet.beliefs.values + .filter { + it.type == beliefType + && gameInfo.religions.values.none { + religion -> religion.hasBelief(it.name) + } + && (!chosenFollowerBeliefs.contains(it) || chosenFollowerBeliefs[leftButtonIndex] == it) + } + for (belief in availableBeliefs) { + val beliefButton = convertBeliefToButton(belief) + beliefButton.onClick { + if (beliefType == "Follower") chosenFollowerBeliefs[leftButtonIndex] = belief + else if (beliefType == "Founder") chosenFounderBeliefs[leftButtonIndex] = belief + updateLeftTable() + checkAndEnableRightSideButton() + } + rightBeliefsToChoose.add(beliefButton).pad(10f).row() + } + } + + private fun convertBeliefToButton(belief: Belief): Button { + val contentsTable = Table() + contentsTable.add(belief.type.toLabel()).row() + contentsTable.add(belief.name.toLabel(fontSize = 24)).row() + contentsTable.add(belief.uniques.joinToString().toLabel()) + return Button(contentsTable, skin) + } + + private fun emptyBeliefButton(beliefType: String): Button { + val contentsTable = Table() + contentsTable.add("Choose a [$beliefType] belief!".toLabel()) + return Button(contentsTable, skin) } } \ No newline at end of file diff --git a/core/src/com/unciv/ui/pickerscreens/PantheonPickerScreen.kt b/core/src/com/unciv/ui/pickerscreens/PantheonPickerScreen.kt index 390e33eddb..ed102b3cf4 100644 --- a/core/src/com/unciv/ui/pickerscreens/PantheonPickerScreen.kt +++ b/core/src/com/unciv/ui/pickerscreens/PantheonPickerScreen.kt @@ -24,7 +24,7 @@ class PantheonPickerScreen(choosingCiv: CivilizationInfo, gameInfo: GameInfo) : topTable.apply { defaults().pad(10f) } for (belief in gameInfo.ruleSet.beliefs.values) { if (!choosingCiv.religionManager.isPickablePantheonBelief(belief)) continue - val beliefTable = Table().apply { touchable = Touchable.enabled; + val beliefTable = Table(skin).apply { touchable = Touchable.enabled; background = // Ideally I want to this to be the darker blue we use for pressed buttons, but I suck at UI so I'll leave it like this. if (belief == chosenPantheon) ImageGetter.getBackground(ImageGetter.getBlue())