modify battle damage calculation method about city attack. (#1141)

This commit is contained in:
lishaoxia1985 2019-10-06 02:10:10 +08:00 committed by Yair Morgenstern
parent 1aa9640d1c
commit 09420786bc
13 changed files with 54 additions and 34 deletions

View file

@ -117,7 +117,7 @@
declaringWar:"小小蝼蚁般的可悲文明,去死吧。", declaringWar:"小小蝼蚁般的可悲文明,去死吧。",
attacked:"可怜的蠢蛋。你在毁灭你自己和你可悲的文明。", attacked:"可怜的蠢蛋。你在毁灭你自己和你可悲的文明。",
defeated:"你什么也没得到。就算把我打倒,我的灵魂也会将你永堕深渊。", defeated:"你什么也没得到。就算把我打倒,我的灵魂也会将你永堕深渊。",
introduction:" 向你致意。我是拉美西斯神,我是所有其他文明的父母之邦——埃及的化身。", introduction:"向你致意。我是拉美西斯神,我是所有其他文明的父母之邦——埃及的化身。",
neutralHello:"真是美好的一天。", neutralHello:"真是美好的一天。",
neutralLetsHearIt:["继续。","请讲。","我正倾耳听之。"], neutralLetsHearIt:["继续。","请讲。","我正倾耳听之。"],

View file

@ -153,6 +153,7 @@
} }
"Free Technology":{ "Free Technology":{
Simplified_Chinese:"获得1项免费科技"
} }
"'Libraries are as the shrine where all the relics of the ancient saints, full of true virtue, and all that without delusion or imposture are preserved and reposed.' - Sir Francis Bacon":{ "'Libraries are as the shrine where all the relics of the ancient saints, full of true virtue, and all that without delusion or imposture are preserved and reposed.' - Sir Francis Bacon":{
@ -346,7 +347,7 @@
German:"Kostenloser Solzialgrundsatz" German:"Kostenloser Solzialgrundsatz"
Dutch:"Gratis sociaalbeleid" Dutch:"Gratis sociaalbeleid"
Spanish:"Política social gratis" Spanish:"Política social gratis"
Simplified_Chinese:"免费推行1项社会政策" Simplified_Chinese:"免费推行1项社会政策"
Portuguese:"Politica social gratis" Portuguese:"Politica social gratis"
Polish:"Darmowy ustrój społeczny" Polish:"Darmowy ustrój społeczny"
} }

View file

