Battle calculation takes into account the tile that the unit will attack from

This commit is contained in:
Yair Morgenstern 2020-06-01 01:51:11 +03:00
parent 9496c4523e
commit 4b649825cd
4 changed files with 18 additions and 17 deletions

View file

@ -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 }

View file

@ -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

View file

@ -110,12 +110,12 @@ object BattleDamage {
return modifiers
}
fun getAttackModifiers(attacker: ICombatant, defender: ICombatant): HashMap<String, Float> {
fun getAttackModifiers(attacker: ICombatant, tileToAttackFrom:TileInfo?, defender: ICombatant): HashMap<String, Float> {
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()
}

View file

@ -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