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
This commit is contained in:
SeventhM 2023-06-28 00:48:33 -07:00 committed by GitHub
parent ee855b8d77
commit 73fa87e6b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 54 additions and 49 deletions

View File

@ -79,6 +79,7 @@ object GUI {
} }
fun isMyTurn(): Boolean { fun isMyTurn(): Boolean {
if (!UncivGame.isCurrentInitialized() || !isWorldLoaded()) return false
return UncivGame.Current.worldScreen!!.isPlayersTurn return UncivGame.Current.worldScreen!!.isPlayersTurn
} }

View File

@ -19,6 +19,8 @@ import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.RulesetCache import com.unciv.models.ruleset.RulesetCache
import com.unciv.models.ruleset.unique.StateForConditionals import com.unciv.models.ruleset.unique.StateForConditionals
import com.unciv.models.ruleset.unique.UniqueType 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.ruleset.unit.BaseUnit
import com.unciv.models.stats.Stats import com.unciv.models.stats.Stats
import com.unciv.models.translations.equalsPlaceholderText import com.unciv.models.translations.equalsPlaceholderText
@ -167,9 +169,14 @@ object GameStarter {
private fun addCivTechs(gameInfo: GameInfo, ruleset: Ruleset, gameSetupInfo: GameSetupInfo) { private fun addCivTechs(gameInfo: GameInfo, ruleset: Ruleset, gameSetupInfo: GameSetupInfo) {
for (civInfo in gameInfo.civilizations.filter { !it.isBarbarian() }) { 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()) if (!civInfo.isHuman())
for (tech in gameInfo.getDifficulty().aiFreeTechs) for (tech in gameInfo.getDifficulty().aiFreeTechs)
civInfo.tech.addTechnology(tech) civInfo.tech.addTechnology(tech, false)
// generic start with technology unique // generic start with technology unique
for (unique in civInfo.getMatchingUniques(UniqueType.StartsWithTech)) { 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 // check if the technology is in the ruleset and not already researched
if (ruleset.technologies.containsKey(techName) && !civInfo.tech.isResearched(techName)) if (ruleset.technologies.containsKey(techName) && !civInfo.tech.isResearched(techName))
civInfo.tech.addTechnology(techName) civInfo.tech.addTechnology(techName, false)
} }
// add all techs to spectators // add all techs to spectators
if (civInfo.isSpectator()) if (civInfo.isSpectator())
for (tech in ruleset.technologies.values) for (tech in ruleset.technologies.values)
if (!civInfo.tech.isResearched(tech.name)) if (!civInfo.tech.isResearched(tech.name))
civInfo.tech.addTechnology(tech.name) civInfo.tech.addTechnology(tech.name, false)
for (tech in ruleset.technologies.values for (tech in ruleset.technologies.values
.filter { ruleset.eras[it.era()]!!.eraNumber < ruleset.eras[gameSetupInfo.gameParameters.startingEra]!!.eraNumber }) .filter { ruleset.eras[it.era()]!!.eraNumber < ruleset.eras[gameSetupInfo.gameParameters.startingEra]!!.eraNumber })
if (!civInfo.tech.isResearched(tech.name)) 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... civInfo.popupAlerts.clear() // Since adding technologies generates popups...
} }
@ -330,8 +337,6 @@ object GameStarter {
ruleset: Ruleset, ruleset: Ruleset,
chosenPlayers: List<Player> chosenPlayers: List<Player>
) { ) {
val startingTechs = ruleset.technologies.values.filter { it.hasUnique(UniqueType.StartingTech) }
if (!newGameParameters.noBarbarians && ruleset.nations.containsKey(Constants.barbarians)) { if (!newGameParameters.noBarbarians && ruleset.nations.containsKey(Constants.barbarians)) {
val barbarianCivilization = Civilization(Constants.barbarians) val barbarianCivilization = Civilization(Constants.barbarians)
gameInfo.civilizations.add(barbarianCivilization) gameInfo.civilizations.add(barbarianCivilization)
@ -349,8 +354,6 @@ object GameStarter {
Constants.spectator -> Constants.spectator ->
civ.playerType = player.playerType civ.playerType = player.playerType
in usedMajorCivs -> { 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.playerType = player.playerType
civ.playerId = player.playerId civ.playerId = player.playerId
} }
@ -422,6 +425,12 @@ object GameStarter {
val startingUnits = getStartingUnitsForEraAndDifficulty(civ, gameInfo, ruleset, startingEra) val startingUnits = getStartingUnitsForEraAndDifficulty(civ, gameInfo, ruleset, startingEra)
adjustStartingUnitsForCityStatesAndOneCityChallenge(civ, gameInfo, startingUnits, settlerLikeUnits) adjustStartingUnitsForCityStatesAndOneCityChallenge(civ, gameInfo, startingUnits, settlerLikeUnits)
placeStartingUnits(civ, startingLocation, startingUnits, ruleset, ruleset.eras[startingEra]!!.startingMilitaryUnit, 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)
} }
} }

View File

