Implemented Follower beliefs for religions (#4530)

* Minor things

* Added a few follower beliefs

* Implemented follower beliefs when founding a religion

* Added missing follower beliefs as much as possible

* Religion screen now scrolls correctly

* Buttons for chosen religions are now disabled  instead of removed, idea couresty to someTroglodyte

* Implemented requested changes
This commit is contained in:
Xander Lenstra
2021-07-19 20:51:34 +02:00
committed by GitHub
parent 50cec97354
commit c81c1b6a1b
8 changed files with 169 additions and 37 deletions

View File

@ -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"]
}
]

View File

@ -931,6 +931,7 @@ All policies adopted =
# Religions
Choose an Icon and name for your Religion =
Choose a [$beliefType] belief! =
Found [religionName] =
# Terrains

View File

@ -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

View File

@ -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<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.followerBeliefs.addAll(followerBeliefs)
newReligion.founderBeliefs.add(founderBelief)
newReligion.holyCityId = foundingCityId
religion = newReligion

View File

@ -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<String> = hashSetOf()
var followerBeliefs: HashSet<String> = hashSetOf()
@ -39,13 +38,32 @@ class Religion() : INamed {
fun setTransients(gameInfo: GameInfo) {
this.gameInfo = gameInfo
}
private fun getUniquesOfBeliefs(beliefs: HashSet<String>): Sequence<Unique> {
private fun mapToExistingBeliefs(beliefs: HashSet<String>): List<Belief> {
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<Belief> {
return mapToExistingBeliefs(followerBeliefs)
.filter { it.type == "Pantheon" }
.asSequence()
}
fun getFollowerBeliefs(): Sequence<Belief> {
return mapToExistingBeliefs(followerBeliefs)
.filter { it.type == "Follower" }
.asSequence()
}
private fun getUniquesOfBeliefs(beliefs: HashSet<String>): Sequence<Unique> {
return mapToExistingBeliefs(beliefs)
.map { it.uniqueObjects }
.flatten()
.asSequence()
}
fun getFollowerUniques(): Sequence<Unique> {
@ -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)
}
}

View File

@ -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<String>()
val uniqueObjects: List<Unique> by lazy { uniques.map { Unique(it) } }
}

View File

@ -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<Belief?> = MutableList(followerBeliefsToChoose) { null }
private val chosenFounderBeliefs: MutableList<Belief?> = 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)
}
}

View File

@ -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())