diff --git a/core/src/com/unciv/logic/BackwardCompatibility.kt b/core/src/com/unciv/logic/BackwardCompatibility.kt new file mode 100644 index 0000000000..111c97ff8a --- /dev/null +++ b/core/src/com/unciv/logic/BackwardCompatibility.kt @@ -0,0 +1,131 @@ +package com.unciv.logic + +import com.unciv.logic.city.CityConstructions +import com.unciv.logic.city.PerpetualConstruction +import com.unciv.logic.civilization.TechManager +import com.unciv.logic.civilization.diplomacy.DiplomacyFlags +import com.unciv.logic.civilization.diplomacy.DiplomacyManager +import com.unciv.models.ruleset.Ruleset + +/** + * Container for all temporarily used code managing transitions from deprecated elements to their replacements. + * + * Please place ***all*** such code here and call it _only_ from [GameInfo.setTransients]. + * Functions are allowed to remain once no longer used if you think they might serve as template for + * similar usecases in the future. Please comment sufficiently :) + */ +@Suppress("unused") // as mentioned above +object BackwardCompatibility { + + /** + * Mods can change, leading to things on the map that are no longer defined in the mod. + * This function removes them so the game doesn't crash when it tries to access them. + */ + fun GameInfo.removeMissingModReferences() { + for (tile in tileMap.values) { + for (terrainFeature in tile.terrainFeatures.filter{ !ruleSet.terrains.containsKey(it) }) + tile.terrainFeatures.remove(terrainFeature) + if (tile.resource != null && !ruleSet.tileResources.containsKey(tile.resource!!)) + tile.resource = null + if (tile.improvement != null && !ruleSet.tileImprovements.containsKey(tile.improvement!!)) + tile.improvement = null + + for (unit in tile.getUnits()) { + if (!ruleSet.units.containsKey(unit.name)) tile.removeUnit(unit) + + for (promotion in unit.promotions.promotions.toList()) + if (!ruleSet.unitPromotions.containsKey(promotion)) + unit.promotions.promotions.remove(promotion) + } + } + + for (city in civilizations.asSequence().flatMap { it.cities.asSequence() }) { + + for (building in city.cityConstructions.builtBuildings.toHashSet()) + if (!ruleSet.buildings.containsKey(building)) + city.cityConstructions.builtBuildings.remove(building) + + fun isInvalidConstruction(construction: String) = + !ruleSet.buildings.containsKey(construction) + && !ruleSet.units.containsKey(construction) + && !PerpetualConstruction.perpetualConstructionsMap.containsKey(construction) + + // Remove invalid buildings or units from the queue - don't just check buildings and units because it might be a special construction as well + for (construction in city.cityConstructions.constructionQueue.toList()) { + if (isInvalidConstruction(construction)) + city.cityConstructions.constructionQueue.remove(construction) + } + // And from being in progress + for (construction in city.cityConstructions.inProgressConstructions.keys.toList()) + if (isInvalidConstruction(construction)) + city.cityConstructions.inProgressConstructions.remove(construction) + } + + for (civInfo in civilizations) { + for (tech in civInfo.tech.techsResearched.toList()) + if (!ruleSet.technologies.containsKey(tech)) + civInfo.tech.techsResearched.remove(tech) + } + } + + /** + * Replaces all occurrences of [oldBuildingName] in [cityConstructions] with [newBuildingName] + * if the former is not contained in the ruleset. + */ + private fun changeBuildingNameIfNotInRuleset( + ruleSet: Ruleset, + cityConstructions: CityConstructions, + oldBuildingName: String, + newBuildingName: String + ) { + if (ruleSet.buildings.containsKey(oldBuildingName)) + return + // Replace in built buildings + if (cityConstructions.builtBuildings.contains(oldBuildingName)) { + cityConstructions.builtBuildings.remove(oldBuildingName) + cityConstructions.builtBuildings.add(newBuildingName) + } + // Replace in construction queue + if (!cityConstructions.builtBuildings.contains(newBuildingName) && !cityConstructions.constructionQueue.contains(newBuildingName)) + cityConstructions.constructionQueue = cityConstructions.constructionQueue + .map { if (it == oldBuildingName) newBuildingName else it } + .toMutableList() + else + cityConstructions.constructionQueue.remove(oldBuildingName) + // Replace in in-progress constructions + if (cityConstructions.inProgressConstructions.containsKey(oldBuildingName)) { + if (!cityConstructions.builtBuildings.contains(newBuildingName) && !cityConstructions.inProgressConstructions.containsKey(newBuildingName)) + cityConstructions.inProgressConstructions[newBuildingName] = cityConstructions.inProgressConstructions[oldBuildingName]!! + cityConstructions.inProgressConstructions.remove(oldBuildingName) + } + } + + /** Replace a changed tech name */ + private fun TechManager.replaceUpdatedTechName(oldTechName: String, newTechName: String) { + if (oldTechName in techsResearched) { + techsResearched.remove(oldTechName) + techsResearched.add(newTechName) + } + val index = techsToResearch.indexOf(oldTechName) + if (index >= 0) { + techsToResearch[index] = newTechName + } + if (oldTechName in techsInProgress) { + techsInProgress[newTechName] = researchOfTech(oldTechName) + techsInProgress.remove(oldTechName) + } + } + + /** Replace a deprecated DiplomacyFlags instance */ + fun GameInfo.replaceDiplomacyFlag(old: DiplomacyFlags, new: DiplomacyFlags) { + fun DiplomacyManager.replaceFlag() { + if (hasFlag(old)) { + val value = getFlag(old) + removeFlag(old) + setFlag(new, value) + } + } + civilizations.flatMap { civ -> civ.diplomacy.values }.forEach { it.replaceFlag() } + } + +} \ No newline at end of file diff --git a/core/src/com/unciv/logic/GameInfo.kt b/core/src/com/unciv/logic/GameInfo.kt index 55adf51036..f0c0657a40 100644 --- a/core/src/com/unciv/logic/GameInfo.kt +++ b/core/src/com/unciv/logic/GameInfo.kt @@ -2,10 +2,11 @@ package com.unciv.logic import com.unciv.Constants import com.unciv.UncivGame +import com.unciv.logic.BackwardCompatibility.removeMissingModReferences +import com.unciv.logic.BackwardCompatibility.replaceDiplomacyFlag import com.unciv.logic.automation.NextTurnAutomation -import com.unciv.logic.city.CityConstructions -import com.unciv.logic.city.PerpetualConstruction import com.unciv.logic.civilization.* +import com.unciv.logic.civilization.diplomacy.DiplomacyFlags import com.unciv.logic.map.TileInfo import com.unciv.logic.map.TileMap import com.unciv.models.Religion @@ -18,20 +19,7 @@ import java.util.* class UncivShowableException(missingMods: String) : Exception(missingMods) class GameInfo { - @Transient - lateinit var difficultyObject: Difficulty // Since this is static game-wide, and was taking a large part of nextTurn - - @Transient - lateinit var currentPlayerCiv: CivilizationInfo // this is called thousands of times, no reason to search for it with a find{} every time - - /** This is used in multiplayer games, where I may have a saved game state on my phone - * that is inconsistent with the saved game on the cloud */ - @Transient - var isUpToDate = false - - @Transient - lateinit var ruleSet: Ruleset - + //region Fields - Serialized var civilizations = mutableListOf() var religions: HashMap = hashMapOf() var difficulty = "Chieftain" // difficulty is game-wide, think what would happen if 2 human players could play on different difficulties? @@ -54,15 +42,36 @@ class GameInfo { @Volatile var customSaveLocation: String? = null + //endregion + //region Fields - Transient + + @Transient + lateinit var difficultyObject: Difficulty // Since this is static game-wide, and was taking a large part of nextTurn + + @Transient + lateinit var currentPlayerCiv: CivilizationInfo // this is called thousands of times, no reason to search for it with a find{} every time + + /** This is used in multiplayer games, where I may have a saved game state on my phone + * that is inconsistent with the saved game on the cloud */ + @Transient + var isUpToDate = false + + @Transient + lateinit var ruleSet: Ruleset + /** Simulate until any player wins, * or turns exceeds indicated number * Does not update World View until finished. * Should be set manually on each new game start. */ + @Transient var simulateMaxTurns: Int = 1000 + @Transient var simulateUntilWin = false - //region pure functions + //endregion + //region Pure functions + fun clone(): GameInfo { val toReturn = GameInfo() toReturn.tileMap = tileMap.clone() @@ -103,7 +112,14 @@ class GameInfo { fun getCities() = civilizations.asSequence().flatMap { it.cities } fun getAliveCityStates() = civilizations.filter { it.isAlive() && it.isCityState() } fun getAliveMajorCivs() = civilizations.filter { it.isAlive() && it.isMajorCiv() } + + fun hasReligionEnabled() = + // Temporary function to check whether religion should be used for this game + (gameParameters.religionEnabled || ruleSet.hasReligion()) + && (ruleSet.eras.isEmpty() || !ruleSet.eras[gameParameters.startingEra]!!.hasUnique("Starting in this era disables religion")) + //endregion + //region State changing functions fun nextTurn() { val previousHumanPlayer = getCurrentPlayerCivilization() @@ -236,7 +252,7 @@ class GameInfo { return tile } - fun placeBarbarianUnit(tileToPlace: TileInfo) { + private fun placeBarbarianUnit(tileToPlace: TileInfo) { // if we don't make this into a separate list then the retain() will happen on the Tech keys, // which effectively removes those techs from the game and causes all sorts of problems val allResearchedTechs = ruleSet.technologies.keys.toMutableList() @@ -252,10 +268,9 @@ class GameInfo { val landUnits = unitList.filter { it.isLandUnit() } val waterUnits = unitList.filter { it.isWaterUnit() } - val unit: String - if (waterUnits.isNotEmpty() && tileToPlace.isCoastalTile() && Random().nextBoolean()) - unit = waterUnits.random().name - else unit = landUnits.random().name + val unit: String = if (waterUnits.isNotEmpty() && tileToPlace.isCoastalTile() && Random().nextBoolean()) + waterUnits.random().name + else landUnits.random().name tileMap.placeUnitNearTile(tileToPlace.position, unit, getBarbarianCivilization()) } @@ -264,7 +279,7 @@ class GameInfo { * [CivilizationInfo.addNotification][Add a notification] to every civilization that have * adopted Honor policy and have explored the [tile] where the Barbarian Encampment has spawned. */ - fun notifyCivsOfBarbarianEncampment(tile: TileInfo) { + private fun notifyCivsOfBarbarianEncampment(tile: TileInfo) { civilizations.filter { it.hasUnique("Notified of new Barbarian encampments") && it.exploredTiles.contains(tile.position) @@ -289,6 +304,8 @@ class GameInfo { removeMissingModReferences() + replaceDiplomacyFlag(DiplomacyFlags.Denunceation, DiplomacyFlags.Denunciation) + for (baseUnit in ruleSet.units.values) baseUnit.ruleset = ruleSet @@ -296,14 +313,14 @@ class GameInfo { // the nation of their civilization when setting transients for (civInfo in civilizations) civInfo.gameInfo = this for (civInfo in civilizations) civInfo.setNationTransient() - + tileMap.setTransients(ruleSet) if (currentPlayer == "") currentPlayer = civilizations.first { it.isPlayerCivilization() }.civName currentPlayerCiv = getCivilization(currentPlayer) difficultyObject = ruleSet.difficulties[difficulty]!! - + for (religion in religions.values) religion.setTransients(this) for (civInfo in civilizations) civInfo.setTransients() @@ -338,105 +355,7 @@ class GameInfo { } } - - // Mods can change, leading to things on the map that are no longer defined in the mod. - // So we remove them so the game doesn't crash when it tries to access them. - private fun removeMissingModReferences() { - for (tile in tileMap.values) { - for (terrainFeature in tile.terrainFeatures.filter{ !ruleSet.terrains.containsKey(it) }) - tile.terrainFeatures.remove(terrainFeature) - if (tile.resource != null && !ruleSet.tileResources.containsKey(tile.resource!!)) - tile.resource = null - if (tile.improvement != null && !ruleSet.tileImprovements.containsKey(tile.improvement!!)) - tile.improvement = null - - for (unit in tile.getUnits()) { - if (!ruleSet.units.containsKey(unit.name)) tile.removeUnit(unit) - - for (promotion in unit.promotions.promotions.toList()) - if (!ruleSet.unitPromotions.containsKey(promotion)) - unit.promotions.promotions.remove(promotion) - } - } - - for (city in civilizations.asSequence().flatMap { it.cities.asSequence() }) { - - for (building in city.cityConstructions.builtBuildings.toHashSet()) - if (!ruleSet.buildings.containsKey(building)) - city.cityConstructions.builtBuildings.remove(building) - - fun isInvalidConstruction(construction: String) = - !ruleSet.buildings.containsKey(construction) - && !ruleSet.units.containsKey(construction) - && !PerpetualConstruction.perpetualConstructionsMap.containsKey(construction) - - // Remove invalid buildings or units from the queue - don't just check buildings and units because it might be a special construction as well - for (construction in city.cityConstructions.constructionQueue.toList()) { - if (isInvalidConstruction(construction)) - city.cityConstructions.constructionQueue.remove(construction) - } - // And from being in progress - for (construction in city.cityConstructions.inProgressConstructions.keys.toList()) - if (isInvalidConstruction(construction)) - city.cityConstructions.inProgressConstructions.remove(construction) - } - - for (civinfo in civilizations) { - for (tech in civinfo.tech.techsResearched.toList()) - if (!ruleSet.technologies.containsKey(tech)) - civinfo.tech.techsResearched.remove(tech) - } - } - - /** - * Replaces all occurrences of [oldBuildingName] in [cityConstructions] with [newBuildingName] - * if the former is not contained in the ruleset. - * This function can be used for backwards compatibility with older save files when a building - * name is changed. - */ - @Suppress("unused") // it's OK if there's no deprecation currently needing this - private fun changeBuildingNameIfNotInRuleset(cityConstructions: CityConstructions, oldBuildingName: String, newBuildingName: String) { - if (ruleSet.buildings.containsKey(oldBuildingName)) - return - // Replace in built buildings - if (cityConstructions.builtBuildings.contains(oldBuildingName)) { - cityConstructions.builtBuildings.remove(oldBuildingName) - cityConstructions.builtBuildings.add(newBuildingName) - } - // Replace in construction queue - if (!cityConstructions.builtBuildings.contains(newBuildingName) && !cityConstructions.constructionQueue.contains(newBuildingName)) - cityConstructions.constructionQueue = cityConstructions.constructionQueue.map{ if (it == oldBuildingName) newBuildingName else it }.toMutableList() - else - cityConstructions.constructionQueue.remove(oldBuildingName) - // Replace in in-progress constructions - if (cityConstructions.inProgressConstructions.containsKey(oldBuildingName)) { - if (!cityConstructions.builtBuildings.contains(newBuildingName) && !cityConstructions.inProgressConstructions.containsKey(newBuildingName)) - cityConstructions.inProgressConstructions[newBuildingName] = cityConstructions.inProgressConstructions[oldBuildingName]!! - cityConstructions.inProgressConstructions.remove(oldBuildingName) - } - } - - /** Replace a changed tech name, only temporarily used for breaking ruleset updates */ - private fun TechManager.replaceUpdatedTechName(oldTechName: String, newTechName: String) { - if (oldTechName in techsResearched) { - techsResearched.remove(oldTechName) - techsResearched.add(newTechName) - } - val index = techsToResearch.indexOf(oldTechName) - if (index >= 0) { - techsToResearch[index] = newTechName - } - if (oldTechName in techsInProgress) { - techsInProgress[newTechName] = researchOfTech(oldTechName) - techsInProgress.remove(oldTechName) - } - } - - - fun hasReligionEnabled() = - // Temporary function to check whether religion should be used for this game - (gameParameters.religionEnabled || ruleSet.hasReligion()) - && (ruleSet.eras.isEmpty() || !ruleSet.eras[gameParameters.startingEra]!!.hasUnique("Starting in this era disables religion")) + //endregion } // reduced variant only for load preview diff --git a/core/src/com/unciv/logic/automation/NextTurnAutomation.kt b/core/src/com/unciv/logic/automation/NextTurnAutomation.kt index 4888e4a54d..b3ce904572 100644 --- a/core/src/com/unciv/logic/automation/NextTurnAutomation.kt +++ b/core/src/com/unciv/logic/automation/NextTurnAutomation.kt @@ -63,7 +63,7 @@ object NextTurnAutomation { // Can only be done now, as the prophet first has to decide to found/enhance a religion chooseReligiousBeliefs(civInfo) } - + reassignWorkedTiles(civInfo) // second most expensive trainSettler(civInfo) tryVoteForDiplomaticVictory(civInfo) @@ -103,7 +103,7 @@ object NextTurnAutomation { val requestingCiv = civInfo.gameInfo.getCivilization(popupAlert.value) val diploManager = civInfo.getDiplomacyManager(requestingCiv) if (diploManager.relationshipLevel() > RelationshipLevel.Neutral - && !diploManager.otherCivDiplomacy().hasFlag(DiplomacyFlags.Denunceation)) { + && !diploManager.otherCivDiplomacy().hasFlag(DiplomacyFlags.Denunciation)) { diploManager.signDeclarationOfFriendship() requestingCiv.addNotification("We have signed a Declaration of Friendship with [${civInfo.civName}]!", NotificationIcon.Diplomacy, civInfo.civName) } else requestingCiv.addNotification("[${civInfo.civName}] has denied our Declaration of Friendship!", NotificationIcon.Diplomacy, civInfo.civName) @@ -206,8 +206,9 @@ object NextTurnAutomation { } // Bonus for luxury resources we can get from them - value += cityState.detailedCivResources.count { it.resource.resourceType == ResourceType.Luxury - && it.resource !in civInfo.detailedCivResources.map { it.resource } + value += cityState.detailedCivResources.count { + it.resource.resourceType == ResourceType.Luxury + && it.resource !in civInfo.detailedCivResources.map { supply -> supply.resource } } return value @@ -298,13 +299,13 @@ object NextTurnAutomation { civInfo.policies.adopt(policyToAdopt) } } - + private fun chooseReligiousBeliefs(civInfo: CivilizationInfo) { choosePantheon(civInfo) foundReligion(civInfo) enhanceReligion(civInfo) } - + private fun choosePantheon(civInfo: CivilizationInfo) { if (!civInfo.religionManager.canFoundPantheon()) return // So looking through the source code of the base game available online, @@ -319,7 +320,7 @@ object NextTurnAutomation { val chosenPantheon = availablePantheons.random() // Why calculate stuff? civInfo.religionManager.choosePantheonBelief(chosenPantheon) } - + private fun foundReligion(civInfo: CivilizationInfo) { if (civInfo.religionManager.religionState != ReligionState.FoundingReligion) return val religionIcon = civInfo.gameInfo.ruleSet.religions @@ -329,7 +330,7 @@ object NextTurnAutomation { val chosenBeliefs = chooseBeliefs(civInfo, civInfo.religionManager.getBeliefsToChooseAtFounding()).toList() civInfo.religionManager.chooseBeliefs(religionIcon, religionIcon, chosenBeliefs) } - + private fun enhanceReligion(civInfo: CivilizationInfo) { civInfo.religionManager.chooseBeliefs( null, @@ -337,11 +338,11 @@ object NextTurnAutomation { chooseBeliefs(civInfo, civInfo.religionManager.getBeliefsToChooseAtEnhancing()).toList() ) } - + private fun chooseBeliefs(civInfo: CivilizationInfo, beliefContainer: BeliefContainer): HashSet { val chosenBeliefs = hashSetOf() - // The 'continues' should never be reached, but just in case I'd rather have AI have a - // belief less than make the game crash. The 'continue's should only be reached whenever + // The `continue`s should never be reached, but just in case I'd rather have the AI have a + // belief less than make the game crash. The `continue`s should only be reached whenever // there are not enough beliefs to choose, but there should be, as otherwise we could // not have used a great prophet to found/enhance our religion. for (counter in 0 until beliefContainer.pantheonBeliefCount) @@ -362,7 +363,7 @@ object NextTurnAutomation { ) return chosenBeliefs } - + private fun chooseBeliefOfType(civInfo: CivilizationInfo, beliefType: BeliefType, additionalBeliefsToExclude: HashSet = hashSetOf()): Belief? { return civInfo.gameInfo.ruleSet.beliefs .filter { @@ -436,7 +437,7 @@ object NextTurnAutomation { it.isMajorCiv() && !it.isAtWarWith(civInfo) && it.getDiplomacyManager(civInfo).relationshipLevel() > RelationshipLevel.Neutral && !civInfo.getDiplomacyManager(it).hasFlag(DiplomacyFlags.DeclarationOfFriendship) - && !civInfo.getDiplomacyManager(it).hasFlag(DiplomacyFlags.Denunceation) + && !civInfo.getDiplomacyManager(it).hasFlag(DiplomacyFlags.Denunciation) } .sortedByDescending { it.getDiplomacyManager(civInfo).relationshipLevel() } for (civ in civsThatWeCanDeclareFriendshipWith) { @@ -682,20 +683,20 @@ object NextTurnAutomation { private fun tryVoteForDiplomaticVictory(civInfo: CivilizationInfo) { if (!civInfo.mayVoteForDiplomaticVictory()) return val chosenCiv: String? = if (civInfo.isMajorCiv()) { - + val knownMajorCivs = civInfo.getKnownCivs().filter { it.isMajorCiv() } val highestOpinion = knownMajorCivs .maxOfOrNull { civInfo.getDiplomacyManager(it).opinionOfOtherCiv() } - + if (highestOpinion == null) null else knownMajorCivs.filter { civInfo.getDiplomacyManager(it).opinionOfOtherCiv() == highestOpinion}.random().civName - + } else { civInfo.getAllyCiv() } - + civInfo.diplomaticVoteForCiv(chosenCiv) } @@ -742,4 +743,4 @@ object NextTurnAutomation { return cityDistances.minByOrNull { it.aerialDistance }!! } -} \ No newline at end of file +} diff --git a/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyManager.kt b/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyManager.kt index 619cca6667..cfb2ae9561 100644 --- a/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyManager.kt +++ b/core/src/com/unciv/logic/civilization/diplomacy/DiplomacyManager.kt @@ -32,6 +32,7 @@ enum class DiplomacyFlags { DeclaredWar, DeclarationOfFriendship, ResearchAgreement, + @Deprecated("Deprecated after 3.16.13", ReplaceWith("Denunciation")) Denunceation, BorderConflict, SettledCitiesNearUs, @@ -43,7 +44,8 @@ enum class DiplomacyFlags { NotifiedAfraid, RecentlyPledgedProtection, RecentlyWithdrewProtection, - AngerFreeIntrusion + AngerFreeIntrusion, + Denunciation } enum class DiplomaticModifiers { @@ -107,7 +109,7 @@ class DiplomacyManager() { get() = if (civInfo.isAtWarWith(otherCiv())) MINIMUM_INFLUENCE else field /** Total of each turn Science during Research Agreement */ - var totalOfScienceDuringRA = 0 + private var totalOfScienceDuringRA = 0 fun clone(): DiplomacyManager { val toReturn = DiplomacyManager() @@ -188,6 +190,7 @@ class DiplomacyManager() { return 0 } + @Suppress("unused") //todo Finish original intent or remove fun matchesCityStateRelationshipFilter(filter: String): Boolean { val relationshipLevel = relationshipLevel() return when (filter) { @@ -210,7 +213,7 @@ class DiplomacyManager() { } // To be run from City-State DiplomacyManager, which holds the influence. Resting point for every major civ can be different. - fun getCityStateInfluenceRestingPoint(): Float { + private fun getCityStateInfluenceRestingPoint(): Float { var restingPoint = 0f for (unique in otherCiv().getMatchingUniques("Resting point for Influence with City-States is increased by []")) @@ -287,7 +290,7 @@ class DiplomacyManager() { return goldPerTurnForUs } - fun scienceFromResearchAgreement() { + private fun scienceFromResearchAgreement() { // https://forums.civfanatics.com/resources/research-agreements-bnw.25568/ val scienceFromResearchAgreement = min(totalOfScienceDuringRA, otherCivDiplomacy().totalOfScienceDuringRA) civInfo.tech.scienceFromResearchAgreements += scienceFromResearchAgreement @@ -696,16 +699,16 @@ class DiplomacyManager() { diplomaticModifiers[modifier.name] = amount } - fun getModifier(modifier: DiplomaticModifiers): Float { + private fun getModifier(modifier: DiplomaticModifiers): Float { if (!hasModifier(modifier)) return 0f return diplomaticModifiers[modifier.name]!! } - fun removeModifier(modifier: DiplomaticModifiers) = diplomaticModifiers.remove(modifier.name) + private fun removeModifier(modifier: DiplomaticModifiers) = diplomaticModifiers.remove(modifier.name) fun hasModifier(modifier: DiplomaticModifiers) = diplomaticModifiers.containsKey(modifier.name) /** @param amount always positive, so you don't need to think about it */ - fun revertToZero(modifier: DiplomaticModifiers, amount: Float) { + private fun revertToZero(modifier: DiplomaticModifiers, amount: Float) { if (!hasModifier(modifier)) return val currentAmount = getModifier(modifier) if (currentAmount > 0) addModifier(modifier, -amount) @@ -728,7 +731,7 @@ class DiplomacyManager() { } } - fun setFriendshipBasedModifier() { + private fun setFriendshipBasedModifier() { removeModifier(DiplomaticModifiers.DeclaredFriendshipWithOurAllies) removeModifier(DiplomaticModifiers.DeclaredFriendshipWithOurEnemies) for (thirdCiv in getCommonKnownCivs() @@ -747,8 +750,8 @@ class DiplomacyManager() { fun denounce() { setModifier(DiplomaticModifiers.Denunciation, -35f) otherCivDiplomacy().setModifier(DiplomaticModifiers.Denunciation, -35f) - setFlag(DiplomacyFlags.Denunceation, 30) - otherCivDiplomacy().setFlag(DiplomacyFlags.Denunceation, 30) + setFlag(DiplomacyFlags.Denunciation, 30) + otherCivDiplomacy().setFlag(DiplomacyFlags.Denunciation, 30) otherCiv().addNotification("[${civInfo.civName}] has denounced us!", NotificationIcon.Diplomacy, civInfo.civName) diff --git a/core/src/com/unciv/ui/trade/DiplomacyScreen.kt b/core/src/com/unciv/ui/trade/DiplomacyScreen.kt index f95df66260..d308d684f0 100644 --- a/core/src/com/unciv/ui/trade/DiplomacyScreen.kt +++ b/core/src/com/unciv/ui/trade/DiplomacyScreen.kt @@ -16,7 +16,6 @@ import com.unciv.logic.civilization.diplomacy.RelationshipLevel import com.unciv.logic.trade.TradeLogic import com.unciv.logic.trade.TradeOffer import com.unciv.logic.trade.TradeType -import com.unciv.models.ruleset.Era import com.unciv.models.ruleset.ModOptionsConstants import com.unciv.models.ruleset.Quest import com.unciv.models.ruleset.tile.ResourceType @@ -593,7 +592,7 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() { diplomacyTable.add(researchAgreementButton).row() } - if (!diplomacyManager.hasFlag(DiplomacyFlags.Denunceation) + if (!diplomacyManager.hasFlag(DiplomacyFlags.Denunciation) && !diplomacyManager.hasFlag(DiplomacyFlags.DeclarationOfFriendship) ) { val denounceButton = "Denounce ([30] turns)".toTextButton()