@ -31,10 +31,6 @@ class CityStateFunctions(val civInfo: Civilization) {
/** Attempts to initialize the city state, returning true if successful. */ /** Attempts to initialize the city state, returning true if successful. */
fun initCityState(ruleset: Ruleset, startingEra: String, unusedMajorCivs: Collection<String>): Boolean { fun initCityState(ruleset: Ruleset, startingEra: String, unusedMajorCivs: Collection<String>): 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 allMercantileResources = ruleset.tileResources.values.filter { it.hasUnique(UniqueType.CityStateOnlyResource) }.map { it.name }
val uniqueTypes = HashSet<UniqueType>() // We look through these to determine what kinds of city states we have val uniqueTypes = HashSet<UniqueType>() // We look through these to determine what kinds of city states we have

View File

@ -214,7 +214,10 @@ class PolicyManager : IsPartOfGameInfoSerialization {
civInfo.cache.updateCivResources() civInfo.cache.updateCivResources()
// This ALSO has the side-effect of updating the CivInfo statForNextTurn so we don't need to call it explicitly // 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 if (!canAdoptPolicy()) shouldOpenPolicyPicker = false
} }

View File

@ -276,7 +276,7 @@ class TechManager : IsPartOfGameInfoSerialization {
addTechnology(techName) addTechnology(techName)
} }
fun addTechnology(techName: String) { fun addTechnology(techName: String, showNotification: Boolean = true) {
val isNewTech = techsResearched.add(techName) val isNewTech = techsResearched.add(techName)
// this is to avoid concurrent modification problems // this is to avoid concurrent modification problems
@ -302,10 +302,10 @@ class TechManager : IsPartOfGameInfoSerialization {
updateTransientBooleans() updateTransientBooleans()
for (city in civInfo.cities) { for (city in civInfo.cities) {
city.cityStats.update() city.cityStats.update()
city.updateCitizens = true city.reassignPopulationDeferred()
} }
if (!civInfo.isSpectator()) if (!civInfo.isSpectator() && showNotification)
civInfo.addNotification("Research of [$techName] has completed!", TechAction(techName), civInfo.addNotification("Research of [$techName] has completed!", TechAction(techName),
NotificationCategory.General, NotificationCategory.General,
NotificationIcon.Science) NotificationIcon.Science)
@ -313,21 +313,15 @@ class TechManager : IsPartOfGameInfoSerialization {
civInfo.popupAlerts.add(PopupAlert(AlertType.TechResearched, techName)) civInfo.popupAlerts.add(PopupAlert(AlertType.TechResearched, techName))
val revealedResources = getRuleset().tileResources.values.filter { techName == it.revealedBy } val revealedResources = getRuleset().tileResources.values.filter { techName == it.revealedBy }
var mayNeedUpdateResources = revealedResources.isNotEmpty() // default for AI
if (civInfo.playerType == PlayerType.Human) { if (civInfo.playerType == PlayerType.Human) {
mayNeedUpdateResources = false
for (revealedResource in revealedResources) { for (revealedResource in revealedResources) {
// notifyExploredResources scans the player's owned tiles and returns false if none civInfo.gameInfo.notifyExploredResources(civInfo, revealedResource.name, 5)
// found with a revealed resource - keep this knowledge to avoid the update call.
mayNeedUpdateResources = mayNeedUpdateResources ||
civInfo.gameInfo.notifyExploredResources(civInfo, revealedResource.name, 5)
} }
} }
// At least in the case of a human player hurrying research, this civ's resource availability // In the case of a player hurrying research, this civ's resource availability may now be out of date
// may now be out of date - e.g. when an owned tile by luck already has an appropriate improvement. // - 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 unless we know there's no resource change. // That can be seen on WorldScreenTopBar, so better update.
if (mayNeedUpdateResources) civInfo.cache.updateCivResources()
civInfo.cache.updateCivResources()
obsoleteOldUnits(techName) obsoleteOldUnits(techName)
@ -341,7 +335,7 @@ class TechManager : IsPartOfGameInfoSerialization {
MayaLongCountAction(), NotificationCategory.General, MayaCalendar.notificationIcon) MayaLongCountAction(), NotificationCategory.General, MayaCalendar.notificationIcon)
} }
moveToNewEra() moveToNewEra(showNotification)
updateResearchProgress() updateResearchProgress()
} }
@ -396,34 +390,36 @@ class TechManager : IsPartOfGameInfoSerialization {
} }
} }
private fun moveToNewEra() { private fun moveToNewEra(showNotification: Boolean = true) {
val previousEra = civInfo.getEra() val previousEra = civInfo.getEra()
updateEra() updateEra()
val currentEra = civInfo.getEra() val currentEra = civInfo.getEra()
if (previousEra != currentEra) { if (previousEra != currentEra) {
if(!civInfo.isSpectator()) if(showNotification) {
civInfo.addNotification( if(!civInfo.isSpectator())
"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())
civInfo.addNotification( civInfo.addNotification(
"[${policyBranch.name}] policy branch unlocked!", "You have entered the [$currentEra]!",
NotificationCategory.General, 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 val erasPassed = getRuleset().eras.values