diff --git a/android/assets/jsons/Civ V - Vanilla/Units.json b/android/assets/jsons/Civ V - Vanilla/Units.json index bc9e8d0926..a74dcfb953 100644 --- a/android/assets/jsons/Civ V - Vanilla/Units.json +++ b/android/assets/jsons/Civ V - Vanilla/Units.json @@ -1290,32 +1290,32 @@ { "name": "Great Artist", "unitType": "Civilian", - "uniques": ["Can start an 8-turn golden age","Can build improvement: Landmark", "Unbuildable"], + "uniques": ["Can start an 8-turn golden age","Can construct [Landmark]", "Unbuildable"], "movement": 2 }, { "name": "Great Scientist", "unitType": "Civilian", - "uniques": ["Can hurry technology research","Can build improvement: Academy", "Unbuildable"], + "uniques": ["Can hurry technology research","Can construct [Academy]", "Unbuildable"], "movement": 2 }, { "name": "Great Merchant", "unitType": "Civilian", "uniques": ["Can undertake a trade mission with City-State, giving a large sum of gold and [30] Influence", - "Can build improvement: Customs house", "Unbuildable"], + "Can construct [Customs house]", "Unbuildable"], "movement": 2 }, { "name": "Great Engineer", "unitType": "Civilian", - "uniques": ["Can speed up construction of a wonder","Can build improvement: Manufactory", "Unbuildable"], + "uniques": ["Can speed up construction of a wonder","Can construct [Manufactory]", "Unbuildable"], "movement": 2 }, { "name": "Great General", "unitType": "Civilian", - "uniques": ["Can start an 8-turn golden age","Bonus for units in 2 tile radius 15%", "Can build improvement: Citadel", "Unbuildable"], + "uniques": ["Can start an 8-turn golden age","Bonus for units in 2 tile radius 15%", "Can construct [Citadel]", "Unbuildable"], "movement": 2 }, { diff --git a/core/src/com/unciv/logic/automation/SpecificUnitAutomation.kt b/core/src/com/unciv/logic/automation/SpecificUnitAutomation.kt index b11e569bbf..17a0130b56 100644 --- a/core/src/com/unciv/logic/automation/SpecificUnitAutomation.kt +++ b/core/src/com/unciv/logic/automation/SpecificUnitAutomation.kt @@ -10,6 +10,8 @@ import com.unciv.logic.map.TileInfo import com.unciv.models.ruleset.tile.ResourceType import com.unciv.models.ruleset.tile.TileResource import com.unciv.models.stats.Stats +import com.unciv.models.translations.equalsPlaceholderText +import com.unciv.models.translations.getPlaceholderParameters import com.unciv.ui.worldscreen.unit.UnitActions object SpecificUnitAutomation { @@ -79,18 +81,18 @@ object SpecificUnitAutomation { if (owner != null) distance - WorkerAutomation(unit).getPriority(it, owner) else distance } - .firstOrNull{ unit.movement.canReach(it) } // canReach is perfrmance-heavy and always a last resort + .firstOrNull{ unit.movement.canReach(it) } // canReach is performance-heavy and always a last resort // if there is a good tile to steal - go there if (tileToSteal != null) { unit.movement.headTowards(tileToSteal) if (unit.currentMovement > 0 && unit.currentTile == tileToSteal) - UnitActions.getBuildImprovementAction(unit)?.action?.invoke() + UnitActions.getImprovementConstructionActions(unit, unit.currentTile).firstOrNull()?.action?.invoke() return } - // try to build a citadel + // try to build a citadel for defensive purposes if (WorkerAutomation(unit).evaluateFortPlacement(unit.currentTile, unit.civInfo, true)) { - UnitActions.getBuildImprovementAction(unit)?.action?.invoke() + UnitActions.getImprovementConstructionActions(unit,unit.currentTile).firstOrNull()?.action?.invoke() return } @@ -110,7 +112,7 @@ object SpecificUnitAutomation { if (tileForCitadel != null) { unit.movement.headTowards(tileForCitadel) if (unit.currentMovement > 0 && unit.currentTile == tileForCitadel) - UnitActions.getBuildImprovementAction(unit)?.action?.invoke() + UnitActions.getImprovementConstructionActions(unit,unit.currentTile).firstOrNull()?.action?.invoke() } else unit.movement.headTowards(cityToGarrison) return @@ -190,10 +192,13 @@ object SpecificUnitAutomation { foundCityAction.action.invoke() } - fun automateGreatPerson(unit: MapUnit) { + fun automateImprovementPlacer(unit: MapUnit) { if (unit.getTile().militaryUnit == null) return // Don't move until you're accompanied by a military unit - val relatedStat = GreatPersonManager().statToGreatPersonMapping.entries.first { it.value == unit.name }.key + val improvementName = unit.getUniques().first { it.equalsPlaceholderText("Can construct []") } + .getPlaceholderParameters()[0] + val improvement = unit.civInfo.gameInfo.ruleSet.tileImprovements[improvementName]!! + val relatedStat = improvement.toHashMap().maxBy { it.value }!!.key val citiesByStatBoost = unit.civInfo.cities.sortedByDescending { val stats = Stats() @@ -221,7 +226,7 @@ object SpecificUnitAutomation { unit.movement.headTowards(chosenTile) if (unit.currentTile == chosenTile) - UnitActions.getBuildImprovementAction(unit)?.action?.invoke() + UnitActions.getImprovementConstructionActions(unit, unit.currentTile).firstOrNull()?.action?.invoke() return } } diff --git a/core/src/com/unciv/logic/automation/UnitAutomation.kt b/core/src/com/unciv/logic/automation/UnitAutomation.kt index 36e1ac0c40..b15104e201 100644 --- a/core/src/com/unciv/logic/automation/UnitAutomation.kt +++ b/core/src/com/unciv/logic/automation/UnitAutomation.kt @@ -4,12 +4,12 @@ import com.badlogic.gdx.graphics.Color import com.unciv.Constants import com.unciv.logic.battle.* import com.unciv.logic.city.CityInfo -import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.civilization.GreatPersonManager import com.unciv.logic.civilization.diplomacy.DiplomaticStatus import com.unciv.logic.map.MapUnit import com.unciv.logic.map.TileInfo import com.unciv.models.ruleset.unit.UnitType +import com.unciv.models.translations.equalsPlaceholderText import com.unciv.ui.worldscreen.unit.UnitActions object UnitAutomation { @@ -90,17 +90,24 @@ object UnitAutomation { if (unit.civInfo.isBarbarian()) throw IllegalStateException("Barbarians is not allowed here.") - if (unit.name == Constants.settler) - return SpecificUnitAutomation.automateSettlerActions(unit) + if(unit.type==UnitType.Civilian) { + if (unit.name == Constants.settler) + return SpecificUnitAutomation.automateSettlerActions(unit) - if (unit.hasUnique(Constants.workerUnique)) - return WorkerAutomation(unit).automateWorkerAction() + if (unit.hasUnique(Constants.workerUnique)) + return WorkerAutomation(unit).automateWorkerAction() - if (unit.name == "Work Boats") - return SpecificUnitAutomation.automateWorkBoats(unit) + if (unit.name == "Work Boats") + return SpecificUnitAutomation.automateWorkBoats(unit) - if (unit.name == Constants.greatGeneral || unit.baseUnit.replaces == Constants.greatGeneral) - return SpecificUnitAutomation.automateGreatGeneral(unit) + if (unit.name == Constants.greatGeneral || unit.baseUnit.replaces == Constants.greatGeneral) + return SpecificUnitAutomation.automateGreatGeneral(unit) + + if (unit.getUniques().any { it.equalsPlaceholderText("Can construct []") }) + return SpecificUnitAutomation.automateImprovementPlacer(unit) // includes great people plus moddable units + + return // The AI doesn't know how to handle unknown civilian units + } if (unit.type == UnitType.Fighter) return SpecificUnitAutomation.automateFighter(unit) @@ -112,10 +119,6 @@ object UnitAutomation { return SpecificUnitAutomation.automateMissile(unit) - if (unit.name.startsWith("Great") - && unit.name in GreatPersonManager().statToGreatPersonMapping.values)// So "Great War Infantry" isn't caught here - return SpecificUnitAutomation.automateGreatPerson(unit) - if (tryGoToRuinAndEncampment(unit)) { if (unit.currentMovement == 0f) return } diff --git a/core/src/com/unciv/ui/worldscreen/unit/UnitActions.kt b/core/src/com/unciv/ui/worldscreen/unit/UnitActions.kt index f88a2f2e67..890efa8b40 100644 --- a/core/src/com/unciv/ui/worldscreen/unit/UnitActions.kt +++ b/core/src/com/unciv/ui/worldscreen/unit/UnitActions.kt @@ -15,6 +15,8 @@ import com.unciv.models.UncivSound import com.unciv.models.UnitAction import com.unciv.models.UnitActionType import com.unciv.models.ruleset.Building +import com.unciv.models.translations.equalsPlaceholderText +import com.unciv.models.translations.getPlaceholderParameters import com.unciv.models.translations.tr import com.unciv.ui.pickerscreens.ImprovementPickerScreen import com.unciv.ui.pickerscreens.PromotionPickerScreen @@ -67,11 +69,13 @@ object UnitActions { addConstructRoadsAction(unit, tile, actionList) addCreateWaterImprovements(unit, actionList) addGreatPersonActions(unit, actionList, tile) + actionList += getImprovementConstructionActions(unit, tile) addDisbandAction(actionList, unit, worldScreen) return actionList } + private fun addDisbandAction(actionList: ArrayList, unit: MapUnit, worldScreen: WorldScreen) { actionList += UnitAction( type = UnitActionType.DisbandUnit, @@ -347,16 +351,14 @@ object UnitActions { unit.destroy() }.takeIf { canConductTradeMission }) } - - val buildImprovementAction = getBuildImprovementAction(unit) - if (buildImprovementAction != null) actionList += buildImprovementAction } - fun getBuildImprovementAction(unit: MapUnit): UnitAction? { - val tile = unit.currentTile - for (unique in unit.getUniques().filter { it.startsWith("Can build improvement: ") }) { - val improvementName = unique.replace("Can build improvement: ", "") - return UnitAction( + + fun getImprovementConstructionActions(unit: MapUnit, tile: TileInfo): ArrayList { + val finalActions = ArrayList() + for (unique in unit.getUniques().filter { it.equalsPlaceholderText("Can construct []") }) { + val improvementName = unique.getPlaceholderParameters()[0] + finalActions += UnitAction( type = UnitActionType.Create, title = "Create [$improvementName]", uncivSound = UncivSound.Chimes, @@ -384,7 +386,7 @@ object UnitActions { (improvementName != Constants.citadel || tile.neighbors.any { it.getOwner() == unit.civInfo })}) } - return null + return finalActions } private fun takeOverTilesAround(unit: MapUnit) {