@ -588,7 +588,7 @@
French:"Nos articles" French:"Nos articles"
Romanian:"Articolele noastre" Romanian:"Articolele noastre"
Spanish:"Nuestros ítems" Spanish:"Nuestros ítems"
Simplified_Chinese:"我们的物品" Simplified_Chinese:"我们的交易项"
Portuguese:"Nossos itens/recursos" Portuguese:"Nossos itens/recursos"
German:"Unsere Gegenstände" German:"Unsere Gegenstände"
} }
@ -621,7 +621,7 @@
French:"Les articles de [otherCiv]" French:"Les articles de [otherCiv]"
Romanian:"Articolele de la [otherCiv]" Romanian:"Articolele de la [otherCiv]"
Spanish:"Ítems de [otherCiv]" Spanish:"Ítems de [otherCiv]"
Simplified_Chinese:"[otherCiv]的物品" Simplified_Chinese:"[otherCiv]的交易项"
Portuguese:"Itens da(o/e) [otherCiv]" Portuguese:"Itens da(o/e) [otherCiv]"
German:"[otherCiv]s Gegenstände" German:"[otherCiv]s Gegenstände"
} }
@ -684,7 +684,7 @@
French:"Il n'y a rien a échangé" //if it's in case of empty trade it's accurate French:"Il n'y a rien a échangé" //if it's in case of empty trade it's accurate
Romanian:"Nu e nimic pe masă" Romanian:"Nu e nimic pe masă"
Spanish:"¿Estas de broma?" Spanish:"¿Estas de broma?"
Simplified_Chinese:"表格上没有任何物品" Simplified_Chinese:"未选中任何交易项"
Portuguese:"Não ha nada á mesa" Portuguese:"Não ha nada á mesa"
German:"Der Verhandlungstisch ist leer" German:"Der Verhandlungstisch ist leer"
} }
@ -764,6 +764,7 @@
"Declare war on [nation]":{ "Declare war on [nation]":{
Italian:"Dichiara guerra a [nation]" Italian:"Dichiara guerra a [nation]"
Simplified_Chinese:"宣战[nation]"
} }
"Luxury resources":{ "Luxury resources":{

View file

@ -758,7 +758,7 @@
German:"Wartungskosten" German:"Wartungskosten"
Dutch:"Onderhouskosten" Dutch:"Onderhouskosten"
Spanish:"Coste de mantenimiento" Spanish:"Coste de mantenimiento"
Simplified_Chinese:"维护费" Simplified_Chinese:"建筑维护费"
Portuguese:"Custo de manutenção" Portuguese:"Custo de manutenção"
Japanese:"メンテナンス費用" Japanese:"メンテナンス費用"
} }
@ -1554,7 +1554,7 @@
French:"Entretien" French:"Entretien"
Romanian:"Întreținere" Romanian:"Întreținere"
Spanish:"Mantenimiento" Spanish:"Mantenimiento"
Simplified_Chinese:"维护费" Simplified_Chinese:"建筑维护费"
Portuguese:"Manutenção" Portuguese:"Manutenção"
German:"Wartung" German:"Wartung"
} }
@ -1565,7 +1565,7 @@
French:"Entretien des transports" French:"Entretien des transports"
Romanian:"Întreținere trasporturi" Romanian:"Întreținere trasporturi"
Spanish:"Mantenimiento de transporte" Spanish:"Mantenimiento de transporte"
Simplified_Chinese:"道(铁)路维护" Simplified_Chinese:"道(铁)路维护"
Portuguese:"Manutenção de transporte" Portuguese:"Manutenção de transporte"
German:"Unterhalt für Transport" German:"Unterhalt für Transport"
} }
@ -1576,7 +1576,7 @@
French:"Entretien des unités" French:"Entretien des unités"
Romanian:"Întreținere unități" Romanian:"Întreținere unități"
Spanish:"Mantenimiento de unidades" Spanish:"Mantenimiento de unidades"
Simplified_Chinese:"单位维护" Simplified_Chinese:"单位维护"
Portuguese:"Manutenção de unidades" Portuguese:"Manutenção de unidades"
German:"Unterhalt für Einheiten" German:"Unterhalt für Einheiten"
} }
@ -1679,7 +1679,7 @@
German:"Um zu gewinnen vervollständigen\nSie 4 Grundsatzzweige!" German:"Um zu gewinnen vervollständigen\nSie 4 Grundsatzzweige!"
French:"Completer 4 Doctrines pour gagner!" French:"Completer 4 Doctrines pour gagner!"
Russian:"Завершите 4 ветви общественных институтов\n чтобы победить!" Russian:"Завершите 4 ветви общественных институтов\n чтобы победить!"
Simplified_Chinese:"完全推行4项社会政策\n胜利" Simplified_Chinese:"完成4个社会政策分支\n胜利"
Portuguese:"Complete 4 árvores de politicas para ganhar" Portuguese:"Complete 4 árvores de politicas para ganhar"
} }
@ -1783,14 +1783,14 @@
"Spaceship parts remaining":{ "Spaceship parts remaining":{
Italian:"Parti dell'astronave rimanenti" Italian:"Parti dell'astronave rimanenti"
French:"Parties de Vaisseau spatial manquantes" French:"Parties de Vaisseau spatial manquantes"
Simplified_Chinese:"未完成建造的飞船组件数量" Simplified_Chinese:"未完成建造的飞船组件"
Russian:"Осталось частей КК" Russian:"Осталось частей КК"
} }
"Branches completed":{ "Branches completed":{
Italian:"Rami completati" Italian:"Rami completati"
French:"Branches complêtées" French:"Branches complêtées"
Simplified_Chinese:"已完全推行的社会政策数量" Simplified_Chinese:"已完成的社会政策分支"
Russian:"Ветвей завершено" Russian:"Ветвей завершено"
} }

View file

