From e6850b857aa7e3312173d92fb173c4c842de5443 Mon Sep 17 00:00:00 2001 From: Xander Lenstra <71121390+xlenstra@users.noreply.github.com> Date: Fri, 25 Jun 2021 15:35:15 +0200 Subject: [PATCH] Generalized building of improvements (#4252) * Generalized building of improvements * Readded support for the deprecated unique "Can build improvements on tiles" * Small code quality changes * Implemented requested chagnes --- .../assets/jsons/Civ V - Vanilla/Units.json | 5 +- core/src/com/unciv/Constants.kt | 5 +- .../automation/ConstructionAutomation.kt | 20 ++- .../unciv/logic/automation/UnitAutomation.kt | 5 +- .../logic/automation/WorkerAutomation.kt | 18 +- core/src/com/unciv/logic/map/MapUnit.kt | 30 +++- core/src/com/unciv/logic/map/TileInfo.kt | 1 + core/src/com/unciv/models/UnitAction.kt | 4 +- .../models/ruleset/tile/TileImprovement.kt | 3 +- .../pickerscreens/ImprovementPickerScreen.kt | 6 +- .../com/unciv/ui/worldscreen/WorldScreen.kt | 7 +- .../unciv/ui/worldscreen/unit/UnitActions.kt | 165 +++++++++--------- 12 files changed, 156 insertions(+), 113 deletions(-) diff --git a/android/assets/jsons/Civ V - Vanilla/Units.json b/android/assets/jsons/Civ V - Vanilla/Units.json index 9fba7dfd4f..5bb6a92a57 100644 --- a/android/assets/jsons/Civ V - Vanilla/Units.json +++ b/android/assets/jsons/Civ V - Vanilla/Units.json @@ -7,7 +7,7 @@ "name": "Worker", "unitType": "Civilian", "movement": 2, - "uniques": ["Can build improvements on tiles"], + "uniques": ["Can build [Land] improvements on tiles"], "cost": 70 }, { @@ -372,10 +372,9 @@ "upgradesTo": "Longswordsman", "obsoleteTech": "Gunpowder", "requiredResource": "Iron", - "uniques": ["Can construct roads"], + "uniques": ["Can build [Road] improvements on tiles", "Can build [Fort] improvements on tiles"], "hurryCostModifier": 20, "attackSound": "metalhit" - // can construct fort (if required for fort tech is researched) }, { "name": "Mohawk Warrior", diff --git a/core/src/com/unciv/Constants.kt b/core/src/com/unciv/Constants.kt index 769b3e8e5a..3e3b0efaa1 100644 --- a/core/src/com/unciv/Constants.kt +++ b/core/src/com/unciv/Constants.kt @@ -2,7 +2,10 @@ package com.unciv object Constants { const val worker = "Worker" - const val workerUnique = "Can build improvements on tiles" + const val canBuildImprovements = "Can build [] improvements on tiles" + // Deprecated as of 3.15.5 + const val workerUnique = "Can build improvements on tiles" + // const val settler = "Settler" const val settlerUnique = "Founds a new city" diff --git a/core/src/com/unciv/logic/automation/ConstructionAutomation.kt b/core/src/com/unciv/logic/automation/ConstructionAutomation.kt index 6a709e67a9..b50d04858a 100644 --- a/core/src/com/unciv/logic/automation/ConstructionAutomation.kt +++ b/core/src/com/unciv/logic/automation/ConstructionAutomation.kt @@ -11,8 +11,8 @@ import com.unciv.logic.map.BFS import com.unciv.models.ruleset.Building import com.unciv.models.ruleset.VictoryType import com.unciv.models.stats.Stat +import com.unciv.models.translations.equalsPlaceholderText import kotlin.math.min -import kotlin.math.roundToInt import kotlin.math.sqrt class ConstructionAutomation(val cityConstructions: CityConstructions){ @@ -26,8 +26,9 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){ .filter { it.isWonder || it.isNationalWonder } val civUnits = civInfo.getCivUnits() - val militaryUnits = civUnits.count { !it.type.isCivilian()} - val workers = civUnits.count { it.hasUnique(Constants.workerUnique) }.toFloat() + val militaryUnits = civUnits.count { !it.type.isCivilian() } + // Constants.workerUnique deprecated since 3.15.5 + val workers = civUnits.count { (it.hasUnique(Constants.canBuildImprovements) || it.hasUnique(Constants.workerUnique)) && it.type.isCivilian() }.toFloat() val cities = civInfo.cities.size val allTechsAreResearched = civInfo.tech.getNumberOfTechsResearched() >= civInfo.gameInfo.ruleSet.technologies.size @@ -68,7 +69,7 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){ addWorkBoatChoice() addMilitaryUnitChoice() } - + val production = cityInfo.cityStats.currentCityStats.production val theChosenOne: String @@ -138,13 +139,18 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){ private fun addWorkerChoice() { val workerEquivalents = civInfo.gameInfo.ruleSet.units.values - .filter { it.uniques.contains(Constants.workerUnique) && it.isBuildable(cityConstructions) } + .filter { it.uniques.any { + // Constants.workerUnique deprecated since 3.15.5 + unique -> unique.equalsPlaceholderText(Constants.canBuildImprovements) || unique.equalsPlaceholderText(Constants.workerUnique) + } && it.isBuildable(cityConstructions) } if (workerEquivalents.isEmpty()) return // for mods with no worker units - if (civInfo.getIdleUnits().any { it.action == Constants.unitActionAutomation && it.hasUnique(Constants.workerUnique) }) + // Constants.workerUnique deprecated since 3.15.5 + if (civInfo.getIdleUnits().any { it.action == Constants.unitActionAutomation && (it.hasUnique(Constants.canBuildImprovements) || it.hasUnique(Constants.workerUnique)) }) return // If we have automated workers who have no work to do then it's silly to construct new workers. val citiesCountedTowardsWorkers = min(5, cities) // above 5 cities, extra cities won't make us want more workers - if (workers < citiesCountedTowardsWorkers * 0.6f && civUnits.none { it.hasUnique(Constants.workerUnique) && it.isIdle() }) { + // Constants.workerUnique deprecated since 3.15.5 + if (workers < citiesCountedTowardsWorkers * 0.6f && civUnits.none { (it.hasUnique(Constants.canBuildImprovements) || it.hasUnique(Constants.workerUnique)) && it.isIdle() }) { var modifier = citiesCountedTowardsWorkers / (workers + 0.1f) if (!cityIsOverAverageProduction) modifier /= 5 // higher production cities will deal with this addChoice(relativeCostEffectiveness, workerEquivalents.minByOrNull { it.cost }!!.name, modifier) diff --git a/core/src/com/unciv/logic/automation/UnitAutomation.kt b/core/src/com/unciv/logic/automation/UnitAutomation.kt index f603e145a9..9744ffa31b 100644 --- a/core/src/com/unciv/logic/automation/UnitAutomation.kt +++ b/core/src/com/unciv/logic/automation/UnitAutomation.kt @@ -89,10 +89,11 @@ object UnitAutomation { if (unit.hasUnique(Constants.settlerUnique)) return SpecificUnitAutomation.automateSettlerActions(unit) - if (unit.hasUnique(Constants.workerUnique)) + // Constants.workerUnique deprecated since 3.15.5 + if (unit.hasUnique(Constants.canBuildImprovements) || unit.hasUnique(Constants.workerUnique)) return WorkerAutomation(unit).automateWorkerAction() - if (unit.name == "Work Boats") + if (unit.name == "Work Boats") // This is really not modular return SpecificUnitAutomation.automateWorkBoats(unit) if (unit.hasUnique("Bonus for units in 2 tile radius 15%")) diff --git a/core/src/com/unciv/logic/automation/WorkerAutomation.kt b/core/src/com/unciv/logic/automation/WorkerAutomation.kt index 9369a44b44..a615a96c27 100644 --- a/core/src/com/unciv/logic/automation/WorkerAutomation.kt +++ b/core/src/com/unciv/logic/automation/WorkerAutomation.kt @@ -15,11 +15,11 @@ class WorkerAutomation(val unit: MapUnit) { val enemyUnitsInWalkingDistance = unit.movement.getDistanceToTiles().keys .filter { UnitAutomation.containsEnemyMilitaryUnit(unit, it) } - if (enemyUnitsInWalkingDistance.isNotEmpty()) return UnitAutomation.runAway(unit) + if (enemyUnitsInWalkingDistance.isNotEmpty() && !unit.type.isMilitary()) return UnitAutomation.runAway(unit) val currentTile = unit.getTile() val tileToWork = findTileToWork() - + if (getPriority(tileToWork, unit.civInfo) < 3) { // building roads is more important if (tryConnectingCities(unit)) return } @@ -63,7 +63,6 @@ class WorkerAutomation(val unit: MapUnit) { //Player can choose not to auto-build roads & railroads. if (unit.civInfo.isPlayerCivilization() && !UncivGame.Current.settings.autoBuildingRoads) return false - val targetRoad = unit.civInfo.tech.getBestRoadAvailable() val citiesThatNeedConnecting = unit.civInfo.cities.asSequence() @@ -137,7 +136,7 @@ class WorkerAutomation(val unit: MapUnit) { return if (selectedTile != null && getPriority(selectedTile, unit.civInfo) > 1 && (!workableTiles.contains(currentTile) - || getPriority(selectedTile, unit.civInfo) > getPriority(currentTile, unit.civInfo))) + || getPriority(selectedTile, unit.civInfo) > getPriority(currentTile, unit.civInfo))) selectedTile else currentTile } @@ -152,15 +151,14 @@ class WorkerAutomation(val unit: MapUnit) { return false if (tile.improvement == null) { - if (tile.improvementInProgress != null) return true + if (tile.improvementInProgress != null && unit.canBuildImprovement(tile.getTileImprovementInProgress()!!, tile)) return true val chosenImprovement = chooseImprovement(tile, civInfo) - if (chosenImprovement != null && tile.canBuildImprovement(chosenImprovement, civInfo)) return true + if (chosenImprovement != null && tile.canBuildImprovement(chosenImprovement, civInfo) && unit.canBuildImprovement(chosenImprovement, tile)) return true } else if (!tile.containsGreatImprovement() && tile.hasViewableResource(civInfo) && tile.getTileResource().improvement != tile.improvement && chooseImprovement(tile, civInfo) // if the chosen improvement is not null and buildable - .let { it != null && tile.canBuildImprovement(it, civInfo) }) + .let { it != null && tile.canBuildImprovement(it, civInfo) && unit.canBuildImprovement(it, tile)}) return true - return false // couldn't find anything to construct here } @@ -204,7 +202,9 @@ class WorkerAutomation(val unit: MapUnit) { // While AI sucks in strategical placement of forts, allow a human does it manually !civInfo.isPlayerCivilization() && evaluateFortPlacement(tile, civInfo, false) -> Constants.fort // I think we can assume that the unique improvement is better - uniqueImprovement != null && tile.canBuildImprovement(uniqueImprovement, civInfo) -> uniqueImprovement.name + uniqueImprovement != null && tile.canBuildImprovement(uniqueImprovement, civInfo) + && unit.canBuildImprovement(uniqueImprovement, tile) -> + uniqueImprovement.name tile.terrainFeatures.contains("Fallout") -> "Remove Fallout" tile.terrainFeatures.contains(Constants.marsh) -> "Remove Marsh" diff --git a/core/src/com/unciv/logic/map/MapUnit.kt b/core/src/com/unciv/logic/map/MapUnit.kt index 69450c0504..3718fe474f 100644 --- a/core/src/com/unciv/logic/map/MapUnit.kt +++ b/core/src/com/unciv/logic/map/MapUnit.kt @@ -10,6 +10,7 @@ import com.unciv.logic.civilization.LocationAction import com.unciv.logic.civilization.NotificationIcon import com.unciv.models.ruleset.Ruleset import com.unciv.models.ruleset.Unique +import com.unciv.models.ruleset.tile.TileImprovement import com.unciv.models.ruleset.unit.BaseUnit import com.unciv.models.ruleset.unit.UnitType import java.text.DecimalFormat @@ -257,8 +258,13 @@ class MapUnit { fun isIdle(): Boolean { if (currentMovement == 0f) return false - if (hasUnique(Constants.workerUnique) && getTile().improvementInProgress != null) return false - if (hasUnique("Can construct roads") && currentTile.improvementInProgress == "Road") return false + // Constants.workerUnique deprecated since 3.15.5 + if (getTile().improvementInProgress != null + && canBuildImprovement(getTile().getTileImprovementInProgress()!!)) + return false + // unique "Can construct roads" deprecated since 3.15.5 + if (hasUnique("Can construct roads") && currentTile.improvementInProgress == "Road") return false + // if (isFortified()) return false if (action == Constants.unitActionExplore || isSleeping() || action == Constants.unitActionAutomation || isMoving() @@ -540,12 +546,16 @@ class MapUnit { fun endTurn() { doAction() - if (currentMovement > 0 && hasUnique(Constants.workerUnique) - && getTile().improvementInProgress != null - ) workOnImprovement() - if (currentMovement > 0 && hasUnique("Can construct roads") - && currentTile.improvementInProgress == "Road" + if (currentMovement > 0 && + // Constants.workerUnique deprecated since 3.15.5 + getTile().improvementInProgress != null + && canBuildImprovement(getTile().getTileImprovementInProgress()!!) ) workOnImprovement() + // unique "Can construct roads" deprecated since 3.15.4 + if (currentMovement > 0 && hasUnique("Can construct roads") + && currentTile.improvementInProgress == "Road" + ) workOnImprovement() + // if (currentMovement == getMaxMovement().toFloat() && isFortified()) { val currentTurnsFortified = getFortificationTurns() if (currentTurnsFortified < 2) @@ -913,5 +923,11 @@ class MapUnit { } } + fun canBuildImprovement(improvement: TileImprovement, tile: TileInfo = currentTile): Boolean { + // Constants.workerUnique deprecated since 3.15.5 + val matchingUniques = getMatchingUniques(Constants.canBuildImprovements) + getMatchingUniques(Constants.workerUnique) + return matchingUniques.any { improvement.matchesFilter(it.params[0]) || tile.matchesTerrainFilter(it.params[0]) } + } + //endregion } diff --git a/core/src/com/unciv/logic/map/TileInfo.kt b/core/src/com/unciv/logic/map/TileInfo.kt index 2e793fc66f..1243595d2b 100644 --- a/core/src/com/unciv/logic/map/TileInfo.kt +++ b/core/src/com/unciv/logic/map/TileInfo.kt @@ -154,6 +154,7 @@ open class TileInfo { fun isImpassible() = getLastTerrain().impassable fun getTileImprovement(): TileImprovement? = if (improvement == null) null else ruleset.tileImprovements[improvement!!] + fun getTileImprovementInProgress(): TileImprovement? = if (improvementInProgress == null) null else ruleset.tileImprovements[improvementInProgress!!] // This is for performance - since we access the neighbors of a tile ALL THE TIME, diff --git a/core/src/com/unciv/models/UnitAction.kt b/core/src/com/unciv/models/UnitAction.kt index a011391e5c..fe2a5a2015 100644 --- a/core/src/com/unciv/models/UnitAction.kt +++ b/core/src/com/unciv/models/UnitAction.kt @@ -26,7 +26,9 @@ enum class UnitActionType(val value: String) { SetUp("Set up"), FoundCity("Found city"), ConstructImprovement("Construct improvement"), - ConstructRoad("Construct road"), + // Deprecated since 3.15.4 + ConstructRoad("Construct road"), + // Create("Create"), HurryResearch("Hurry Research"), StartGoldenAge("Start Golden Age"), diff --git a/core/src/com/unciv/models/ruleset/tile/TileImprovement.kt b/core/src/com/unciv/models/ruleset/tile/TileImprovement.kt index 14839b1918..3c904683fe 100644 --- a/core/src/com/unciv/models/ruleset/tile/TileImprovement.kt +++ b/core/src/com/unciv/models/ruleset/tile/TileImprovement.kt @@ -99,7 +99,8 @@ class TileImprovement : NamedStats() { return when (filter) { name -> true "All" -> true - "Great Improvement" -> isGreatImprovement() + "All Road" -> name == "road" || name == "railroad" + "Great Improvement", "Great" -> isGreatImprovement() else -> false } } diff --git a/core/src/com/unciv/ui/pickerscreens/ImprovementPickerScreen.kt b/core/src/com/unciv/ui/pickerscreens/ImprovementPickerScreen.kt index d8e7ada192..315891d401 100644 --- a/core/src/com/unciv/ui/pickerscreens/ImprovementPickerScreen.kt +++ b/core/src/com/unciv/ui/pickerscreens/ImprovementPickerScreen.kt @@ -8,6 +8,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table import com.badlogic.gdx.utils.Align import com.unciv.Constants import com.unciv.UncivGame +import com.unciv.logic.map.MapUnit import com.unciv.logic.map.RoadStatus import com.unciv.logic.map.TileInfo import com.unciv.models.ruleset.tile.TileImprovement @@ -17,7 +18,7 @@ import com.unciv.ui.utils.* import com.unciv.ui.utils.StaticTooltip.Companion.addStaticTip import kotlin.math.round -class ImprovementPickerScreen(val tileInfo: TileInfo, val onAccept: ()->Unit) : PickerScreen() { +class ImprovementPickerScreen(val tileInfo: TileInfo, unit: MapUnit, val onAccept: ()->Unit) : PickerScreen() { private var selectedImprovement: TileImprovement? = null private val gameInfo = tileInfo.tileMap.gameInfo private val ruleSet = gameInfo.ruleSet @@ -56,8 +57,9 @@ class ImprovementPickerScreen(val tileInfo: TileInfo, val onAccept: ()->Unit) : for (improvement in ruleSet.tileImprovements.values) { // canBuildImprovement() would allow e.g. great improvements thus we need to exclude them - except cancel if (improvement.turnsToBuild == 0 && improvement.name != Constants.cancelImprovementOrder) continue - if (improvement.name == tileInfo.improvement) continue // also checked by canImprovementBeBuiltHere, but after more expensive tests + if (improvement.name == tileInfo.improvement) continue // also checked by canImprovementBeBuiltHere, but after more expensive tests if (!tileInfo.canBuildImprovement(improvement, currentPlayerCiv)) continue + if (!unit.canBuildImprovement(improvement)) continue val improvementButtonTable = Table() diff --git a/core/src/com/unciv/ui/worldscreen/WorldScreen.kt b/core/src/com/unciv/ui/worldscreen/WorldScreen.kt index f1de517f81..db688f2341 100644 --- a/core/src/com/unciv/ui/worldscreen/WorldScreen.kt +++ b/core/src/com/unciv/ui/worldscreen/WorldScreen.kt @@ -478,7 +478,12 @@ class WorldScreen(val gameInfo: GameInfo, val viewingCiv:CivilizationInfo) : Cam displayTutorial(Tutorial.InjuredUnits) { gameInfo.getCurrentPlayerCivilization().getCivUnits().any { it.health < 100 } } - displayTutorial(Tutorial.Workers) { gameInfo.getCurrentPlayerCivilization().getCivUnits().any { it.hasUnique(Constants.workerUnique) } } + displayTutorial(Tutorial.Workers) { + gameInfo.getCurrentPlayerCivilization().getCivUnits().any { + (it.hasUnique(Constants.canBuildImprovements) || it.hasUnique(Constants.workerUnique)) + && it.type.isCivilian() + } + } } private fun updateDiplomacyButton(civInfo: CivilizationInfo) { diff --git a/core/src/com/unciv/ui/worldscreen/unit/UnitActions.kt b/core/src/com/unciv/ui/worldscreen/unit/UnitActions.kt index 61712f8cf2..9a9f38bab8 100644 --- a/core/src/com/unciv/ui/worldscreen/unit/UnitActions.kt +++ b/core/src/com/unciv/ui/worldscreen/unit/UnitActions.kt @@ -32,8 +32,8 @@ object UnitActions { if (unit.isMoving()) actionList += UnitAction(UnitActionType.StopMovement) { unit.action = null } - val workingOnImprovement = unit.hasUnique("Can build improvements on tiles") - && unit.currentTile.hasImprovementInProgress() + // Constants.workerUnique deprecated since 3.15.5 + val workingOnImprovement = unit.currentTile.hasImprovementInProgress() && unit.canBuildImprovement(unit.currentTile.getTileImprovementInProgress()!!) if (!unit.isFortified() && !unit.canFortify() && unit.currentMovement > 0 && !workingOnImprovement) { addSleepActions(actionList, unit, unitTable) } @@ -58,7 +58,9 @@ object UnitActions { addSetupAction(unit, actionList) addFoundCityAction(unit, actionList, tile) addWorkerActions(unit, actionList, tile, worldScreen, unitTable) - addConstructRoadsAction(unit, tile, actionList) + // Deprecated since 3.15.4 + addConstructRoadsAction(unit, tile, actionList) + // addCreateWaterImprovements(unit, actionList) addGreatPersonActions(unit, actionList, tile) actionList += getImprovementConstructionActions(unit, tile) @@ -121,20 +123,22 @@ object UnitActions { return null } - - private fun addConstructRoadsAction(unit: MapUnit, tile: TileInfo, actionList: ArrayList) { - val improvement = RoadStatus.Road.improvement(unit.civInfo.gameInfo.ruleSet) ?: return - if (unit.hasUnique("Can construct roads") - && tile.roadStatus == RoadStatus.None - && tile.improvementInProgress != "Road" - && tile.isLand - && (improvement.techRequired == null || unit.civInfo.tech.isResearched(improvement.techRequired!!))) - actionList += UnitAction(UnitActionType.ConstructRoad, - action = { - tile.improvementInProgress = "Road" - tile.turnsToImprovement = improvement.getTurnsToBuild(unit.civInfo) - }.takeIf { unit.currentMovement > 0 }) - } + + // This entire function is deprecated since 3.15.4, as the 'can construct roads' unique is deprecated + private fun addConstructRoadsAction(unit: MapUnit, tile: TileInfo, actionList: ArrayList) { + val improvement = RoadStatus.Road.improvement(unit.civInfo.gameInfo.ruleSet) ?: return + if (unit.hasUnique("Can construct roads") + && tile.roadStatus == RoadStatus.None + && tile.improvementInProgress != "Road" + && tile.isLand + && (improvement.techRequired == null || unit.civInfo.tech.isResearched(improvement.techRequired!!))) + actionList += UnitAction(UnitActionType.ConstructRoad, + action = { + tile.improvementInProgress = "Road" + tile.turnsToImprovement = improvement.getTurnsToBuild(unit.civInfo) + }.takeIf { unit.currentMovement > 0 }) + } + // private fun addFoundCityAction(unit: MapUnit, actionList: ArrayList, tile: TileInfo) { val getFoundCityAction = getFoundCityAction(unit, tile) @@ -330,7 +334,8 @@ object UnitActions { } private fun addWorkerActions(unit: MapUnit, actionList: ArrayList, tile: TileInfo, worldScreen: WorldScreen, unitTable: UnitTable) { - if (!unit.hasUnique("Can build improvements on tiles")) return + // Constants.workerUnique deprecated since 3.15.5 + if (!unit.hasUnique(Constants.canBuildImprovements) && !unit.hasUnique(Constants.workerUnique)) return // Allow automate/unautomate when embarked, but not building improvements - see #1963 if (Constants.unitActionAutomation == unit.action) { @@ -347,12 +352,12 @@ object UnitActions { val canConstruct = unit.currentMovement > 0 && !tile.isCityCenter() - && unit.civInfo.gameInfo.ruleSet.tileImprovements.values.any { tile.canBuildImprovement(it, unit.civInfo) } - + && unit.civInfo.gameInfo.ruleSet.tileImprovements.values.any { tile.canBuildImprovement(it, unit.civInfo) && unit.canBuildImprovement(it) } + actionList += UnitAction(UnitActionType.ConstructImprovement, isCurrentAction = unit.currentTile.hasImprovementInProgress(), action = { - worldScreen.game.setScreen(ImprovementPickerScreen(tile) { unitTable.selectUnit() }) + worldScreen.game.setScreen(ImprovementPickerScreen(tile, unit) { unitTable.selectUnit() }) }.takeIf { canConstruct }) } @@ -361,22 +366,22 @@ object UnitActions { if (unit.currentMovement > 0) for (unique in unit.getUniques()) when (unique.placeholderText) { "Can hurry technology research" -> { actionList += UnitAction(UnitActionType.HurryResearch, - uncivSound = UncivSound.Chimes, - action = { - unit.civInfo.tech.addScience(unit.civInfo.tech.getScienceFromGreatScientist()) - addGoldPerGreatPersonUsage(unit.civInfo) - unit.destroy() - }.takeIf { unit.civInfo.tech.currentTechnologyName() != null }) + uncivSound = UncivSound.Chimes, + action = { + unit.civInfo.tech.addScience(unit.civInfo.tech.getScienceFromGreatScientist()) + addGoldPerGreatPersonUsage(unit.civInfo) + unit.destroy() + }.takeIf { unit.civInfo.tech.currentTechnologyName() != null }) } "Can start an []-turn golden age" -> { val turnsToGoldenAge = unique.params[0].toInt() actionList += UnitAction(UnitActionType.StartGoldenAge, - uncivSound = UncivSound.Chimes, - action = { - unit.civInfo.goldenAges.enterGoldenAge(turnsToGoldenAge) - addGoldPerGreatPersonUsage(unit.civInfo) - unit.destroy() - }.takeIf { unit.currentTile.getOwner() != null && unit.currentTile.getOwner() == unit.civInfo }) + uncivSound = UncivSound.Chimes, + action = { + unit.civInfo.goldenAges.enterGoldenAge(turnsToGoldenAge) + addGoldPerGreatPersonUsage(unit.civInfo) + unit.destroy() + }.takeIf { unit.currentTile.getOwner() != null && unit.currentTile.getOwner() == unit.civInfo }) } "Can speed up construction of a wonder" -> { val canHurryWonder = if (!tile.isCityCenter()) false @@ -386,39 +391,38 @@ object UnitActions { else currentConstruction.isWonder || currentConstruction.isNationalWonder } actionList += UnitAction(UnitActionType.HurryWonder, - uncivSound = UncivSound.Chimes, - action = { - tile.getCity()!!.cityConstructions.apply { - addProductionPoints(300 + 30 * tile.getCity()!!.population.population) //http://civilization.wikia.com/wiki/Great_engineer_(Civ5) - constructIfEnough() - } - addGoldPerGreatPersonUsage(unit.civInfo) - unit.destroy() - }.takeIf { canHurryWonder }) + uncivSound = UncivSound.Chimes, + action = { + tile.getCity()!!.cityConstructions.apply { + addProductionPoints(300 + 30 * tile.getCity()!!.population.population) //http://civilization.wikia.com/wiki/Great_engineer_(Civ5) + constructIfEnough() + } + addGoldPerGreatPersonUsage(unit.civInfo) + unit.destroy() + }.takeIf { canHurryWonder }) } "Can undertake a trade mission with City-State, giving a large sum of gold and [] Influence" -> { val canConductTradeMission = tile.owningCity?.civInfo?.isCityState() == true && tile.owningCity?.civInfo?.isAtWarWith(unit.civInfo) == false val influenceEarned = unique.params[0].toInt() actionList += UnitAction(UnitActionType.ConductTradeMission, - uncivSound = UncivSound.Chimes, - action = { - // http://civilization.wikia.com/wiki/Great_Merchant_(Civ5) - var goldEarned = ((350 + 50 * unit.civInfo.getEraNumber()) * unit.civInfo.gameInfo.gameParameters.gameSpeed.modifier).toInt() - if (unit.civInfo.hasUnique("Double gold from Great Merchant trade missions")) - goldEarned *= 2 - unit.civInfo.addGold(goldEarned) - tile.owningCity!!.civInfo.getDiplomacyManager(unit.civInfo).influence += influenceEarned - unit.civInfo.addNotification("Your trade mission to [${tile.owningCity!!.civInfo}] has earned you [${goldEarned}] gold and [$influenceEarned] influence!", - tile.owningCity!!.civInfo.civName, NotificationIcon.Gold, NotificationIcon.Culture) - addGoldPerGreatPersonUsage(unit.civInfo) - unit.destroy() - }.takeIf { canConductTradeMission }) + uncivSound = UncivSound.Chimes, + action = { + // http://civilization.wikia.com/wiki/Great_Merchant_(Civ5) + var goldEarned = ((350 + 50 * unit.civInfo.getEraNumber()) * unit.civInfo.gameInfo.gameParameters.gameSpeed.modifier).toInt() + if (unit.civInfo.hasUnique("Double gold from Great Merchant trade missions")) + goldEarned *= 2 + unit.civInfo.addGold(goldEarned) + tile.owningCity!!.civInfo.getDiplomacyManager(unit.civInfo).influence += influenceEarned + unit.civInfo.addNotification("Your trade mission to [${tile.owningCity!!.civInfo}] has earned you [${goldEarned}] gold and [$influenceEarned] influence!", + tile.owningCity!!.civInfo.civName, NotificationIcon.Gold, NotificationIcon.Culture) + addGoldPerGreatPersonUsage(unit.civInfo) + unit.destroy() + }.takeIf { canConductTradeMission }) } } } - - + fun getImprovementConstructionActions(unit: MapUnit, tile: TileInfo): ArrayList { val finalActions = ArrayList() for (unique in unit.getMatchingUniques("Can construct []")) { @@ -426,28 +430,31 @@ object UnitActions { val improvement = tile.ruleset.tileImprovements[improvementName] if (improvement == null) continue finalActions += UnitAction(UnitActionType.Create, - title = "Create [$improvementName]", - uncivSound = UncivSound.Chimes, - action = { - val unitTile = unit.getTile() - for (terrainFeature in tile.terrainFeatures.filter { unitTile.ruleset.tileImprovements.containsKey("Remove $it") }) - unitTile.terrainFeatures.remove(terrainFeature)// remove forest/jungle/marsh - unitTile.improvement = improvementName - unitTile.improvementInProgress = null - unitTile.turnsToImprovement = 0 - if (improvementName == Constants.citadel) - takeOverTilesAround(unit) - val city = unitTile.getCity() - if (city != null) { - city.cityStats.update() - city.civInfo.updateDetailedCivResources() - } - addGoldPerGreatPersonUsage(unit.civInfo) - unit.destroy() - }.takeIf { - unit.currentMovement > 0f && tile.canBuildImprovement(improvement, unit.civInfo) - && !tile.isImpassible() // Not 100% sure that this check is necessary... - }) + title = "Create [$improvementName]", + uncivSound = UncivSound.Chimes, + action = { + val unitTile = unit.getTile() + for (terrainFeature in tile.terrainFeatures.filter { unitTile.ruleset.tileImprovements.containsKey("Remove $it") }) + unitTile.terrainFeatures.remove(terrainFeature)// remove forest/jungle/marsh + unitTile.improvement = improvementName + unitTile.improvementInProgress = null + unitTile.turnsToImprovement = 0 + if (improvementName == Constants.citadel) + takeOverTilesAround(unit) + val city = unitTile.getCity() + if (city != null) { + city.cityStats.update() + city.civInfo.updateDetailedCivResources() + } + // Why is this here? How do we now the unit is actually a great person? + // What if in some mod some unit can construct a certain type of improvement using the "Can construct []" unique? + // That unit does not need to be a great person at all, and yet it would trigger mausoleum of halicarnassus (?) here. + addGoldPerGreatPersonUsage(unit.civInfo) + unit.destroy() + }.takeIf { + unit.currentMovement > 0f && tile.canBuildImprovement(improvement, unit.civInfo) + && !tile.isImpassible() // Not 100% sure that this check is necessary... + }) } return finalActions }