mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-22 19:08:48 -04:00
Damage calculations are now according to extrapolated Civ V rules
This commit is contained in:
parent
a230676325
commit
9625a12ba2
@ -21,7 +21,7 @@ android {
|
|||||||
applicationId "com.unciv.game"
|
applicationId "com.unciv.game"
|
||||||
minSdkVersion 14
|
minSdkVersion 14
|
||||||
targetSdkVersion 26
|
targetSdkVersion 26
|
||||||
versionCode 48
|
versionCode 49
|
||||||
versionName "2.1.0"
|
versionName "2.1.0"
|
||||||
}
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
|
@ -7,24 +7,28 @@ import com.unciv.logic.map.UnitType
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.HashMap
|
import kotlin.collections.HashMap
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Damage calculations according to civ v wiki and https://steamcommunity.com/sharedfiles/filedetails/?id=170194443
|
||||||
|
*/
|
||||||
class Battle(val gameInfo:GameInfo) {
|
class Battle(val gameInfo:GameInfo) {
|
||||||
|
|
||||||
|
|
||||||
fun getGeneralModifiers(combatant:ICombatant,enemy:ICombatant): HashMap<String, Float> {
|
|
||||||
val modifiers = HashMap<String,Float>()
|
fun getGeneralModifiers(combatant: ICombatant, enemy: ICombatant): HashMap<String, Float> {
|
||||||
if(combatant is MapUnitCombatant){
|
val modifiers = HashMap<String, Float>()
|
||||||
|
if (combatant is MapUnitCombatant) {
|
||||||
val uniques = combatant.unit.getBaseUnit().uniques
|
val uniques = combatant.unit.getBaseUnit().uniques
|
||||||
if(uniques!=null) {
|
if (uniques != null) {
|
||||||
// This beut allows us to have generic unit uniques: "Bonus vs City 75%", "Penatly vs Mounted 25%" etc.
|
// This beut allows us to have generic unit uniques: "Bonus vs City 75%", "Penatly vs Mounted 25%" etc.
|
||||||
for (unique in uniques){
|
for (unique in uniques) {
|
||||||
val regexResult = Regex("""(Bonus|Penalty) vs (\S*) (\d*)%""").matchEntire(unique)
|
val regexResult = Regex("""(Bonus|Penalty) vs (\S*) (\d*)%""").matchEntire(unique)
|
||||||
if(regexResult==null) continue
|
if (regexResult == null) continue
|
||||||
val vsType = UnitType.valueOf(regexResult.groups[2]!!.value)
|
val vsType = UnitType.valueOf(regexResult.groups[2]!!.value)
|
||||||
val modificationAmount = regexResult.groups[3]!!.value.toFloat()/100 // if it says 15%, that's 0.15f in modification
|
val modificationAmount = regexResult.groups[3]!!.value.toFloat() / 100 // if it says 15%, that's 0.15f in modification
|
||||||
if(enemy.getUnitType() == vsType){
|
if (enemy.getUnitType() == vsType) {
|
||||||
if(regexResult.groups[1]!!.value=="Bonus")
|
if (regexResult.groups[1]!!.value == "Bonus")
|
||||||
modifiers.put("Bonus vs $vsType",modificationAmount)
|
modifiers.put("Bonus vs $vsType", modificationAmount)
|
||||||
else modifiers.put("Penalty vs $vsType",-modificationAmount)
|
else modifiers.put("Penalty vs $vsType", -modificationAmount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -33,35 +37,41 @@ class Battle(val gameInfo:GameInfo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getAttackModifiers(attacker: ICombatant, defender: ICombatant): HashMap<String, Float> {
|
fun getAttackModifiers(attacker: ICombatant, defender: ICombatant): HashMap<String, Float> {
|
||||||
val modifiers = getGeneralModifiers(attacker,defender)
|
val modifiers = getGeneralModifiers(attacker, defender)
|
||||||
if(attacker.isMelee()) {
|
if (attacker.isMelee()) {
|
||||||
val numberOfAttackersSurroundingDefender = defender.getTile().neighbors.count {
|
val numberOfAttackersSurroundingDefender = defender.getTile().neighbors.count {
|
||||||
it.unit != null
|
it.unit != null
|
||||||
&& it.unit!!.owner == attacker.getCivilization().civName
|
&& it.unit!!.owner == attacker.getCivilization().civName
|
||||||
&& MapUnitCombatant(it.unit!!).isMelee()
|
&& MapUnitCombatant(it.unit!!).isMelee()
|
||||||
}
|
}
|
||||||
if(numberOfAttackersSurroundingDefender >1) modifiers["Flanking"] = 0.15f
|
if (numberOfAttackersSurroundingDefender > 1) modifiers["Flanking"] = 0.15f
|
||||||
}
|
}
|
||||||
|
|
||||||
return modifiers
|
return modifiers
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getDefenceModifiers(attacker: ICombatant, defender: ICombatant): HashMap<String, Float> {
|
fun getDefenceModifiers(attacker: ICombatant, defender: ICombatant): HashMap<String, Float> {
|
||||||
val modifiers = getGeneralModifiers(defender,attacker)
|
val modifiers = getGeneralModifiers(defender, attacker)
|
||||||
if(!(defender is MapUnitCombatant && defender.unit.getBaseUnit().hasUnique("No defensive terrain bonus"))){
|
if (!(defender is MapUnitCombatant && defender.unit.getBaseUnit().hasUnique("No defensive terrain bonus"))) {
|
||||||
val tileDefenceBonus = defender.getTile().getDefensiveBonus()
|
val tileDefenceBonus = defender.getTile().getDefensiveBonus()
|
||||||
if (tileDefenceBonus > 0) modifiers["Terrain"] = tileDefenceBonus
|
if (tileDefenceBonus > 0) modifiers["Terrain"] = tileDefenceBonus
|
||||||
}
|
}
|
||||||
return modifiers
|
return modifiers
|
||||||
}
|
}
|
||||||
|
|
||||||
fun modifiersToMultiplicationBonus(modifiers:HashMap<String,Float> ):Float{
|
fun modifiersToMultiplicationBonus(modifiers: HashMap<String, Float>): Float {
|
||||||
// modifiers are like 0.1 for a 10% bonus, -0.1 for a 10% loss
|
// modifiers are like 0.1 for a 10% bonus, -0.1 for a 10% loss
|
||||||
var modifier = 1f
|
var modifier = 1f
|
||||||
for(m in modifiers.values) modifier *= (1+m)
|
for (m in modifiers.values) modifier *= (1 + m)
|
||||||
return modifier
|
return modifier
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getHealthDependantDamageRatio(combatant: ICombatant): Float {
|
||||||
|
if (combatant.getUnitType() == UnitType.City) return 1f;
|
||||||
|
return 1 / 2f + combatant.getHealth() / 200f // Each point of health reduces damage dealt by 0.5%
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Includes attack modifiers
|
* Includes attack modifiers
|
||||||
*/
|
*/
|
||||||
@ -81,11 +91,13 @@ class Battle(val gameInfo:GameInfo) {
|
|||||||
|
|
||||||
fun calculateDamageToAttacker(attacker: ICombatant, defender: ICombatant): Int {
|
fun calculateDamageToAttacker(attacker: ICombatant, defender: ICombatant): Int {
|
||||||
if(attacker.isRanged()) return 0
|
if(attacker.isRanged()) return 0
|
||||||
return (getDefendingStrength(attacker,defender) * 50 / getAttackingStrength(attacker,defender)).toInt()
|
val ratio = getDefendingStrength(attacker,defender) / getAttackingStrength(attacker,defender)
|
||||||
|
return (ratio * 30 * getHealthDependantDamageRatio(defender)).toInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun calculateDamageToDefender(attacker: ICombatant, defender: ICombatant): Int {
|
fun calculateDamageToDefender(attacker: ICombatant, defender: ICombatant): Int {
|
||||||
return (getAttackingStrength(attacker, defender)*50/ getDefendingStrength(attacker,defender)).toInt()
|
val ratio = getAttackingStrength(attacker,defender) / getDefendingStrength(attacker,defender)
|
||||||
|
return (ratio * 30 * getHealthDependantDamageRatio(attacker)).toInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun attack(attacker: ICombatant, defender: ICombatant) {
|
fun attack(attacker: ICombatant, defender: ICombatant) {
|
||||||
|
@ -39,6 +39,7 @@ class CivStatsTable(val screen: WorldScreen) : Table() {
|
|||||||
resourceLabels.put(resource.name, resourceLabel)
|
resourceLabels.put(resource.name, resourceLabel)
|
||||||
resourceTable.add(resourceLabel)
|
resourceTable.add(resourceLabel)
|
||||||
}
|
}
|
||||||
|
resourceTable.pack()
|
||||||
add(resourceTable).row()
|
add(resourceTable).row()
|
||||||
|
|
||||||
|
|
||||||
@ -50,11 +51,12 @@ class CivStatsTable(val screen: WorldScreen) : Table() {
|
|||||||
statsTable.add(scienceLabel.apply { setAlignment(Align.center) })
|
statsTable.add(scienceLabel.apply { setAlignment(Align.center) })
|
||||||
statsTable.add(happinessLabel.apply { setAlignment(Align.center) })
|
statsTable.add(happinessLabel.apply { setAlignment(Align.center) })
|
||||||
statsTable.add(cultureLabel.apply { setAlignment(Align.center) })
|
statsTable.add(cultureLabel.apply { setAlignment(Align.center) })
|
||||||
add(statsTable)
|
|
||||||
|
|
||||||
|
statsTable.pack()
|
||||||
|
statsTable.width = screen.stage.width - 20
|
||||||
|
add(statsTable)
|
||||||
pack()
|
pack()
|
||||||
width = screen.stage.width - 20
|
width = screen.stage.width - 20
|
||||||
statsTable.width = width
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun getMenuButton(): TextButton {
|
internal fun getMenuButton(): TextButton {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user