From ddb26dc56d4f60fb416223434c1ff509862a11df Mon Sep 17 00:00:00 2001 From: SomeTroglodyte <63000004+SomeTroglodyte@users.noreply.github.com> Date: Mon, 21 Mar 2022 20:02:50 +0100 Subject: [PATCH] Fix CS unit gift crash (#6393) * Fix CS unit gift crash * Clarify CityStateGreatPersonGift decision * Removed misplaced comment --- .../logic/civilization/CityStateFunctions.kt | 34 ++++++++++++++----- .../logic/civilization/CivilizationInfo.kt | 14 ++++---- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/core/src/com/unciv/logic/civilization/CityStateFunctions.kt b/core/src/com/unciv/logic/civilization/CityStateFunctions.kt index bbdefd1266..26013be6dd 100644 --- a/core/src/com/unciv/logic/civilization/CityStateFunctions.kt +++ b/core/src/com/unciv/logic/civilization/CityStateFunctions.kt @@ -7,6 +7,7 @@ import com.unciv.models.ruleset.Ruleset import com.unciv.models.ruleset.tile.ResourceSupplyList import com.unciv.models.ruleset.unique.Unique import com.unciv.models.ruleset.unique.UniqueType +import com.unciv.models.ruleset.unit.BaseUnit import com.unciv.models.stats.Stat import com.unciv.ui.victoryscreen.RankingType import java.util.* @@ -88,14 +89,24 @@ class CityStateFunctions(val civInfo: CivilizationInfo) { fun giveMilitaryUnitToPatron(receivingCiv: CivilizationInfo) { val cities = NextTurnAutomation.getClosestCities(receivingCiv, civInfo) val city = cities.city1 - val uniqueUnit = civInfo.gameInfo.ruleSet.units[civInfo.cityStateUniqueUnit] - // If the receiving civ has discovered the required tech and not the obsolete tech for our unique, always give them the unique - val militaryUnit = if (uniqueUnit != null && receivingCiv.tech.isResearched(uniqueUnit.requiredTech!!) - && (uniqueUnit.obsoleteTech == null || !receivingCiv.tech.isResearched(uniqueUnit.obsoleteTech!!))) uniqueUnit - // Otherwise pick at random - else city.cityConstructions.getConstructableUnits() - .filter { !it.isCivilian() && it.isLandUnit() && it.uniqueTo==null } - .toList().random() + + fun giftableUniqueUnit(): BaseUnit? { + val uniqueUnit = civInfo.gameInfo.ruleSet.units[civInfo.cityStateUniqueUnit] + ?: return null + if (uniqueUnit.requiredTech != null && !receivingCiv.tech.isResearched(uniqueUnit.requiredTech!!)) + return null + if (uniqueUnit.obsoleteTech != null && receivingCiv.tech.isResearched(uniqueUnit.obsoleteTech!!)) + return null + return uniqueUnit + } + fun randomGiftableUnit() = + city.cityConstructions.getConstructableUnits() + .filter { !it.isCivilian() && it.isLandUnit() && it.uniqueTo == null } + .toList().randomOrNull() + val militaryUnit = giftableUniqueUnit() // If the receiving civ has discovered the required tech and not the obsolete tech for our unique, always give them the unique + ?: randomGiftableUnit() // Otherwise pick at random + ?: return // That filter _can_ result in no candidates, if so, quit silently + // placing the unit may fail - in that case stay quiet val placedUnit = receivingCiv.placeUnitNearTile(city.location, militaryUnit.name) ?: return @@ -110,7 +121,12 @@ class CityStateFunctions(val civInfo: CivilizationInfo) { // Point to the places mentioned in the message _in that order_ (debatable) val placedLocation = placedUnit.getTile().position val locations = LocationAction(placedLocation, cities.city2.location, city.location) - receivingCiv.addNotification("[${civInfo.civName}] gave us a [${militaryUnit.name}] as gift near [${city.name}]!", locations, civInfo.civName, militaryUnit.name) + receivingCiv.addNotification( + "[${civInfo.civName}] gave us a [${militaryUnit.name}] as gift near [${city.name}]!", + locations, + civInfo.civName, + militaryUnit.name + ) } fun influenceGainedByGift(donorCiv: CivilizationInfo, giftAmount: Int): Int { diff --git a/core/src/com/unciv/logic/civilization/CivilizationInfo.kt b/core/src/com/unciv/logic/civilization/CivilizationInfo.kt index bc6691cc58..f4b441dd8b 100644 --- a/core/src/com/unciv/logic/civilization/CivilizationInfo.kt +++ b/core/src/com/unciv/logic/civilization/CivilizationInfo.kt @@ -876,14 +876,15 @@ class CivilizationInfo { if (!flagsCountdown.containsKey(flag)) continue if (flag == CivFlags.CityStateGreatPersonGift.name) { - val cityStateAllies = getKnownCivs().filter { it.isCityState() && it.getAllyCiv() == civName } + val cityStateAllies: List = + getKnownCivs().filter { it.isCityState() && it.getAllyCiv() == civName } + val givingCityState = cityStateAllies.filter { it.cities.isNotEmpty() }.randomOrNull() - if (cityStateAllies.any()) flagsCountdown[flag] = flagsCountdown[flag]!! - 1 + if (cityStateAllies.isNotEmpty()) flagsCountdown[flag] = flagsCountdown[flag]!! - 1 - if (flagsCountdown[flag]!! < min(cityStateAllies.count(), 10) && cities.isNotEmpty() - && cityStateAllies.any { it.cities.isNotEmpty() } + if (flagsCountdown[flag]!! < min(cityStateAllies.size, 10) && cities.isNotEmpty() + && givingCityState != null ) { - val givingCityState = getKnownCivs().filter { it.isCityState() && it.getAllyCiv() == civName && it.cities.isNotEmpty()}.random() givingCityState.cityStateFunctions.giveGreatPersonToPatron(this) flagsCountdown[flag] = turnsForGreatPersonFromCityState() } @@ -1247,10 +1248,9 @@ class CivilizationInfo { return proximity } - + //////////////////////// City State wrapper functions //////////////////////// - /** Gain a random great person from the city state */ fun receiveGoldGift(donorCiv: CivilizationInfo, giftAmount: Int) = cityStateFunctions.receiveGoldGift(donorCiv, giftAmount) fun turnsForGreatPersonFromCityState(): Int = ((37 + Random().nextInt(7)) * gameInfo.gameParameters.gameSpeed.modifier).toInt()