Added battle modifiers, specifically - terrain defence bonuses

This commit is contained in:
Yair Morgenstern 2018-04-04 23:10:16 +03:00
parent 4e36aa0d5a
commit 7ff9f17943
6 changed files with 84 additions and 19 deletions

View File

@ -40,6 +40,7 @@
type:"BaseTerrain", type:"BaseTerrain",
production:2, production:2,
movementCost:2, movementCost:2,
defenceBonus: 0.25,
RGB: [74,81,40] RGB: [74,81,40]
}, },
@ -52,6 +53,7 @@
movementCost:2, movementCost:2,
overrideStats:true, overrideStats:true,
unbuildable:true, unbuildable:true,
defenceBonus: 0.25,
occursOn:["Tundra","Plains","Grassland"] occursOn:["Tundra","Plains","Grassland"]
}, },
{ {
@ -61,6 +63,7 @@
movementCost:2, movementCost:2,
overrideStats:true, overrideStats:true,
unbuildable:true, unbuildable:true,
defenceBonus: 0.25,
occursOn:["Plains","Grassland"] occursOn:["Plains","Grassland"]
}, },
{ {
@ -69,6 +72,7 @@
food:-1, food:-1,
movementCost:3, movementCost:3,
unbuildable:true, unbuildable:true,
defenceBonus: -0.1,
occursOn:["Grassland"] occursOn:["Grassland"]
}, },
{ {
@ -77,6 +81,7 @@
food:3, food:3,
movementCost:1, movementCost:1,
unbuildable:true, unbuildable:true,
defenceBonus: -0.1,
occursOn:["Desert"] occursOn:["Desert"]
}, },
{ {
@ -84,6 +89,7 @@
type:"TerrainFeature", type:"TerrainFeature",
food:2, food:2,
movementCost:1, movementCost:1,
defenceBonus: -0.1,
occursOn:["Desert"] occursOn:["Desert"]
} }
] ]

View File

@ -2,15 +2,51 @@ package com.unciv.logic.battle
import com.unciv.logic.GameInfo import com.unciv.logic.GameInfo
import java.util.* import java.util.*
import kotlin.collections.HashMap
class Battle(val gameInfo:GameInfo) { class Battle(val gameInfo:GameInfo) {
fun getAttackModifiers(attacker: ICombatant, defender: ICombatant): HashMap<String, Float> {
return HashMap<String,Float>()
}
fun getDefenceModifiers(attacker: ICombatant, defender: ICombatant): HashMap<String, Float> {
val modifiers = HashMap<String,Float>()
val tileDefenceBonus = defender.getTile().getDefensiveBonus()
if(tileDefenceBonus > 0) modifiers.put("Terrain",tileDefenceBonus)
return modifiers
}
fun modifiersToMultiplicationBonus(modifiers:HashMap<String,Float> ):Float{
// modifiers are like 0.1 for a 10% bonus, -0.1 for a 10% loss
var modifier = 1f
for(m in modifiers.values) modifier *= (1+m)
return modifier
}
/**
* Includes attack modifiers
*/
fun getAttackingStrength(attacker: ICombatant, defender: ICombatant): Float {
val attackModifier = modifiersToMultiplicationBonus(getAttackModifiers(attacker,defender))
return attacker.getAttackingStrength(defender) * attackModifier
}
/**
* Includes defence modifiers
*/
fun getDefendingStrength(attacker: ICombatant, defender: ICombatant): Float {
val defenceModifier = modifiersToMultiplicationBonus(getDefenceModifiers(attacker,defender))
return defender.getDefendingStrength(attacker) * defenceModifier
}
fun calculateDamageToAttacker(attacker: ICombatant, defender: ICombatant): Int { fun calculateDamageToAttacker(attacker: ICombatant, defender: ICombatant): Int {
return defender.getDefendingStrength(attacker) * 50 / attacker.getAttackingStrength(defender) return (getDefendingStrength(attacker,defender) * 50 / getAttackingStrength(attacker,defender)).toInt()
} }
fun calculateDamageToDefender(attacker: ICombatant, defender: ICombatant): Int { fun calculateDamageToDefender(attacker: ICombatant, defender: ICombatant): Int {
return attacker.getAttackingStrength(defender)*50/defender.getDefendingStrength(attacker) return (getAttackingStrength(attacker, defender)*50/ getDefendingStrength(attacker,defender)).toInt()
} }
fun attack(attacker: ICombatant, defender: ICombatant) { fun attack(attacker: ICombatant, defender: ICombatant) {

View File

@ -173,4 +173,10 @@ class TileInfo {
return tileMap.getViewableTiles(this.position,distance) return tileMap.getViewableTiles(this.position,distance)
} }
fun getDefensiveBonus(): Float {
var bonus = getBaseTerrain().defenceBonus
if(terrainFeature!=null) bonus += getTerrainFeature()!!.defenceBonus
return bonus
}
} }

View File

@ -32,6 +32,7 @@ class Terrain : NamedStats(), ICivilopedia {
var movementCost = 1 var movementCost = 1
var defenceBonus:Float = 0f
} }

View File

