From 6ff712b6251b6f43f008eb3ee44bba7a43be24a5 Mon Sep 17 00:00:00 2001 From: Yair Morgenstern Date: Mon, 24 Aug 2020 10:58:14 +0300 Subject: [PATCH] A mishmash of different fixes: Unit uniques and promotions, happiness calculation, etc. --- .../assets/jsons/Civ V - Vanilla/Buildings.json | 2 +- .../assets/jsons/Civ V - Vanilla/Policies.json | 2 +- .../jsons/Civ V - Vanilla/UnitPromotions.json | 2 +- android/assets/jsons/Civ V - Vanilla/Units.json | 4 ++-- .../jsons/translations/template.properties | 1 - core/src/com/unciv/logic/battle/Battle.kt | 12 ++++++------ core/src/com/unciv/logic/battle/BattleDamage.kt | 7 ++++++- core/src/com/unciv/logic/city/CityStats.kt | 16 ++++++---------- core/src/com/unciv/logic/map/MapUnit.kt | 12 ++++-------- 9 files changed, 27 insertions(+), 31 deletions(-) diff --git a/android/assets/jsons/Civ V - Vanilla/Buildings.json b/android/assets/jsons/Civ V - Vanilla/Buildings.json index 2cb2702b..90a313bf 100644 --- a/android/assets/jsons/Civ V - Vanilla/Buildings.json +++ b/android/assets/jsons/Civ V - Vanilla/Buildings.json @@ -786,7 +786,7 @@ "culture": 1, "isWonder": true, "greatPersonPoints": {"production": 2}, - "uniques": ["+1 Production from specialists"], + "uniques": ["[+1 Production] from every specialist"], "requiredTech": "Replaceable Parts", "quote": "'Give me your tired, your poor, your huddled masses yearning to breathe free, the wretched refuse of your teeming shore. Send these, the homeless, tempest-tossed to me, I lift my lamp beside the golden door!' - Emma Lazarus" }, diff --git a/android/assets/jsons/Civ V - Vanilla/Policies.json b/android/assets/jsons/Civ V - Vanilla/Policies.json index 9ef42637..f332c66e 100644 --- a/android/assets/jsons/Civ V - Vanilla/Policies.json +++ b/android/assets/jsons/Civ V - Vanilla/Policies.json @@ -8,7 +8,7 @@ { "name": "Aristocracy", "effect": "+15% production when constructing wonders, +1 happiness for every 10 citizens in a city", - "uniques": ["+[15]% Production when constructing [Wonders]", "+1 happiness for every 10 citizens in a city"], + "uniques": ["+[15]% Production when constructing [Wonders]", "[+1 Happiness] per [10] population in all cities"], "row": 1, "column": 1 }, diff --git a/android/assets/jsons/Civ V - Vanilla/UnitPromotions.json b/android/assets/jsons/Civ V - Vanilla/UnitPromotions.json index 41c46e33..eff29115 100644 --- a/android/assets/jsons/Civ V - Vanilla/UnitPromotions.json +++ b/android/assets/jsons/Civ V - Vanilla/UnitPromotions.json @@ -451,6 +451,6 @@ }, { "name": "Slinger Withdraw", // only for Slinger and subsequent upgrades - "effect": "May withdraw before melee (133%)" + "effect": "May withdraw before melee ([133]%)" } ] \ No newline at end of file diff --git a/android/assets/jsons/Civ V - Vanilla/Units.json b/android/assets/jsons/Civ V - Vanilla/Units.json index ff47fff7..6648765b 100644 --- a/android/assets/jsons/Civ V - Vanilla/Units.json +++ b/android/assets/jsons/Civ V - Vanilla/Units.json @@ -656,7 +656,7 @@ "requiredTech": "Astronomy", "upgradesTo": "Ironclad", "obsoleteTech": "Combustion", - "uniques": ["+1 Visibility Range","May withdraw before melee"], + "uniques": ["+1 Visibility Range","May withdraw before melee ([50]%)"], "hurryCostModifier": 20 }, { @@ -1071,7 +1071,7 @@ "interceptRange": 2, "cost": 375, "requiredTech": "Combustion", - "uniques": ["Can attack submarines", "[40]% chance to intercept air attacks", "May withdraw before melee"], // todo: add bonus vs submarines + "uniques": ["Can attack submarines", "[40]% chance to intercept air attacks", "May withdraw before melee ([50]%)"], // todo: add bonus vs submarines "hurryCostModifier": 20 }, { diff --git a/android/assets/jsons/translations/template.properties b/android/assets/jsons/translations/template.properties index 5ca76fd2..f0c1e621 100644 --- a/android/assets/jsons/translations/template.properties +++ b/android/assets/jsons/translations/template.properties @@ -26,7 +26,6 @@ Get = Hydro Plant = +1 population in each city = -+1 happiness in each city = # Diplomacy,Trade,Nations diff --git a/core/src/com/unciv/logic/battle/Battle.kt b/core/src/com/unciv/logic/battle/Battle.kt index 51c53bad..a47256de 100644 --- a/core/src/com/unciv/logic/battle/Battle.kt +++ b/core/src/com/unciv/logic/battle/Battle.kt @@ -11,6 +11,7 @@ import com.unciv.logic.civilization.diplomacy.DiplomaticModifiers import com.unciv.logic.map.RoadStatus import com.unciv.logic.map.TileInfo import com.unciv.models.AttackableTile +import com.unciv.models.ruleset.Unique import com.unciv.models.ruleset.unit.UnitType import java.util.* import kotlin.math.max @@ -49,8 +50,8 @@ object Battle { // Withdraw from melee ability if (attacker is MapUnitCombatant && attacker.isMelee() && defender is MapUnitCombatant ) { - val withdraw = defender.unit.getUniques().firstOrNull { it.text.startsWith("May withdraw before melee")} - if (withdraw != null && doWithdrawFromMeleeAbility(attacker, defender, withdraw.text)) return + val withdraw = defender.unit.getMatchingUniques("May withdraw before melee ([]%)").firstOrNull() + if (withdraw != null && doWithdrawFromMeleeAbility(attacker, defender, withdraw)) return } val isAlreadyDefeatedCity = defender is CityCombatant && defender.isDefeated() @@ -411,7 +412,7 @@ object Battle { } } - private fun doWithdrawFromMeleeAbility(attacker: ICombatant, defender: ICombatant, withdraw: String): Boolean { + private fun doWithdrawFromMeleeAbility(attacker: ICombatant, defender: ICombatant, withdrawUnique: Unique): Boolean { // Some notes... // unit.getUniques() is a union of baseunit uniques and promotion effects. // according to some strategy guide the slinger's withdraw ability is inherited on upgrade, @@ -427,9 +428,8 @@ object Battle { // Promotions have no effect as per what I could find in available documentation val attackBaseUnit = attacker.unit.baseUnit val defendBaseUnit = defender.unit.baseUnit - val withdrawMatch = Regex("""\((\d+)%\)""").find(withdraw) - val percentChance = ( - (if(withdrawMatch!=null) withdrawMatch.groups[1]!!.value.toFloat() else 50f) + val baseChance = withdrawUnique.params[0].toFloat() + val percentChance = (baseChance * defendBaseUnit.strength / attackBaseUnit.strength * defendBaseUnit.movement / attackBaseUnit.movement).toInt() // Roll the dice - note the effect of the surroundings, namely how much room there is to evade to, diff --git a/core/src/com/unciv/logic/battle/BattleDamage.kt b/core/src/com/unciv/logic/battle/BattleDamage.kt index 35b3337c..7ec57da2 100644 --- a/core/src/com/unciv/logic/battle/BattleDamage.kt +++ b/core/src/com/unciv/logic/battle/BattleDamage.kt @@ -181,7 +181,7 @@ object BattleDamage { modifiers["Tile"] = tileDefenceBonus } - if(attacker.isRanged()) { + if (attacker.isRanged()) { val defenceVsRanged = 0.25f * defender.unit.getUniques().count { it.text == "+25% Defence against ranged attacks" } if (defenceVsRanged > 0) modifiers["defence vs ranged"] = defenceVsRanged } @@ -189,6 +189,11 @@ object BattleDamage { val carrierDefenceBonus = 0.25f * defender.unit.getUniques().count { it.text == "+25% Combat Bonus when defending" } if (carrierDefenceBonus > 0) modifiers["Armor Plating"] = carrierDefenceBonus + for(unique in defender.unit.getMatchingUniques("+[]% defence in [] tiles")) { + if (tile.baseTerrain == unique.params[1] || tile.terrainFeature == unique.params[1]) + modifiers["[${unique.params[1]}] defence"] = unique.params[0].toFloat() / 100 + } + if (defender.unit.isFortified()) modifiers["Fortification"] = 0.2f * defender.unit.getFortificationTurns() diff --git a/core/src/com/unciv/logic/city/CityStats.kt b/core/src/com/unciv/logic/city/CityStats.kt index b1310217..6cc89bc7 100644 --- a/core/src/com/unciv/logic/city/CityStats.kt +++ b/core/src/com/unciv/logic/city/CityStats.kt @@ -200,14 +200,10 @@ class CityStats { newHappinessList["Population"] = -unhappinessFromCitizens * unhappinessModifier var happinessFromPolicies = 0f - if (civInfo.hasUnique("+1 happiness for every 10 citizens in a city")) - happinessFromPolicies += (cityInfo.population.population / 10).toFloat() - if (civInfo.hasUnique("+1 gold and -1 unhappiness for every 2 citizens in capital") - && cityInfo.isCapital()) - happinessFromPolicies += (cityInfo.population.population / 2).toFloat() if (civInfo.hasUnique("+1 happiness for every city connected to capital") && cityInfo.isConnectedToCapital()) happinessFromPolicies += 1f + happinessFromPolicies += getStatsFromUniques(civInfo.policies.policyUniques.getAllUniques()).happiness if (cityInfo.getCenterTile().militaryUnit != null) for (unique in civInfo.getMatchingUniques("[] in all cities with a garrison")) @@ -220,8 +216,7 @@ class CityStats { val happinessFromBuildings = cityInfo.cityConstructions.getStats().happiness.toInt().toFloat() newHappinessList["Buildings"] = happinessFromBuildings - if (civInfo.hasUnique("+1 happiness in each city")) - newHappinessList["Wonders"] = 1f + newHappinessList["Wonders"] = getStatsFromUniques(civInfo.getBuildingUniques()).happiness newHappinessList["Tile yields"] = getStatsFromTiles().happiness @@ -243,8 +238,7 @@ class CityStats { for(unique in cityInfo.civInfo.getMatchingUniques("[] from every specialist")) stats.add(Stats.parse(unique.params[0])) - if (cityInfo.civInfo.hasUnique("+1 Production from specialists")) - stats.production += 1 + return stats } @@ -267,8 +261,10 @@ class CityStats { val amountOfEffects = (cityInfo.population.population / unique.params[1].toInt()).toFloat() stats.add(Stats.parse(unique.params[0]).times(amountOfEffects)) } - if (unique.text == "+1 gold and -1 unhappiness for every 2 citizens in capital" && cityInfo.isCapital()) + if (unique.text == "+1 gold and -1 unhappiness for every 2 citizens in capital" && cityInfo.isCapital()) { stats.gold += (cityInfo.population.population / 2).toFloat() + stats.happiness += (cityInfo.population.population / 2).toFloat() + } } return stats diff --git a/core/src/com/unciv/logic/map/MapUnit.kt b/core/src/com/unciv/logic/map/MapUnit.kt index f4dad863..06cc311e 100644 --- a/core/src/com/unciv/logic/map/MapUnit.kt +++ b/core/src/com/unciv/logic/map/MapUnit.kt @@ -214,10 +214,10 @@ class MapUnit { } fun getRange(): Int { - if(type.isMelee()) return 1 + if (type.isMelee()) return 1 var range = baseUnit().range - if(hasUnique("+1 Range")) range++ - if(hasUnique("+2 Range")) range+=2 + if (hasUnique("+1 Range")) range++ + if (hasUnique("+2 Range")) range += 2 return range } @@ -634,11 +634,7 @@ class MapUnit { } fun interceptChance():Int{ - val interceptUnique = getUniques() - .firstOrNull { it.text.endsWith(CHANCE_TO_INTERCEPT_AIR_ATTACKS) } - if(interceptUnique==null) return 0 - val percent = Regex("\\d+").find(interceptUnique.text)!!.value.toInt() - return percent + return getMatchingUniques("[100]% chance to intercept air attacks").sumBy { it.params[0].toInt() } } fun isTransportTypeOf(mapUnit: MapUnit): Boolean {