From 4b649825cd8aa819a07d4823317abdde68474537 Mon Sep 17 00:00:00 2001 From: Yair Morgenstern Date: Mon, 1 Jun 2020 01:51:11 +0300 Subject: [PATCH] Battle calculation takes into account the tile that the unit will attack from --- .../unciv/logic/automation/BattleHelper.kt | 2 ++ core/src/com/unciv/logic/battle/Battle.kt | 6 +++--- .../com/unciv/logic/battle/BattleDamage.kt | 20 +++++++++---------- .../ui/worldscreen/bottombar/BattleTable.kt | 7 +++---- 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/core/src/com/unciv/logic/automation/BattleHelper.kt b/core/src/com/unciv/logic/automation/BattleHelper.kt index a33313878d..61e0c78fc5 100644 --- a/core/src/com/unciv/logic/automation/BattleHelper.kt +++ b/core/src/com/unciv/logic/automation/BattleHelper.kt @@ -17,6 +17,7 @@ object BattleHelper { // Only take enemies we can fight without dying .filter { BattleDamage.calculateDamageToAttacker(MapUnitCombatant(unit), + it.tileToAttackFrom, Battle.getMapCombatantOfTile(it.tileToAttack)!!) < unit.health } @@ -112,6 +113,7 @@ object BattleHelper { // Only take enemies we can fight without dying .filter { BattleDamage.calculateDamageToAttacker(MapUnitCombatant(unit), + it.tileToAttackFrom, Battle.getMapCombatantOfTile(it.tileToAttack)!!) < unit.health } .filter { it.tileToAttackFrom.isLand } diff --git a/core/src/com/unciv/logic/battle/Battle.kt b/core/src/com/unciv/logic/battle/Battle.kt index e27d6d05eb..da0a239f93 100644 --- a/core/src/com/unciv/logic/battle/Battle.kt +++ b/core/src/com/unciv/logic/battle/Battle.kt @@ -53,8 +53,8 @@ object Battle { } } - var damageToDefender = BattleDamage.calculateDamageToDefender(attacker,defender) - var damageToAttacker = BattleDamage.calculateDamageToAttacker(attacker,defender) + var damageToDefender = BattleDamage.calculateDamageToDefender(attacker, attacker.getTile(), defender) + var damageToAttacker = BattleDamage.calculateDamageToAttacker(attacker, attacker.getTile(), defender) if(defender.getUnitType().isCivilian() && attacker.isMelee()){ captureCivilianUnit(attacker,defender) @@ -387,7 +387,7 @@ object Battle { for (interceptor in defender.getCivInfo().getCivUnits().filter { it.canIntercept(attackedTile) }) { if (Random().nextFloat() > 100f / interceptor.interceptChance()) continue - var damage = BattleDamage.calculateDamageToDefender(MapUnitCombatant(interceptor), attacker) + var damage = BattleDamage.calculateDamageToDefender(MapUnitCombatant(interceptor), interceptor.getTile(), attacker) damage += damage * interceptor.interceptDamagePercentBonus() / 100 if (attacker.unit.hasUnique("Reduces damage taken from interception by 50%")) damage /= 2 diff --git a/core/src/com/unciv/logic/battle/BattleDamage.kt b/core/src/com/unciv/logic/battle/BattleDamage.kt index 02a80b20c0..6fc6c043af 100644 --- a/core/src/com/unciv/logic/battle/BattleDamage.kt +++ b/core/src/com/unciv/logic/battle/BattleDamage.kt @@ -110,12 +110,12 @@ object BattleDamage { return modifiers } - fun getAttackModifiers(attacker: ICombatant, defender: ICombatant): HashMap { + fun getAttackModifiers(attacker: ICombatant, tileToAttackFrom:TileInfo?, defender: ICombatant): HashMap { val modifiers = getGeneralModifiers(attacker, defender) val policies = attacker.getCivInfo().policies if(attacker is MapUnitCombatant) { - modifiers.putAll(getTileSpecificModifiers(attacker,defender.getTile())) + modifiers.putAll(getTileSpecificModifiers(attacker, defender.getTile())) for (ability in attacker.unit.getUniques()) { val regexResult = Regex(BONUS_AS_ATTACKER).matchEntire(ability) //to do: extend to defender, and penalyy @@ -138,8 +138,8 @@ object BattleDamage { if (numberOfAttackersSurroundingDefender > 1) modifiers["Flanking"] = 0.1f * (numberOfAttackersSurroundingDefender-1) //https://www.carlsguides.com/strategy/civilization5/war/combatbonuses.php - if (attacker.getTile().isConnectedByRiver(defender.getTile())){ - if (!attacker.getTile().hasConnection(attacker.getCivInfo()) // meaning, the tiles are not road-connected for this civ + if (tileToAttackFrom!=null && tileToAttackFrom.isConnectedByRiver(defender.getTile())){ + if (!tileToAttackFrom.hasConnection(attacker.getCivInfo()) // meaning, the tiles are not road-connected for this civ || !defender.getTile().hasConnection(attacker.getCivInfo()) || !attacker.getCivInfo().tech.roadsConnectAcrossRivers){ modifiers["Across river"] = -0.2f @@ -272,8 +272,8 @@ object BattleDamage { /** * Includes attack modifiers */ - private fun getAttackingStrength(attacker: ICombatant, defender: ICombatant): Float { - val attackModifier = modifiersToMultiplicationBonus(getAttackModifiers(attacker,defender)) + private fun getAttackingStrength(attacker: ICombatant, tileToAttackFrom: TileInfo?, defender: ICombatant): Float { + val attackModifier = modifiersToMultiplicationBonus(getAttackModifiers(attacker,tileToAttackFrom, defender)) return attacker.getAttackingStrength() * attackModifier } @@ -287,15 +287,15 @@ object BattleDamage { return defender.getDefendingStrength() * defenceModifier } - fun calculateDamageToAttacker(attacker: ICombatant, defender: ICombatant): Int { + fun calculateDamageToAttacker(attacker: ICombatant, tileToAttackFrom: TileInfo?, defender: ICombatant): Int { if(attacker.isRanged()) return 0 if(defender.getUnitType().isCivilian()) return 0 - val ratio = getAttackingStrength(attacker,defender) / getDefendingStrength(attacker,defender) + val ratio = getAttackingStrength(attacker, tileToAttackFrom, defender) / getDefendingStrength(attacker,defender) return (damageModifier(ratio, true) * getHealthDependantDamageRatio(defender)).roundToInt() } - fun calculateDamageToDefender(attacker: ICombatant, defender: ICombatant): Int { - val ratio = getAttackingStrength(attacker,defender) / getDefendingStrength(attacker,defender) + fun calculateDamageToDefender(attacker: ICombatant, tileToAttackFrom: TileInfo?, defender: ICombatant): Int { + val ratio = getAttackingStrength(attacker,tileToAttackFrom, defender) / getDefendingStrength(attacker,defender) return (damageModifier(ratio,false) * getHealthDependantDamageRatio(attacker)).roundToInt() } diff --git a/core/src/com/unciv/ui/worldscreen/bottombar/BattleTable.kt b/core/src/com/unciv/ui/worldscreen/bottombar/BattleTable.kt index 5700a27e37..036adbe0d4 100644 --- a/core/src/com/unciv/ui/worldscreen/bottombar/BattleTable.kt +++ b/core/src/com/unciv/ui/worldscreen/bottombar/BattleTable.kt @@ -7,7 +7,6 @@ import com.badlogic.gdx.scenes.scene2d.actions.RepeatAction import com.badlogic.gdx.scenes.scene2d.ui.Image import com.badlogic.gdx.scenes.scene2d.ui.Label import com.badlogic.gdx.scenes.scene2d.ui.Table -import com.badlogic.gdx.scenes.scene2d.ui.TextButton import com.unciv.UncivGame import com.unciv.logic.automation.BattleHelper import com.unciv.logic.automation.UnitAutomation @@ -122,7 +121,7 @@ class BattleTable(val worldScreen: WorldScreen): Table() { add("{Strength}: ".tr()+defender.getDefendingStrength()).row() val attackerModifiers = - BattleDamage.getAttackModifiers(attacker,defender).map { + BattleDamage.getAttackModifiers(attacker,null,defender).map { val description = if(it.key.startsWith("vs ")) ("vs ["+it.key.replace("vs ","")+"]").tr() else it.key.tr() val percentage = (if(it.value>0)"+" else "")+(it.value*100).toInt()+"%" "$description: $percentage" @@ -142,8 +141,8 @@ class BattleTable(val worldScreen: WorldScreen): Table() { row().pad(2f) } - var damageToDefender = BattleDamage.calculateDamageToDefender(attacker,defender) - var damageToAttacker = BattleDamage.calculateDamageToAttacker(attacker,defender) + var damageToDefender = BattleDamage.calculateDamageToDefender(attacker,null,defender) + var damageToAttacker = BattleDamage.calculateDamageToAttacker(attacker,null,defender) if (damageToAttacker>attacker.getHealth() && damageToDefender>defender.getHealth()) // when damage exceeds health, we don't want to show negative health numbers