diff --git a/android/assets/jsons/Civ V - Gods & Kings/Units.json b/android/assets/jsons/Civ V - Gods & Kings/Units.json index 30c041db86..d934521377 100644 --- a/android/assets/jsons/Civ V - Gods & Kings/Units.json +++ b/android/assets/jsons/Civ V - Gods & Kings/Units.json @@ -1610,7 +1610,7 @@ "unitType": "Civilian", "uniques": [ "Can hurry technology research", - "Can instantly construct a [Academy] improvement ", + "Can instantly construct a [Academy] improvement <[2] times>", "Great Person - [Science]", "Unbuildable", "Uncapturable"], "movement": 2 }, diff --git a/core/src/com/unciv/logic/map/mapunit/MapUnit.kt b/core/src/com/unciv/logic/map/mapunit/MapUnit.kt index 333dfd9296..0278267dcc 100644 --- a/core/src/com/unciv/logic/map/mapunit/MapUnit.kt +++ b/core/src/com/unciv/logic/map/mapunit/MapUnit.kt @@ -110,9 +110,15 @@ class MapUnit : IsPartOfGameInfoSerialization { var isTransported: Boolean = false var turnsFortified = 0 + // Old, to be deprecated + @Deprecated("As of 4.5.3") var abilityUsesLeft: HashMap = hashMapOf() + @Deprecated("As of 4.5.3") var maxAbilityUses: HashMap = hashMapOf() + // New - track only *how many have been used*, derive max from uniques, left = max - used + var abilityToTimesUsed: HashMap = hashMapOf() + var religion: String? = null var religiousStrengthLost = 0 @@ -174,6 +180,7 @@ class MapUnit : IsPartOfGameInfoSerialization { toReturn.isTransported = isTransported toReturn.abilityUsesLeft.putAll(abilityUsesLeft) toReturn.maxAbilityUses.putAll(maxAbilityUses) + toReturn.abilityToTimesUsed.putAll(abilityToTimesUsed) toReturn.religion = religion toReturn.religiousStrengthLost = religiousStrengthLost toReturn.movementMemories = movementMemories.copy() diff --git a/core/src/com/unciv/ui/screens/worldscreen/unit/actions/UnitActions.kt b/core/src/com/unciv/ui/screens/worldscreen/unit/actions/UnitActions.kt index 14c5b86f12..7bab215a5e 100644 --- a/core/src/com/unciv/ui/screens/worldscreen/unit/actions/UnitActions.kt +++ b/core/src/com/unciv/ui/screens/worldscreen/unit/actions/UnitActions.kt @@ -180,6 +180,7 @@ object UnitActions { if (unique == null || tile.isWater || tile.isImpassible()) return null // Spain should still be able to build Conquistadors in a one city challenge - but can't settle them if (unit.civ.isOneCityChallenger() && unit.civ.hasEverOwnedOriginalCapital == true) return null + if (usagesLeft(unit, unique)==0) return null if (unit.currentMovement <= 0 || !tile.canBeSettled()) return UnitAction(UnitActionType.FoundCity, action = null) @@ -202,7 +203,7 @@ object UnitActions { return UnitAction( type = UnitActionType.FoundCity, - title = actionTextWithSideEffects(UnitActionType.FoundCity.value, unique), + title = actionTextWithSideEffects(UnitActionType.FoundCity.value, unique, unit), uncivSound = UncivSound.Chimes, action = { // check if we would be breaking a promise @@ -467,6 +468,7 @@ object UnitActions { val improvementName = unique.params[0] val improvement = tile.ruleset.tileImprovements[improvementName] ?: continue + if (usagesLeft(unit, unique)==0) continue val resourcesAvailable = improvement.uniqueObjects.none { it.isOfType(UniqueType.ConsumesResources) && @@ -474,7 +476,7 @@ object UnitActions { } finalActions += UnitAction(UnitActionType.Create, - title = actionTextWithSideEffects("Create [$improvementName]", unique), + title = actionTextWithSideEffects("Create [$improvementName]", unique, unit), action = { val unitTile = unit.getTile() unitTile.improvementFunctions.removeCreatesOneImprovementMarker() @@ -652,9 +654,10 @@ object UnitActions { for (unique in unit.getUniques()) { if (unique.conditionals.none { it.type?.targetTypes?.contains(UniqueTarget.UnitActionModifier) == true }) continue if (unique.type?.targetTypes?.any { it in triggerableTypes }!=true) continue + if (usagesLeft(unit, unique)==0) continue val unitAction = UnitAction(type = UnitActionType.TriggerUnique, - title = actionTextWithSideEffects(unique.text.removeConditionals(), unique) + title = actionTextWithSideEffects(unique.text.removeConditionals(), unique, unit) ){ UniqueTriggerActivation.triggerUnitwideUnique(unique, unit) activateSideEffects(unit, unique) @@ -699,22 +702,42 @@ object UnitActions { for (conditional in actionUnique.conditionals){ when (conditional.type){ UniqueType.UnitActionConsumeUnit -> unit.consume() + UniqueType.UnitActionLimitedTimes -> { + val usagesSoFar = unit.abilityToTimesUsed[actionUnique.placeholderText] ?: 0 + unit.abilityToTimesUsed[actionUnique.placeholderText] = usagesSoFar + 1 + } else -> continue } } } - fun actionTextWithSideEffects(originalText:String, actionUnique: Unique): String { - val sideEffectString = getSideEffectString(actionUnique) + /** Returns 'null' if usages are not limited */ + fun usagesLeft(unit:MapUnit, actionUnique: Unique): Int?{ + val usagesTotal = getMaxUsages(actionUnique) ?: return null + val usagesSoFar = unit.abilityToTimesUsed[actionUnique.placeholderText] ?: 0 + return usagesTotal - usagesSoFar + } + + fun getMaxUsages(actionUnique: Unique): Int? { + return actionUnique.conditionals + .filter { it.type == UniqueType.UnitActionLimitedTimes } + .maxOfOrNull { it.params[0].toInt() } + } + + fun actionTextWithSideEffects(originalText:String, actionUnique: Unique, unit: MapUnit): String { + val sideEffectString = getSideEffectString(unit, actionUnique) if (sideEffectString == "") return originalText else return "$originalText $sideEffectString" } - fun getSideEffectString(actionUnique: Unique): String { + fun getSideEffectString(unit:MapUnit, actionUnique: Unique): String { val effects = ArrayList() if (actionUnique.conditionals.any { it.type == UniqueType.UnitActionConsumeUnit }) effects += Fonts.death.toString() else effects += getMovementPointsToUse(actionUnique).toString() + Fonts.movement + val maxUsages = getMaxUsages(actionUnique) + if (maxUsages!=null) effects += "${usagesLeft(unit, actionUnique)}/$maxUsages" + return if (effects.isEmpty()) "" else "(${effects.joinToString { it.tr() }})" } diff --git a/docs/Modders/uniques.md b/docs/Modders/uniques.md index 6717d1ce8a..95d325d0f7 100644 --- a/docs/Modders/uniques.md +++ b/docs/Modders/uniques.md @@ -1983,6 +1983,11 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl Applicable to: UnitActionModifier +??? example "<[amount] times>" + Example: "<[3] times>" + + Applicable to: UnitActionModifier + *[action]: An action that a unit can perform. Currently, there are only two actions part of this: 'Spread Religion' and 'Remove Foreign religions from your own cities' *[amount]: This indicates a whole number, possibly with a + or - sign, such as `2`, `+13`, or `-3`.