mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-25 12:54:06 -04:00
Air Units take damage in Combat (#6533)
* Changes required Add isAirUnit to iCombatant * Updating XP Rewards to match Civ5 Add isAirUnit() Boolean for ICombatant * Air Units can only Intercept if they haven't moved this turn * Change Intercept to only have the highest chance unit take the chance * Exempt the defending unit from being able to Intercept Add back in tryInterceptAirAttack() for all units of a civ to attempt intercept * Combine back to 1 function. Add filtering for defender * Fix logic bug * Change base damage to be centered on 25f (instead of 30f) if City is attacking. addRandomDamage is a guess * Revert dmanageModifier code * XP fix Co-authored-by: itanasi <spellman23@gmail.com>
This commit is contained in:
parent
8457c7ab1d
commit
7a89c84790
@ -70,7 +70,7 @@ object Battle {
|
||||
}
|
||||
|
||||
if (attacker is MapUnitCombatant && attacker.unit.baseUnit.isAirUnit()) {
|
||||
tryInterceptAirAttack(attacker, attackedTile, defender.getCivInfo())
|
||||
tryInterceptAirAttack(attacker, attackedTile, defender.getCivInfo(), defender)
|
||||
if (attacker.isDefeated()) return
|
||||
}
|
||||
|
||||
@ -221,7 +221,7 @@ object Battle {
|
||||
|
||||
if (defender is MapUnitCombatant && defender.unit.isCivilian() && attacker.isMelee()) {
|
||||
captureCivilianUnit(attacker, defender)
|
||||
} else if (attacker.isRanged()) {
|
||||
} else if (attacker.isRanged() && !attacker.isAirUnit()) { // Air Units are Ranged, but take damage as well
|
||||
defender.takeDamage(potentialDamageToDefender) // straight up
|
||||
} else {
|
||||
//melee attack is complicated, because either side may defeat the other midway
|
||||
@ -662,7 +662,7 @@ object Battle {
|
||||
.filter{it != attackingCiv}) {
|
||||
tryDeclareWar(civWhoseUnitWasAttacked)
|
||||
if (attacker.unit.baseUnit.isAirUnit() && !attacker.isDefeated()) {
|
||||
tryInterceptAirAttack(attacker, targetTile, civWhoseUnitWasAttacked)
|
||||
tryInterceptAirAttack(attacker, targetTile, civWhoseUnitWasAttacked, null)
|
||||
}
|
||||
}
|
||||
if (attacker.isDefeated()) return
|
||||
@ -790,17 +790,22 @@ object Battle {
|
||||
targetedCity.population.addPopulation(-populationLoss.toInt())
|
||||
if (targetedCity.population.population < 1) targetedCity.population.setPopulation(1)
|
||||
}
|
||||
|
||||
private fun tryInterceptAirAttack(attacker: MapUnitCombatant, attackedTile:TileInfo, interceptingCiv:CivilizationInfo) {
|
||||
|
||||
private fun tryInterceptAirAttack(attacker: MapUnitCombatant, attackedTile: TileInfo, interceptingCiv: CivilizationInfo, defender: ICombatant?) {
|
||||
if (attacker.unit.hasUnique("Cannot be intercepted")) return
|
||||
// Pick highest chance interceptor
|
||||
for (interceptor in interceptingCiv.getCivUnits()
|
||||
.filter { it.canIntercept(attackedTile) }) {
|
||||
if (Random().nextFloat() > interceptor.interceptChance() / 100f) continue
|
||||
.filter { it.canIntercept(attackedTile) }
|
||||
.sortedByDescending { it.interceptChance() }) {
|
||||
// defender can't also intercept
|
||||
if (defender != null && defender is MapUnitCombatant && interceptor == defender.unit) continue
|
||||
// Does Intercept happen? If not, exit
|
||||
if (Random().nextFloat() > interceptor.interceptChance() / 100f) return
|
||||
|
||||
var damage = BattleDamage.calculateDamageToDefender(
|
||||
MapUnitCombatant(interceptor),
|
||||
null,
|
||||
attacker
|
||||
MapUnitCombatant(interceptor),
|
||||
null,
|
||||
attacker
|
||||
)
|
||||
|
||||
var damageFactor = 1f + interceptor.interceptDamagePercentBonus().toFloat() / 100f
|
||||
@ -813,19 +818,22 @@ object Battle {
|
||||
if (damage > 0)
|
||||
addXp(MapUnitCombatant(interceptor), 2, attacker)
|
||||
|
||||
if (damage > 0)
|
||||
addXp(MapUnitCombatant(interceptor), 2, attacker)
|
||||
|
||||
val attackerName = attacker.getName()
|
||||
val interceptorName = interceptor.name
|
||||
val locations = LocationAction(interceptor.currentTile.position, attacker.unit.currentTile.position)
|
||||
val attackerText = if (attacker.isDefeated())
|
||||
"Our [$attackerName] was destroyed by an intercepting [$interceptorName]"
|
||||
else "Our [$attackerName] was attacked by an intercepting [$interceptorName]"
|
||||
else "Our [$attackerName] was attacked by an intercepting [$interceptorName]"
|
||||
val interceptorText = if (attacker.isDefeated())
|
||||
"Our [$interceptorName] intercepted and destroyed an enemy [$attackerName]"
|
||||
else "Our [$interceptorName] intercepted and attacked an enemy [$attackerName]"
|
||||
else "Our [$interceptorName] intercepted and attacked an enemy [$attackerName]"
|
||||
attacker.getCivInfo().addNotification(attackerText, interceptor.currentTile.position,
|
||||
attackerName, NotificationIcon.War, interceptorName)
|
||||
attackerName, NotificationIcon.War, interceptorName)
|
||||
interceptingCiv.addNotification(interceptorText, locations,
|
||||
interceptorName, NotificationIcon.War, attackerName)
|
||||
interceptorName, NotificationIcon.War, attackerName)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -264,7 +264,7 @@ object BattleDamage {
|
||||
defender: ICombatant,
|
||||
ignoreRandomness: Boolean = false,
|
||||
): Int {
|
||||
if (attacker.isRanged()) return 0
|
||||
if (attacker.isRanged() && !attacker.isAirUnit()) return 0
|
||||
if (defender.isCivilian()) return 0
|
||||
val ratio =
|
||||
getAttackingStrength(attacker, defender) / getDefendingStrength(
|
||||
@ -302,9 +302,9 @@ object BattleDamage {
|
||||
if (damageToAttacker && attackerToDefenderRatio > 1 || !damageToAttacker && attackerToDefenderRatio < 1) // damage ratio from the weaker party is inverted
|
||||
ratioModifier = ratioModifier.pow(-1)
|
||||
val randomSeed = attacker.getCivInfo().gameInfo.turns * attacker.getTile().position.hashCode() // so people don't save-scum to get optimal results
|
||||
val randomCenteredAround30 = 24 +
|
||||
if (ignoreRandomness) 6f
|
||||
else 12 * Random(randomSeed.toLong()).nextFloat()
|
||||
val randomCenteredAround30 = 24 +
|
||||
if (ignoreRandomness) 6f
|
||||
else 12 * Random(randomSeed.toLong()).nextFloat()
|
||||
return randomCenteredAround30 * ratioModifier
|
||||
}
|
||||
}
|
||||
|
@ -979,6 +979,8 @@ class MapUnit {
|
||||
|
||||
fun canIntercept(): Boolean {
|
||||
if (interceptChance() == 0) return false
|
||||
// Air Units can only Intercept if they didn't move this turn
|
||||
if (baseUnit.isAirUnit() && currentMovement == 0f) return false
|
||||
val maxAttacksPerTurn = 1 +
|
||||
getMatchingUniques("[] extra interceptions may be made per turn").sumOf { it.params[0].toInt() }
|
||||
if (attacksThisTurn >= maxAttacksPerTurn) return false
|
||||
|
Loading…
x
Reference in New Issue
Block a user