@ -60,9 +60,9 @@ class WorldTileGroup(tileInfo: TileInfo) : TileGroup(tileInfo) {
unitImage = null unitImage = null
} }
if (tileInfo.unit != null) { if (tileInfo.unit != null && color.a==1f) { // Tile is visible
val unit = tileInfo.unit!! val unit = tileInfo.unit!!
unitImage = getUnitImage(unit.name!!, unit.civInfo.getCivilization().getColor()) unitImage = getUnitImage(unit.name, unit.civInfo.getCivilization().getColor())
addActor(unitImage!!) addActor(unitImage!!)
unitImage!!.setSize(20f, 20f) unitImage!!.setSize(20f, 20f)
unitImage!!.setPosition(width/2 - unitImage!!.width/2, unitImage!!.setPosition(width/2 - unitImage!!.width/2,

View File

@ -8,10 +8,14 @@ import com.unciv.logic.map.UnitType
import com.unciv.ui.cityscreen.addClickListener import com.unciv.ui.cityscreen.addClickListener
import com.unciv.ui.utils.CameraStageBaseScreen import com.unciv.ui.utils.CameraStageBaseScreen
import com.unciv.ui.utils.disable import com.unciv.ui.utils.disable
import kotlin.math.max
class BattleTable(val worldScreen: WorldScreen): Table() { class BattleTable(val worldScreen: WorldScreen): Table() {
private val battle = Battle(worldScreen.civInfo.gameInfo) private val battle = Battle(worldScreen.civInfo.gameInfo)
init{
skin = CameraStageBaseScreen.skin
}
fun update(){ fun update(){
if(worldScreen.unitTable.selectedUnit==null if(worldScreen.unitTable.selectedUnit==null
@ -38,17 +42,34 @@ class BattleTable(val worldScreen: WorldScreen): Table() {
fun simulateBattle(attacker: MapUnitCombatant, defender: ICombatant){ fun simulateBattle(attacker: MapUnitCombatant, defender: ICombatant){
clear() clear()
val attackerLabel = Label(attacker.getName(), CameraStageBaseScreen.skin) row().pad(5f)
val attackerLabel = Label(attacker.getName(), skin)
attackerLabel.style= Label.LabelStyle(attackerLabel.style) attackerLabel.style= Label.LabelStyle(attackerLabel.style)
attackerLabel.style.fontColor=attacker.getCivilization().getCivilization().getColor() attackerLabel.style.fontColor=attacker.getCivilization().getCivilization().getColor()
add(attackerLabel) add(attackerLabel)
val defenderLabel = Label(attacker.getName(), CameraStageBaseScreen.skin) val defenderLabel = Label(attacker.getName(), skin)
defenderLabel.style= Label.LabelStyle(defenderLabel.style) defenderLabel.style= Label.LabelStyle(defenderLabel.style)
defenderLabel.style.fontColor=defender.getCivilization().getCivilization().getColor() defenderLabel.style.fontColor=defender.getCivilization().getCivilization().getColor()
add(defenderLabel) add(defenderLabel)
row() row().pad(5f)
add("Strength: "+attacker.getAttackingStrength(defender)/100f)
add("Strength: "+defender.getDefendingStrength(attacker)/100f)
row().pad(5f)
val attackerModifiers = battle.getAttackModifiers(attacker,defender) .map { it.key+": "+(if(it.value>0)"+" else "")+(it.value*100).toInt()+"%" }
val defenderModifiers = battle.getDefenceModifiers(attacker, defender).map { it.key+": "+(if(it.value>0)"+" else "")+(it.value*100).toInt()+"%" }
for(i in 0..max(attackerModifiers.size,defenderModifiers.size)){
if (attackerModifiers.size > i) add(attackerModifiers[i]) else add()
if (defenderModifiers.size > i) add(defenderModifiers[i]) else add()
row().pad(5f)
}
add((battle.getAttackingStrength(attacker,defender)/100f).toString())
add((battle.getDefendingStrength(attacker,defender)/100f).toString())
row().pad(5f)
var damageToDefender = battle.calculateDamageToDefender(attacker,defender) var damageToDefender = battle.calculateDamageToDefender(attacker,defender)
var damageToAttacker = battle.calculateDamageToAttacker(attacker,defender) var damageToAttacker = battle.calculateDamageToAttacker(attacker,defender)
@ -73,20 +94,16 @@ class BattleTable(val worldScreen: WorldScreen): Table() {
else if (damageToDefender>defender.getHealth()) damageToDefender=defender.getHealth() else if (damageToDefender>defender.getHealth()) damageToDefender=defender.getHealth()
val attackLabel = Label(attacker.getHealth().toString() + " -> " add("Health: "+attacker.getHealth().toString() + " -> "
+ (attacker.getHealth()- damageToAttacker), CameraStageBaseScreen.skin) + (attacker.getHealth()- damageToAttacker))
add(attackLabel)
val defendLabel = Label(defender.getHealth().toString() + " -> " add("Health: "+defender.getHealth().toString() + " -> "
+ (defender.getHealth()- damageToDefender), + (defender.getHealth()- damageToDefender))
CameraStageBaseScreen.skin)
add(defendLabel)
row() row().pad(5f)
val attackButton = TextButton("Attack",CameraStageBaseScreen.skin) val attackButton = TextButton("Attack", skin)
attackButton.addClickListener { attackButton.addClickListener {
//todo this should be in battletabl and not n the logic! It's to make things easier for the player!
if(attacker.getCombatantType() == CombatantType.Melee) if(attacker.getCombatantType() == CombatantType.Melee)
attacker.unit.headTowards(defender.getTile().position) attacker.unit.headTowards(defender.getTile().position)
battle.attack(attacker,defender) battle.attack(attacker,defender)
@ -98,8 +115,7 @@ class BattleTable(val worldScreen: WorldScreen): Table() {
add(attackButton).colspan(2) add(attackButton).colspan(2)
pack() pack()
setPosition(worldScreen.stage.width/2-width/2, setPosition(worldScreen.stage.width/2-width/2, 5f)
5f)
} }
} }