From 73fa87e6b4947e92b02ee039dc402b7855d0f696 Mon Sep 17 00:00:00 2001 From: SeventhM <127357473+SeventhM@users.noreply.github.com> Date: Wed, 28 Jun 2023 00:48:33 -0700 Subject: [PATCH] Check for trigger uniques when starting and recaluating population (#9673) * Check for trigger uniques when starting and recaluating population * Adding imports * whoops * Moved where starting techs are added, added a parameter, and fixed the check for GUI --- core/src/com/unciv/UncivGame.kt | 1 + core/src/com/unciv/logic/GameStarter.kt | 25 ++++--- .../diplomacy/CityStateFunctions.kt | 4 -- .../civilization/managers/PolicyManager.kt | 5 +- .../civilization/managers/TechManager.kt | 68 +++++++++---------- 5 files changed, 54 insertions(+), 49 deletions(-) diff --git a/core/src/com/unciv/UncivGame.kt b/core/src/com/unciv/UncivGame.kt index 97dd140cf6..20c7ba86e6 100644 --- a/core/src/com/unciv/UncivGame.kt +++ b/core/src/com/unciv/UncivGame.kt @@ -79,6 +79,7 @@ object GUI { } fun isMyTurn(): Boolean { + if (!UncivGame.isCurrentInitialized() || !isWorldLoaded()) return false return UncivGame.Current.worldScreen!!.isPlayersTurn } diff --git a/core/src/com/unciv/logic/GameStarter.kt b/core/src/com/unciv/logic/GameStarter.kt index 5b2e9aef99..b16b2bcc81 100644 --- a/core/src/com/unciv/logic/GameStarter.kt +++ b/core/src/com/unciv/logic/GameStarter.kt @@ -19,6 +19,8 @@ import com.unciv.models.ruleset.Ruleset import com.unciv.models.ruleset.RulesetCache import com.unciv.models.ruleset.unique.StateForConditionals import com.unciv.models.ruleset.unique.UniqueType +import com.unciv.models.ruleset.unique.UniqueTarget +import com.unciv.models.ruleset.unique.UniqueTriggerActivation import com.unciv.models.ruleset.unit.BaseUnit import com.unciv.models.stats.Stats import com.unciv.models.translations.equalsPlaceholderText @@ -167,9 +169,14 @@ object GameStarter { private fun addCivTechs(gameInfo: GameInfo, ruleset: Ruleset, gameSetupInfo: GameSetupInfo) { for (civInfo in gameInfo.civilizations.filter { !it.isBarbarian() }) { + for(tech in ruleset.technologies.values.filter { it.hasUnique(UniqueType.StartingTech) }) + { + civInfo.tech.addTechnology(tech.name, false) + } + if (!civInfo.isHuman()) for (tech in gameInfo.getDifficulty().aiFreeTechs) - civInfo.tech.addTechnology(tech) + civInfo.tech.addTechnology(tech, false) // generic start with technology unique for (unique in civInfo.getMatchingUniques(UniqueType.StartsWithTech)) { @@ -178,19 +185,19 @@ object GameStarter { // check if the technology is in the ruleset and not already researched if (ruleset.technologies.containsKey(techName) && !civInfo.tech.isResearched(techName)) - civInfo.tech.addTechnology(techName) + civInfo.tech.addTechnology(techName, false) } // add all techs to spectators if (civInfo.isSpectator()) for (tech in ruleset.technologies.values) if (!civInfo.tech.isResearched(tech.name)) - civInfo.tech.addTechnology(tech.name) + civInfo.tech.addTechnology(tech.name, false) for (tech in ruleset.technologies.values .filter { ruleset.eras[it.era()]!!.eraNumber < ruleset.eras[gameSetupInfo.gameParameters.startingEra]!!.eraNumber }) if (!civInfo.tech.isResearched(tech.name)) - civInfo.tech.addTechnology(tech.name) + civInfo.tech.addTechnology(tech.name, false) civInfo.popupAlerts.clear() // Since adding technologies generates popups... } @@ -330,8 +337,6 @@ object GameStarter { ruleset: Ruleset, chosenPlayers: List ) { - val startingTechs = ruleset.technologies.values.filter { it.hasUnique(UniqueType.StartingTech) } - if (!newGameParameters.noBarbarians && ruleset.nations.containsKey(Constants.barbarians)) { val barbarianCivilization = Civilization(Constants.barbarians) gameInfo.civilizations.add(barbarianCivilization) @@ -349,8 +354,6 @@ object GameStarter { Constants.spectator -> civ.playerType = player.playerType in usedMajorCivs -> { - for (tech in startingTechs) - civ.tech.techsResearched.add(tech.name) // can't be .addTechnology because the civInfo isn't assigned yet civ.playerType = player.playerType civ.playerId = player.playerId } @@ -422,6 +425,12 @@ object GameStarter { val startingUnits = getStartingUnitsForEraAndDifficulty(civ, gameInfo, ruleset, startingEra) adjustStartingUnitsForCityStatesAndOneCityChallenge(civ, gameInfo, startingUnits, settlerLikeUnits) placeStartingUnits(civ, startingLocation, startingUnits, ruleset, ruleset.eras[startingEra]!!.startingMilitaryUnit, settlerLikeUnits) + + //Trigger any global or nation uniques that should triggered. + //We may need the starting location for some uniques, which is why we're doing it now + for (unique in ruleset.globalUniques.uniqueObjects + civ.nation.uniqueObjects) + if(unique.isTriggerable) + UniqueTriggerActivation.triggerCivwideUnique(unique,civ, tile = startingLocation) } } diff --git a/core/src/com/unciv/logic/civilization/diplomacy/CityStateFunctions.kt b/core/src/com/unciv/logic/civilization/diplomacy/CityStateFunctions.kt index f00252119e..909b713a1f 100644 --- a/core/src/com/unciv/logic/civilization/diplomacy/CityStateFunctions.kt +++ b/core/src/com/unciv/logic/civilization/diplomacy/CityStateFunctions.kt @@ -31,10 +31,6 @@ class CityStateFunctions(val civInfo: Civilization) { /** Attempts to initialize the city state, returning true if successful. */ fun initCityState(ruleset: Ruleset, startingEra: String, unusedMajorCivs: Collection): Boolean { - val startingTechs = ruleset.technologies.values.filter { it.hasUnique(UniqueType.StartingTech) } - for (tech in startingTechs) - civInfo.tech.techsResearched.add(tech.name) // can't be .addTechnology because the civInfo isn't assigned yet - val allMercantileResources = ruleset.tileResources.values.filter { it.hasUnique(UniqueType.CityStateOnlyResource) }.map { it.name } val uniqueTypes = HashSet() // We look through these to determine what kinds of city states we have diff --git a/core/src/com/unciv/logic/civilization/managers/PolicyManager.kt b/core/src/com/unciv/logic/civilization/managers/PolicyManager.kt index d3921672c8..ceb47e9a00 100644 --- a/core/src/com/unciv/logic/civilization/managers/PolicyManager.kt +++ b/core/src/com/unciv/logic/civilization/managers/PolicyManager.kt @@ -214,7 +214,10 @@ class PolicyManager : IsPartOfGameInfoSerialization { civInfo.cache.updateCivResources() // This ALSO has the side-effect of updating the CivInfo statForNextTurn so we don't need to call it explicitly - for (cityInfo in civInfo.cities) cityInfo.cityStats.update() + for (cityInfo in civInfo.cities) { + cityInfo.cityStats.update() + cityInfo.reassignPopulationDeferred() + } if (!canAdoptPolicy()) shouldOpenPolicyPicker = false } diff --git a/core/src/com/unciv/logic/civilization/managers/TechManager.kt b/core/src/com/unciv/logic/civilization/managers/TechManager.kt index 45f4b88ba2..9255063375 100644 --- a/core/src/com/unciv/logic/civilization/managers/TechManager.kt +++ b/core/src/com/unciv/logic/civilization/managers/TechManager.kt @@ -276,7 +276,7 @@ class TechManager : IsPartOfGameInfoSerialization { addTechnology(techName) } - fun addTechnology(techName: String) { + fun addTechnology(techName: String, showNotification: Boolean = true) { val isNewTech = techsResearched.add(techName) // this is to avoid concurrent modification problems @@ -302,10 +302,10 @@ class TechManager : IsPartOfGameInfoSerialization { updateTransientBooleans() for (city in civInfo.cities) { city.cityStats.update() - city.updateCitizens = true + city.reassignPopulationDeferred() } - if (!civInfo.isSpectator()) + if (!civInfo.isSpectator() && showNotification) civInfo.addNotification("Research of [$techName] has completed!", TechAction(techName), NotificationCategory.General, NotificationIcon.Science) @@ -313,21 +313,15 @@ class TechManager : IsPartOfGameInfoSerialization { civInfo.popupAlerts.add(PopupAlert(AlertType.TechResearched, techName)) val revealedResources = getRuleset().tileResources.values.filter { techName == it.revealedBy } - var mayNeedUpdateResources = revealedResources.isNotEmpty() // default for AI if (civInfo.playerType == PlayerType.Human) { - mayNeedUpdateResources = false for (revealedResource in revealedResources) { - // notifyExploredResources scans the player's owned tiles and returns false if none - // found with a revealed resource - keep this knowledge to avoid the update call. - mayNeedUpdateResources = mayNeedUpdateResources || - civInfo.gameInfo.notifyExploredResources(civInfo, revealedResource.name, 5) + civInfo.gameInfo.notifyExploredResources(civInfo, revealedResource.name, 5) } } - // At least in the case of a human player hurrying research, this civ's resource availability - // may now be out of date - e.g. when an owned tile by luck already has an appropriate improvement. - // That can be seen on WorldScreenTopBar, so better update unless we know there's no resource change. - if (mayNeedUpdateResources) - civInfo.cache.updateCivResources() + // In the case of a player hurrying research, this civ's resource availability may now be out of date + // - e.g. when an owned tile by luck already has an appropriate improvement or when a tech provides a resource. + // That can be seen on WorldScreenTopBar, so better update. + civInfo.cache.updateCivResources() obsoleteOldUnits(techName) @@ -341,7 +335,7 @@ class TechManager : IsPartOfGameInfoSerialization { MayaLongCountAction(), NotificationCategory.General, MayaCalendar.notificationIcon) } - moveToNewEra() + moveToNewEra(showNotification) updateResearchProgress() } @@ -396,34 +390,36 @@ class TechManager : IsPartOfGameInfoSerialization { } } - private fun moveToNewEra() { + private fun moveToNewEra(showNotification: Boolean = true) { val previousEra = civInfo.getEra() updateEra() val currentEra = civInfo.getEra() if (previousEra != currentEra) { - if(!civInfo.isSpectator()) - civInfo.addNotification( - "You have entered the [$currentEra]!", - NotificationCategory.General, - NotificationIcon.Science - ) - if (civInfo.isMajorCiv()) { - for (knownCiv in civInfo.getKnownCivs()) { - knownCiv.addNotification( - "[${civInfo.civName}] has entered the [$currentEra]!", - NotificationCategory.General, civInfo.civName, NotificationIcon.Science - ) - } - } - for (policyBranch in getRuleset().policyBranches.values.filter { - it.era == currentEra.name && civInfo.policies.isAdoptable(it) - }) { - if (!civInfo.isSpectator()) + if(showNotification) { + if(!civInfo.isSpectator()) civInfo.addNotification( - "[${policyBranch.name}] policy branch unlocked!", + "You have entered the [$currentEra]!", NotificationCategory.General, - NotificationIcon.Culture + NotificationIcon.Science ) + if (civInfo.isMajorCiv()) { + for (knownCiv in civInfo.getKnownCivs()) { + knownCiv.addNotification( + "[${civInfo.civName}] has entered the [$currentEra]!", + NotificationCategory.General, civInfo.civName, NotificationIcon.Science + ) + } + } + for (policyBranch in getRuleset().policyBranches.values.filter { + it.era == currentEra.name && civInfo.policies.isAdoptable(it) + }) { + if (!civInfo.isSpectator()) + civInfo.addNotification( + "[${policyBranch.name}] policy branch unlocked!", + NotificationCategory.General, + NotificationIcon.Culture + ) + } } val erasPassed = getRuleset().eras.values