Resolved #3408 - Unit maintenance cost reduction generalized, now works for Ottomans

This commit is contained in:
Yair Morgenstern 2020-12-11 14:24:09 +02:00
parent 3ab57f1ada
commit d0774db030
7 changed files with 36 additions and 30 deletions

View File

@ -337,7 +337,7 @@
"outerColor": [150,150,150], "outerColor": [150,150,150],
"innerColor": [60,60,60], "innerColor": [60,60,60],
"uniqueName": "Furor Teutonicus", "uniqueName": "Furor Teutonicus",
"uniques": ["67% chance to earn 25 Gold and recruit a Barbarian unit from a conquered encampment", "-25% land units maintenance"], "uniques": ["67% chance to earn 25 Gold and recruit a Barbarian unit from a conquered encampment", "-[25]% [Land] unit maintenance costs"],
"cities": ["Berlin","Hamburg","Munich","Cologne","Frankfurt","Essen","Dortmund","Stuttgart","Dusseldorf","Bremen", "cities": ["Berlin","Hamburg","Munich","Cologne","Frankfurt","Essen","Dortmund","Stuttgart","Dusseldorf","Bremen",
"Hannover","Duisburg","Leipzig","Dresden","Bonn","Bochum","Bielefeld","Karlsruhe","Gelsenkirchen","Wiesbaden", "Hannover","Duisburg","Leipzig","Dresden","Bonn","Bochum","Bielefeld","Karlsruhe","Gelsenkirchen","Wiesbaden",
"Munster","Rostok","Chemnitz","Braunschweig","Halle","Mצnchengladbach","Kiel","Wuppertal","Freiburg","Hagen", "Munster","Rostok","Chemnitz","Braunschweig","Halle","Mצnchengladbach","Kiel","Wuppertal","Freiburg","Hagen",
@ -366,7 +366,7 @@
"outerColor": [245,248,185], "outerColor": [245,248,185],
"innerColor": [18,84,30], "innerColor": [18,84,30],
"uniqueName": "Barbary Corsairs", "uniqueName": "Barbary Corsairs",
"uniques": ["Pay only one third the usual cost for naval unit maintenance", "50% chance of capturing defeated Barbarian naval units and earning 25 Gold"], "uniques": ["-[66]% [Water] unit maintenance costs", "50% chance of capturing defeated Barbarian naval units and earning 25 Gold"],
"cities": ["Istanbul","Edirne","Ankara","Bursa","Konya","Samsun","Gaziantep","Diyabakir","Izmir","Kayseri","Malatya", "cities": ["Istanbul","Edirne","Ankara","Bursa","Konya","Samsun","Gaziantep","Diyabakir","Izmir","Kayseri","Malatya",
"Marsin","Antalya","Zonguldak","Denizli","Ordu","Mugia","Eskishehir","Inebolu","Sinop","Adana","Artuin", "Marsin","Antalya","Zonguldak","Denizli","Ordu","Mugia","Eskishehir","Inebolu","Sinop","Adana","Artuin",
"Bodrum","Eregli","Silifke","Sivas","Amasya","Marmaris","Trabzon","Erzurum","Urfa","Izmit","Afyonkarhisar", "Bodrum","Eregli","Silifke","Sivas","Amasya","Marmaris","Trabzon","Erzurum","Urfa","Izmit","Afyonkarhisar",

View File

@ -14,7 +14,7 @@ class MapUnitCombatant(val unit: MapUnit) : ICombatant {
override fun isDefeated(): Boolean = unit.health <= 0 override fun isDefeated(): Boolean = unit.health <= 0
override fun isInvisible(): Boolean = unit.isInvisible() override fun isInvisible(): Boolean = unit.isInvisible()
override fun canAttack(): Boolean = unit.canAttack() override fun canAttack(): Boolean = unit.canAttack()
override fun matchesCategory(category:String) = unit.matchesCategory(category) override fun matchesCategory(category:String) = unit.matchesFilter(category)
override fun takeDamage(damage: Int) { override fun takeDamage(damage: Int) {
unit.health -= damage unit.health -= damage

View File

@ -1,6 +1,5 @@
package com.unciv.logic.civilization package com.unciv.logic.civilization
import com.unciv.Constants
import com.unciv.logic.civilization.diplomacy.RelationshipLevel import com.unciv.logic.civilization.diplomacy.RelationshipLevel
import com.unciv.logic.map.RoadStatus import com.unciv.logic.map.RoadStatus
import com.unciv.models.metadata.BASE_GAME_DURATION_TURNS import com.unciv.models.metadata.BASE_GAME_DURATION_TURNS
@ -15,7 +14,7 @@ import kotlin.math.pow
/** CivInfo class was getting too crowded */ /** CivInfo class was getting too crowded */
class CivInfoStats(val civInfo: CivilizationInfo){ class CivInfoStats(val civInfo: CivilizationInfo){
private fun getUnitUpkeep(): Int { private fun getUnitMaintenance(): Int {
val baseUnitCost = 0.5f val baseUnitCost = 0.5f
val freeUnits = 3 val freeUnits = 3
var unitsToPayFor = civInfo.getCivUnits() var unitsToPayFor = civInfo.getCivUnits()
@ -25,12 +24,20 @@ class CivInfoStats(val civInfo: CivilizationInfo){
it.getTile().isCityCenter() && it.canGarrison() it.getTile().isCityCenter() && it.canGarrison()
} }
var numberOfUnitsToPayFor = max(0f, unitsToPayFor.count().toFloat() - freeUnits) var numberOfUnitsToPayFor = max(0f, unitsToPayFor.count().toFloat() - freeUnits)
// Deprecated and generalized as of 3.11.20 - here for mod transition period
if (civInfo.hasUnique("-25% land units maintenance")) { if (civInfo.hasUnique("-25% land units maintenance")) {
val numberOfUnitsWithDiscount = min(numberOfUnitsToPayFor, unitsToPayFor.count { it.type.isLandUnit() }.toFloat()) val numberOfUnitsWithDiscount = min(numberOfUnitsToPayFor, unitsToPayFor.count { it.type.isLandUnit() }.toFloat())
numberOfUnitsToPayFor -= 0.25f * numberOfUnitsWithDiscount numberOfUnitsToPayFor -= 0.25f * numberOfUnitsWithDiscount
} }
for (unique in civInfo.getMatchingUniques("-[]% [] unit maintenance costs")) {
val numberOfUnitsWithDiscount = min(numberOfUnitsToPayFor, unitsToPayFor.count { it.matchesFilter(unique.params[1]) }.toFloat())
numberOfUnitsToPayFor -= numberOfUnitsWithDiscount * (1 - unique.params[0].toFloat() / 100)
}
val turnLimit = BASE_GAME_DURATION_TURNS * civInfo.gameInfo.gameParameters.gameSpeed.modifier val turnLimit = BASE_GAME_DURATION_TURNS * civInfo.gameInfo.gameParameters.gameSpeed.modifier
val gameProgress = civInfo.gameInfo.turns / turnLimit // as game progresses Maintenance cost rises val gameProgress = civInfo.gameInfo.turns / turnLimit // as game progresses Maintenance cost rises
var cost = baseUnitCost * numberOfUnitsToPayFor * (1 + gameProgress) var cost = baseUnitCost * numberOfUnitsToPayFor * (1 + gameProgress)
@ -100,7 +107,7 @@ class CivInfoStats(val civInfo: CivilizationInfo){
} }
statMap["Transportation upkeep"] = Stats().apply { gold=- getTransportationUpkeep().toFloat()} statMap["Transportation upkeep"] = Stats().apply { gold=- getTransportationUpkeep().toFloat()}
statMap["Unit upkeep"] = Stats().apply { gold=- getUnitUpkeep().toFloat()} statMap["Unit upkeep"] = Stats().apply { gold=- getUnitMaintenance().toFloat()}
if (civInfo.hasUnique("50% of excess happiness added to culture towards policies")) { if (civInfo.hasUnique("50% of excess happiness added to culture towards policies")) {
val happiness = civInfo.getHappiness() val happiness = civInfo.getHappiness()

View File

@ -109,7 +109,7 @@ class MapUnit {
movement += 2 movement += 2
for (unique in civInfo.getMatchingUniques("+[] Movement for all [] units")) for (unique in civInfo.getMatchingUniques("+[] Movement for all [] units"))
if (matchesCategory(unique.params[1])) if (matchesFilter(unique.params[1]))
movement += unique.params[0].toInt() movement += unique.params[0].toInt()
if (civInfo.goldenAges.isGoldenAge() && if (civInfo.goldenAges.isGoldenAge() &&
@ -719,17 +719,17 @@ class MapUnit {
} }
} }
fun matchesCategory(category: String): Boolean { fun matchesFilter(filter: String): Boolean {
if (category == type.name) return true if (filter == type.name) return true
if (category == name) return true if (filter == name) return true
if ((category == "Wounded" || category == "wounded units") && health < 100) return true if ((filter == "Wounded" || filter == "wounded units") && health < 100) return true
if ((category == "Land" || category == "land units") && type.isLandUnit()) return true if ((filter == "Land" || filter == "land units") && type.isLandUnit()) return true
if ((category == "Water" || category == "water units") && type.isWaterUnit()) return true if ((filter == "Water" || filter == "water units") && type.isWaterUnit()) return true
if ((category == "Air" || category == "air units") && type.isAirUnit()) return true if ((filter == "Air" || filter == "air units") && type.isAirUnit()) return true
if (category == "non-air" && !type.isAirUnit()) return true if (filter == "non-air" && !type.isAirUnit()) return true
if ((category == "military" || category == "military units") && type.isMilitary()) return true if ((filter == "military" || filter == "military units") && type.isMilitary()) return true
if (hasUnique(category)) return true if (hasUnique(filter)) return true
if ((category == "Barbarians" || category == "Barbarian") && civInfo.isBarbarian()) return true if ((filter == "Barbarians" || filter == "Barbarian") && civInfo.isBarbarian()) return true
return false return false
} }

View File

@ -169,7 +169,7 @@ class TileMap {
unit.promotions.addPromotion(promotion, true) unit.promotions.addPromotion(promotion, true)
for (unique in civInfo.getMatchingUniques("[] units gain the [] promotion")) { for (unique in civInfo.getMatchingUniques("[] units gain the [] promotion")) {
if (unit.matchesCategory(unique.params[0])) { if (unit.matchesFilter(unique.params[0])) {
unit.promotions.addPromotion(unique.params[1], true) unit.promotions.addPromotion(unique.params[1], true)
} }
} }

View File

@ -83,7 +83,7 @@ object UniqueTriggerActivation {
val filter = unique.params[0] val filter = unique.params[0]
val promotion = unique.params[1] val promotion = unique.params[1]
for (unit in civInfo.getCivUnits()) for (unit in civInfo.getCivUnits())
if (unit.matchesCategory(filter) if (unit.matchesFilter(filter)
|| (civInfo.gameInfo.ruleSet.unitPromotions.values.any { it.name == promotion || (civInfo.gameInfo.ruleSet.unitPromotions.values.any { it.name == promotion
&& unit.type.name in it.unitTypes })) && unit.type.name in it.unitTypes }))
unit.promotions.addPromotion(promotion, isFree = true)} unit.promotions.addPromotion(promotion, isFree = true)}

View File

@ -5,7 +5,6 @@ import com.unciv.logic.city.CityConstructions
import com.unciv.logic.city.IConstruction import com.unciv.logic.city.IConstruction
import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.map.MapUnit import com.unciv.logic.map.MapUnit
import com.unciv.models.ruleset.Building
import com.unciv.models.ruleset.Ruleset import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.Unique import com.unciv.models.ruleset.Unique
import com.unciv.models.translations.Translations import com.unciv.models.translations.Translations
@ -179,7 +178,7 @@ class BaseUnit : INamed, IConstruction {
for (unique in construction.cityInfo.cityConstructions.builtBuildingUniqueMap.getUniques("New [] units start with [] Experience in this city") for (unique in construction.cityInfo.cityConstructions.builtBuildingUniqueMap.getUniques("New [] units start with [] Experience in this city")
+ civInfo.getMatchingUniques("New [] units start with [] Experience")) { + civInfo.getMatchingUniques("New [] units start with [] Experience")) {
if (unit.matchesCategory(unique.params[0])) if (unit.matchesFilter(unique.params[0]))
XP += unique.params[1].toInt() XP += unique.params[1].toInt()
} }
unit.promotions.XP = XP unit.promotions.XP = XP
@ -188,7 +187,7 @@ class BaseUnit : INamed, IConstruction {
val filter = unique.params[0] val filter = unique.params[0]
val promotion = unique.params[1] val promotion = unique.params[1]
if (unit.matchesCategory(filter) || (filter == "relevant" && civInfo.gameInfo.ruleSet.unitPromotions.values.any { unit.type.toString() in it.unitTypes && it.name == promotion })) if (unit.matchesFilter(filter) || (filter == "relevant" && civInfo.gameInfo.ruleSet.unitPromotions.values.any { unit.type.toString() in it.unitTypes && it.name == promotion }))
unit.promotions.addPromotion(promotion, isFree = true) unit.promotions.addPromotion(promotion, isFree = true)
} }