mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-21 13:18:56 +07:00
Resolved #3476 - captured civilian units can no longer move on the same turn
This commit is contained in:
@ -21,7 +21,7 @@ import kotlin.math.max
|
||||
*/
|
||||
object Battle {
|
||||
|
||||
fun moveAndAttack(attacker: ICombatant, attackableTile: AttackableTile){
|
||||
fun moveAndAttack(attacker: ICombatant, attackableTile: AttackableTile) {
|
||||
if (attacker is MapUnitCombatant) {
|
||||
attacker.unit.movement.moveToTile(attackableTile.tileToAttackFrom)
|
||||
if (attacker.unit.hasUnique("Must set up to ranged attack") && attacker.unit.action != Constants.unitActionSetUp) {
|
||||
@ -38,18 +38,18 @@ object Battle {
|
||||
|
||||
fun attack(attacker: ICombatant, defender: ICombatant) {
|
||||
if (UncivGame.Current.alertBattle) {
|
||||
println(attacker.getCivInfo().civName+" "+attacker.getName()+" attacked "+
|
||||
defender.getCivInfo().civName+" "+defender.getName())
|
||||
println(attacker.getCivInfo().civName + " " + attacker.getName() + " attacked " +
|
||||
defender.getCivInfo().civName + " " + defender.getName())
|
||||
}
|
||||
val attackedTile = defender.getTile()
|
||||
|
||||
if(attacker is MapUnitCombatant && attacker.getUnitType().isAirUnit()) {
|
||||
if (attacker is MapUnitCombatant && attacker.getUnitType().isAirUnit()) {
|
||||
tryInterceptAirAttack(attacker, defender)
|
||||
if (attacker.isDefeated()) return
|
||||
}
|
||||
|
||||
// Withdraw from melee ability
|
||||
if (attacker is MapUnitCombatant && attacker.isMelee() && defender is MapUnitCombatant ) {
|
||||
if (attacker is MapUnitCombatant && attacker.isMelee() && defender is MapUnitCombatant) {
|
||||
val withdraw = defender.unit.getMatchingUniques("May withdraw before melee ([]%)").firstOrNull()
|
||||
if (withdraw != null && doWithdrawFromMeleeAbility(attacker, defender, withdraw)) return
|
||||
}
|
||||
@ -71,7 +71,7 @@ object Battle {
|
||||
|
||||
reduceAttackerMovementPointsAndAttacks(attacker, defender)
|
||||
|
||||
if(!isAlreadyDefeatedCity) postBattleAddXp(attacker, defender)
|
||||
if (!isAlreadyDefeatedCity) postBattleAddXp(attacker, defender)
|
||||
|
||||
// Add culture when defeating a barbarian when Honor policy is adopted, gold from enemy killed when honor is complete
|
||||
// or any enemy military unit with Sacrificial captives unique (can be either attacker or defender!)
|
||||
@ -91,7 +91,7 @@ object Battle {
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryEarnFromKilling(civUnit:ICombatant, defeatedUnit:MapUnitCombatant){
|
||||
private fun tryEarnFromKilling(civUnit: ICombatant, defeatedUnit: MapUnitCombatant) {
|
||||
val unitStr = max(defeatedUnit.unit.baseUnit.strength, defeatedUnit.unit.baseUnit.rangedStrength)
|
||||
val unitCost = defeatedUnit.unit.baseUnit.cost
|
||||
val bonusUniquePlaceholderText = "Earn []% of [] opponent's [] as [] for kills"
|
||||
@ -132,7 +132,7 @@ object Battle {
|
||||
var damageToAttacker = BattleDamage.calculateDamageToAttacker(attacker, attacker.getTile(), defender)
|
||||
|
||||
if (defender.getUnitType().isCivilian() && attacker.isMelee()) {
|
||||
captureCivilianUnit(attacker, defender)
|
||||
captureCivilianUnit(attacker, defender as MapUnitCombatant)
|
||||
} else if (attacker.isRanged()) {
|
||||
defender.takeDamage(damageToDefender) // straight up
|
||||
} else {
|
||||
@ -251,22 +251,22 @@ object Battle {
|
||||
}
|
||||
|
||||
// XP!
|
||||
private fun addXp(thisCombatant:ICombatant, amount:Int, otherCombatant:ICombatant){
|
||||
if(thisCombatant !is MapUnitCombatant) return
|
||||
if(thisCombatant.unit.promotions.totalXpProduced() >= thisCombatant.unit.civInfo.gameInfo.ruleSet.modOptions.maxXPfromBarbarians
|
||||
private fun addXp(thisCombatant: ICombatant, amount: Int, otherCombatant: ICombatant) {
|
||||
if (thisCombatant !is MapUnitCombatant) return
|
||||
if (thisCombatant.unit.promotions.totalXpProduced() >= thisCombatant.unit.civInfo.gameInfo.ruleSet.modOptions.maxXPfromBarbarians
|
||||
&& otherCombatant.getCivInfo().isBarbarian())
|
||||
return
|
||||
|
||||
var XPModifier = 1f
|
||||
if (thisCombatant.getCivInfo().hasUnique("Military units gain 50% more Experience from combat")) XPModifier += 0.5f
|
||||
for (unique in thisCombatant.unit.getMatchingUniques("[]% Bonus XP gain"))
|
||||
XPModifier += unique.params[0].toFloat() / 100
|
||||
XPModifier += unique.params[0].toFloat() / 100
|
||||
|
||||
val XPGained = (amount * XPModifier).toInt()
|
||||
thisCombatant.unit.promotions.XP += XPGained
|
||||
|
||||
|
||||
if(thisCombatant.getCivInfo().isMajorCiv()) {
|
||||
if (thisCombatant.getCivInfo().isMajorCiv()) {
|
||||
var greatGeneralPointsModifier = 1f
|
||||
val unitUniques = thisCombatant.unit.getMatchingUniques("[] is earned []% faster")
|
||||
val civUniques = thisCombatant.getCivInfo().getMatchingUniques("[] is earned []% faster")
|
||||
@ -311,17 +311,17 @@ object Battle {
|
||||
}
|
||||
}
|
||||
|
||||
fun getMapCombatantOfTile(tile:TileInfo): ICombatant? {
|
||||
fun getMapCombatantOfTile(tile: TileInfo): ICombatant? {
|
||||
if (tile.isCityCenter()) return CityCombatant(tile.getCity()!!)
|
||||
if (tile.militaryUnit != null) return MapUnitCombatant(tile.militaryUnit!!)
|
||||
if (tile.civilianUnit != null) return MapUnitCombatant(tile.civilianUnit!!)
|
||||
return null
|
||||
}
|
||||
|
||||
private fun captureCivilianUnit(attacker: ICombatant, defender: ICombatant){
|
||||
private fun captureCivilianUnit(attacker: ICombatant, defender: MapUnitCombatant) {
|
||||
// barbarians don't capture civilians
|
||||
if(attacker.getCivInfo().isBarbarian()
|
||||
||(defender as MapUnitCombatant).unit.hasUnique("Uncapturable")){
|
||||
if (attacker.getCivInfo().isBarbarian()
|
||||
|| (defender as MapUnitCombatant).unit.hasUnique("Uncapturable")) {
|
||||
defender.takeDamage(100)
|
||||
return
|
||||
}
|
||||
@ -330,25 +330,25 @@ object Battle {
|
||||
val defenderCiv = defender.getCivInfo()
|
||||
|
||||
val capturedUnit = defender.unit
|
||||
capturedUnit.civInfo.addNotification("An enemy ["+attacker.getName()+"] has captured our ["+defender.getName()+"]",
|
||||
capturedUnit.civInfo.addNotification("An enemy [" + attacker.getName() + "] has captured our [" + defender.getName() + "]",
|
||||
defender.getTile().position, Color.RED)
|
||||
|
||||
// Apparently in Civ V, captured settlers are converted to workers.
|
||||
if(capturedUnit.name==Constants.settler) {
|
||||
if (capturedUnit.name == Constants.settler) {
|
||||
val tile = capturedUnit.getTile()
|
||||
capturedUnit.destroy()
|
||||
attacker.getCivInfo().placeUnitNearTile(tile.position, Constants.worker)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
capturedUnit.civInfo.removeUnit(capturedUnit)
|
||||
capturedUnit.assignOwner(attacker.getCivInfo())
|
||||
capturedUnit.currentMovement = 0f
|
||||
}
|
||||
|
||||
destroyIfDefeated(defenderCiv, attacker.getCivInfo())
|
||||
capturedUnit.updateVisibleTiles()
|
||||
}
|
||||
|
||||
fun destroyIfDefeated(attackedCiv:CivilizationInfo, attacker: CivilizationInfo){
|
||||
fun destroyIfDefeated(attackedCiv: CivilizationInfo, attacker: CivilizationInfo) {
|
||||
if (attackedCiv.isDefeated()) {
|
||||
attackedCiv.destroy()
|
||||
attacker.popupAlerts.add(PopupAlert(AlertType.Defeated, attackedCiv.civName))
|
||||
@ -366,11 +366,11 @@ object Battle {
|
||||
if (city.population.population <= 5 && !city.isOriginalCapital) {
|
||||
city.destroyCity()
|
||||
} else {
|
||||
city.population.population = max(city.population.population-5, 1)
|
||||
city.population.population = max(city.population.population - 5, 1)
|
||||
city.population.unassignExtraPopulation()
|
||||
continue
|
||||
}
|
||||
destroyIfDefeated(city.civInfo,attackingCiv)
|
||||
destroyIfDefeated(city.civInfo, attackingCiv)
|
||||
}
|
||||
|
||||
fun declareWar(civSuffered: CivilizationInfo) {
|
||||
@ -381,7 +381,7 @@ object Battle {
|
||||
}
|
||||
}
|
||||
|
||||
for(unit in tile.getUnits()){
|
||||
for (unit in tile.getUnits()) {
|
||||
unit.destroy()
|
||||
postBattleNotifications(attacker, MapUnitCombatant(unit), unit.currentTile)
|
||||
declareWar(unit.civInfo)
|
||||
@ -399,16 +399,16 @@ object Battle {
|
||||
if (tile.isLand && !tile.isImpassible()) tile.terrainFeature = "Fallout"
|
||||
}
|
||||
|
||||
for(civ in attacker.getCivInfo().getKnownCivs()){
|
||||
for (civ in attacker.getCivInfo().getKnownCivs()) {
|
||||
civ.getDiplomacyManager(attackingCiv)
|
||||
.setModifier(DiplomaticModifiers.UsedNuclearWeapons,-50f)
|
||||
.setModifier(DiplomaticModifiers.UsedNuclearWeapons, -50f)
|
||||
}
|
||||
|
||||
// Instead of postBattleAction() just destroy the missile, all other functions are not relevant
|
||||
(attacker as MapUnitCombatant).unit.destroy()
|
||||
}
|
||||
|
||||
private fun tryInterceptAirAttack(attacker:MapUnitCombatant, defender: ICombatant) {
|
||||
private fun tryInterceptAirAttack(attacker: MapUnitCombatant, defender: ICombatant) {
|
||||
val attackedTile = defender.getTile()
|
||||
for (interceptor in defender.getCivInfo().getCivUnits().filter { it.canIntercept(attackedTile) }) {
|
||||
if (Random().nextFloat() > 100f / interceptor.interceptChance()) continue
|
||||
@ -426,17 +426,17 @@ object Battle {
|
||||
if (attacker.isDefeated()) {
|
||||
attacker.getCivInfo()
|
||||
.addNotification("Our [$attackerName] was destroyed by an intercepting [$interceptorName]",
|
||||
Color.RED)
|
||||
Color.RED)
|
||||
defender.getCivInfo()
|
||||
.addNotification("Our [$interceptorName] intercepted and destroyed an enemy [$attackerName]",
|
||||
interceptor.currentTile.position, Color.RED)
|
||||
interceptor.currentTile.position, Color.RED)
|
||||
} else {
|
||||
attacker.getCivInfo()
|
||||
.addNotification("Our [$attackerName] was attacked by an intercepting [$interceptorName]",
|
||||
Color.RED)
|
||||
Color.RED)
|
||||
defender.getCivInfo()
|
||||
.addNotification("Our [$interceptorName] intercepted and attacked an enemy [$attackerName]",
|
||||
interceptor.currentTile.position, Color.RED)
|
||||
interceptor.currentTile.position, Color.RED)
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -460,8 +460,8 @@ object Battle {
|
||||
val defendBaseUnit = defender.unit.baseUnit
|
||||
val baseChance = withdrawUnique.params[0].toFloat()
|
||||
val percentChance = (baseChance
|
||||
* defendBaseUnit.strength / attackBaseUnit.strength
|
||||
* defendBaseUnit.movement / attackBaseUnit.movement).toInt()
|
||||
* defendBaseUnit.strength / attackBaseUnit.strength
|
||||
* defendBaseUnit.movement / attackBaseUnit.movement).toInt()
|
||||
// Roll the dice - note the effect of the surroundings, namely how much room there is to evade to,
|
||||
// isn't yet factored in. But it should, and that's factored in by allowing the dice to choose
|
||||
// any geometrically fitting tile first and *then* fail when checking the tile for viability.
|
||||
@ -494,11 +494,11 @@ object Battle {
|
||||
defender.unit.removeFromTile()
|
||||
defender.unit.putInTile(toTile)
|
||||
// and count 1 attack for attacker but leave it in place
|
||||
reduceAttackerMovementPointsAndAttacks(attacker,defender)
|
||||
reduceAttackerMovementPointsAndAttacks(attacker, defender)
|
||||
val notificationString = "[" + defendBaseUnit.name + "] withdrew from a [" + attackBaseUnit.name + "]"
|
||||
defender.getCivInfo().addNotification(notificationString, toTile.position, Color.GREEN)
|
||||
attacker.getCivInfo().addNotification(notificationString, toTile.position, Color.RED)
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user