chore: deprecated old uniques

This commit is contained in:
yairm210 2025-08-12 18:00:35 +03:00
parent 7f690c3f51
commit 7b796e3ee7
15 changed files with 38 additions and 92 deletions

View File

@ -54,14 +54,6 @@ object BattleDamage {
if (greatGeneralBonus != 0)
modifiers[greatGeneralName] = greatGeneralBonus
for (unique in combatant.unit.getMatchingUniques(UniqueType.StrengthWhenStacked)) {
var stackedUnitsBonus = 0
if (combatant.unit.getTile().getUnits().any { it.matchesFilter(unique.params[1]) })
stackedUnitsBonus += unique.params[0].toInt()
if (stackedUnitsBonus > 0)
modifiers["Stacked with [${unique.params[1]}]"] = stackedUnitsBonus
}
} else if (combatant is CityCombatant) {
for (unique in combatant.city.getMatchingUniques(UniqueType.StrengthForCities, conditionalState)) {
modifiers.add(getModifierStringFromUnique(unique), unique.params[0].toInt())

View File

@ -141,11 +141,6 @@ class CityConstructions : IsPartOfGameInfoSerialization {
maintenanceCost += maintenanceForThisBuilding
}
for (unique in city.getMatchingUniques(UniqueType.BuildingMaintenanceOld)) {
maintenanceCost = (maintenanceCost * unique.params[0].toPercent())
}
return maintenanceCost
}

View File

@ -174,8 +174,7 @@ class CityStats(val city: City) {
@Readonly
fun hasExtraAnnexUnhappiness(): Boolean {
if (city.civ.civName == city.foundingCiv || city.isPuppet) return false
return !city.containsBuildingUnique(UniqueType.RemoveAnnexUnhappiness)
&& !city.containsBuildingUnique(UniqueType.RemovesAnnexUnhappiness)
return !city.containsBuildingUnique(UniqueType.RemovesAnnexUnhappiness)
}
@Readonly

View File

@ -42,7 +42,6 @@ import com.unciv.models.ruleset.nation.Nation
import com.unciv.models.ruleset.nation.Personality
import com.unciv.models.ruleset.tech.Era
import com.unciv.models.ruleset.tile.ResourceSupplyList
import com.unciv.models.ruleset.tile.ResourceType
import com.unciv.models.ruleset.tile.TileImprovement
import com.unciv.models.ruleset.tile.TileResource
import com.unciv.models.ruleset.unique.*
@ -509,15 +508,9 @@ class Civilization : IsPartOfGameInfoSerialization {
fun getResourceModifier(resource: TileResource): Float {
var finalModifier = 1f
if (resource.resourceType == ResourceType.Strategic)
for (unique in getMatchingUniques(UniqueType.StrategicResourcesIncrease))
finalModifier += unique.params[0].toFloat() / 100f
for (unique in getMatchingUniques(UniqueType.PercentResourceProduction))
if (resource.matchesFilter(unique.params[1]))
finalModifier += unique.params[0].toFloat() / 100f
for (unique in getMatchingUniques(UniqueType.DoubleResourceProduced))
if (unique.params[0] == resource.name)
finalModifier += 1f
return finalModifier
}

View File

@ -522,9 +522,7 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
}
if (getMatchingUniques(UniqueType.StatsFromTiles).any { it.stats[stat] > 0 }) return true
if (getMatchingUniques(UniqueType.StatsPerPopulation).any { it.stats[stat] > 0 }) return true
if (stat == Stat.Happiness &&
(hasUnique(UniqueType.RemoveAnnexUnhappiness) || hasUnique(UniqueType.RemovesAnnexUnhappiness))
) return true
if (stat == Stat.Happiness && hasUnique(UniqueType.RemovesAnnexUnhappiness)) return true
return false
}

View File

@ -22,7 +22,6 @@ class GlobalUniques: RulesetObject() {
return when (unique.modifiers.first().type) {
UniqueType.ConditionalGoldenAge -> "Golden Age"
UniqueType.ConditionalHappy -> "Happiness"
UniqueType.ConditionalBetweenHappiness, UniqueType.ConditionalBelowHappiness -> "Unhappiness"
UniqueType.ConditionalWLTKD -> "We Love The King Day"
else -> "Global Effect"
}

View File

@ -197,7 +197,6 @@ class RejectionReason(val type: RejectionReasonType,
RejectionReasonType.RequiresBuildingInSomeCity,
RejectionReasonType.RequiresBuildingInSomeCities,
RejectionReasonType.CanOnlyBeBuiltInSpecificCities,
RejectionReasonType.CannotBeBuiltUnhappiness,
RejectionReasonType.PopulationRequirement,
RejectionReasonType.ConsumesResources,
RejectionReasonType.CanOnlyBePurchased,
@ -207,7 +206,6 @@ class RejectionReason(val type: RejectionReasonType,
// Exceptions. Used for units spawned/upgrade path, not built
private val constructionRejectionReasonType = listOf(
RejectionReasonType.Unbuildable,
RejectionReasonType.CannotBeBuiltUnhappiness,
RejectionReasonType.CannotBeBuilt,
RejectionReasonType.CanOnlyBeBuiltInSpecificCities,
)
@ -249,12 +247,10 @@ enum class RejectionReasonType(val shouldShow: Boolean, val errorMessage: String
UniqueToOtherNation(false, "Unique to another nation"),
ReplacedByOurUnique(false, "Our unique replaces this"),
CannotBeBuilt(false, "Cannot be built by this nation"),
CannotBeBuiltUnhappiness(true, "Unhappiness"),
Obsoleted(false, "Obsolete"),
RequiresTech(false, "Required tech not researched"),
RequiresPolicy(false, "Requires a specific policy!"),
UnlockedWithEra(false, "Unlocked when reaching a specific era"),
MorePolicyBranches(false, "Hidden until more policy branches are fully adopted"),
RequiresNearbyResource(false, "Requires a certain resource being exploited nearby"),

View File

@ -137,8 +137,12 @@ class Ruleset {
sequence {
for (unique in this@Ruleset.allUniques())
for (conditional in unique.modifiers){
if (conditional.type == UniqueType.ConditionalBelowHappiness) yield(conditional.params[0].toInt())
if (conditional.type == UniqueType.ConditionalBetweenHappiness){
if (conditional.type == UniqueType.ConditionalWhenBelowAmountStatResource
&& conditional.params[1] == "Happiness") yield(conditional.params[0].toInt())
if (conditional.type == UniqueType.ConditionalWhenAboveAmountStatResource
&& conditional.params[1] == "Happiness") yield(conditional.params[0].toInt())
if (conditional.type == UniqueType.ConditionalWhenBetweenStatResource
&& conditional.params[2] == "Happiness"){
yield(conditional.params[0].toInt())
yield(conditional.params[1].toInt() + 1)
}

View File

@ -136,10 +136,6 @@ object Conditionals {
{ current, lowerLimit, upperLimit -> current >= lowerLimit && current <= upperLimit }
UniqueType.ConditionalHappy -> checkOnCiv { stats.happiness >= 0 }
UniqueType.ConditionalBetweenHappiness ->
checkOnCiv { stats.happiness in conditional.params[0].toInt() .. conditional.params[1].toInt() }
UniqueType.ConditionalAboveHappiness -> checkOnCiv { stats.happiness > conditional.params[0].toInt() }
UniqueType.ConditionalBelowHappiness -> checkOnCiv { stats.happiness < conditional.params[0].toInt() }
UniqueType.ConditionalGoldenAge -> checkOnCiv { goldenAges.isGoldenAge() }
UniqueType.ConditionalNotGoldenAge -> checkOnCiv { !goldenAges.isGoldenAge() }

View File

@ -502,19 +502,6 @@ object UniqueTriggerActivation {
}
}
UniqueType.StrategicResourcesIncrease -> {
return {
civInfo.cache.updateCivResources()
if (notification != null)
civInfo.addNotification(
notification,
NotificationCategory.General,
NotificationIcon.Construction
)
true
}
}
UniqueType.OneTimeProvideResources -> {
val resourceName = unique.params[1]
val resource = ruleset.tileResources[resourceName] ?: return null

View File

@ -7,7 +7,6 @@ import com.unciv.models.ruleset.validation.RulesetValidator
import com.unciv.models.ruleset.validation.Suppression
import com.unciv.models.translations.getPlaceholderParameters
import com.unciv.models.translations.getPlaceholderText
import yairm210.purity.annotations.LocalState
import yairm210.purity.annotations.Readonly
// I didn't put this in a companion object because APPARENTLY doing that means you can't use it in the init function.
@ -144,8 +143,6 @@ enum class UniqueType(
GainFreeBuildings("Gain a free [buildingName] [cityFilter]", UniqueTarget.Global, UniqueTarget.Triggerable,
docDescription = "Free buildings CANNOT be self-removing - this leads to an endless loop of trying to add the building"),
BuildingMaintenance("[relativeAmount]% maintenance cost for [buildingFilter] buildings [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
@Deprecated(message = "as of 4.16.13", ReplaceWith("[relativeAmount]% maintenance cost for [all] buildings [cityFilter]"), level = DeprecationLevel.WARNING)
BuildingMaintenanceOld("[relativeAmount]% maintenance cost for buildings [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
RemoveBuilding("Remove [buildingFilter] [cityFilter]", UniqueTarget.Global, UniqueTarget.Triggerable),
OneTimeSellBuilding("Sell [buildingFilter] buildings [cityFilter]", UniqueTarget.Global, UniqueTarget.Triggerable),
@ -212,10 +209,6 @@ enum class UniqueType(
flags = setOf(UniqueFlag.AcceptsSpeedModifier)),
PercentResourceProduction("[relativeAmount]% [resourceFilter] resource production", UniqueTarget.Global),
@Deprecated("As of 4.16.18", ReplaceWith("[relativeAmount]% [Strategic] resource production"))
StrategicResourcesIncrease("Quantity of strategic resources produced by the empire +[relativeAmount]%", UniqueTarget.Global), // used by Policies
@Deprecated("As of 4.16.18", ReplaceWith("[+100]% [resource] resource production"))
DoubleResourceProduced("Double quantity of [resource] produced", UniqueTarget.Global),
/// Diplomacy
EnablesEmbassies("Enables establishment of embassies", UniqueTarget.Tech),
@ -352,8 +345,6 @@ enum class UniqueType(
DoublesGoldFromCapturingCity("Doubles Gold given to enemy if city is captured", UniqueTarget.Building),
@Deprecated("As of 4.16.14", ReplaceWith("Removes extra unhappiness from annexed cities"))
RemoveAnnexUnhappiness("Remove extra unhappiness from annexed cities", UniqueTarget.Building),
RemovesAnnexUnhappiness("Removes extra unhappiness from annexed cities", UniqueTarget.Building),
ConnectTradeRoutes("Connects trade routes over water", UniqueTarget.Building),
GainBuildingWhereBuildable("Automatically built in all cities where it is buildable", UniqueTarget.Building),
@ -404,8 +395,6 @@ enum class UniqueType(
StrengthNearCapital("[relativeAmount]% Strength decreasing with distance from the capital", UniqueTarget.Unit, UniqueTarget.Global),
FlankAttackBonus("[relativeAmount]% to Flank Attack bonuses", UniqueTarget.Unit, UniqueTarget.Global),
StrengthForAdjacentEnemies("[relativeAmount]% Strength for enemy [mapUnitFilter] units in adjacent [tileFilter] tiles", UniqueTarget.Unit),
@Deprecated("As of 4.16.14", ReplaceWith("[relativeAmount]% Strength <when stacked with a [mapUnitFilter] unit>"), DeprecationLevel.WARNING)
StrengthWhenStacked("[relativeAmount]% Strength when stacked with [mapUnitFilter]", UniqueTarget.Unit), // candidate for conditional!
StrengthBonusInRadius("[relativeAmount]% Strength bonus for [mapUnitFilter] units within [amount] tiles", UniqueTarget.Unit),
// Stat bonuses
@ -716,14 +705,7 @@ enum class UniqueType(
ConditionalWLTKD("during We Love The King Day", UniqueTarget.Conditional),
ConditionalHappy("while the empire is happy", UniqueTarget.Conditional),
@Deprecated("As of 4.16.18", ReplaceWith("when between [amount] and [amount] [Happiness]"), DeprecationLevel.WARNING)
ConditionalBetweenHappiness("when between [amount] and [amount] Happiness", UniqueTarget.Conditional,
docDescription = " 'Between' is inclusive - so 'between 1 and 5' includes 1 and 5."),
@Deprecated("As of 4.16.18", ReplaceWith("when above [amount] [Happiness]"), DeprecationLevel.WARNING)
ConditionalAboveHappiness("when above [amount] Happiness", UniqueTarget.Conditional),
@Deprecated("As of 4.16.18", ReplaceWith("when below [amount] [Happiness]"), DeprecationLevel.WARNING)
ConditionalBelowHappiness("when below [amount] Happiness", UniqueTarget.Conditional),
ConditionalDuringEra("during the [era]", UniqueTarget.Conditional),
ConditionalBeforeEra("before the [era]", UniqueTarget.Conditional),
ConditionalStartingFromEra("starting from the [era]", UniqueTarget.Conditional),
@ -1034,6 +1016,23 @@ enum class UniqueType(
// endregion
///////////////////////////////////////////// region 99 DEPRECATED AND REMOVED /////////////////////////////////////////////
@Deprecated("As of 4.16.18", ReplaceWith("[relativeAmount]% [Strategic] resource production"))
StrategicResourcesIncrease("Quantity of strategic resources produced by the empire +[relativeAmount]%", UniqueTarget.Global), // used by Policies
@Deprecated("As of 4.16.18", ReplaceWith("[+100]% [resource] resource production"))
DoubleResourceProduced("Double quantity of [resource] produced", UniqueTarget.Global),
@Deprecated(message = "as of 4.16.13", ReplaceWith("[relativeAmount]% maintenance cost for [all] buildings [cityFilter]"), level = DeprecationLevel.WARNING)
BuildingMaintenanceOld("[relativeAmount]% maintenance cost for buildings [cityFilter]", UniqueTarget.Global, UniqueTarget.FollowerBelief),
@Deprecated("As of 4.16.14", ReplaceWith("Removes extra unhappiness from annexed cities"), DeprecationLevel.ERROR)
RemoveAnnexUnhappiness("Remove extra unhappiness from annexed cities", UniqueTarget.Building),
@Deprecated("As of 4.16.14", ReplaceWith("[relativeAmount]% Strength <when stacked with a [mapUnitFilter] unit>"), DeprecationLevel.ERROR)
StrengthWhenStacked("[relativeAmount]% Strength when stacked with [mapUnitFilter]", UniqueTarget.Unit), // candidate for conditional!
@Deprecated("As of 4.16.18", ReplaceWith("when between [amount] and [amount] [Happiness]"), DeprecationLevel.ERROR)
ConditionalBetweenHappiness("when between [amount] and [amount] Happiness", UniqueTarget.Conditional,
docDescription = " 'Between' is inclusive - so 'between 1 and 5' includes 1 and 5."),
@Deprecated("As of 4.16.18", ReplaceWith("when above [amount] [Happiness]"), DeprecationLevel.ERROR)
ConditionalAboveHappiness("when above [amount] Happiness", UniqueTarget.Conditional),
@Deprecated("As of 4.16.18", ReplaceWith("when below [amount] [Happiness]"), DeprecationLevel.ERROR)
ConditionalBelowHappiness("when below [amount] Happiness", UniqueTarget.Conditional),
@Deprecated("As of 4.16.0", ReplaceWith("Unavailable <when number of [Completed Policy branches] is less than [amount]>"), DeprecationLevel.ERROR)
HiddenBeforeAmountPolicies("Hidden until [amount] social policy branches have been completed", UniqueTarget.Building, UniqueTarget.Unit),
@Deprecated("As of 4.15.11", ReplaceWith("New [baseUnitFilter] units start with [amount] XP [cityFilter]"), DeprecationLevel.ERROR)

View File

@ -286,11 +286,7 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction {
for (unique in civ.getMatchingUniques(UniqueType.CannotBuildUnits, stateForConditionals))
if (this@BaseUnit.matchesFilter(unique.params[0], stateForConditionals)) {
val hasHappinessCondition = unique.hasModifier(UniqueType.ConditionalBelowHappiness)
|| unique.hasModifier(UniqueType.ConditionalBetweenHappiness)
if (hasHappinessCondition)
yield(RejectionReasonType.CannotBeBuiltUnhappiness.toInstance(unique.getDisplayText()))
else yield(RejectionReasonType.CannotBeBuilt.toInstance())
yield(RejectionReasonType.CannotBeBuilt.toInstance())
}
if (city != null && isAirUnit() && !canUnitEnterTile(city)) {

View File

@ -183,7 +183,7 @@ class UniqueValidator(val ruleset: Ruleset) {
}
private val resourceUniques = setOf(UniqueType.ProvidesResources, UniqueType.ConsumesResources,
UniqueType.DoubleResourceProduced, UniqueType.StrategicResourcesIncrease, UniqueType.PercentResourceProduction)
UniqueType.PercentResourceProduction)
private val resourceConditionals = setOf(
UniqueType.ConditionalWithResource,
UniqueType.ConditionalWithoutResource,

View File

@ -135,10 +135,12 @@ class StatsOverviewTab(
init {
defaults().pad(5f)
uniques = sequenceOf(
UniqueType.ConditionalBetweenHappiness,
UniqueType.ConditionalBelowHappiness
UniqueType.ConditionalWhenAboveAmountStatResource,
UniqueType.ConditionalWhenBetweenStatResource,
UniqueType.ConditionalWhenBelowAmountStatResource,
).flatMap { conditionalType ->
viewingPlayer.getTriggeredUniques(conditionalType)
viewingPlayer.getMatchingUniques(conditionalType)
.filter { it.params.last() == "Happiness" }
.sortedBy { it.type } // otherwise order might change as a HashMap is involved
}.filterNot { it.isHiddenToUsers() }
.toSet()

View File

@ -3,8 +3,6 @@ package com.unciv.uniques
import com.badlogic.gdx.math.Vector2
import com.unciv.logic.civilization.PlayerType
import com.unciv.models.ruleset.BeliefType
import com.unciv.models.ruleset.unique.Unique
import com.unciv.models.ruleset.unique.UniqueTriggerActivation
import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.testing.GdxTestRunner
import com.unciv.testing.TestGame
@ -51,24 +49,16 @@ class ResourceTests {
fun testResourceProductionAndConsumptionModifierDoesNotAffectConsumption() {
val consumesCoal = game.createBuilding("Consumes [1] [Coal]")
val providesCoal = game.createBuilding("Provides [1] [Coal]")
val doubleCoal = game.createBuilding("Double quantity of [Coal] produced")
val doubleStrategic = game.createBuilding("Quantity of strategic resources produced by the empire +[100]%")
val doubleStrategicProduction = game.createBuilding("[+100]% [Strategic] resource production")
city.cityConstructions.addBuilding(providesCoal)
Assert.assertTrue(civInfo.getCivResourcesByName()["Coal"] == 1)
city.cityConstructions.addBuilding(doubleCoal)
city.cityConstructions.addBuilding(doubleStrategicProduction)
Assert.assertTrue(civInfo.getCivResourcesByName()["Coal"] == 2)
city.cityConstructions.addBuilding(doubleStrategic)
Assert.assertTrue(civInfo.getCivResourcesByName()["Coal"] == 3)
city.cityConstructions.addBuilding(doubleStrategicProduction)
Assert.assertTrue(civInfo.getCivResourcesByName()["Coal"] == 4)
city.cityConstructions.addBuilding(consumesCoal)
Assert.assertTrue(civInfo.getCivResourcesByName()["Coal"] == 3) // Produce 4 (1 + 1 + 1 + 1), consume 1
Assert.assertTrue(civInfo.getCivResourcesByName()["Coal"] == 1) // Produce 2, consume 1
}
@Test
@ -128,11 +118,11 @@ class ResourceTests {
tile.setImprovement(improvement.name, civInfo)
Assert.assertTrue(civInfo.getCivResourcesByName()["Coal"] == 1)
val doubleCoal = game.createBuilding("Double quantity of [Coal] produced")
val doubleCoal = game.createBuilding("[+100]% [Coal] resource production")
city.cityConstructions.addBuilding(doubleCoal)
Assert.assertTrue(civInfo.getCivResourcesByName()["Coal"] == 2)
val doubleStrategic = game.createBuilding("Quantity of strategic resources produced by the empire +[100]%")
val doubleStrategic = game.createBuilding("[+100]% [Strategic] resource production")
city.cityConstructions.addBuilding(doubleStrategic)
Assert.assertTrue(civInfo.getCivResourcesByName()["Coal"] == 3)