@ -630,7 +630,7 @@
Russian:"+1 культура за каждый монумент, храм и монастырь. Даёт бесплатный общественный институт" Russian:"+1 культура за каждый монумент, храм и монастырь. Даёт бесплатный общественный институт"
Romanian:"+1 cultură pentru fiecare monument, templu sau mănăstire. Obține o politică gratuită" Romanian:"+1 cultură pentru fiecare monument, templu sau mănăstire. Obține o politică gratuită"
Spanish:"+1 cultura por cada monumento, templo y monasterio. Ganas una política gratis" Spanish:"+1 cultura por cada monumento, templo y monasterio. Ganas una política gratis"
Simplified_Chinese:"每座纪念碑、神庙和修道院+1文化获得1次免费推行社会政策的机会" Simplified_Chinese:"每座纪念碑、神庙和修道院+1文化免费推行1项社会政策"
Portuguese:"+1 cultura por cada monumento, templo e monastério. Ganha uma apolítica grátis" Portuguese:"+1 cultura por cada monumento, templo e monastério. Ganha uma apolítica grátis"
German:"+1 Kultur für jedes Monument, Kloster und Tempel; Ein kostenloser Grundsatz." German:"+1 Kultur für jedes Monument, Kloster und Tempel; Ein kostenloser Grundsatz."
French:"+1 culture pour chaque monument, temple et monastère, donne une doctrine gratuite" French:"+1 culture pour chaque monument, temple et monastère, donne une doctrine gratuite"
@ -849,7 +849,7 @@
Russian:"+1 к счастью от каждого редкого ресурса" Russian:"+1 к счастью от каждого редкого ресурса"
Romanian:"+1 fericire din fiecare resursă de lux" Romanian:"+1 fericire din fiecare resursă de lux"
Spanish:"+1 felicidad por cada recurso de lujo" Spanish:"+1 felicidad por cada recurso de lujo"
Simplified_Chinese:"每个奢侈资源+1快乐" Simplified_Chinese:"每种奢侈资源额外+1快乐"
Portuguese:"+1 Felicidade por cade recurso de luxo" Portuguese:"+1 Felicidade por cade recurso de luxo"
German:"+1 Zufriedenheit für jede Luxusresource" German:"+1 Zufriedenheit für jede Luxusresource"
French:"+1 Bonheur pour chaque ressource de luxe" French:"+1 Bonheur pour chaque ressource de luxe"
@ -1005,7 +1005,7 @@
Russian:"Даёт 2 бесплатные технологии" Russian:"Даёт 2 бесплатные технологии"
Romanian:"Obține 2 tehnologii gratuite" Romanian:"Obține 2 tehnologii gratuite"
Spanish:"Ganas 2 tecnologías gratis" Spanish:"Ganas 2 tecnologías gratis"
Simplified_Chinese:"给予2项免费科技" Simplified_Chinese:"获得2项免费科技"
Portuguese:"Ganhe 2 tecnologias grátis" Portuguese:"Ganhe 2 tecnologias grátis"
German:"2 kostenlose Technologien" German:"2 kostenlose Technologien"
French:"2 technologies gratuites" French:"2 technologies gratuites"

View file

