mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-23 03:23:17 -04:00
Merge 45d251ce7e3442342bb5eb18ceaefd82a9d528cd into d51ef24c205b6b05330b3c4d7ce79c402db44447
This commit is contained in:
commit
13c200d7f8
@ -183,10 +183,93 @@ object Battle {
|
|||||||
.firstOrNull { it.text == "Your city [${attacker.getName()}] can bombard the enemy!" }
|
.firstOrNull { it.text == "Your city [${attacker.getName()}] can bombard the enemy!" }
|
||||||
attacker.getCivInfo().notifications.remove(cityCanBombardNotification)
|
attacker.getCivInfo().notifications.remove(cityCanBombardNotification)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Aoe attack
|
||||||
|
if (attacker is MapUnitCombatant && (attacker.unit.hasUnique(UniqueType.AoeDegradeAttack) || attacker.unit.hasUnique(UniqueType.AoeFlatAttack))) {
|
||||||
|
applyAoeAttack(attacker, defender)
|
||||||
|
}
|
||||||
|
|
||||||
return damageDealt + interceptDamage
|
return damageDealt + interceptDamage
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Aoe Logic function
|
||||||
|
fun applyAoeAttack(attacker: MapUnitCombatant, defender: ICombatant) {
|
||||||
|
|
||||||
|
//degrading AOE is used if both AoeDegradeAttack and AoeFlatAttack uniques are present
|
||||||
|
val degradeUnique = attacker.unit.getMatchingUniques(UniqueType.AoeDegradeAttack).firstOrNull()
|
||||||
|
val flatUnique = attacker.unit.getMatchingUniques(UniqueType.AoeFlatAttack).firstOrNull()
|
||||||
|
val aoeUnique = degradeUnique ?: flatUnique ?: return
|
||||||
|
val isDegrade = degradeUnique != null
|
||||||
|
|
||||||
|
val radius = aoeUnique.params.getOrNull(0)?.toIntOrNull() ?: return
|
||||||
|
if (radius <= 0) return
|
||||||
|
|
||||||
|
val includeAllies = attacker.unit.hasUnique(UniqueType.CanDamageAlliesInAOE)
|
||||||
|
val excludeSelf = !attacker.unit.hasUnique(UniqueType.CanDamageSelfInAOE)
|
||||||
|
val receivesCounterDamage = attacker.unit.hasUnique(UniqueType.TakeCounterDamageFromAOE)
|
||||||
|
val centerTile = defender.getTile()
|
||||||
|
val attackerCiv = attacker.getCivInfo()
|
||||||
|
|
||||||
|
for (tile in centerTile.getTilesInDistance(radius)) {
|
||||||
|
val distance = centerTile.aerialDistanceTo(tile)
|
||||||
|
val distanceFactor = if (isDegrade)
|
||||||
|
(1.0 - distance.toDouble() / (radius + 1)).coerceAtLeast(0.0)
|
||||||
|
else 1.0
|
||||||
|
|
||||||
|
for (unit in tile.getUnits()) {
|
||||||
|
if (excludeSelf && unit == attacker.unit) continue
|
||||||
|
if (unit == (defender as? MapUnitCombatant)?.unit && unit != attacker.unit) continue
|
||||||
|
|
||||||
|
val isAlly = !unit.civ.isAtWarWith(attackerCiv)
|
||||||
|
if (!includeAllies && isAlly && unit != attacker.unit) continue
|
||||||
|
|
||||||
|
val aoeDefender = MapUnitCombatant(unit)
|
||||||
|
val damage = (BattleDamage.calculateDamageToDefender(attacker, aoeDefender) * distanceFactor).toInt().coerceAtLeast(1)
|
||||||
|
|
||||||
|
if (aoeDefender.isCivilian() && attacker.isMelee()) {
|
||||||
|
// Capture civilian units if attacker can capture
|
||||||
|
BattleUnitCapture.captureCivilianUnit(attacker, aoeDefender)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply combat effects but no counter-damage
|
||||||
|
triggerCombatUniques(attacker, aoeDefender, tile)
|
||||||
|
aoeDefender.takeDamage(damage)
|
||||||
|
triggerDamageUniquesForUnit(attacker, aoeDefender, tile, CombatAction.Attack)
|
||||||
|
|
||||||
|
if (aoeDefender.isDefeated() && !aoeDefender.isCivilian()) {
|
||||||
|
// Try to capture first - if successful, skip other defeat effects
|
||||||
|
val captured = BattleUnitCapture.tryCaptureMilitaryUnit(attacker, aoeDefender, tile)
|
||||||
|
if (!captured) {
|
||||||
|
// If not captured, proceed with normal defeat effects
|
||||||
|
triggerPostKillingUniques(aoeDefender, attacker, tile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (receivesCounterDamage && !aoeDefender.isCivilian()) {
|
||||||
|
val isMainTarget =
|
||||||
|
(defender is MapUnitCombatant && unit == defender.unit) ||
|
||||||
|
(defender is CityCombatant && unit == defender.city)
|
||||||
|
|
||||||
|
val isSelf = (unit == attacker.unit)
|
||||||
|
|
||||||
|
// Counter damage from every valid target except main defender + self
|
||||||
|
if (!isMainTarget && !isSelf) {
|
||||||
|
val baseCounterDamage = BattleDamage.calculateDamageToAttacker(attacker, aoeDefender)
|
||||||
|
val finalCounterDamage =
|
||||||
|
if (isDegrade) (baseCounterDamage * distanceFactor).toInt().coerceAtLeast(1)
|
||||||
|
else baseCounterDamage
|
||||||
|
|
||||||
|
attacker.takeDamage(finalCounterDamage)
|
||||||
|
|
||||||
|
if (attacker.isDefeated()) return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (attacker.isDefeated()) return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun triggerPostKillingUniques(
|
private fun triggerPostKillingUniques(
|
||||||
defender: ICombatant,
|
defender: ICombatant,
|
||||||
attacker: ICombatant,
|
attacker: ICombatant,
|
||||||
|
@ -426,6 +426,21 @@ enum class UniqueType(
|
|||||||
IndirectFire("Ranged attacks may be performed over obstacles", UniqueTarget.Unit, UniqueTarget.Global),
|
IndirectFire("Ranged attacks may be performed over obstacles", UniqueTarget.Unit, UniqueTarget.Global),
|
||||||
NuclearWeapon("Nuclear weapon of Strength [amount]", UniqueTarget.Unit),
|
NuclearWeapon("Nuclear weapon of Strength [amount]", UniqueTarget.Unit),
|
||||||
|
|
||||||
|
//Aoe Attacks
|
||||||
|
AoeFlatAttack("Attacks also target all units within [positiveAmount] tiles", UniqueTarget.Unit,
|
||||||
|
docDescription = "Performs an attack against every unit in the radius, dealing equal damage. Status effects and on-hit abilities apply to all affected units. " +
|
||||||
|
"If both this and decreasing area attacks are present, only decreasing area attacks will be used."),
|
||||||
|
AoeDegradeAttack("Attacks also target units within [positiveAmount] tiles, with damage decreasing by distance", UniqueTarget.Unit,
|
||||||
|
docDescription = "Performs an attack against every unit in the radius. Status effects and on-hit abilities apply. " +
|
||||||
|
"Damage decreases with distance from the main target. If both this and equal area attacks are present, only this will be used. " +
|
||||||
|
"Damage formula: Damage = (1 - (distance / radius)) * baseDamage"),
|
||||||
|
CanDamageSelfInAOE("Damages self with Aoe attacks", UniqueTarget.Unit,
|
||||||
|
docDescription = "This unit takes damage from its own Aoe attacks, does not mean it will take damage from allied Aoe attacks."),
|
||||||
|
CanDamageAlliesInAOE("Damages allied units with Aoe attacks", UniqueTarget.Unit,
|
||||||
|
docDescription = "This unit damages allied units with Aoe attacks, does not mean it will take damage from its own Aoe attacks unless Damages self with Aoe attacks is also set."),
|
||||||
|
TakeCounterDamageFromAOE("Takes counter damage from each unit hit by its area attacks", UniqueTarget.Unit,
|
||||||
|
docDescription = "Only works for melee units, counter damage does not activate on self if \"Damages self with Aoe attacks\" unique is also present."),
|
||||||
|
|
||||||
NoDefensiveTerrainBonus("No defensive terrain bonus", UniqueTarget.Unit, UniqueTarget.Global),
|
NoDefensiveTerrainBonus("No defensive terrain bonus", UniqueTarget.Unit, UniqueTarget.Global),
|
||||||
NoDefensiveTerrainPenalty("No defensive terrain penalty", UniqueTarget.Unit, UniqueTarget.Global),
|
NoDefensiveTerrainPenalty("No defensive terrain penalty", UniqueTarget.Unit, UniqueTarget.Global),
|
||||||
NoDamagePenaltyWoundedUnits("No damage penalty for wounded units", UniqueTarget.Unit, UniqueTarget.Global),
|
NoDamagePenaltyWoundedUnits("No damage penalty for wounded units", UniqueTarget.Unit, UniqueTarget.Global),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user