From 0def261012810f51346c30ba7794ba3b7208303f Mon Sep 17 00:00:00 2001 From: yairm210 Date: Fri, 3 Dec 2021 10:45:27 +0200 Subject: [PATCH] Added unique types, added regions for easier location --- .../unciv/logic/automation/UnitAutomation.kt | 2 +- .../civilization/CivInfoTransientUpdater.kt | 2 +- .../logic/civilization/CivilizationInfo.kt | 2 +- .../logic/civilization/VictoryManager.kt | 5 +- .../mapgenerator/NaturalWonderGenerator.kt | 12 ++--- .../unciv/models/ruleset/unique/UniqueType.kt | 54 +++++++++++++------ docs/uniques.md | 12 +++++ 7 files changed, 63 insertions(+), 26 deletions(-) diff --git a/core/src/com/unciv/logic/automation/UnitAutomation.kt b/core/src/com/unciv/logic/automation/UnitAutomation.kt index 3226393541..3821673b90 100644 --- a/core/src/com/unciv/logic/automation/UnitAutomation.kt +++ b/core/src/com/unciv/logic/automation/UnitAutomation.kt @@ -129,7 +129,7 @@ object UnitAutomation { // Might die next turn - move! if (unit.health <= unit.getDamageFromTerrain() && tryHealUnit(unit)) return - if (unit.isCivilian() || unit.hasUnique(UniqueType.CannotAttack)) { + if (unit.isCivilian()) { if (tryRunAwayIfNeccessary(unit)) return if (unit.hasUnique(UniqueType.FoundCity)) diff --git a/core/src/com/unciv/logic/civilization/CivInfoTransientUpdater.kt b/core/src/com/unciv/logic/civilization/CivInfoTransientUpdater.kt index ff3ff2b862..6a5e930532 100644 --- a/core/src/com/unciv/logic/civilization/CivInfoTransientUpdater.kt +++ b/core/src/com/unciv/logic/civilization/CivInfoTransientUpdater.kt @@ -122,7 +122,7 @@ class CivInfoTransientUpdater(val civInfo: CivilizationInfo) { var goldGained = 0 val discoveredNaturalWonders = civInfo.gameInfo.civilizations.filter { it != civInfo && it.isMajorCiv() } .flatMap { it.naturalWonders } - if (tile.hasUnique("Grants 500 Gold to the first civilization to discover it") + if (tile.hasUnique(UniqueType.GrantsGoldToFirstToDiscover) && !discoveredNaturalWonders.contains(tile.naturalWonder!!)) { goldGained += 500 } diff --git a/core/src/com/unciv/logic/civilization/CivilizationInfo.kt b/core/src/com/unciv/logic/civilization/CivilizationInfo.kt index 7328d62e71..90698a1e3b 100644 --- a/core/src/com/unciv/logic/civilization/CivilizationInfo.kt +++ b/core/src/com/unciv/logic/civilization/CivilizationInfo.kt @@ -595,7 +595,7 @@ class CivilizationInfo { fun canSignResearchAgreement(): Boolean { if (!isMajorCiv()) return false - if (!hasUnique("Enables Research agreements")) return false + if (!hasUnique(UniqueType.EnablesResearchAgreements)) return false if (gameInfo.ruleSet.technologies.values .none { tech.canBeResearched(it.name) && !tech.isResearched(it.name) }) return false return true diff --git a/core/src/com/unciv/logic/civilization/VictoryManager.kt b/core/src/com/unciv/logic/civilization/VictoryManager.kt index 22b59b119c..beabb951a5 100644 --- a/core/src/com/unciv/logic/civilization/VictoryManager.kt +++ b/core/src/com/unciv/logic/civilization/VictoryManager.kt @@ -2,6 +2,7 @@ package com.unciv.logic.civilization import com.unciv.models.Counter import com.unciv.models.ruleset.VictoryType +import com.unciv.models.ruleset.unique.UniqueType class VictoryManager { @Transient @@ -68,7 +69,7 @@ class VictoryManager { fun hasWonScientificVictory() = hasVictoryType(VictoryType.Scientific) && spaceshipPartsRemaining() == 0 fun hasWonCulturalVictory() = hasVictoryType(VictoryType.Cultural) - && civInfo.hasUnique("Triggers a Cultural Victory upon completion") + && civInfo.hasUnique(UniqueType.TriggersCulturalVictory) fun hasWonDominationVictory(): Boolean { return hasVictoryType(VictoryType.Domination) @@ -85,7 +86,7 @@ class VictoryManager { if (hasWonScientificVictory()) return VictoryType.Scientific if (hasWonCulturalVictory()) return VictoryType.Cultural if (hasWonDiplomaticVictory()) return VictoryType.Diplomatic - if (civInfo.hasUnique("Triggers victory")) return VictoryType.Neutral + if (civInfo.hasUnique(UniqueType.TriggersVictory)) return VictoryType.Neutral return null } diff --git a/core/src/com/unciv/logic/map/mapgenerator/NaturalWonderGenerator.kt b/core/src/com/unciv/logic/map/mapgenerator/NaturalWonderGenerator.kt index 50ba8db7da..17057a9c31 100644 --- a/core/src/com/unciv/logic/map/mapgenerator/NaturalWonderGenerator.kt +++ b/core/src/com/unciv/logic/map/mapgenerator/NaturalWonderGenerator.kt @@ -53,9 +53,9 @@ class NaturalWonderGenerator(val ruleset: Ruleset, val randomness: MapGeneration private fun Unique.getIntParam(index: Int) = params[index].toInt() - private fun spawnSpecificWonder(tileMap: TileMap, wonder: Terrain): Boolean { - val continentsRelevant = wonder.hasUnique(UniqueType.NaturalWonderLargerLandmass) || - wonder.hasUnique(UniqueType.NaturalWonderSmallerLandmass) + private fun spawnSpecificWonder(tileMap: TileMap, naturalWonder: Terrain): Boolean { + val continentsRelevant = naturalWonder.hasUnique(UniqueType.NaturalWonderLargerLandmass) || + naturalWonder.hasUnique(UniqueType.NaturalWonderSmallerLandmass) val sortedContinents = if (continentsRelevant) tileMap.continentSizes.asSequence() .sortedByDescending { it.value } @@ -65,8 +65,8 @@ class NaturalWonderGenerator(val ruleset: Ruleset, val randomness: MapGeneration val suitableLocations = tileMap.values.filter { tile-> tile.resource == null && - wonder.occursOn.contains(tile.getLastTerrain().name) && - wonder.uniqueObjects.all { unique -> + naturalWonder.occursOn.contains(tile.getLastTerrain().name) && + naturalWonder.uniqueObjects.all { unique -> when (unique.type) { UniqueType.NaturalWonderNeighborCount -> { val count = tile.neighbors.count { @@ -96,7 +96,7 @@ class NaturalWonderGenerator(val ruleset: Ruleset, val randomness: MapGeneration } } - return trySpawnOnSuitableLocation(suitableLocations, wonder) + return trySpawnOnSuitableLocation(suitableLocations, naturalWonder) } private fun trySpawnOnSuitableLocation(suitableLocations: List, wonder: Terrain): Boolean { diff --git a/core/src/com/unciv/models/ruleset/unique/UniqueType.kt b/core/src/com/unciv/models/ruleset/unique/UniqueType.kt index fd5a49284f..f44e390d0a 100644 --- a/core/src/com/unciv/models/ruleset/unique/UniqueType.kt +++ b/core/src/com/unciv/models/ruleset/unique/UniqueType.kt @@ -61,10 +61,9 @@ enum class UniqueFlag { enum class UniqueType(val text:String, vararg targets: UniqueTarget, val flags: List = emptyList()) { - //////////////////////////////////////// GLOBAL UNIQUES //////////////////////////////////////// + //////////////////////////////////////// region GLOBAL UNIQUES //////////////////////////////////////// - - /////// Stat providing uniques + // region Stat providing uniques Stats("[stats]", UniqueTarget.Global, UniqueTarget.FollowerBelief, UniqueTarget.Improvement), StatsPerCity("[stats] [cityFilter]", UniqueTarget.Global), @@ -101,6 +100,8 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget, val flags: StatPercentFromReligionFollowers("[amount]% [stat] from every follower, up to [amount]%", UniqueTarget.FollowerBelief, UniqueTarget.Global), + //endregion Stat providing uniques + PercentProductionWonders("[amount]% Production when constructing [buildingFilter] wonders [cityFilter]", UniqueTarget.Global, UniqueTarget.Resource, UniqueTarget.FollowerBelief), PercentProductionBuildings("[amount]% Production when constructing [buildingFilter] buildings [cityFilter]", UniqueTarget.Global), PercentProductionUnits("[amount]% Production when constructing [baseUnitFilter] units [cityFilter]", UniqueTarget.Global), @@ -125,7 +126,7 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget, val flags: UnhappinessFromPopulationPercentageChangeOld2("Unhappiness from population decreased by [amount]% [cityFilter]", UniqueTarget.Global), - /////// City-State related uniques + // region City-State related uniques // I don't like the fact that currently "city state bonuses" are separate from the "global bonuses", // todo: merge city state bonuses into global bonuses @@ -142,6 +143,8 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget, val flags: CityStateCanGiftGreatPeople("Allied City-States will occasionally gift Great People", UniqueTarget.Global), // used in Policy CityStateDeprecated("Will not be chosen for new games", UniqueTarget.Nation), // implemented for CS only for now + // endregion + /////// Other global uniques FreeUnits("[amount] units cost no maintenance", UniqueTarget.Global), @@ -195,8 +198,13 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget, val flags: RetainHappinessFromLuxury("Retain [amount]% of the happiness from a luxury after the last copy has been traded away", UniqueTarget.Nation), + EnablesResearchAgreements("Enables Research agreements", UniqueTarget.Global), + TriggersVictory("Triggers victory", UniqueTarget.Global), + TriggersCulturalVictory("Triggers a Cultural Victory upon completion", UniqueTarget.Global), - ///////////////////////////////////////// CONSTRUCTION UNIQUES ///////////////////////////////////////// + //endregion Global uniques + + ///////////////////////////////////////// region CONSTRUCTION UNIQUES ///////////////////////////////////////// Unbuildable("Unbuildable", UniqueTarget.Building, UniqueTarget.Unit), CannotBePurchased("Cannot be purchased", UniqueTarget.Building, UniqueTarget.Unit), @@ -204,7 +212,10 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget, val flags: CanBePurchasedForAmountStat("Can be purchased for [amount] [stat] [cityFilter]", UniqueTarget.Building, UniqueTarget.Unit), MaxNumberBuildable("Limited to [amount] per Civilization", UniqueTarget.Building, UniqueTarget.Unit), - ///////////////////////////////////////// BUILDING UNIQUES ///////////////////////////////////////// + //endregion + + + ///////////////////////////////////////// region BUILDING UNIQUES ///////////////////////////////////////// CostIncreasesPerCity("Cost increases by [amount] per owned city", UniqueTarget.Building), @@ -221,8 +232,10 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget, val flags: MustBeNextTo("Must be next to [terrainFilter]", UniqueTarget.Building), MustNotBeNextTo("Must not be next to [terrainFilter]", UniqueTarget.Building), + //endregion - ///////////////////////////////////////// UNIT UNIQUES ///////////////////////////////////////// + + ///////////////////////////////////////// region UNIT UNIQUES ///////////////////////////////////////// FoundCity("Founds a new city", UniqueTarget.Unit), BuildImprovements("Can build [improvementFilter/terrainFilter] improvements on tiles", UniqueTarget.Unit), @@ -322,9 +335,11 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget, val flags: ReligiousUnit("Religious Unit", UniqueTarget.Unit), - ///////////////////////////////////////// TILE UNIQUES ///////////////////////////////////////// + //endregion + ///////////////////////////////////////// region TILE UNIQUES ///////////////////////////////////////// + // region natural wonders NaturalWonderNeighborCount("Must be adjacent to [amount] [simpleTerrain] tiles", UniqueTarget.Terrain, flags = listOf(UniqueFlag.HideInCivilopedia)), NaturalWonderNeighborsRange("Must be adjacent to [amount] to [amount] [simpleTerrain] tiles", UniqueTarget.Terrain, flags = listOf(UniqueFlag.HideInCivilopedia)), NaturalWonderSmallerLandmass("Must not be on [amount] largest landmasses", UniqueTarget.Terrain, flags = listOf(UniqueFlag.HideInCivilopedia)), @@ -332,9 +347,10 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget, val flags: NaturalWonderLatitude("Occurs on latitudes from [amount] to [amount] percent of distance equator to pole", UniqueTarget.Terrain, flags = listOf(UniqueFlag.HideInCivilopedia)), NaturalWonderGroups("Occurs in groups of [amount] to [amount] tiles", UniqueTarget.Terrain, flags = listOf(UniqueFlag.HideInCivilopedia)), NaturalWonderConvertNeighbors("Neighboring tiles will convert to [baseTerrain]", UniqueTarget.Terrain, flags = listOf(UniqueFlag.HideInCivilopedia)), - // The "Except [terrainFilter]" could theoretically be implemented with a conditional NaturalWonderConvertNeighborsExcept("Neighboring tiles except [baseTerrain] will convert to [baseTerrain]", UniqueTarget.Terrain, flags = listOf(UniqueFlag.HideInCivilopedia)), + GrantsGoldToFirstToDiscover("Grants 500 Gold to the first civilization to discover it", UniqueTarget.Terrain), + // endregion DamagesContainingUnits("Units ending their turn on this terrain take [amount] damage", UniqueTarget.Terrain), TerrainGrantsPromotion("Grants [promotion] ([comment]) to adjacent [mapUnitFilter] units for the rest of the game", UniqueTarget.Terrain), @@ -381,8 +397,10 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget, val flags: /////// Resource uniques ResourceAmountOnTiles("Deposits in [tileFilter] tiles always provide [amount] resources", UniqueTarget.Resource), CityStateOnlyResource("Can only be created by Mercantile City-States", UniqueTarget.Resource), - - ////// Improvement uniques + + //endregion + + ////// region Improvement uniques ImprovementBuildableByFreshWater("Can also be built on tiles adjacent to fresh water", UniqueTarget.Improvement), ImprovementStatsOnTile("[stats] from [tileFilter] tiles", UniqueTarget.Improvement), @Deprecated("As of 3.17.10", ReplaceWith("[stats] from [tileFilter] tiles "), DeprecationLevel.WARNING) @@ -409,7 +427,9 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget, val flags: Unpillagable("Unpillagable", UniqueTarget.Improvement), Indestructible("Indestructible", UniqueTarget.Improvement), - ///////////////////////////////////////// CONDITIONALS ///////////////////////////////////////// + //endregion + + ///////////////////////////////////////// region CONDITIONALS ///////////////////////////////////////// /////// civ conditionals @@ -446,12 +466,14 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget, val flags: ConditionalNeighborTiles("with [amount] to [amount] neighboring [tileFilter] tiles", UniqueTarget.Conditional), ConditionalNeighborTilesAnd("with [amount] to [amount] neighboring [tileFilter] [tileFilter] tiles", UniqueTarget.Conditional), - /////// region conditionals + /////// area conditionals ConditionalOnWaterMaps("on water maps", UniqueTarget.Conditional), ConditionalInRegionOfType("in [regionType] Regions", UniqueTarget.Conditional), ConditionalInRegionExceptOfType("in all except [regionType] Regions", UniqueTarget.Conditional), - ///////////////////////////////////////// TRIGGERED ONE-TIME ///////////////////////////////////////// + //endregion + + ///////////////////////////////////////// region TRIGGERED ONE-TIME ///////////////////////////////////////// OneTimeFreeUnit("Free [baseUnitFilter] appears", UniqueTarget.Global), // used in Policies, Buildings @@ -494,7 +516,9 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget, val flags: FreeStatBuildingsDeprecated("Immediately creates the cheapest available cultural building in each of your first [amount] cities for free", UniqueTarget.Global), @Deprecated("As of 3.16.15 - removed 3.18.4", ReplaceWith("Provides a [buildingName] in your first [amount] cities for free"), DeprecationLevel.ERROR) FreeSpecificBuildingsDeprecated("Immediately creates a [buildingName] in each of your first [amount] cities for free", UniqueTarget.Global), - + + //endregion + ///////////////////////////////////////////// META ///////////////////////////////////////////// diff --git a/docs/uniques.md b/docs/uniques.md index 4982fe975d..e8973d73f0 100644 --- a/docs/uniques.md +++ b/docs/uniques.md @@ -210,6 +210,15 @@ Example: "May buy [buildingFilter] buildings with [Culture] for [20] times their Applicable to: Global, FollowerBelief +#### Enables Research agreements +Applicable to: Global + +#### Triggers victory +Applicable to: Global + +#### Triggers a Cultural Victory upon completion +Applicable to: Global + #### [amount]% Strength Example: "[20]% Strength" @@ -566,6 +575,9 @@ Example: "Neighboring tiles except [baseTerrain] will convert to [baseTerrain]" Applicable to: Terrain +#### Grants 500 Gold to the first civilization to discover it +Applicable to: Terrain + #### Units ending their turn on this terrain take [amount] damage Example: "Units ending their turn on this terrain take [20] damage"