@ -233,7 +233,7 @@
], ],
[ [
"在Unciv游戏中有三种赢得胜利的方式。分别是", "在Unciv游戏中有三种赢得胜利的方式。分别是",
"文化胜利---完全推行4项社会政策", "文化胜利---完成4个社会政策分支",
"征服胜利---通过消灭其他文明成为世界上唯一的存在;", "征服胜利---通过消灭其他文明成为世界上唯一的存在;",
"科技胜利---成为第一个建造太空飞船飞向遥远的半人马阿尔法星的文明。" "科技胜利---成为第一个建造太空飞船飞向遥远的半人马阿尔法星的文明。"
], ],
@ -282,6 +282,21 @@
] ]
] ]
ConqueredEnemyCity: [
[
"恭喜!您已经攻占了一座敌人的城市!",
"您可以选择摧毁、傀儡甚至吞并它。",
"“摧毁城市”可以令城市人口每回合-1人口为0时城市将完全被摧毁。"
],
[
"“傀儡城市”意味着您将无法控制该城市的产能,",
"好处是该城市将不会额外增加您研发科技和推行社会政策时的花费同时该城市人口产生的不满是正常值的1.5倍。",
"“吞并城市”将会给予您该城市的绝对控制权但该城市人口产生的不满将是正常值的2倍。",
"在城市内建造“法庭”可以使人口产生的不满降低到正常值。",
"可以在任何时候吞并已傀儡的城市,但已吞并的城市无法再变为傀儡状态。选择前请考虑清楚!"
]
]
BarbarianEncountered: [ BarbarianEncountered: [
[ [
"您遇到蛮族了!", "您遇到蛮族了!",
@ -303,7 +318,7 @@
"NO!看起来游戏好像出现了灾难性的Bug!", "NO!看起来游戏好像出现了灾难性的Bug!",
"这绝对不应该发生!", "这绝对不应该发生!",
"请将游戏存档信息发送给我,方法如下:", "请将游戏存档信息发送给我,方法如下:",
"依次点击“菜单->储存游戏->复制到剪贴板”将剪贴板的内容通过email发送给我。", "依次点击“菜单->储存游戏->复制当前游戏数据到剪贴板”将剪贴板的内容通过email发送给我。",
"我的email地址yairm210@hotmail.com。我会尽快处理!" "我的email地址yairm210@hotmail.com。我会尽快处理!"
] ]
] ]

View file

@ -21,7 +21,7 @@ buildscript {
} }
dependencies { dependencies {
classpath 'de.richsource.gradle.plugins:gwt-gradle-plugin:0.6' classpath 'de.richsource.gradle.plugins:gwt-gradle-plugin:0.6'
classpath 'com.android.tools.build:gradle:3.5.0' classpath 'com.android.tools.build:gradle:3.5.1'
classpath 'com.mobidevelop.robovm:robovm-gradle-plugin:2.3.1' classpath 'com.mobidevelop.robovm:robovm-gradle-plugin:2.3.1'
} }
} }

View file

