Added limited usage for actions!

This commit is contained in:
Yair Morgenstern 2023-03-03 14:47:50 +02:00
parent fc22f0900b
commit 608e0dfb71
4 changed files with 42 additions and 7 deletions

View File

@ -1610,7 +1610,7 @@
"unitType": "Civilian", "unitType": "Civilian",
"uniques": [ "uniques": [
"Can hurry technology research", "Can hurry technology research",
"Can instantly construct a [Academy] improvement <by consuming this unit>", "Can instantly construct a [Academy] improvement <[2] times>",
"Great Person - [Science]", "Unbuildable", "Uncapturable"], "Great Person - [Science]", "Unbuildable", "Uncapturable"],
"movement": 2 "movement": 2
}, },

View File

@ -110,9 +110,15 @@ class MapUnit : IsPartOfGameInfoSerialization {
var isTransported: Boolean = false var isTransported: Boolean = false
var turnsFortified = 0 var turnsFortified = 0
// Old, to be deprecated
@Deprecated("As of 4.5.3")
var abilityUsesLeft: HashMap<String, Int> = hashMapOf() var abilityUsesLeft: HashMap<String, Int> = hashMapOf()
@Deprecated("As of 4.5.3")
var maxAbilityUses: HashMap<String, Int> = hashMapOf() var maxAbilityUses: HashMap<String, Int> = hashMapOf()
// New - track only *how many have been used*, derive max from uniques, left = max - used
var abilityToTimesUsed: HashMap<String, Int> = hashMapOf()
var religion: String? = null var religion: String? = null
var religiousStrengthLost = 0 var religiousStrengthLost = 0
@ -174,6 +180,7 @@ class MapUnit : IsPartOfGameInfoSerialization {
toReturn.isTransported = isTransported toReturn.isTransported = isTransported
toReturn.abilityUsesLeft.putAll(abilityUsesLeft) toReturn.abilityUsesLeft.putAll(abilityUsesLeft)
toReturn.maxAbilityUses.putAll(maxAbilityUses) toReturn.maxAbilityUses.putAll(maxAbilityUses)
toReturn.abilityToTimesUsed.putAll(abilityToTimesUsed)
toReturn.religion = religion toReturn.religion = religion
toReturn.religiousStrengthLost = religiousStrengthLost toReturn.religiousStrengthLost = religiousStrengthLost
toReturn.movementMemories = movementMemories.copy() toReturn.movementMemories = movementMemories.copy()

View File

@ -180,6 +180,7 @@ object UnitActions {
if (unique == null || tile.isWater || tile.isImpassible()) return null 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 // 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 (unit.civ.isOneCityChallenger() && unit.civ.hasEverOwnedOriginalCapital == true) return null
if (usagesLeft(unit, unique)==0) return null
if (unit.currentMovement <= 0 || !tile.canBeSettled()) if (unit.currentMovement <= 0 || !tile.canBeSettled())
return UnitAction(UnitActionType.FoundCity, action = null) return UnitAction(UnitActionType.FoundCity, action = null)
@ -202,7 +203,7 @@ object UnitActions {
return UnitAction( return UnitAction(
type = UnitActionType.FoundCity, type = UnitActionType.FoundCity,
title = actionTextWithSideEffects(UnitActionType.FoundCity.value, unique), title = actionTextWithSideEffects(UnitActionType.FoundCity.value, unique, unit),
uncivSound = UncivSound.Chimes, uncivSound = UncivSound.Chimes,
action = { action = {
// check if we would be breaking a promise // check if we would be breaking a promise
@ -467,6 +468,7 @@ object UnitActions {
val improvementName = unique.params[0] val improvementName = unique.params[0]
val improvement = tile.ruleset.tileImprovements[improvementName] val improvement = tile.ruleset.tileImprovements[improvementName]
?: continue ?: continue
if (usagesLeft(unit, unique)==0) continue
val resourcesAvailable = improvement.uniqueObjects.none { val resourcesAvailable = improvement.uniqueObjects.none {
it.isOfType(UniqueType.ConsumesResources) && it.isOfType(UniqueType.ConsumesResources) &&
@ -474,7 +476,7 @@ object UnitActions {
} }
finalActions += UnitAction(UnitActionType.Create, finalActions += UnitAction(UnitActionType.Create,
title = actionTextWithSideEffects("Create [$improvementName]", unique), title = actionTextWithSideEffects("Create [$improvementName]", unique, unit),
action = { action = {
val unitTile = unit.getTile() val unitTile = unit.getTile()
unitTile.improvementFunctions.removeCreatesOneImprovementMarker() unitTile.improvementFunctions.removeCreatesOneImprovementMarker()
@ -652,9 +654,10 @@ object UnitActions {
for (unique in unit.getUniques()) { for (unique in unit.getUniques()) {
if (unique.conditionals.none { it.type?.targetTypes?.contains(UniqueTarget.UnitActionModifier) == true }) continue if (unique.conditionals.none { it.type?.targetTypes?.contains(UniqueTarget.UnitActionModifier) == true }) continue
if (unique.type?.targetTypes?.any { it in triggerableTypes }!=true) continue if (unique.type?.targetTypes?.any { it in triggerableTypes }!=true) continue
if (usagesLeft(unit, unique)==0) continue
val unitAction = UnitAction(type = UnitActionType.TriggerUnique, val unitAction = UnitAction(type = UnitActionType.TriggerUnique,
title = actionTextWithSideEffects(unique.text.removeConditionals(), unique) title = actionTextWithSideEffects(unique.text.removeConditionals(), unique, unit)
){ ){
UniqueTriggerActivation.triggerUnitwideUnique(unique, unit) UniqueTriggerActivation.triggerUnitwideUnique(unique, unit)
activateSideEffects(unit, unique) activateSideEffects(unit, unique)
@ -699,22 +702,42 @@ object UnitActions {
for (conditional in actionUnique.conditionals){ for (conditional in actionUnique.conditionals){
when (conditional.type){ when (conditional.type){
UniqueType.UnitActionConsumeUnit -> unit.consume() UniqueType.UnitActionConsumeUnit -> unit.consume()
UniqueType.UnitActionLimitedTimes -> {
val usagesSoFar = unit.abilityToTimesUsed[actionUnique.placeholderText] ?: 0
unit.abilityToTimesUsed[actionUnique.placeholderText] = usagesSoFar + 1
}
else -> continue else -> continue
} }
} }
} }
fun actionTextWithSideEffects(originalText:String, actionUnique: Unique): String { /** Returns 'null' if usages are not limited */
val sideEffectString = getSideEffectString(actionUnique) 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 if (sideEffectString == "") return originalText
else return "$originalText $sideEffectString" else return "$originalText $sideEffectString"
} }
fun getSideEffectString(actionUnique: Unique): String { fun getSideEffectString(unit:MapUnit, actionUnique: Unique): String {
val effects = ArrayList<String>() val effects = ArrayList<String>()
if (actionUnique.conditionals.any { it.type == UniqueType.UnitActionConsumeUnit }) effects += Fonts.death.toString() if (actionUnique.conditionals.any { it.type == UniqueType.UnitActionConsumeUnit }) effects += Fonts.death.toString()
else effects += getMovementPointsToUse(actionUnique).toString() + Fonts.movement else effects += getMovementPointsToUse(actionUnique).toString() + Fonts.movement
val maxUsages = getMaxUsages(actionUnique)
if (maxUsages!=null) effects += "${usagesLeft(unit, actionUnique)}/$maxUsages"
return if (effects.isEmpty()) "" return if (effects.isEmpty()) ""
else "(${effects.joinToString { it.tr() }})" else "(${effects.joinToString { it.tr() }})"
} }

View File

@ -1983,6 +1983,11 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: UnitActionModifier Applicable to: UnitActionModifier
??? example "&lt;[amount] times&gt;"
Example: "&lt;[3] times&gt;"
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' *[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`. *[amount]: This indicates a whole number, possibly with a + or - sign, such as `2`, `+13`, or `-3`.