diff --git a/core/src/com/unciv/ui/worldscreen/unit/UnitActions.kt b/core/src/com/unciv/ui/worldscreen/unit/UnitActions.kt index 96f7519382..c560635c02 100644 --- a/core/src/com/unciv/ui/worldscreen/unit/UnitActions.kt +++ b/core/src/com/unciv/ui/worldscreen/unit/UnitActions.kt @@ -53,155 +53,40 @@ class UnitActions { ) } - if (!unit.type.isAirUnit()) { - if (unit.action != Constants.unitActionExplore) { - actionList += UnitAction( - type = UnitActionType.Explore, - canAct = true, - action = { - UnitAutomation().automatedExplore(unit) - unit.action = Constants.unitActionExplore - }) - } else { - actionList += UnitAction( - type = UnitActionType.StopExploration, - canAct = true, - action = { unit.action = null } - ) - } - } + addExplorationActions(unit, actionList) + addPromoteAction(unit, actionList) + addUnitUpgradeAction(unit, tile, actionList, worldScreen) + addPillageAction(unit, tile, actionList) + addSetupAction(unit, actionList) + addFoundCityAction(unit, actionList, tile) + addWorkerActions(unit, actionList, tile, worldScreen, unitTable) + addConstructRoadsAction(unit, tile, actionList) + addCreateWaterImprovements(unit, tile, actionList) + addGreatPersonActions(unit, actionList, tile) + addDisbandAction(actionList, unit, worldScreen) - if (!unit.type.isCivilian() && unit.promotions.canBePromoted()) { - // promotion does not consume movement points, so we can do it always - actionList += UnitAction( - type = UnitActionType.Promote, - canAct = true, - uncivSound = UncivSound.Promote, - action = { - UncivGame.Current.setScreen(PromotionPickerScreen(unit)) - }) - } + return actionList + } - if (unit.baseUnit().upgradesTo != null && tile.getOwner() == unit.civInfo) { - if (unit.canUpgrade()) { - val goldCostOfUpgrade = unit.getCostOfUpgrade() - val upgradedUnit = unit.getUnitToUpgradeTo() - - actionList += UnitAction( - type = UnitActionType.Upgrade, - title = "Upgrade to [${upgradedUnit.name}] ([$goldCostOfUpgrade] gold)", - canAct = unit.civInfo.gold >= goldCostOfUpgrade && !unit.isEmbarked() && unit.currentMovement == unit.getMaxMovement().toFloat(), - uncivSound = UncivSound.Upgrade, - action = { - unit.civInfo.gold -= goldCostOfUpgrade - val unitTile = unit.getTile() - unit.destroy() - val newunit = unit.civInfo.placeUnitNearTile(unitTile.position, upgradedUnit.name)!! - newunit.health = unit.health - newunit.promotions = unit.promotions - - for (promotion in newunit.baseUnit.promotions) - if (promotion !in newunit.promotions.promotions) - newunit.promotions.addPromotion(promotion, true) - - newunit.updateUniques() - newunit.updateVisibleTiles() - newunit.currentMovement = 0f - worldScreen.shouldUpdate = true - }) - } - } - - if (!unit.type.isCivilian() && tile.improvement != null) { - actionList += UnitAction( - type = UnitActionType.Pillage, - canAct = unit.currentMovement > 0 && canPillage(unit, tile), - action = { - // http://well-of-souls.com/civ/civ5_improvements.html says that naval improvements are destroyed upon pilllage - // and I can't find any other sources so I'll go with that - if (tile.isLand) { - tile.improvementInProgress = tile.improvement - tile.turnsToImprovement = 2 - } - tile.improvement = null - if (!unit.hasUnique("No movement cost to pillage")) unit.useMovementPoints(1f) - unit.healBy(25) - }) - } - - if (unit.hasUnique("Must set up to ranged attack") && !unit.isEmbarked()) { - val setUp = unit.action == "Set Up" - actionList += UnitAction( - type = UnitActionType.SetUp, - canAct = unit.currentMovement > 0 && !setUp, - isCurrentAction = setUp, - uncivSound = UncivSound.Setup, - action = { - unit.action = Constants.unitActionSetUp - unit.useMovementPoints(1f) - }) - } - - if (unit.hasUnique("Founds a new city") && !unit.isEmbarked()) { - actionList += UnitAction( - type = UnitActionType.FoundCity, - canAct = unit.currentMovement > 0 && !tile.getTilesInDistance(3).any { it.isCityCenter() }, - uncivSound = UncivSound.Chimes, - action = { - UncivGame.Current.settings.addCompletedTutorialTask("Found city") - unit.civInfo.addCity(tile.position) - tile.improvement = null - unit.destroy() - }) - } - - if (unit.hasUnique("Can build improvements on tiles") && !unit.isEmbarked()) { - actionList += UnitAction( - type = UnitActionType.ConstructImprovement, - canAct = unit.currentMovement > 0 - && !tile.isCityCenter() - && unit.civInfo.gameInfo.ruleSet.tileImprovements.values.any { tile.canBuildImprovement(it, unit.civInfo) }, - isCurrentAction = unit.currentTile.hasImprovementInProgress(), - action = { - worldScreen.game.setScreen(ImprovementPickerScreen(tile) { unitTable.selectedUnit = null }) - }) - - if (Constants.unitActionAutomation == unit.action) { - actionList += UnitAction( - type = UnitActionType.StopAutomation, - canAct = true, - action = { unit.action = null } - ) - } else { - actionList += UnitAction( - type = UnitActionType.Automate, - canAct = unit.currentMovement > 0, - action = { - unit.action = Constants.unitActionAutomation - WorkerAutomation(unit).automateWorkerAction() - }) - } - } - - if (unit.hasUnique("Can construct roads") - && tile.roadStatus == RoadStatus.None - && tile.improvementInProgress != "Road" - && tile.isLand - && unit.civInfo.tech.isResearched(RoadStatus.Road.improvement(unit.civInfo.gameInfo.ruleSet)!!.techRequired!!)) - actionList += UnitAction( - type = UnitActionType.ConstructRoad, - canAct = unit.currentMovement > 0, - action = { - tile.improvementInProgress = "Road" - tile.turnsToImprovement = 4 - }) + private fun addDisbandAction(actionList: ArrayList, unit: MapUnit, worldScreen: WorldScreen) { + actionList += UnitAction( + type = UnitActionType.DisbandUnit, + canAct = unit.currentMovement > 0, + action = { + val disbandText = if (unit.currentTile.getOwner() == unit.civInfo) + "Disband this unit for [${unit.baseUnit.getDisbandGold()}] gold?".tr() + else "Do you really want to disband this unit?".tr() + YesNoPopup(disbandText, { unit.disband(); worldScreen.shouldUpdate = true }).open() + }) + } + private fun addCreateWaterImprovements(unit: MapUnit, tile: TileInfo, actionList: ArrayList) { for (improvement in listOf("Fishing Boats", "Oil well")) { if (unit.hasUnique("May create improvements on water resources") && tile.resource != null - && tile.isWater // because fishing boats can enter cities, and if there's oil in the city... ;) - && tile.improvement == null - && tile.getTileResource().improvement == improvement - && unit.civInfo.tech.isResearched(unit.civInfo.gameInfo.ruleSet.tileImprovements[improvement]!!.techRequired!!) + && tile.isWater // because fishing boats can enter cities, and if there's oil in the city... ;) + && tile.improvement == null + && tile.getTileResource().improvement == improvement + && unit.civInfo.tech.isResearched(unit.civInfo.gameInfo.ruleSet.tileImprovements[improvement]!!.techRequired!!) ) actionList += UnitAction( type = UnitActionType.Create, @@ -212,7 +97,160 @@ class UnitActions { unit.destroy() }) } + } + private fun addConstructRoadsAction(unit: MapUnit, tile: TileInfo, actionList: ArrayList) { + if (unit.hasUnique("Can construct roads") + && tile.roadStatus == RoadStatus.None + && tile.improvementInProgress != "Road" + && tile.isLand + && unit.civInfo.tech.isResearched(RoadStatus.Road.improvement(unit.civInfo.gameInfo.ruleSet)!!.techRequired!!)) + actionList += UnitAction( + type = UnitActionType.ConstructRoad, + canAct = unit.currentMovement > 0, + action = { + tile.improvementInProgress = "Road" + tile.turnsToImprovement = 4 + }) + } + + private fun addFoundCityAction(unit: MapUnit, actionList: ArrayList, tile: TileInfo) { + if (!unit.hasUnique("Founds a new city") || unit.isEmbarked()) return + actionList += UnitAction( + type = UnitActionType.FoundCity, + canAct = unit.currentMovement > 0 && !tile.getTilesInDistance(3).any { it.isCityCenter() }, + uncivSound = UncivSound.Chimes, + action = { + UncivGame.Current.settings.addCompletedTutorialTask("Found city") + unit.civInfo.addCity(tile.position) + tile.improvement = null + unit.destroy() + }) + } + + private fun addPromoteAction(unit: MapUnit, actionList: ArrayList) { + if (unit.type.isCivilian() || !unit.promotions.canBePromoted()) return + // promotion does not consume movement points, so we can do it always + actionList += UnitAction( + type = UnitActionType.Promote, + canAct = true, + uncivSound = UncivSound.Promote, + action = { + UncivGame.Current.setScreen(PromotionPickerScreen(unit)) + }) + } + + private fun addSetupAction(unit: MapUnit, actionList: ArrayList) { + if (!unit.hasUnique("Must set up to ranged attack") || unit.isEmbarked()) return + val isSetUp = unit.action == "Set Up" + actionList += UnitAction( + type = UnitActionType.SetUp, + canAct = unit.currentMovement > 0 && !isSetUp, + isCurrentAction = isSetUp, + uncivSound = UncivSound.Setup, + action = { + unit.action = Constants.unitActionSetUp + unit.useMovementPoints(1f) + }) + } + + private fun addPillageAction(unit: MapUnit, tile: TileInfo, actionList: ArrayList) { + if (unit.type.isCivilian() || tile.improvement == null) return + actionList += UnitAction( + type = UnitActionType.Pillage, + canAct = unit.currentMovement > 0 && canPillage(unit, tile), + action = { + // http://well-of-souls.com/civ/civ5_improvements.html says that naval improvements are destroyed upon pilllage + // and I can't find any other sources so I'll go with that + if (tile.isLand) { + tile.improvementInProgress = tile.improvement + tile.turnsToImprovement = 2 + } + tile.improvement = null + if (!unit.hasUnique("No movement cost to pillage")) unit.useMovementPoints(1f) + unit.healBy(25) + }) + } + + private fun addExplorationActions(unit: MapUnit, actionList: ArrayList) { + if (unit.type.isAirUnit()) return + if (unit.action != Constants.unitActionExplore) { + actionList += UnitAction( + type = UnitActionType.Explore, + canAct = true, + action = { + UnitAutomation().automatedExplore(unit) + unit.action = Constants.unitActionExplore + }) + } else { + actionList += UnitAction( + type = UnitActionType.StopExploration, + canAct = true, + action = { unit.action = null } + ) + } + } + + private fun addUnitUpgradeAction(unit: MapUnit, tile: TileInfo, actionList: ArrayList, worldScreen: WorldScreen) { + if (unit.baseUnit().upgradesTo == null || tile.getOwner() != unit.civInfo) return + if (!unit.canUpgrade()) return + val goldCostOfUpgrade = unit.getCostOfUpgrade() + val upgradedUnit = unit.getUnitToUpgradeTo() + + actionList += UnitAction( + type = UnitActionType.Upgrade, + title = "Upgrade to [${upgradedUnit.name}] ([$goldCostOfUpgrade] gold)", + canAct = unit.civInfo.gold >= goldCostOfUpgrade && !unit.isEmbarked() && unit.currentMovement == unit.getMaxMovement().toFloat(), + uncivSound = UncivSound.Upgrade, + action = { + unit.civInfo.gold -= goldCostOfUpgrade + val unitTile = unit.getTile() + unit.destroy() + val newunit = unit.civInfo.placeUnitNearTile(unitTile.position, upgradedUnit.name)!! + newunit.health = unit.health + newunit.promotions = unit.promotions + + for (promotion in newunit.baseUnit.promotions) + if (promotion !in newunit.promotions.promotions) + newunit.promotions.addPromotion(promotion, true) + + newunit.updateUniques() + newunit.updateVisibleTiles() + newunit.currentMovement = 0f + worldScreen.shouldUpdate = true + }) + } + + private fun addWorkerActions(unit: MapUnit, actionList: ArrayList, tile: TileInfo, worldScreen: WorldScreen, unitTable: UnitTable) { + if (!unit.hasUnique("Can build improvements on tiles") || unit.isEmbarked()) return + actionList += UnitAction( + type = UnitActionType.ConstructImprovement, + canAct = unit.currentMovement > 0 + && !tile.isCityCenter() + && unit.civInfo.gameInfo.ruleSet.tileImprovements.values.any { tile.canBuildImprovement(it, unit.civInfo) }, + isCurrentAction = unit.currentTile.hasImprovementInProgress(), + action = { + worldScreen.game.setScreen(ImprovementPickerScreen(tile) { unitTable.selectedUnit = null }) + }) + + if (Constants.unitActionAutomation == unit.action) { + actionList += UnitAction( + type = UnitActionType.StopAutomation, + canAct = true, + action = { unit.action = null } + ) + } else { + actionList += UnitAction( + type = UnitActionType.Automate, + canAct = unit.currentMovement > 0, + action = { + unit.action = Constants.unitActionAutomation + WorkerAutomation(unit).automateWorkerAction() + }) + } + } + + private fun addGreatPersonActions(unit: MapUnit, actionList: ArrayList, tile: TileInfo) { for (unique in unit.getUniques().filter { it.startsWith("Can build improvement: ") }) { val improvementName = unique.replace("Can build improvement: ", "") actionList += UnitAction( @@ -274,8 +312,8 @@ class UnitActions { if (unit.name == "Great Merchant" && !unit.isEmbarked()) { val canConductTradeMission = tile.owningCity?.civInfo?.isCityState() == true - && tile.owningCity?.civInfo?.isAtWarWith(unit.civInfo) == false - && unit.currentMovement > 0 + && tile.owningCity?.civInfo?.isAtWarWith(unit.civInfo) == false + && unit.currentMovement > 0 actionList += UnitAction( type = UnitActionType.ConductTradeMission, canAct = canConductTradeMission, @@ -293,18 +331,6 @@ class UnitActions { unit.destroy() }) } - - actionList += UnitAction( - type = UnitActionType.DisbandUnit, - canAct = unit.currentMovement > 0, - action = { - val disbandText = if (unit.currentTile.getOwner() == unit.civInfo) - "Disband this unit for [${unit.baseUnit.getDisbandGold()}] gold?".tr() - else "Do you really want to disband this unit?".tr() - YesNoPopup(disbandText, { unit.disband(); worldScreen.shouldUpdate = true }).open() - }) - - return actionList } private fun addFortifyActions(actionList: ArrayList, unit: MapUnit, unitTable: UnitTable) {