@ -9,6 +9,7 @@ import kotlin.collections.HashMap
import kotlin.collections.set import kotlin.collections.set
import kotlin.math.max import kotlin.math.max
import kotlin.math.pow import kotlin.math.pow
import kotlin.math.roundToInt
class BattleDamageModifier(val vs:String,val modificationAmount:Float){ class BattleDamageModifier(val vs:String,val modificationAmount:Float){
fun getText(): String = "vs $vs" fun getText(): String = "vs $vs"
@ -199,8 +200,8 @@ class BattleDamage{
} }
private fun getHealthDependantDamageRatio(combatant: ICombatant): Float { private fun getHealthDependantDamageRatio(combatant: ICombatant): Float {
return if (combatant.getUnitType() == UnitType.City) 0.75f return if(combatant.getUnitType() == UnitType.City
else if(combatant.getCivInfo().nation.unique == "Units fight as though they were at full strength even when damaged" && !combatant.getUnitType().isAirUnit()) || combatant.getCivInfo().nation.unique == "Units fight as though they were at full strength even when damaged" && !combatant.getUnitType().isAirUnit())
1f 1f
else 1 - (100 - combatant.getHealth()) / 300f// Each 3 points of health reduces damage dealt by 1% like original game else 1 - (100 - combatant.getHealth()) / 300f// Each 3 points of health reduces damage dealt by 1% like original game
} }
@ -228,12 +229,12 @@ class BattleDamage{
if(attacker.isRanged()) return 0 if(attacker.isRanged()) return 0
if(defender.getUnitType().isCivilian()) return 0 if(defender.getUnitType().isCivilian()) return 0
val ratio = getAttackingStrength(attacker,defender) / getDefendingStrength(attacker,defender) val ratio = getAttackingStrength(attacker,defender) / getDefendingStrength(attacker,defender)
return (damageModifier(ratio, true) * getHealthDependantDamageRatio(defender)).toInt() return (damageModifier(ratio, true) * getHealthDependantDamageRatio(defender)).roundToInt()
} }
fun calculateDamageToDefender(attacker: ICombatant, defender: ICombatant): Int { fun calculateDamageToDefender(attacker: ICombatant, defender: ICombatant): Int {
val ratio = getAttackingStrength(attacker,defender) / getDefendingStrength(attacker,defender) val ratio = getAttackingStrength(attacker,defender) / getDefendingStrength(attacker,defender)
return (damageModifier(ratio,false) * getHealthDependantDamageRatio(attacker)).toInt() return (damageModifier(ratio,false) * getHealthDependantDamageRatio(attacker)).roundToInt()
} }
fun damageModifier(attackerToDefenderRatio:Float, damageToAttacker:Boolean): Float { fun damageModifier(attackerToDefenderRatio:Float, damageToAttacker:Boolean): Float {

View file

@ -6,6 +6,7 @@ import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.map.TileInfo import com.unciv.logic.map.TileInfo
import com.unciv.models.gamebasics.GameBasics import com.unciv.models.gamebasics.GameBasics
import com.unciv.models.gamebasics.unit.UnitType import com.unciv.models.gamebasics.unit.UnitType
import kotlin.math.roundToInt
class CityCombatant(val city: CityInfo) : ICombatant { class CityCombatant(val city: CityInfo) : ICombatant {
override fun getMaxHealth(): Int { override fun getMaxHealth(): Int {
@ -26,7 +27,7 @@ class CityCombatant(val city: CityInfo) : ICombatant {
} }
override fun getUnitType(): UnitType = UnitType.City override fun getUnitType(): UnitType = UnitType.City
override fun getAttackingStrength(): Int = getCityStrength()*2/5 // I remember reading this but I don't recall where override fun getAttackingStrength(): Int = (getCityStrength() * 0.75).roundToInt()
override fun getDefendingStrength(): Int{ override fun getDefendingStrength(): Int{
if(isDefeated()) return 1 if(isDefeated()) return 1
return getCityStrength() return getCityStrength()
@ -34,7 +35,7 @@ class CityCombatant(val city: CityInfo) : ICombatant {
fun getCityStrength(): Int { // Civ fanatics forum, from a modder who went through the original code fun getCityStrength(): Int { // Civ fanatics forum, from a modder who went through the original code
var strength = 8f var strength = 8f
if(city.isCapital()) strength+=2.5f if(city.isCapital()) strength+=2f
strength += (city.population.population/5) * 2 // Each 5 pop gives 2 defence strength += (city.population.population/5) * 2 // Each 5 pop gives 2 defence
val cityTile = city.getCenterTile() val cityTile = city.getCenterTile()
if(cityTile.baseTerrain== Constants.hill) strength+=5 if(cityTile.baseTerrain== Constants.hill) strength+=5
@ -50,14 +51,14 @@ class CityCombatant(val city: CityInfo) : ICombatant {
// Garrisoned unit gives up to 20% of strength to city, health-dependant // Garrisoned unit gives up to 20% of strength to city, health-dependant
if(cityTile.militaryUnit!=null) if(cityTile.militaryUnit!=null)
strength += cityTile.militaryUnit!!.baseUnit().strength * cityTile.militaryUnit!!.health/100f strength += cityTile.militaryUnit!!.baseUnit().strength * (cityTile.militaryUnit!!.health / 100f) * 0.2f
var buildingsStrength = city.cityConstructions.getBuiltBuildings().sumBy{ it.cityStrength }.toFloat() var buildingsStrength = city.cityConstructions.getBuiltBuildings().sumBy{ it.cityStrength }.toFloat()
if(getCivInfo().containsBuildingUnique("Defensive buildings in all cities are 25% more effective")) if(getCivInfo().containsBuildingUnique("Defensive buildings in all cities are 25% more effective"))
buildingsStrength*=1.25f buildingsStrength*=1.25f
strength += buildingsStrength strength += buildingsStrength
return strength.toInt() return strength.roundToInt()
} }
override fun toString(): String {return city.name} // for debug override fun toString(): String {return city.name} // for debug

View file

@ -102,7 +102,8 @@ class CivInfoStats(val civInfo: CivilizationInfo){
val statMap = HashMap<String, Float>() val statMap = HashMap<String, Float>()
statMap["Base happiness"] = civInfo.getDifficulty().baseHappiness.toFloat() statMap["Base happiness"] = civInfo.getDifficulty().baseHappiness.toFloat()
var happinessPerUniqueLuxury = 5f + civInfo.getDifficulty().extraHappinessPerLuxury // TODO - happinessPerUnique should be difficulty-dependent, 5 on Settler and Chieftian and 4 on other difficulties (should be parameter, not in code)
var happinessPerUniqueLuxury = 4f + civInfo.getDifficulty().extraHappinessPerLuxury
if (civInfo.policies.isAdopted("Protectionism")) happinessPerUniqueLuxury += 1 if (civInfo.policies.isAdopted("Protectionism")) happinessPerUniqueLuxury += 1
statMap["Luxury resources"]= civInfo.getCivResources().map { it.resource } statMap["Luxury resources"]= civInfo.getCivResources().map { it.resource }
.count { it.resourceType === ResourceType.Luxury } * happinessPerUniqueLuxury .count { it.resourceType === ResourceType.Luxury } * happinessPerUniqueLuxury
@ -135,4 +136,4 @@ class CivInfoStats(val civInfo: CivilizationInfo){
return statMap return statMap
} }
} }

View file

@ -417,7 +417,7 @@ class CivilizationInfo {
fun addGreatPerson(greatPerson: String, city:CityInfo) { fun addGreatPerson(greatPerson: String, city:CityInfo) {
placeUnitNearTile(city.location, greatPerson) placeUnitNearTile(city.location, greatPerson)
addNotification("A [$greatPerson] has been born!".tr(), city.location, Color.GOLD) addNotification("A [$greatPerson] has been born!", city.location, Color.GOLD)
} }
fun placeUnitNearTile(location: Vector2, unitName: String): MapUnit? { fun placeUnitNearTile(location: Vector2, unitName: String): MapUnit? {
@ -456,7 +456,7 @@ class CivilizationInfo {
.filter { !it.unitType.isCivilian() && it.unitType.isLandUnit() } .filter { !it.unitType.isCivilian() && it.unitType.isLandUnit() }
.random() .random()
placeUnitNearTile(city.location, militaryUnit.name) placeUnitNearTile(city.location, militaryUnit.name)
addNotification("[${otherCiv.civName}] gave us a [${militaryUnit.name}] as gift near [${city.name}]!".tr(), null, Color.GREEN) addNotification("[${otherCiv.civName}] gave us a [${militaryUnit.name}] as gift near [${city.name}]!", null, Color.GREEN)
} }
//endregion //endregion

View file

@ -139,9 +139,9 @@ class TechManager {
val currentEra = civInfo.getEra() val currentEra = civInfo.getEra()
if (previousEra < currentEra) { if (previousEra < currentEra) {
civInfo.addNotification("You have entered the [$currentEra era]!".tr(), null, Color.GOLD) civInfo.addNotification("You have entered the [$currentEra era]!", null, Color.GOLD)
GameBasics.PolicyBranches.values.filter { it.era == currentEra } GameBasics.PolicyBranches.values.filter { it.era == currentEra }
.forEach { civInfo.addNotification("[" + it.name + "] policy branch unlocked!".tr(), null, Color.PURPLE) } .forEach { civInfo.addNotification("[" + it.name + "] policy branch unlocked!", null, Color.PURPLE) }
} }
val revealedResource = GameBasics.TileResources.values.firstOrNull { techName == it.revealedBy } val revealedResource = GameBasics.TileResources.values.firstOrNull { techName == it.revealedBy }

View file

@ -185,8 +185,8 @@ class DiplomacyManager() {
trades.remove(trade) trades.remove(trade)
val otherCivTrades = otherCiv().getDiplomacyManager(civInfo).trades val otherCivTrades = otherCiv().getDiplomacyManager(civInfo).trades
otherCivTrades.removeAll{ it.equals(trade.reverse()) } otherCivTrades.removeAll{ it.equals(trade.reverse()) }
civInfo.addNotification("One of our trades with [$otherCivName] has been cut short".tr(),null, Color.GOLD) civInfo.addNotification("One of our trades with [$otherCivName] has been cut short",null, Color.GOLD)
otherCiv().addNotification("One of our trades with [${civInfo.civName}] has been cut short".tr(),null, Color.GOLD) otherCiv().addNotification("One of our trades with [${civInfo.civName}] has been cut short",null, Color.GOLD)
} }
} }
} }