mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-21 18:36:17 -04:00
Unique: May Paradrop to [tileFilter] tiles up to [positiveAmount] tiles away
(#13586)
* Paradrop: Allow mods to enable paradropping from outside friendly territory * Fix Paratrooper range in Vanilla * Keep support for the deprecated unique * Update docs * Allow setting a destination tileFilter for Paradrops * Apply suggestion from @RobLoach * Apply suggestion from @RobLoach * Update language for paradrop
This commit is contained in:
parent
4819cf1053
commit
9b4ed0d4ff
@ -1362,7 +1362,7 @@
|
||||
"strength": 65,
|
||||
"cost": 375,
|
||||
"requiredTech": "Radar",
|
||||
"uniques": ["May Paradrop up to [5] tiles from inside friendly territory", "Never appears as a Barbarian unit"],
|
||||
"uniques": ["May Paradrop to [Land] tiles up to [5] tiles away <in [{Friendly} {Land}] tiles>", "Never appears as a Barbarian unit"],
|
||||
"attackSound": "shot"
|
||||
// upgradesTo "XCOM Squad", "No Movement Cost to Pillage" in BNW
|
||||
},
|
||||
|
@ -1039,7 +1039,7 @@
|
||||
"strength": 65,
|
||||
"cost": 375,
|
||||
"requiredTech": "Radar",
|
||||
"uniques": ["May Paradrop up to [5] tiles from inside friendly territory", "Never appears as a Barbarian unit"],
|
||||
"uniques": ["May Paradrop to [Land] tiles up to [5] tiles away <in [{Friendly} {Land}] tiles>", "Never appears as a Barbarian unit"],
|
||||
"attackSound": "shot"
|
||||
// upgradesTo "XCOM Squad", "No Movement Cost to Pillage" in BNW
|
||||
},
|
||||
|
@ -59,7 +59,9 @@ class MapUnitCache(private val mapUnit: MapUnit) {
|
||||
var canEnterCityStates: Boolean = false
|
||||
var costToDisembark: Float? = null
|
||||
var costToEmbark: Float? = null
|
||||
var paradropRange = 0
|
||||
|
||||
/** A hashmap where the key represents the tileFilter, and the value is how far away the tile could be */
|
||||
val paradropDestinationTileFilters = mutableMapOf<String, Int>()
|
||||
|
||||
var hasUniqueToBuildImprovements = false // not canBuildImprovements to avoid confusion
|
||||
var hasUniqueToCreateWaterImprovements = false
|
||||
|
@ -289,7 +289,7 @@ class UnitMovement(val unit: MapUnit) {
|
||||
unit.baseUnit.movesLikeAirUnits ->
|
||||
unit.currentTile.aerialDistanceTo(destination) <= unit.getMaxMovementForAirUnits()
|
||||
unit.isPreparingParadrop() ->
|
||||
unit.currentTile.aerialDistanceTo(destination) <= unit.cache.paradropRange && canParadropOn(destination)
|
||||
canParadropOn(destination, unit.currentTile.aerialDistanceTo(destination))
|
||||
else ->
|
||||
specificFunction(destination) // Note: Could pass destination as implicit closure from outer fun to lambda, but explicit is clearer
|
||||
}
|
||||
@ -303,9 +303,10 @@ class UnitMovement(val unit: MapUnit) {
|
||||
unit.cache.cannotMove -> sequenceOf(unit.getTile())
|
||||
unit.baseUnit.movesLikeAirUnits ->
|
||||
unit.getTile().getTilesInDistanceRange(IntRange(1, unit.getMaxMovementForAirUnits()))
|
||||
unit.isPreparingParadrop() ->
|
||||
unit.getTile().getTilesInDistance(unit.cache.paradropRange)
|
||||
.filter { unit.movement.canParadropOn(it) }
|
||||
unit.isPreparingParadrop() -> {
|
||||
unit.getTile().getTilesInDistance(unit.cache.paradropDestinationTileFilters.maxOf { it.value } )
|
||||
.filter { unit.movement.canParadropOn(it, it.aerialDistanceTo(unit.getTile())) }
|
||||
}
|
||||
includeOtherEscortUnit && unit.isEscorting() -> {
|
||||
val otherUnitTiles = unit.getOtherEscortUnit()!!.movement.getReachableTilesInCurrentTurn(false).toSet()
|
||||
unit.movement.getDistanceToTiles().filter { otherUnitTiles.contains(it.key) }.keys.asSequence()
|
||||
@ -636,12 +637,19 @@ class UnitMovement(val unit: MapUnit) {
|
||||
}
|
||||
|
||||
// Can a paratrooper land at this tile?
|
||||
private fun canParadropOn(destination: Tile): Boolean {
|
||||
private fun canParadropOn(destination: Tile, distance: Int): Boolean {
|
||||
if (unit.cache.cannotMove) return false
|
||||
// Can only move to land tiles within range that are visible and not impassible
|
||||
|
||||
// Can only move to tiles within range that are visible and not impassible
|
||||
// Based on some testing done in the base game
|
||||
if (!destination.isLand || destination.isImpassible() || !unit.civ.viewableTiles.contains(destination)) return false
|
||||
return true
|
||||
if (destination.isImpassible() || !unit.civ.viewableTiles.contains(destination)) return false
|
||||
|
||||
// The destination is valid if any of the `tileFilters` match, and is within range
|
||||
for ((tileFilter, distanceAllowed) in unit.cache.paradropDestinationTileFilters) {
|
||||
if (distance <= distanceAllowed && destination.matchesFilter(tileFilter, unit.civ)) return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -377,7 +377,9 @@ enum class UniqueType(
|
||||
PreventSpreadingReligion("Prevents spreading of religion to the city it is next to", UniqueTarget.Unit),
|
||||
RemoveOtherReligions("Removes other religions when spreading religion", UniqueTarget.Unit),
|
||||
|
||||
MayParadrop("May Paradrop up to [amount] tiles from inside friendly territory", UniqueTarget.Unit),
|
||||
@Deprecated("As of 4.17.4", ReplaceWith("May Paradrop to [Land] tiles up to [positiveAmount] tiles away <in [{Friendly} {Land}] tiles>"), DeprecationLevel.WARNING)
|
||||
MayParadropOld("May Paradrop up to [positiveAmount] tiles from inside friendly territory", UniqueTarget.Unit),
|
||||
MayParadrop("May Paradrop to [tileFilter] tiles up to [positiveAmount] tiles away", UniqueTarget.Unit),
|
||||
CanAirsweep("Can perform Air Sweep", UniqueTarget.Unit),
|
||||
|
||||
CanSpeedupConstruction("Can speed up construction of a building", UniqueTarget.Unit),
|
||||
|
@ -545,6 +545,8 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction {
|
||||
|
||||
UniqueType.MayParadrop // Paradrop - 25% bonus
|
||||
-> power += power / 4
|
||||
UniqueType.MayParadropOld // ParadropOld - 25% bonus
|
||||
-> power += power / 4
|
||||
UniqueType.MustSetUp // Must set up - 20 % penalty
|
||||
-> power -= power / 5
|
||||
UniqueType.AdditionalAttacks // Extra attacks - 20% bonus per extra attack
|
||||
|
@ -142,10 +142,29 @@ object UnitActionsFromUniques {
|
||||
}
|
||||
|
||||
internal fun getParadropActions(unit: MapUnit, tile: Tile): Sequence<UnitAction> {
|
||||
val paradropUniques =
|
||||
unit.getMatchingUniques(UniqueType.MayParadrop)
|
||||
if (!paradropUniques.any() || unit.isEmbarked()) return emptySequence()
|
||||
unit.cache.paradropRange = paradropUniques.maxOfOrNull { it.params[0] }!!.toInt()
|
||||
unit.cache.paradropDestinationTileFilters.clear()
|
||||
|
||||
// Support the old paradrop unique, going from Friendly Land to any Land tile
|
||||
val paradropOldUniques = unit.getMatchingUniques(UniqueType.MayParadropOld)
|
||||
if (paradropOldUniques.any() && !unit.isEmbarked() && !unit.getTile().isWater && unit.getTile().isFriendlyTerritory(unit.civ)) {
|
||||
unit.cache.paradropDestinationTileFilters["Land"] = paradropOldUniques.maxOf { it.params[0] }.toInt()
|
||||
}
|
||||
|
||||
// Retrieve all parardrop uniques, considering the state of the unit
|
||||
val paradropUniques = unit.getMatchingUniques(UniqueType.MayParadrop, unit.cache.state)
|
||||
|
||||
// Construct the list of possible destination tile filters, keeping the largest distance
|
||||
for (unique in paradropUniques) {
|
||||
val tileFilter = unique.params[0]
|
||||
val distance = unique.params[1].toInt()
|
||||
val existingDistance = unit.cache.paradropDestinationTileFilters[tileFilter]
|
||||
if (existingDistance == null || distance > existingDistance) {
|
||||
unit.cache.paradropDestinationTileFilters[tileFilter] = distance
|
||||
}
|
||||
}
|
||||
|
||||
if (unit.cache.paradropDestinationTileFilters.isEmpty()) return emptySequence()
|
||||
|
||||
return sequenceOf(UnitAction(UnitActionType.Paradrop,
|
||||
isCurrentAction = unit.isPreparingParadrop(),
|
||||
useFrequency = 60f, // While it is important to see, it isn't nessesary used a lot
|
||||
@ -153,9 +172,7 @@ object UnitActionsFromUniques {
|
||||
if (unit.isPreparingParadrop()) unit.action = null
|
||||
else unit.action = UnitActionType.Paradrop.value
|
||||
}.takeIf {
|
||||
!unit.hasUnitMovedThisTurn() &&
|
||||
tile.isFriendlyTerritory(unit.civ) &&
|
||||
!tile.isWater
|
||||
!unit.hasUnitMovedThisTurn()
|
||||
})
|
||||
)
|
||||
}
|
||||
|
@ -1861,8 +1861,8 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
|
||||
??? example "Removes other religions when spreading religion"
|
||||
Applicable to: Unit
|
||||
|
||||
??? example "May Paradrop up to [amount] tiles from inside friendly territory"
|
||||
Example: "May Paradrop up to [3] tiles from inside friendly territory"
|
||||
??? example "May Paradrop to [tileFilter] tiles up to [positiveAmount] tiles away"
|
||||
Example: "May Paradrop to [Farm] tiles up to [3] tiles away"
|
||||
|
||||
Applicable to: Unit
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user