Generalize Great Wall unique (#7660)

* Generalize Great Wall unique

* Update JSON entries

* And movement calculation too

* Rename other functions

* Cache movement penalty uniques

* Check destination tile instead of unit type
This commit is contained in:
OptimizedForDensity 2022-09-15 09:00:19 -04:00 committed by GitHub
parent 891b609da4
commit 291b962f97
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 46 additions and 15 deletions

View File

@ -406,7 +406,7 @@
"culture": 3,
"greatPersonPoints": {"Great Engineer": 1},
"isWonder": true,
"uniques": ["Enemy land units must spend 1 extra movement point when inside your territory (obsolete upon Dynamite)",
"uniques": ["Enemy [Land] units must spend [1] extra movement points when inside your territory <before discovering [Dynamite]>",
"Gain a free [Walls] [in this city]"],
"requiredTech": "Engineering",
"quote": "'The art of war teaches us to rely not on the likelihood of the enemy's not attacking, but rather on the fact that we have made our position unassailable.' - Sun Tzu"

View File

@ -253,7 +253,7 @@
"culture": 3,
"greatPersonPoints": {"Great Engineer": 1},
"isWonder": true,
"uniques": ["Enemy land units must spend 1 extra movement point when inside your territory (obsolete upon Dynamite)",
"uniques": ["Enemy [Land] units must spend [1] extra movement points when inside your territory <before discovering [Dynamite]>",
"Gain a free [Walls] [in this city]"],
"requiredTech": "Construction",
"quote": "'The art of war teaches us to rely not on the likelihood of the enemy's not attacking, but rather on the fact that we have made our position unassailable.' - Sun Tzu"

View File

@ -145,9 +145,12 @@ class CivInfoTransientUpdater(val civInfo: CivilizationInfo) {
}
}
fun updateHasActiveGreatWall() {
civInfo.hasActiveGreatWall = !civInfo.tech.isResearched("Dynamite") &&
civInfo.hasUnique(UniqueType.EnemyLandUnitsSpendExtraMovement)
fun updateHasActiveEnemyMovementPenalty() {
civInfo.hasActiveEnemyMovementPenalty = (!civInfo.tech.isResearched("Dynamite") && civInfo.hasUnique(UniqueType.EnemyLandUnitsSpendExtraMovementDepreciated))
|| civInfo.hasUnique(UniqueType.EnemyLandUnitsSpendExtraMovement)
civInfo.enemyMovementPenaltyUniques =
civInfo.getMatchingUniques(UniqueType.EnemyLandUnitsSpendExtraMovement) +
civInfo.getMatchingUniques(UniqueType.EnemyLandUnitsSpendExtraMovementDepreciated)
}
fun updateCitiesConnectedToCapital(initialSetup: Boolean = false) {

View File

@ -33,6 +33,7 @@ import com.unciv.models.ruleset.tile.ResourceType
import com.unciv.models.ruleset.tile.TileResource
import com.unciv.models.ruleset.unique.StateForConditionals
import com.unciv.models.ruleset.unique.TemporaryUnique
import com.unciv.models.ruleset.unique.Unique
import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.ruleset.unit.BaseUnit
import com.unciv.models.stats.Stat
@ -105,7 +106,11 @@ class CivilizationInfo : IsPartOfGameInfoSerialization {
/** This is for performance since every movement calculation depends on this, see MapUnit comment */
@Transient
var hasActiveGreatWall = false
var hasActiveEnemyMovementPenalty = false
/** Same as above variable */
@Transient
var enemyMovementPenaltyUniques: Sequence<Unique>? = null
@Transient
var statsForNextTurn = Stats()
@ -673,6 +678,27 @@ class CivilizationInfo : IsPartOfGameInfoSerialization {
return diplomacyManager.hasOpenBorders
}
fun getEnemyMovementPenalty(enemyUnit: MapUnit, toMoveTo: TileInfo): Float {
if (enemyMovementPenaltyUniques != null && enemyMovementPenaltyUniques!!.any()) {
return enemyMovementPenaltyUniques!!.sumOf {
when (it.type!!) {
UniqueType.EnemyLandUnitsSpendExtraMovement -> {
if (enemyUnit.matchesFilter(it.params[0]))
it.params[1].toInt()
else 0 // doesn't match
}
UniqueType.EnemyLandUnitsSpendExtraMovementDepreciated -> {
if (toMoveTo.isLand) {
1 // depreciated unique only works on land tiles
} else 0
}
else -> 0
}
}.toFloat()
}
return 0f // should not reach this point
}
/**
* Returns a civilization caption suitable for greetings including player type info:
* Like "Milan" if the nation is a city state, "Caesar of Rome" otherwise, with an added
@ -869,7 +895,7 @@ class CivilizationInfo : IsPartOfGameInfoSerialization {
fun updateSightAndResources() {
updateViewableTiles()
updateHasActiveGreatWall()
updateHasActiveEnemyMovementPenalty()
updateDetailedCivResources()
}
@ -879,7 +905,7 @@ class CivilizationInfo : IsPartOfGameInfoSerialization {
// implementation in a separate class, to not clog up CivInfo
fun initialSetCitiesConnectedToCapitalTransients() = transients().updateCitiesConnectedToCapital(true)
fun updateHasActiveGreatWall() = transients().updateHasActiveGreatWall()
fun updateHasActiveEnemyMovementPenalty() = transients().updateHasActiveEnemyMovementPenalty()
fun updateViewableTiles() = transients().updateViewableTiles()
fun updateDetailedCivResources() = transients().updateCivResources()
@ -982,7 +1008,7 @@ class CivilizationInfo : IsPartOfGameInfoSerialization {
goldenAges.endTurn(getHappiness())
getCivUnits().forEach { it.endTurn() } // This is the most expensive part of endTurn
diplomacy.values.toList().forEach { it.nextTurn() } // we copy the diplomacy values so if it changes in-loop we won't crash
updateHasActiveGreatWall()
updateHasActiveEnemyMovementPenalty()
cachedMilitaryMight = -1 // Reset so we don't use a value from a previous turn
}

View File

@ -34,10 +34,9 @@ class UnitMovementAlgorithms(val unit: MapUnit) {
val toOwner = to.getOwner()
val extraCost = if (
toOwner != null &&
to.isLand &&
toOwner.hasActiveGreatWall &&
toOwner.hasActiveEnemyMovementPenalty &&
civInfo.isAtWarWith(toOwner)
) 1f else 0f
) toOwner.getEnemyMovementPenalty(unit, to) else 0f
if (from.roadStatus == RoadStatus.Railroad && to.roadStatus == RoadStatus.Railroad)
return RoadStatus.Railroad.movement + extraCost

View File

@ -666,8 +666,9 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
for (unique in uniqueObjects)
UniqueTriggerActivation.triggerCivwideUnique(unique, civInfo, cityConstructions.cityInfo)
if ("Enemy land units must spend 1 extra movement point when inside your territory (obsolete upon Dynamite)" in uniques)
civInfo.updateHasActiveGreatWall()
if (hasUnique(UniqueType.EnemyLandUnitsSpendExtraMovement)
|| hasUnique(UniqueType.EnemyLandUnitsSpendExtraMovementDepreciated))
civInfo.updateHasActiveEnemyMovementPenalty()
// Korean unique - apparently gives the same as the research agreement
if (science > 0 && civInfo.hasUnique(UniqueType.TechBoostWhenScientificBuildingsBuiltInCapital))

View File

@ -215,7 +215,9 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
DoubleHappinessFromNaturalWonders("Double Happiness from Natural Wonders", UniqueTarget.Global),
EnablesConstructionOfSpaceshipParts("Enables construction of Spaceship parts", UniqueTarget.Global),
EnemyLandUnitsSpendExtraMovement("Enemy land units must spend 1 extra movement point when inside your territory (obsolete upon Dynamite)", UniqueTarget.Global),
EnemyLandUnitsSpendExtraMovement("Enemy [mapUnitFilter] units must spend [amount] extra movement points when inside your territory", UniqueTarget.Global),
@Deprecated("As of 4.2.4", ReplaceWith("Enemy [Land] units must spend [1] extra movement points when inside your territory <before discovering [Dynamite]>"))
EnemyLandUnitsSpendExtraMovementDepreciated("Enemy land units must spend 1 extra movement point when inside your territory (obsolete upon Dynamite)", UniqueTarget.Global),
@Deprecated("s of 4.1.14", ReplaceWith("Production to [Science] conversion in cities changed by [33]%"))
ProductionToScienceConversionBonus("Production to science conversion in cities increased by 33%", UniqueTarget.Global),