From 421cce0a4372d58b078707b308256b04e7a29afa Mon Sep 17 00:00:00 2001 From: Xander Lenstra <71121390+xlenstra@users.noreply.github.com> Date: Mon, 9 Aug 2021 12:57:13 +0200 Subject: [PATCH 1/4] Fixed crash when selecting certain buildings in the civilopedia (#4819) (cherry picked from commit 6d04bf424bbfcf2ee940a248e1ee8f01dc997858) --- android/assets/jsons/Civ V - Vanilla/Buildings.json | 8 ++++---- core/src/com/unciv/models/ruleset/Building.kt | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/android/assets/jsons/Civ V - Vanilla/Buildings.json b/android/assets/jsons/Civ V - Vanilla/Buildings.json index 8c6e9e1157..f7d472202c 100644 --- a/android/assets/jsons/Civ V - Vanilla/Buildings.json +++ b/android/assets/jsons/Civ V - Vanilla/Buildings.json @@ -1125,14 +1125,14 @@ "culture": 3, "happiness": 1, "specialistSlots": {"Artist": 1}, - "uniques": ["Unbuildable"] + "uniques": ["Unbuildable", "Hidden when religion is disabled"] }, { "name": "Monastery", "cost": 0, "culture": 2, "faith": 2, - "uniques": ["[+1 Culture, +1 Faith] from [Wine] tiles [in this city]", + "uniques": ["[+1 Culture, +1 Faith] from [Wine] tiles [in this city]", "Hidden when religion is disabled", "[+1 Culture, +1 Faith] from [Incense] tiles [in this city]","Unbuildable"] }, { @@ -1141,7 +1141,7 @@ "culture": 2, "faith": 3, "happiness": 1, - "uniques": ["Unbuildable"] + "uniques": ["Unbuildable", "Hidden when religion is disabled"] }, { "name": "Pagoda", @@ -1149,6 +1149,6 @@ "culture": 2, "faith": 2, "happiness": 2, - "uniques": ["Unbuildable"] + "uniques": ["Unbuildable", "Hidden when religion is disabled"] }, ] diff --git a/core/src/com/unciv/models/ruleset/Building.kt b/core/src/com/unciv/models/ruleset/Building.kt index 8fa82946b2..28163dfd65 100644 --- a/core/src/com/unciv/models/ruleset/Building.kt +++ b/core/src/com/unciv/models/ruleset/Building.kt @@ -203,7 +203,7 @@ class Building : NamedStats(), INonPerpetualConstruction, ICivilopediaText { override fun canBePurchasedWithStat(cityInfo: CityInfo, stat: Stat, ignoreCityRequirements: Boolean): Boolean { if (stat == Stat.Gold && isAnyWonder()) return false // May buy [buildingFilter] buildings for [amount] [Stat] [cityFilter] - if (cityInfo.getMatchingUniques("May buy [] buildings for [] [] []") + if (!ignoreCityRequirements && cityInfo.getMatchingUniques("May buy [] buildings for [] [] []") .any { it.params[2] == stat.name && matchesFilter(it.params[0]) && cityInfo.matchesFilter(it.params[3]) } ) return true return super.canBePurchasedWithStat(cityInfo, stat, ignoreCityRequirements) From 85ecddad2f78c1c5f679a05f15691ab2f45be78e Mon Sep 17 00:00:00 2001 From: yairm210 Date: Wed, 11 Aug 2021 19:53:21 +0300 Subject: [PATCH 2/4] Fixed crash with diplomacy screen and city-states with no cities (cherry picked from commit 7c1c58580171a4abacb4e5a4231f47e0d224a452) --- .../unciv/logic/civilization/CivInfoStats.kt | 7 +- .../logic/civilization/CivilizationInfo.kt | 5 +- .../src/com/unciv/ui/trade/DiplomacyScreen.kt | 217 ++++++++++++------ 3 files changed, 151 insertions(+), 78 deletions(-) diff --git a/core/src/com/unciv/logic/civilization/CivInfoStats.kt b/core/src/com/unciv/logic/civilization/CivInfoStats.kt index aa05c86fc5..8e2a191e3e 100644 --- a/core/src/com/unciv/logic/civilization/CivInfoStats.kt +++ b/core/src/com/unciv/logic/civilization/CivInfoStats.kt @@ -149,13 +149,14 @@ class CivInfoStats(val civInfo: CivilizationInfo) { val luxuriesProvidedByCityStates = civInfo.getKnownCivs().asSequence() .filter { it.isCityState() && it.getAllyCiv() == civInfo.civName } - .map { it.getCivResources().map { res -> res.resource } } - .flatten().distinct().count { it.resourceType === ResourceType.Luxury } + .flatMap { it.getCivResources().map { res -> res.resource } } + .distinct().count { it.resourceType === ResourceType.Luxury } statMap["City-State Luxuries"] = happinessBonusForCityStateProvidedLuxuries * luxuriesProvidedByCityStates * happinessPerUniqueLuxury val luxuriesAllOfWhichAreTradedAway = civInfo.detailedCivResources - .filter { it.amount < 0 && it.resource.resourceType == ResourceType.Luxury && (it.origin == "Trade" || it.origin == "Trade request")} + .filter { it.amount < 0 && it.resource.resourceType == ResourceType.Luxury + && (it.origin == "Trade" || it.origin == "Trade request")} .map { it.resource } .filter { !ownedLuxuries.contains(it) } diff --git a/core/src/com/unciv/logic/civilization/CivilizationInfo.kt b/core/src/com/unciv/logic/civilization/CivilizationInfo.kt index f19d2a70de..8875b98390 100644 --- a/core/src/com/unciv/logic/civilization/CivilizationInfo.kt +++ b/core/src/com/unciv/logic/civilization/CivilizationInfo.kt @@ -369,10 +369,7 @@ class CivilizationInfo { otherCiv.addNotification(meetString, cityStateLocation, NotificationIcon.Gold) else otherCiv.addNotification(meetString, NotificationIcon.Gold) - for (stat in giftAmount.toHashMap().filter { it.value != 0f }) - otherCiv.addStat(stat.key, stat.value.toInt()) - - + otherCiv.addStats(giftAmount) } fun discoverNaturalWonder(naturalWonderName: String) { diff --git a/core/src/com/unciv/ui/trade/DiplomacyScreen.kt b/core/src/com/unciv/ui/trade/DiplomacyScreen.kt index 535d8ba670..46ba5d897d 100644 --- a/core/src/com/unciv/ui/trade/DiplomacyScreen.kt +++ b/core/src/com/unciv/ui/trade/DiplomacyScreen.kt @@ -32,7 +32,7 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() { private val leftSideTable = Table().apply { defaults().pad(10f) } private val rightSideTable = Table() - + private fun isNotPlayersTurn() = !UncivGame.Current.worldScreen.isPlayersTurn init { @@ -52,14 +52,19 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() { closeButton.labelCell.pad(10f) closeButton.pack() closeButton.y = stage.height - closeButton.height - 10 - closeButton.x = (stage.width * 0.2f - closeButton.width) / 2 // center, leftSideTable.width not known yet + closeButton.x = + (stage.width * 0.2f - closeButton.width) / 2 // center, leftSideTable.width not known yet stage.addActor(closeButton) // This must come after the split pane so it will be above, that the button will be clickable } private fun updateLeftSideTable() { leftSideTable.clear() for (civ in viewingCiv.gameInfo.civilizations - .filterNot { it.isDefeated() || it == viewingCiv || it.isBarbarian() || it.isSpectator() || !viewingCiv.knows(it) }) { + .filterNot { + it.isDefeated() || it == viewingCiv || it.isBarbarian() || it.isSpectator() || !viewingCiv.knows( + it + ) + }) { val civIndicator = ImageGetter.getNationIndicator(civ.nation, 100f) @@ -70,7 +75,8 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() { civIndicator.addActor(relationship) if (civ.isCityState() && civ.questManager.haveQuestsFor(viewingCiv)) { - val questIcon = ImageGetter.getImage("OtherIcons/Quest").surroundWithCircle(size = 30f, color = Color.GOLDENROD) + val questIcon = ImageGetter.getImage("OtherIcons/Quest") + .surroundWithCircle(size = 30f, color = Color.GOLDENROD) civIndicator.addActor(questIcon) questIcon.x = floor(civIndicator.width - questIcon.width) } @@ -83,8 +89,11 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() { fun updateRightSide(otherCiv: CivilizationInfo) { rightSideTable.clear() - if (otherCiv.isCityState()) rightSideTable.add(ScrollPane(getCityStateDiplomacyTable(otherCiv))) - else rightSideTable.add(ScrollPane(getMajorCivDiplomacyTable(otherCiv))).height(stage.height) + if (otherCiv.isCityState()) rightSideTable.add( + ScrollPane(getCityStateDiplomacyTable(otherCiv)) + ) + else rightSideTable.add(ScrollPane(getMajorCivDiplomacyTable(otherCiv))) + .height(stage.height) } fun setTrade(civ: CivilizationInfo): TradeTable { @@ -118,8 +127,11 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() { wrapper.add(supplyList.amount.toLabel()) resourcesTable.add(wrapper).padRight(20f) wrapper.addTooltip(name, 18f) - wrapper.onClick { - val pedia = CivilopediaScreen(UncivGame.Current.gameInfo.ruleSet, link = "Resource/$name") + wrapper.onClick { + val pedia = CivilopediaScreen( + UncivGame.Current.gameInfo.ruleSet, + link = "Resource/$name" + ) UncivGame.Current.setScreen(pedia) } } @@ -162,14 +174,15 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() { friendBonusLabelColor = Color.GREEN // RelationshipChange = Ally -> Friend or Friend -> Favorable val turnsToRelationshipChange = otherCivDiplomacyManager.getTurnsToRelationshipChange() - diplomacyTable.add("Relationship changes in another [$turnsToRelationshipChange] turns".toLabel()).row() + diplomacyTable.add("Relationship changes in another [$turnsToRelationshipChange] turns".toLabel()) + .row() } else friendBonusLabelColor = Color.GRAY val friendBonusLabel = friendBonusText.toLabel(friendBonusLabelColor) .apply { setAlignment(Align.center) } diplomacyTable.add(friendBonusLabel).row() - + return diplomacyTable } @@ -188,29 +201,10 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() { diplomacyTable.add(giveGiftButton).row() if (isNotPlayersTurn()) giveGiftButton.disable() - val improvableTiles = otherCiv.getCapital().getImprovableTiles().filterNot {it.getTileResource().resourceType == ResourceType.Bonus}.toList() - val improvements = otherCiv.gameInfo.ruleSet.tileImprovements.filter { it.value.turnsToBuild != 0 } - var needsImprovements = false + val improveTileButton = getImproveTilesButton(otherCiv, otherCivDiplomacyManager) + if (improveTileButton != null) diplomacyTable.add(improveTileButton).row() - for (improvableTile in improvableTiles) - for (tileImprovement in improvements.values) - if (improvableTile.canBuildImprovement(tileImprovement, otherCiv) && improvableTile.getTileResource().improvement == tileImprovement.name) - needsImprovements = true - - - val improveTileButton = "Gift Improvement".toTextButton() - improveTileButton.onClick { - rightSideTable.clear() - rightSideTable.add(ScrollPane(getImprovementGiftTable(otherCiv))) - } - - - if (isNotPlayersTurn() || otherCivDiplomacyManager.influence < 60 || !needsImprovements) - improveTileButton.disable() - - - diplomacyTable.add(improveTileButton).row() - if (otherCivDiplomacyManager.diplomaticStatus == DiplomaticStatus.Protector){ + if (otherCivDiplomacyManager.diplomaticStatus == DiplomaticStatus.Protector) { val revokeProtectionButton = "Revoke Protection".toTextButton() revokeProtectionButton.onClick { YesNoPopup("Revoke protection for [${otherCiv.civName}]?", { @@ -230,7 +224,7 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() { updateRightSide(otherCiv) }, this).open() } - if(viewingCiv.isAtWarWith(otherCiv)) { + if (viewingCiv.isAtWarWith(otherCiv)) { protectionButton.disable() } diplomacyTable.add(protectionButton).row() @@ -244,8 +238,18 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() { peaceButton.onClick { YesNoPopup("Peace with [${otherCiv.civName}]?", { val tradeLogic = TradeLogic(viewingCiv, otherCiv) - tradeLogic.currentTrade.ourOffers.add(TradeOffer(Constants.peaceTreaty, TradeType.Treaty)) - tradeLogic.currentTrade.theirOffers.add(TradeOffer(Constants.peaceTreaty, TradeType.Treaty)) + tradeLogic.currentTrade.ourOffers.add( + TradeOffer( + Constants.peaceTreaty, + TradeType.Treaty + ) + ) + tradeLogic.currentTrade.theirOffers.add( + TradeOffer( + Constants.peaceTreaty, + TradeType.Treaty + ) + ) tradeLogic.acceptTrade() updateLeftSideTable() updateRightSide(otherCiv) @@ -253,7 +257,8 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() { } diplomacyTable.add(peaceButton).row() val cityStatesAlly = otherCiv.getAllyCiv() - val atWarWithItsAlly = viewingCiv.getKnownCivs().any { it.civName == cityStatesAlly && it.isAtWarWith(viewingCiv) } + val atWarWithItsAlly = viewingCiv.getKnownCivs() + .any { it.civName == cityStatesAlly && it.isAtWarWith(viewingCiv) } if (isNotPlayersTurn() || atWarWithItsAlly) peaceButton.disable() } else { val declareWarButton = getDeclareWarButton(diplomacyManager, otherCiv) @@ -269,14 +274,50 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() { return diplomacyTable } - + + private fun getImproveTilesButton( + otherCiv: CivilizationInfo, + otherCivDiplomacyManager: DiplomacyManager + ): TextButton? { + if (otherCiv.cities.isEmpty()) return null + val improvableTiles = otherCiv.getCapital().getImprovableTiles() + .filterNot { it.getTileResource().resourceType == ResourceType.Bonus }.toList() + val improvements = + otherCiv.gameInfo.ruleSet.tileImprovements.filter { it.value.turnsToBuild != 0 } + var needsImprovements = false + + for (improvableTile in improvableTiles) + for (tileImprovement in improvements.values) + if (improvableTile.canBuildImprovement( + tileImprovement, + otherCiv + ) && improvableTile.getTileResource().improvement == tileImprovement.name + ) + needsImprovements = true + + if (!needsImprovements) return null + + + val improveTileButton = "Gift Improvement".toTextButton() + improveTileButton.onClick { + rightSideTable.clear() + rightSideTable.add(ScrollPane(getImprovementGiftTable(otherCiv))) + } + + + if (isNotPlayersTurn() || otherCivDiplomacyManager.influence < 60 || !needsImprovements) + improveTileButton.disable() + return improveTileButton + } + private fun getGoldGiftTable(otherCiv: CivilizationInfo): Table { val diplomacyTable = getCityStateDiplomacyTableHeader(otherCiv) diplomacyTable.addSeparator() - + for (giftAmount in listOf(250, 500, 1000)) { val influenceAmount = viewingCiv.influenceGainedByGift(giftAmount) - val giftButton = "Gift [$giftAmount] gold (+[$influenceAmount] influence)".toTextButton() + val giftButton = + "Gift [$giftAmount] gold (+[$influenceAmount] influence)".toTextButton() giftButton.onClick { viewingCiv.giveGoldGift(otherCiv, giftAmount) updateRightSide(otherCiv) @@ -284,7 +325,7 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() { diplomacyTable.add(giftButton).row() if (viewingCiv.gold < giftAmount || isNotPlayersTurn()) giftButton.disable() } - + val backButton = "Back".toTextButton() backButton.onClick { rightSideTable.clear() @@ -293,19 +334,23 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() { diplomacyTable.add(backButton) return diplomacyTable } - private fun getImprovementGiftTable(otherCiv: CivilizationInfo): Table{ + + private fun getImprovementGiftTable(otherCiv: CivilizationInfo): Table { val improvementGiftTable = getCityStateDiplomacyTableHeader(otherCiv) improvementGiftTable.addSeparator() val improvableTiles = otherCiv.getCapital().getImprovableTiles() .filterNot { it.getTileResource().resourceType == ResourceType.Bonus }.toList() - val tileImprovements = otherCiv.gameInfo.ruleSet.tileImprovements.filter { it.value.turnsToBuild != 0 } + val tileImprovements = + otherCiv.gameInfo.ruleSet.tileImprovements.filter { it.value.turnsToBuild != 0 } - for (improvableTile in improvableTiles){ - for (tileImprovement in tileImprovements.values){ + for (improvableTile in improvableTiles) { + for (tileImprovement in tileImprovements.values) { if (improvableTile.canBuildImprovement(tileImprovement, otherCiv) && - improvableTile.getTileResource().improvement == tileImprovement.name) { - val improveTileButton = "Build [${tileImprovement}] on [${improvableTile.getTileResource()}] (200 Gold)".toTextButton() + improvableTile.getTileResource().improvement == tileImprovement.name + ) { + val improveTileButton = + "Build [${tileImprovement}] on [${improvableTile.getTileResource()}] (200 Gold)".toTextButton() improveTileButton.onClick { viewingCiv.addGold(-200) improvableTile.stopWorkingOnImprovement() @@ -342,7 +387,7 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() { questTable.add(title.toLabel(fontSize = 24)).row() questTable.add(description.toLabel().apply { wrap = true; setAlignment(Align.center) }) - .width(stage.width / 2).row() + .width(stage.width / 2).row() if (quest.duration > 0) questTable.add("[${remainingTurns}] turns remaining".toLabel()).row() @@ -359,13 +404,14 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() { diplomacyTable.defaults().pad(10f) val helloText = if (otherCivDiplomacyManager.relationshipLevel() <= RelationshipLevel.Enemy) - otherCiv.nation.hateHello - else otherCiv.nation.neutralHello + otherCiv.nation.hateHello + else otherCiv.nation.neutralHello val leaderIntroTable = LeaderIntroTable(otherCiv, helloText) diplomacyTable.add(leaderIntroTable).row() diplomacyTable.addSeparator() - val diplomaticRelationshipsCanChange = !viewingCiv.gameInfo.ruleSet.modOptions.uniques.contains(ModOptionsConstants.diplomaticRelationshipsCannotChange) + val diplomaticRelationshipsCanChange = + !viewingCiv.gameInfo.ruleSet.modOptions.uniques.contains(ModOptionsConstants.diplomaticRelationshipsCannotChange) if (!viewingCiv.isAtWarWith(otherCiv)) { val tradeButton = "Trade".toTextButton() @@ -402,14 +448,21 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() { if (!viewingCiv.isAtWarWith(otherCiv)) { if (!diplomacyManager.hasFlag(DiplomacyFlags.DeclarationOfFriendship)) { - val declareFriendshipButton = "Offer Declaration of Friendship ([30] turns)".toTextButton() + val declareFriendshipButton = + "Offer Declaration of Friendship ([30] turns)".toTextButton() declareFriendshipButton.onClick { - otherCiv.popupAlerts.add(PopupAlert(AlertType.DeclarationOfFriendship, viewingCiv.civName)) + otherCiv.popupAlerts.add( + PopupAlert( + AlertType.DeclarationOfFriendship, + viewingCiv.civName + ) + ) declareFriendshipButton.disable() } diplomacyTable.add(declareFriendshipButton).row() if (isNotPlayersTurn() || otherCiv.popupAlerts - .any { it.type == AlertType.DeclarationOfFriendship && it.value == viewingCiv.civName }) + .any { it.type == AlertType.DeclarationOfFriendship && it.value == viewingCiv.civName } + ) declareFriendshipButton.disable() } @@ -420,8 +473,10 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() { val requiredGold = viewingCiv.getResearchAgreementCost() researchAgreementButton.onClick { val tradeTable = setTrade(otherCiv) - val researchAgreement = TradeOffer(Constants.researchAgreement, TradeType.Treaty, requiredGold) - val goldCostOfSignResearchAgreement = TradeOffer("Gold".tr(), TradeType.Gold, -requiredGold) + val researchAgreement = + TradeOffer(Constants.researchAgreement, TradeType.Treaty, requiredGold) + val goldCostOfSignResearchAgreement = + TradeOffer("Gold".tr(), TradeType.Gold, -requiredGold) tradeTable.tradeLogic.currentTrade.theirOffers.add(researchAgreement) tradeTable.tradeLogic.ourAvailableOffers.add(researchAgreement) tradeTable.tradeLogic.ourAvailableOffers.add(goldCostOfSignResearchAgreement) @@ -436,7 +491,8 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() { } if (!diplomacyManager.hasFlag(DiplomacyFlags.Denunceation) - && !diplomacyManager.hasFlag(DiplomacyFlags.DeclarationOfFriendship)) { + && !diplomacyManager.hasFlag(DiplomacyFlags.DeclarationOfFriendship) + ) { val denounceButton = "Denounce ([30] turns)".toTextButton() denounceButton.onClick { YesNoPopup("Denounce [${otherCiv.civName}]?", { @@ -473,17 +529,22 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() { return diplomacyTable } - private fun getPromisesTable(diplomacyManager: DiplomacyManager, otherCivDiplomacyManager: DiplomacyManager): Table? { + private fun getPromisesTable( + diplomacyManager: DiplomacyManager, + otherCivDiplomacyManager: DiplomacyManager + ): Table? { val promisesTable = Table() // Not for (flag in DiplomacyFlags.values()) - all other flags should result in DiplomaticModifiers or stay internal? val flag = DiplomacyFlags.AgreedToNotSettleNearUs if (otherCivDiplomacyManager.hasFlag(flag)) { - val text = "We promised not to settle near them ([${otherCivDiplomacyManager.getFlag(flag)}] turns remaining)" + val text = + "We promised not to settle near them ([${otherCivDiplomacyManager.getFlag(flag)}] turns remaining)" promisesTable.add(text.toLabel(Color.LIGHT_GRAY)).row() } if (diplomacyManager.hasFlag(flag)) { - val text = "They promised not to settle near us ([${diplomacyManager.getFlag(flag)}] turns remaining)" + val text = + "They promised not to settle near us ([${diplomacyManager.getFlag(flag)}] turns remaining)" promisesTable.add(text.toLabel(Color.LIGHT_GRAY)).row() } @@ -533,7 +594,12 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() { if (otherCiv.popupAlerts.any { it.type == AlertType.DemandToStopSettlingCitiesNear && it.value == viewingCiv.civName }) dontSettleCitiesButton.disable() dontSettleCitiesButton.onClick { - otherCiv.popupAlerts.add(PopupAlert(AlertType.DemandToStopSettlingCitiesNear, viewingCiv.civName)) + otherCiv.popupAlerts.add( + PopupAlert( + AlertType.DemandToStopSettlingCitiesNear, + viewingCiv.civName + ) + ) dontSettleCitiesButton.disable() } demandsTable.add(dontSettleCitiesButton).row() @@ -545,8 +611,9 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() { private fun getRelationshipTable(otherCivDiplomacyManager: DiplomacyManager): Table { val relationshipTable = Table() - val opinionOfUs = if (otherCivDiplomacyManager.civInfo.isCityState()) otherCivDiplomacyManager.influence.toInt() - else otherCivDiplomacyManager.opinionOfOtherCiv().toInt() + val opinionOfUs = + if (otherCivDiplomacyManager.civInfo.isCityState()) otherCivDiplomacyManager.influence.toInt() + else otherCivDiplomacyManager.opinionOfOtherCiv().toInt() relationshipTable.add("{Our relationship}: ".toLabel()) val relationshipLevel = otherCivDiplomacyManager.relationshipLevel() @@ -561,15 +628,19 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() { relationshipTable.add(relationshipText.toLabel(relationshipColor)).row() if (otherCivDiplomacyManager.civInfo.isCityState()) relationshipTable.add( - CityButton.getInfluenceBar( - otherCivDiplomacyManager.influence, - otherCivDiplomacyManager.relationshipLevel(), - 200f, 10f) + CityButton.getInfluenceBar( + otherCivDiplomacyManager.influence, + otherCivDiplomacyManager.relationshipLevel(), + 200f, 10f + ) ).colspan(2).pad(5f) return relationshipTable } - private fun getDeclareWarButton(diplomacyManager: DiplomacyManager, otherCiv: CivilizationInfo): TextButton { + private fun getDeclareWarButton( + diplomacyManager: DiplomacyManager, + otherCiv: CivilizationInfo + ): TextButton { val declareWarButton = "Declare war".toTextButton() declareWarButton.color = Color.RED val turnsToPeaceTreaty = diplomacyManager.turnsToPeaceTreaty() @@ -589,7 +660,11 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() { // response currently always gets "Very Well.", but that may expand in the future. @Suppress("SameParameterValue") - private fun setRightSideFlavorText(otherCiv: CivilizationInfo, flavorText: String, response: String) { + private fun setRightSideFlavorText( + otherCiv: CivilizationInfo, + flavorText: String, + response: String + ) { val diplomacyTable = Table() diplomacyTable.defaults().pad(10f) diplomacyTable.add(LeaderIntroTable(otherCiv)) @@ -598,8 +673,8 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() { val responseButton = response.toTextButton() val action = { - keyPressDispatcher.remove(KeyCharAndCode.SPACE) - updateRightSide(otherCiv) + keyPressDispatcher.remove(KeyCharAndCode.SPACE) + updateRightSide(otherCiv) } responseButton.onClick(action) keyPressDispatcher[KeyCharAndCode.SPACE] = action @@ -609,4 +684,4 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() { rightSideTable.add(diplomacyTable) } -} +} \ No newline at end of file From a08a0e1489284f4d423de1e7c137fcb3958ac0d0 Mon Sep 17 00:00:00 2001 From: yairm210 Date: Wed, 11 Aug 2021 20:40:44 +0300 Subject: [PATCH 3/4] Added ruleset check for units whose type is not defined in the unitTypes --- core/src/com/unciv/logic/civilization/CivilizationInfo.kt | 4 +++- core/src/com/unciv/models/ruleset/Ruleset.kt | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/core/src/com/unciv/logic/civilization/CivilizationInfo.kt b/core/src/com/unciv/logic/civilization/CivilizationInfo.kt index 8875b98390..c9aa0ad754 100644 --- a/core/src/com/unciv/logic/civilization/CivilizationInfo.kt +++ b/core/src/com/unciv/logic/civilization/CivilizationInfo.kt @@ -369,7 +369,9 @@ class CivilizationInfo { otherCiv.addNotification(meetString, cityStateLocation, NotificationIcon.Gold) else otherCiv.addNotification(meetString, NotificationIcon.Gold) - otherCiv.addStats(giftAmount) + + for (stat in giftAmount.toHashMap().filter { it.value != 0f }) + otherCiv.addStat(stat.key, stat.value.toInt()) } fun discoverNaturalWonder(naturalWonderName: String) { diff --git a/core/src/com/unciv/models/ruleset/Ruleset.kt b/core/src/com/unciv/models/ruleset/Ruleset.kt index 0538dc28ed..099b0dcc9a 100644 --- a/core/src/com/unciv/models/ruleset/Ruleset.kt +++ b/core/src/com/unciv/models/ruleset/Ruleset.kt @@ -289,6 +289,7 @@ class Ruleset { fun isError() = status == CheckModLinksStatus.Error fun isNotOK() = status != CheckModLinksStatus.OK } + fun checkModLinks(): CheckModLinksResult { val lines = ArrayList() var warningCount = 0 @@ -338,8 +339,9 @@ class Ruleset { lines += "${unit.name} replaces ${unit.replaces} which does not exist!" for (promotion in unit.promotions) if (!unitPromotions.containsKey(promotion)) - lines += "${unit.replaces} contains promotion $promotion which does not exist!" - + lines += "${unit.name} contains promotion $promotion which does not exist!" + if (!unitTypes.containsKey(unit.unitType)) + lines += "${unit.name} is of type ${unit.unitType}, which does not exist!" } for (building in buildings.values) { From b276250dfca1981cebfa184fba3898f61cab5e2a Mon Sep 17 00:00:00 2001 From: yairm210 Date: Wed, 11 Aug 2021 20:50:52 +0300 Subject: [PATCH 4/4] 3.16.2-patch1 --- buildSrc/src/main/kotlin/BuildConfig.kt | 4 ++-- changelog.md | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/buildSrc/src/main/kotlin/BuildConfig.kt b/buildSrc/src/main/kotlin/BuildConfig.kt index 5f234b23a1..6655b1016b 100644 --- a/buildSrc/src/main/kotlin/BuildConfig.kt +++ b/buildSrc/src/main/kotlin/BuildConfig.kt @@ -3,8 +3,8 @@ package com.unciv.build object BuildConfig { const val kotlinVersion = "1.4.30" const val appName = "Unciv" - const val appCodeNumber = 604 - const val appVersion = "3.16.2" + const val appCodeNumber = 605 + const val appVersion = "3.16.2-patch1" const val gdxVersion = "1.10.0" const val roboVMVersion = "2.3.1" diff --git a/changelog.md b/changelog.md index a7c5659761..e77482d330 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,11 @@ +## 3.16.2-patch1 + +Fixed diplomacy screen crash for city-states with no cities + +Added mod check for units whose unitType is not defined + +Fixed crash when selecting certain buildings in the civilopedia - by xlenstra + ## 3.16.2 Fixed crashing Diplomatic victory bug