mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-27 05:46:43 -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()) {
|
if (attacker is MapUnitCombatant && attacker.unit.baseUnit.isAirUnit()) {
|
||||||
tryInterceptAirAttack(attacker, attackedTile, defender.getCivInfo())
|
tryInterceptAirAttack(attacker, attackedTile, defender.getCivInfo(), defender)
|
||||||
if (attacker.isDefeated()) return
|
if (attacker.isDefeated()) return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,7 +221,7 @@ object Battle {
|
|||||||
|
|
||||||
if (defender is MapUnitCombatant && defender.unit.isCivilian() && attacker.isMelee()) {
|
if (defender is MapUnitCombatant && defender.unit.isCivilian() && attacker.isMelee()) {
|
||||||
captureCivilianUnit(attacker, defender)
|
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
|
defender.takeDamage(potentialDamageToDefender) // straight up
|
||||||
} else {
|
} else {
|
||||||
//melee attack is complicated, because either side may defeat the other midway
|
//melee attack is complicated, because either side may defeat the other midway
|
||||||
@ -662,7 +662,7 @@ object Battle {
|
|||||||
.filter{it != attackingCiv}) {
|
.filter{it != attackingCiv}) {
|
||||||
tryDeclareWar(civWhoseUnitWasAttacked)
|
tryDeclareWar(civWhoseUnitWasAttacked)
|
||||||
if (attacker.unit.baseUnit.isAirUnit() && !attacker.isDefeated()) {
|
if (attacker.unit.baseUnit.isAirUnit() && !attacker.isDefeated()) {
|
||||||
tryInterceptAirAttack(attacker, targetTile, civWhoseUnitWasAttacked)
|
tryInterceptAirAttack(attacker, targetTile, civWhoseUnitWasAttacked, null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (attacker.isDefeated()) return
|
if (attacker.isDefeated()) return
|
||||||
@ -790,17 +790,22 @@ object Battle {
|
|||||||
targetedCity.population.addPopulation(-populationLoss.toInt())
|
targetedCity.population.addPopulation(-populationLoss.toInt())
|
||||||
if (targetedCity.population.population < 1) targetedCity.population.setPopulation(1)
|
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
|
if (attacker.unit.hasUnique("Cannot be intercepted")) return
|
||||||
|
// Pick highest chance interceptor
|
||||||
for (interceptor in interceptingCiv.getCivUnits()
|
for (interceptor in interceptingCiv.getCivUnits()
|
||||||
.filter { it.canIntercept(attackedTile) }) {
|
.filter { it.canIntercept(attackedTile) }
|
||||||
if (Random().nextFloat() > interceptor.interceptChance() / 100f) continue
|
.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(
|
var damage = BattleDamage.calculateDamageToDefender(
|
||||||
MapUnitCombatant(interceptor),
|
MapUnitCombatant(interceptor),
|
||||||
null,
|
null,
|
||||||
attacker
|
attacker
|
||||||
)
|
)
|
||||||
|
|
||||||
var damageFactor = 1f + interceptor.interceptDamagePercentBonus().toFloat() / 100f
|
var damageFactor = 1f + interceptor.interceptDamagePercentBonus().toFloat() / 100f
|
||||||
@ -813,19 +818,22 @@ object Battle {
|
|||||||
if (damage > 0)
|
if (damage > 0)
|
||||||
addXp(MapUnitCombatant(interceptor), 2, attacker)
|
addXp(MapUnitCombatant(interceptor), 2, attacker)
|
||||||
|
|
||||||
|
if (damage > 0)
|
||||||
|
addXp(MapUnitCombatant(interceptor), 2, attacker)
|
||||||
|
|
||||||
val attackerName = attacker.getName()
|
val attackerName = attacker.getName()
|
||||||
val interceptorName = interceptor.name
|
val interceptorName = interceptor.name
|
||||||
val locations = LocationAction(interceptor.currentTile.position, attacker.unit.currentTile.position)
|
val locations = LocationAction(interceptor.currentTile.position, attacker.unit.currentTile.position)
|
||||||
val attackerText = if (attacker.isDefeated())
|
val attackerText = if (attacker.isDefeated())
|
||||||
"Our [$attackerName] was destroyed by an intercepting [$interceptorName]"
|
"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())
|
val interceptorText = if (attacker.isDefeated())
|
||||||
"Our [$interceptorName] intercepted and destroyed an enemy [$attackerName]"
|
"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,
|
attacker.getCivInfo().addNotification(attackerText, interceptor.currentTile.position,
|
||||||
attackerName, NotificationIcon.War, interceptorName)
|
attackerName, NotificationIcon.War, interceptorName)
|
||||||
interceptingCiv.addNotification(interceptorText, locations,
|
interceptingCiv.addNotification(interceptorText, locations,
|
||||||
interceptorName, NotificationIcon.War, attackerName)
|
interceptorName, NotificationIcon.War, attackerName)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -264,7 +264,7 @@ object BattleDamage {
|
|||||||
defender: ICombatant,
|
defender: ICombatant,
|
||||||
ignoreRandomness: Boolean = false,
|
ignoreRandomness: Boolean = false,
|
||||||
): Int {
|
): Int {
|
||||||
if (attacker.isRanged()) return 0
|
if (attacker.isRanged() && !attacker.isAirUnit()) return 0
|
||||||
if (defender.isCivilian()) return 0
|
if (defender.isCivilian()) return 0
|
||||||
val ratio =
|
val ratio =
|
||||||
getAttackingStrength(attacker, defender) / getDefendingStrength(
|
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
|
if (damageToAttacker && attackerToDefenderRatio > 1 || !damageToAttacker && attackerToDefenderRatio < 1) // damage ratio from the weaker party is inverted
|
||||||
ratioModifier = ratioModifier.pow(-1)
|
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 randomSeed = attacker.getCivInfo().gameInfo.turns * attacker.getTile().position.hashCode() // so people don't save-scum to get optimal results
|
||||||
val randomCenteredAround30 = 24 +
|
val randomCenteredAround30 = 24 +
|
||||||
if (ignoreRandomness) 6f
|
if (ignoreRandomness) 6f
|
||||||
else 12 * Random(randomSeed.toLong()).nextFloat()
|
else 12 * Random(randomSeed.toLong()).nextFloat()
|
||||||
return randomCenteredAround30 * ratioModifier
|
return randomCenteredAround30 * ratioModifier
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -979,6 +979,8 @@ class MapUnit {
|
|||||||
|
|
||||||
fun canIntercept(): Boolean {
|
fun canIntercept(): Boolean {
|
||||||
if (interceptChance() == 0) return false
|
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 +
|
val maxAttacksPerTurn = 1 +
|
||||||
getMatchingUniques("[] extra interceptions may be made per turn").sumOf { it.params[0].toInt() }
|
getMatchingUniques("[] extra interceptions may be made per turn").sumOf { it.params[0].toInt() }
|
||||||
if (attacksThisTurn >= maxAttacksPerTurn) return false
|
if (attacksThisTurn >= maxAttacksPerTurn) return false
|
||||||
|
Loading…
x
Reference in New Issue
Block a user