Fixed a few combat bugs and changed the religions founded label (#5846)

* Fixed a bug where bonusses applying 'in friendly tiles' would not apply

* Reworded something so it actually makes sense

* Fixed capitalization error leading to autocracy complete bonus no longer working

* Fixed save serialization errors and finally correctly implemented the time limit for autocracy bonus

* Made value const and static
This commit is contained in:
Xander Lenstra 2021-12-26 06:31:07 +01:00 committed by GitHub
parent c62006cf72
commit f03918f610
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 56 additions and 28 deletions

View File

@ -1177,7 +1177,7 @@ Cities following this religion: =
Click an icon to see the stats of this religion =
Religion: Off =
Minimal faith required for\nthe next [Great Prophet]: =
Religions founded: =
Religions to be founded: =
Religious status: =
None =

View File

@ -19,6 +19,7 @@ import com.unciv.models.ruleset.tile.ResourceSupplyList
import com.unciv.models.ruleset.tile.ResourceType
import com.unciv.models.ruleset.tile.TileResource
import com.unciv.models.ruleset.unique.StateForConditionals
import com.unciv.models.ruleset.unique.TemporaryUnique
import com.unciv.models.ruleset.unique.Unique
import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.ruleset.unit.BaseUnit
@ -142,12 +143,12 @@ class CivilizationInfo {
/** See DiplomacyManager.flagsCountdown for why this does not map Enums to ints */
private var flagsCountdown = HashMap<String, Int>()
/** Arraylist instead of HashMap as there might be doubles
* 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
/** Arraylist instead of HashMap as the same unique might appear multiple times
* We don't use pairs, as these cannot be serialized due to having no no-arg constructor
*/
val temporaryUniques = ArrayList<Pair<Unique, Int>>()
val temporaryUniques = ArrayList<TemporaryUnique>()
// if we only use lists, and change the list each time the cities are changed,
// we won't get concurrent modification exceptions.
// This is basically a way to ensure our lists are immutable.
@ -358,7 +359,7 @@ class CivilizationInfo {
// Does not return local uniques, only global ones.
/** Destined to replace getMatchingUniques, gradually, as we fill the enum */
fun getMatchingUniques(uniqueType: UniqueType, stateForConditionals: StateForConditionals? = null, cityToIgnore: CityInfo? = null) = sequence {
yieldAll(nation.uniqueObjects.asSequence().filter {it.isOfType(uniqueType) })
yieldAll(nation.uniqueObjects.asSequence().filter { it.isOfType(uniqueType) })
yieldAll(cities.asSequence()
.filter { it != cityToIgnore }
.flatMap { city -> city.getMatchingUniquesWithNonLocalEffects(uniqueType) }
@ -366,7 +367,7 @@ class CivilizationInfo {
yieldAll(policies.policyUniques.getUniques(uniqueType))
yieldAll(tech.techUniques.getUniques(uniqueType))
yieldAll(temporaryUniques.asSequence()
.map { it.first }
.map { it.uniqueObject }
.filter { it.isOfType(uniqueType) }
)
yieldAll(getEra().getMatchingUniques(uniqueType, stateForConditionals))
@ -385,7 +386,8 @@ class CivilizationInfo {
yieldAll(policies.policyUniques.getUniques(uniqueTemplate))
yieldAll(tech.techUniques.getUniques(uniqueTemplate))
yieldAll(temporaryUniques.asSequence()
.filter { it.first.placeholderText == uniqueTemplate }.map { it.first }
.map { it.uniqueObject }
.filter { it.placeholderText == uniqueTemplate }
)
yieldAll(getEra().getMatchingUniques(uniqueTemplate).asSequence())
if (religionManager.religion != null)
@ -725,7 +727,7 @@ class CivilizationInfo {
tech.setTransients()
ruinsManager.setTransients(this)
for (diplomacyManager in diplomacy.values) {
diplomacyManager.civInfo = this
diplomacyManager.updateHasOpenBorders()
@ -852,10 +854,10 @@ class CivilizationInfo {
}
// Update turn counter for temporary uniques
for (unique in temporaryUniques.toList()) {
temporaryUniques.remove(unique)
if (unique.second > 1) temporaryUniques.add(Pair(unique.first, unique.second - 1))
for (unique in temporaryUniques) {
unique.turnsLeft -= 1
}
temporaryUniques.removeAll { it.turnsLeft <= 0 }
goldenAges.endTurn(getHappiness())
getCivUnits().forEach { it.endTurn() } // This is the most expensive part of endTurn

View File

@ -28,7 +28,11 @@ class PolicyManager {
var shouldOpenPolicyPicker = false
get() = field && canAdoptPolicy()
// Only instantiate a single value for all policy managers
companion object {
private val turnCountRegex by lazy { Regex("for \\[[0-9]*\\] turns") }
}
fun clone(): PolicyManager {
val toReturn = PolicyManager()
toReturn.numberOfAdoptedPolicies = numberOfAdoptedPolicies
@ -47,8 +51,11 @@ class PolicyManager {
}
fun addPolicyToTransients(policy: Policy) {
for (unique in policy.uniqueObjects)
policyUniques.addUnique(unique)
for (unique in policy.uniqueObjects) {
// Should be replaced with a conditional of the same form later
if (!unique.text.contains(turnCountRegex))
policyUniques.addUnique(unique)
}
}
fun addCulture(culture: Int) {

View File

@ -88,16 +88,16 @@ class Unique(val text: String, val sourceObjectType: UniqueTarget? = null, val s
UniqueType.ConditionalBelowHP ->
state.ourCombatant != null && state.ourCombatant.getHealth() < condition.params[0].toInt()
UniqueType.ConditionalInTiles ->
(state.attackedTile != null && state.attackedTile.matchesFilter(condition.params[0]))
|| (state.unit != null && state.unit.getTile().matchesFilter(condition.params[0]))
(state.attackedTile != null && state.attackedTile.matchesFilter(condition.params[0], state.civInfo))
|| (state.unit != null && state.unit.getTile().matchesFilter(condition.params[0], state.civInfo))
UniqueType.ConditionalFightingInTiles ->
state.attackedTile != null && state.attackedTile.matchesFilter(condition.params[0])
state.attackedTile != null && state.attackedTile.matchesFilter(condition.params[0], state.civInfo)
UniqueType.ConditionalInTilesAnd ->
(state.attackedTile != null && state.attackedTile.matchesFilter(condition.params[0]) && state.attackedTile.matchesFilter(condition.params[1]))
|| (state.unit != null && state.unit.getTile().matchesFilter(condition.params[0]) && state.unit.getTile().matchesFilter(condition.params[1]))
(state.attackedTile != null && state.attackedTile.matchesFilter(condition.params[0], state.civInfo) && state.attackedTile.matchesFilter(condition.params[1], state.civInfo))
|| (state.unit != null && state.unit.getTile().matchesFilter(condition.params[0], state.civInfo) && state.unit.getTile().matchesFilter(condition.params[1], state.civInfo))
UniqueType.ConditionalInTilesNot ->
state.attackedTile != null && !state.attackedTile.matchesFilter(condition.params[0])
|| (state.unit != null && !state.unit.getTile().matchesFilter(condition.params[0]))
state.attackedTile != null && !state.attackedTile.matchesFilter(condition.params[0], state.civInfo)
|| (state.unit != null && !state.unit.getTile().matchesFilter(condition.params[0], state.civInfo))
UniqueType.ConditionalVsLargerCiv -> {
val yourCities = state.civInfo?.cities?.size ?: 1
val theirCities = state.theirCombatant?.getCivInfo()?.cities?.size ?: 0
@ -159,4 +159,21 @@ class UniqueMapTyped: EnumMap<UniqueType, ArrayList<Unique>>(UniqueType::class.j
fun getUniques(uniqueType: UniqueType): Sequence<Unique> =
this[uniqueType]?.asSequence() ?: sequenceOf()
}
// Will probably be allowed to be used as a conditional when I get the motivation to work on that -xlenstra
class TemporaryUnique() {
constructor(uniqueObject: Unique, turns: Int) : this() {
unique = uniqueObject.text
turnsLeft = turns
}
var unique: String = ""
@delegate:Transient
val uniqueObject: Unique by lazy { Unique(unique) }
var turnsLeft: Int = 0
}

View File

@ -246,7 +246,8 @@ object UniqueTriggerActivation {
}
TimedAttackStrength -> {
civInfo.temporaryUniques.add(Pair(unique, unique.params[2].toInt()))
val temporaryUnique = TemporaryUnique(unique, unique.params[2].toInt())
civInfo.temporaryUniques.add(temporaryUnique)
if (notification != null) {
civInfo.addNotification(notification, NotificationIcon.War)
}

View File

@ -451,7 +451,8 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget, val flags:
// todo: remove forced sign
StrategicResourcesIncrease("Quantity of strategic resources produced by the empire +[amount]%", UniqueTarget.Global), // used in Policy
// todo: remove forced sign
TimedAttackStrength("+[amount]% attack strength to all [mapUnitFilter] Units for [amount] turns", UniqueTarget.Global), // used in Policy
// todo: convert to "[amount]% Strength <when attacking> <for [baseUnitFilter] units> <for [amount] turns>"
TimedAttackStrength("+[amount]% attack strength to all [mapUnitFilter] units for [amount] turns", UniqueTarget.Global), // used in Policy
FreeStatBuildings("Provides the cheapest [stat] building in your first [amount] cities for free", UniqueTarget.Global), // used in Policy
FreeSpecificBuildings("Provides a [buildingName] in your first [amount] cities for free", UniqueTarget.Global), // used in Policy

View File

@ -57,7 +57,7 @@ class ReligionOverviewTable(
).right().pad(5f).row()
}
statsTable.add("Religions founded:".toLabel()).left()
statsTable.add("Religions to be founded:".toLabel()).left()
val foundedReligions = viewingPlayer.gameInfo.civilizations.count { it.religionManager.religionState >= ReligionState.Religion }
statsTable.add((viewingPlayer.religionManager.amountOfFoundableReligions() - foundedReligions).toLabel()).right().pad(5f).row()

View File

@ -334,8 +334,8 @@ Example: "Quantity of strategic resources produced by the empire +[20]%"
Applicable to: Global
#### +[amount]% attack strength to all [mapUnitFilter] Units for [amount] turns
Example: "+[20]% attack strength to all [Wounded] Units for [20] turns"
#### +[amount]% attack strength to all [mapUnitFilter] units for [amount] turns
Example: "+[20]% attack strength to all [Wounded] units for [20] turns"
Applicable to: Global