mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-13 09:18:43 +07:00
Updated promotions - make more generalizable, update to G&K (#4292)
* Generalized the "Heal Instantly" promotion * Extended "Indirect Fire" to WaterRanged units, conform the main game * Generalized Extend Range, Operational Range * Generalized "logistics" * Typo * Generalized the healing from "Medic" * Implemented requested changes * Generalized "[amount] Movement"; "[amount] Visibility Range" * Added survavalism promotions * Updated Boarding Party strength bonus values to G&K * Implemented requested changes
This commit is contained in:
@ -6,7 +6,6 @@ import com.unciv.logic.city.CityInfo
|
||||
import com.unciv.logic.civilization.*
|
||||
import com.unciv.logic.civilization.diplomacy.DiplomaticModifiers
|
||||
import com.unciv.logic.civilization.diplomacy.DiplomaticStatus
|
||||
import com.unciv.logic.map.MapUnit
|
||||
import com.unciv.logic.map.RoadStatus
|
||||
import com.unciv.logic.map.TileInfo
|
||||
import com.unciv.models.AttackableTile
|
||||
@ -15,7 +14,6 @@ import com.unciv.models.ruleset.unit.UnitType
|
||||
import com.unciv.models.stats.Stat
|
||||
import com.unciv.models.translations.tr
|
||||
import java.util.*
|
||||
import kotlin.math.min
|
||||
import kotlin.math.max
|
||||
|
||||
/**
|
||||
@ -250,8 +248,7 @@ object Battle {
|
||||
private fun reduceAttackerMovementPointsAndAttacks(attacker: ICombatant, defender: ICombatant) {
|
||||
if (attacker is MapUnitCombatant) {
|
||||
val unit = attacker.unit
|
||||
if (unit.hasUnique("Can move after attacking")
|
||||
|| (unit.hasUnique("1 additional attack per turn") && unit.attacksThisTurn == 0)) {
|
||||
if (unit.hasUnique("Can move after attacking") || unit.maxAttacksPerTurn() > unit.attacksThisTurn) {
|
||||
// if it was a melee attack and we won, then the unit ALREADY got movement points deducted,
|
||||
// for the movement to the enemy's tile!
|
||||
// and if it's an air unit, it only has 1 movement anyway, so...
|
||||
|
@ -141,8 +141,11 @@ class MapUnit {
|
||||
if (isEmbarked()) return getEmbarkedMovement()
|
||||
|
||||
var movement = baseUnit.movement
|
||||
movement += getUniques().count { it.text == "+1 Movement" }
|
||||
movement += getMatchingUniques("[] Movement").sumBy { it.params[0].toInt() }
|
||||
|
||||
// Deprecated since 3.15.6
|
||||
movement += getUniques().count { it.text == "+1 Movement" }
|
||||
//
|
||||
// Deprecated since 3.14.17
|
||||
if (type.isMilitary() && type.isWaterUnit() && civInfo.hasUnique("All military naval units receive +1 movement and +1 sight")) {
|
||||
movement += 1
|
||||
@ -206,15 +209,21 @@ class MapUnit {
|
||||
*/
|
||||
private fun getVisibilityRange(): Int {
|
||||
var visibilityRange = 2
|
||||
visibilityRange += getUniques().count { it.text == "+1 Visibility Range" }
|
||||
for (unique in civInfo.getMatchingUniques("+[] Sight for all [] units"))
|
||||
if (matchesFilter(unique.params[1]))
|
||||
visibilityRange += unique.params[0].toInt()
|
||||
if (hasUnique("+2 Visibility Range")) visibilityRange += 2 // This shouldn't be stackable
|
||||
visibilityRange += getMatchingUniques("[] Visibility Range").sumBy { it.params[0].toInt() }
|
||||
|
||||
if (hasUnique("Limited Visibility")) visibilityRange -= 1
|
||||
|
||||
// Deprecated since 3.15.6
|
||||
visibilityRange += getUniques().count { it.text == "+1 Visibility Range" }
|
||||
if (hasUnique("+2 Visibility Range")) visibilityRange += 2 // This shouldn't be stackable
|
||||
//
|
||||
// Deprecated since 3.15.1
|
||||
if (civInfo.hasUnique("+1 Sight for all land military units") && type.isMilitary() && type.isLandUnit())
|
||||
visibilityRange += 1
|
||||
if (civInfo.hasUnique("+1 Sight for all land military units") && type.isMilitary() && type.isLandUnit())
|
||||
visibilityRange += 1
|
||||
//
|
||||
|
||||
// Deprecated since 3.14.17
|
||||
if (type.isMilitary() && type.isWaterUnit() && civInfo.hasUnique("All military naval units receive +1 movement and +1 sight"))
|
||||
@ -273,18 +282,28 @@ class MapUnit {
|
||||
return true
|
||||
}
|
||||
|
||||
fun maxAttacksPerTurn(): Int {
|
||||
var maxAttacksPerTurn = 1 + getMatchingUniques("[] additional attacks per turn").sumBy { it.params[0].toInt() }
|
||||
// Deprecated since 3.15.6
|
||||
if (hasUnique("+1 additional attack per turn"))
|
||||
maxAttacksPerTurn++
|
||||
//
|
||||
return maxAttacksPerTurn
|
||||
}
|
||||
|
||||
fun canAttack(): Boolean {
|
||||
if (currentMovement == 0f) return false
|
||||
if (attacksThisTurn > 0 && !hasUnique("1 additional attack per turn")) return false
|
||||
if (attacksThisTurn > 1) return false
|
||||
return true
|
||||
return attacksThisTurn < maxAttacksPerTurn()
|
||||
}
|
||||
|
||||
fun getRange(): Int {
|
||||
if (type.isMelee()) return 1
|
||||
var range = baseUnit().range
|
||||
if (hasUnique("+1 Range")) range++
|
||||
if (hasUnique("+2 Range")) range += 2
|
||||
// Deprecated since 3.15.6
|
||||
if (hasUnique("+1 Range")) range++
|
||||
if (hasUnique("+2 Range")) range += 2
|
||||
//
|
||||
range += getMatchingUniques("[] Range").sumBy { it.params[0].toInt() }
|
||||
return range
|
||||
}
|
||||
|
||||
@ -375,8 +394,11 @@ class MapUnit {
|
||||
|
||||
private fun adjacentHealingBonus(): Int {
|
||||
var healingBonus = 0
|
||||
if (hasUnique("This unit and all others in adjacent tiles heal 5 additional HP per turn")) healingBonus += 5
|
||||
if (hasUnique("This unit and all others in adjacent tiles heal 5 additional HP. This unit heals 5 additional HP outside of friendly territory.")) healingBonus += 5
|
||||
healingBonus += getMatchingUniques("All adjacent units heal [] HP when healing").sumBy { it.params[0].toInt() }
|
||||
// Deprecated since 3.15.6
|
||||
if (hasUnique("This unit and all others in adjacent tiles heal 5 additional HP per turn")) healingBonus += 5
|
||||
if (hasUnique("This unit and all others in adjacent tiles heal 5 additional HP. This unit heals 5 additional HP outside of friendly territory.")) healingBonus += 5
|
||||
//
|
||||
return healingBonus
|
||||
}
|
||||
|
||||
@ -507,7 +529,11 @@ class MapUnit {
|
||||
var amountToHealBy = rankTileForHealing(getTile())
|
||||
if (amountToHealBy == 0) return
|
||||
|
||||
if (hasUnique("+10 HP when healing")) amountToHealBy += 10
|
||||
// Deprecated since 3.15.6
|
||||
if (hasUnique("+10 HP when healing")) amountToHealBy += 10
|
||||
//
|
||||
amountToHealBy += getMatchingUniques("[] HP when healing").sumBy { it.params[0].toInt() }
|
||||
|
||||
val maxAdjacentHealingBonus = currentTile.getTilesInDistance(1)
|
||||
.flatMap { it.getUnits().asSequence() }.map { it.adjacentHealingBonus() }.maxOrNull()
|
||||
if (maxAdjacentHealingBonus != null)
|
||||
@ -535,11 +561,20 @@ class MapUnit {
|
||||
else -> 5 // Enemy territory
|
||||
}
|
||||
|
||||
if (hasUnique("This unit and all others in adjacent tiles heal 5 additional HP. This unit heals 5 additional HP outside of friendly territory.")
|
||||
&& !isFriendlyTerritory
|
||||
&& healing > 0
|
||||
)// Additional healing from medic is only applied when the unit is able to heal
|
||||
healing += 5
|
||||
// Deprecated since 3.15.6
|
||||
if (hasUnique("This unit and all others in adjacent tiles heal 5 additional HP. This unit heals 5 additional HP outside of friendly territory.")
|
||||
&& !isFriendlyTerritory
|
||||
&& healing > 0
|
||||
)// Additional healing from medic is only applied when the unit is able to heal
|
||||
healing += 5
|
||||
//
|
||||
if (healing > 0) {
|
||||
for (unique in getMatchingUniques("[] HP when healing in [] tiles")) {
|
||||
if (tileInfo.matchesFilter(unique.params[1])) {
|
||||
healing += unique.params[0].toInt()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return healing
|
||||
}
|
||||
|
@ -415,8 +415,8 @@ open class TileInfo {
|
||||
naturalWonder -> true
|
||||
"Open terrain" -> !isRoughTerrain()
|
||||
"Rough terrain" -> isRoughTerrain()
|
||||
"Foreign Land" -> observingCiv != null && !isFriendlyTerritory(observingCiv)
|
||||
"Friendly Land" -> observingCiv != null && isFriendlyTerritory(observingCiv)
|
||||
"Foreign Land", "Foreign" -> observingCiv != null && !isFriendlyTerritory(observingCiv)
|
||||
"Friendly Land", "Friendly" -> observingCiv != null && isFriendlyTerritory(observingCiv)
|
||||
resource -> observingCiv != null && hasViewableResource(observingCiv)
|
||||
else -> {
|
||||
if (terrainFeatures.contains(filter)) return true
|
||||
|
@ -26,8 +26,12 @@ class UnitPromotions{
|
||||
numberOfPromotions++
|
||||
}
|
||||
|
||||
if(promotionName=="Heal Instantly") unit.healBy(50)
|
||||
else promotions.add(promotionName)
|
||||
val promotion = unit.civInfo.gameInfo.ruleSet.unitPromotions[promotionName]!!
|
||||
doDirectPromotionEffects(promotion)
|
||||
|
||||
// This usage of a promotion name as its identifier is deprecated since 3.15.6
|
||||
if (promotionName != "Heal Instantly" && promotion.uniqueObjects.none { it.placeholderText == "Doing so will consume this opportunity to choose a Promotion" })
|
||||
promotions.add(promotionName)
|
||||
|
||||
unit.updateUniques()
|
||||
|
||||
@ -36,6 +40,11 @@ class UnitPromotions{
|
||||
// So, if the addPromotion was triggered from there, simply don't update
|
||||
unit.updateVisibleTiles() // some promotions/uniques give the unit bonus sight
|
||||
}
|
||||
|
||||
fun doDirectPromotionEffects(promotion: Promotion) {
|
||||
for (unique in promotion.uniqueObjects.filter { it.placeholderText == "Heal this unit by [] HP"})
|
||||
unit.healBy(unique.params[0].toInt())
|
||||
}
|
||||
|
||||
fun getAvailablePromotions(): List<Promotion> {
|
||||
return unit.civInfo.gameInfo.ruleSet.unitPromotions.values
|
||||
|
Reference in New Issue
Block a user