More Spectator/Barbarians fixes related to income (#9011)

* Prevent Barbarians and Spectator having income or Allies

* Prevent Barbarians and Spectator having income or Allies - fix test
This commit is contained in:
SomeTroglodyte
2023-03-23 22:57:23 +01:00
committed by GitHub
parent df879b1c02
commit da7786a2cb
5 changed files with 30 additions and 23 deletions

View File

@ -505,7 +505,7 @@ class Civilization : IsPartOfGameInfoSerialization {
*/ */
fun isDefeated() = when { fun isDefeated() = when {
isBarbarian() || isSpectator() -> false // Barbarians and voyeurs can't lose isBarbarian() || isSpectator() -> false // Barbarians and voyeurs can't lose
hasEverOwnedOriginalCapital == true -> cities.isEmpty() hasEverOwnedOriginalCapital -> cities.isEmpty()
else -> units.getCivUnits().none() else -> units.getCivUnits().none()
} }

View File

@ -222,7 +222,7 @@ class CityStateFunctions(val civInfo: Civilization) {
var newAllyName: String? = null var newAllyName: String? = null
if (!civInfo.isCityState()) return if (!civInfo.isCityState()) return
val maxInfluence = civInfo.diplomacy val maxInfluence = civInfo.diplomacy
.filter { !it.value.otherCiv().isCityState() && !it.value.otherCiv().isDefeated() } .filter { it.value.otherCiv().isMajorCiv() && !it.value.otherCiv().isDefeated() }
.maxByOrNull { it.value.getInfluence() } .maxByOrNull { it.value.getInfluence() }
if (maxInfluence != null && maxInfluence.value.getInfluence() >= 60) { if (maxInfluence != null && maxInfluence.value.getInfluence() >= 60) {
newAllyName = maxInfluence.key newAllyName = maxInfluence.key

View File

@ -17,6 +17,7 @@ import com.unciv.logic.trade.TradeEvaluation
import com.unciv.models.ruleset.ModOptionsConstants import com.unciv.models.ruleset.ModOptionsConstants
import com.unciv.models.ruleset.unique.UniqueType import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.ruleset.unique.endTurn import com.unciv.models.ruleset.unique.endTurn
import com.unciv.models.stats.Stats
import com.unciv.ui.components.MayaCalendar import com.unciv.ui.components.MayaCalendar
import java.util.* import java.util.*
import kotlin.math.max import kotlin.math.max
@ -213,8 +214,6 @@ class TurnManager(val civInfo: Civilization) {
fun endTurn() { fun endTurn() {
if (civInfo.isSpectator()) return
val notificationsLog = civInfo.notificationsLog val notificationsLog = civInfo.notificationsLog
val notificationsThisTurn = Civilization.NotificationsLog(civInfo.gameInfo.turns) val notificationsThisTurn = Civilization.NotificationsLog(civInfo.gameInfo.turns)
notificationsThisTurn.notifications.addAll(civInfo.notifications) notificationsThisTurn.notifications.addAll(civInfo.notifications)
@ -228,9 +227,15 @@ class TurnManager(val civInfo: Civilization) {
civInfo.notifications.clear() civInfo.notifications.clear()
civInfo.updateStatsForNextTurn() if (civInfo.isDefeated() || civInfo.isSpectator()) return // yes they do call this, best not update any further stuff
val nextTurnStats = civInfo.stats.statsForNextTurn var nextTurnStats =
if (civInfo.isBarbarian())
Stats()
else {
civInfo.updateStatsForNextTurn()
civInfo.stats.statsForNextTurn
}
civInfo.policies.endTurn(nextTurnStats.culture.toInt()) civInfo.policies.endTurn(nextTurnStats.culture.toInt())
civInfo.totalCultureForContests += nextTurnStats.culture.toInt() civInfo.totalCultureForContests += nextTurnStats.culture.toInt()
@ -239,17 +244,18 @@ class TurnManager(val civInfo: Civilization) {
civInfo.questManager.endTurn() civInfo.questManager.endTurn()
// disband units until there are none left OR the gold values are normal // disband units until there are none left OR the gold values are normal
if (!civInfo.isBarbarian() && civInfo.gold < -100 && nextTurnStats.gold.toInt() < 0) { if (!civInfo.isBarbarian() && civInfo.gold <= -200 && nextTurnStats.gold.toInt() < 0) {
for (i in 1 until (civInfo.gold / -100)) { val militaryUnits = civInfo.units.getCivUnits().filter { it.isMilitary() }
var civMilitaryUnits = civInfo.units.getCivUnits().filter { it.baseUnit.isMilitary() } do {
if (civMilitaryUnits.any()) { val unitToDisband = militaryUnits.minByOrNull { it.baseUnit.cost }
val unitToDisband = civMilitaryUnits.first() // or .firstOrNull()?
unitToDisband.disband() ?: break
civMilitaryUnits -= unitToDisband unitToDisband.disband()
val unitName = unitToDisband.shortDisplayName() val unitName = unitToDisband.shortDisplayName()
civInfo.addNotification("Cannot provide unit upkeep for $unitName - unit has been disbanded!", NotificationCategory.Units, unitName, NotificationIcon.Death) civInfo.addNotification("Cannot provide unit upkeep for $unitName - unit has been disbanded!", NotificationCategory.Units, unitName, NotificationIcon.Death)
} civInfo.updateStatsForNextTurn() // recalculate unit upkeep
} nextTurnStats = civInfo.stats.statsForNextTurn
} while (civInfo.gold <= -200 && nextTurnStats.gold.toInt() < 0)
} }
civInfo.addGold( nextTurnStats.gold.toInt() ) civInfo.addGold( nextTurnStats.gold.toInt() )
@ -265,13 +271,10 @@ class TurnManager(val civInfo: Civilization) {
if (civInfo.isMajorCiv()) // City-states don't get great people! if (civInfo.isMajorCiv()) // City-states don't get great people!
civInfo.greatPeople.addGreatPersonPoints() civInfo.greatPeople.addGreatPersonPoints()
// To handle tile's owner issue (#8246), we need to run being razed city first. // To handle tile's owner issue (#8246), we need to run cities being razed first.
for (city in sequence { // a city can be removed while iterating (if it's being razed) so we need to iterate over a copy - sorting does one
yieldAll(civInfo.cities.filter { it.isBeingRazed }) for (city in civInfo.cities.sortedByDescending { it.isBeingRazed })
yieldAll(civInfo.cities.filterNot { it.isBeingRazed })
}.toList()) { // a city can be removed while iterating (if it's being razed) so we need to iterate over a copy
CityTurnManager(city).endTurn() CityTurnManager(city).endTurn()
}
civInfo.temporaryUniques.endTurn() civInfo.temporaryUniques.endTurn()

View File

@ -25,6 +25,7 @@ enum class EmpireOverviewCategories(
Stats("StatIcons/Gold", 'S', Align.top) { Stats("StatIcons/Gold", 'S', Align.top) {
override fun createTab(viewingPlayer: Civilization, overviewScreen: EmpireOverviewScreen, persistedData: EmpireOverviewTabPersistableData?) = override fun createTab(viewingPlayer: Civilization, overviewScreen: EmpireOverviewScreen, persistedData: EmpireOverviewTabPersistableData?) =
StatsOverviewTab(viewingPlayer, overviewScreen) StatsOverviewTab(viewingPlayer, overviewScreen)
override fun showDisabled(viewingPlayer: Civilization) = viewingPlayer.isSpectator()
}, },
Trades("StatIcons/Acquire", 'T', Align.top) { Trades("StatIcons/Acquire", 'T', Align.top) {
override fun createTab(viewingPlayer: Civilization, overviewScreen: EmpireOverviewScreen, persistedData: EmpireOverviewTabPersistableData?) = override fun createTab(viewingPlayer: Civilization, overviewScreen: EmpireOverviewScreen, persistedData: EmpireOverviewTabPersistableData?) =

View File

@ -39,6 +39,9 @@ class TriggeredUniquesTests {
@Test @Test
fun testConditionalTimedUniqueExpires() { fun testConditionalTimedUniqueExpires() {
civInfo.policies.adopt(policy, true) civInfo.policies.adopt(policy, true)
// For endTurn to do the part we need, the civ must be alive - have a city or unit,
// and right now that attacker is not in the civ's unit list
civInfo.units.addUnit(attacker.unit, false)
TurnManager(civInfo).endTurn() TurnManager(civInfo).endTurn()
val modifiers = BattleDamage.getAttackModifiers(attacker, defender) val modifiers = BattleDamage.getAttackModifiers(attacker, defender)
Assert.assertTrue("Timed Strength should no longer work after endTurn", modifiers.sumValues() == 0) Assert.assertTrue("Timed Strength should no longer work after endTurn", modifiers.sumValues() == 0)