A mishmash of different fixes: Unit uniques and promotions, happiness calculation, etc.

This commit is contained in:
Yair Morgenstern 2020-08-24 10:58:14 +03:00
parent 21c8336563
commit 6ff712b625
9 changed files with 27 additions and 31 deletions

View file

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

View file

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

View file

@ -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]%)"
}
]

View file

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

View file

@ -26,7 +26,6 @@ Get =
Hydro Plant =
+1 population in each city =
+1 happiness in each city =
# Diplomacy,Trade,Nations

View file

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

View file

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

View file

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

View file

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