mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-23 03:23:17 -04:00
chore: separated unit actions into several files
This commit is contained in:
parent
35399eb74c
commit
783a469da5
@ -1,16 +0,0 @@
|
||||
java.lang.NullPointerException
|
||||
at com.unciv.ui.worldscreen.AlertPopup.<init>(AlertPopup.kt:318)
|
||||
at com.unciv.ui.worldscreen.WorldScreen.update(WorldScreen.kt:450)
|
||||
at com.unciv.ui.worldscreen.WorldScreen.render(WorldScreen.kt:830)
|
||||
at com.badlogic.gdx.Game.render(Game.java:48)
|
||||
at com.unciv.UncivGame.access$render$s2211858(UncivGame.kt:50)
|
||||
at com.unciv.UncivGame$wrappedCrashHandlingRender$1.invoke(UncivGame.kt:89)
|
||||
at com.unciv.UncivGame$wrappedCrashHandlingRender$1.invoke(UncivGame.kt:89)
|
||||
at com.unciv.ui.crashhandling.CrashHandlingExtensionsKt$wrapCrashHandling$1.invoke(CrashHandlingExtensions.kt:17)
|
||||
at com.unciv.ui.crashhandling.CrashHandlingExtensionsKt$wrapCrashHandlingUnit$1.invoke(CrashHandlingExtensions.kt:33)
|
||||
at com.unciv.ui.crashhandling.CrashHandlingExtensionsKt$wrapCrashHandlingUnit$1.invoke(CrashHandlingExtensions.kt:33)
|
||||
at com.unciv.UncivGame.render(UncivGame.kt:392)
|
||||
at com.badlogic.gdx.backends.lwjgl3.Lwjgl3Window.update(Lwjgl3Window.java:387)
|
||||
at com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application.loop(Lwjgl3Application.java:192)
|
||||
at com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application.<init>(Lwjgl3Application.java:166)
|
||||
at com.unciv.app.desktop.DesktopLauncher.main(DesktopLauncher.kt:87)
|
@ -16,7 +16,8 @@ import com.unciv.models.ruleset.tile.ResourceType
|
||||
import com.unciv.models.ruleset.tile.TileResource
|
||||
import com.unciv.models.ruleset.unique.UniqueType
|
||||
import com.unciv.models.stats.Stat
|
||||
import com.unciv.ui.worldscreen.unit.UnitActions
|
||||
import com.unciv.ui.worldscreen.unit.actions.UnitActions
|
||||
import com.unciv.ui.worldscreen.unit.actions.UnitActionsReligion
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
@ -557,7 +558,7 @@ object SpecificUnitAutomation {
|
||||
return
|
||||
}
|
||||
|
||||
UnitActions.getFoundReligionAction(unit)()
|
||||
UnitActionsReligion.getFoundReligionAction(unit)()
|
||||
}
|
||||
|
||||
fun enhanceReligion(unit: MapUnit) {
|
||||
@ -569,12 +570,12 @@ object SpecificUnitAutomation {
|
||||
if (!unit.getTile().isCityCenter())
|
||||
return
|
||||
|
||||
UnitActions.getEnhanceReligionAction(unit)()
|
||||
UnitActionsReligion.getEnhanceReligionAction(unit)()
|
||||
}
|
||||
|
||||
private fun doReligiousAction(unit: MapUnit, destination: Tile) {
|
||||
val religiousActions = ArrayList<UnitAction>()
|
||||
UnitActions.addActionsWithLimitedUses(unit, religiousActions, destination)
|
||||
UnitActionsReligion.addActionsWithLimitedUses(unit, religiousActions, destination)
|
||||
if (religiousActions.firstOrNull()?.action == null) return
|
||||
religiousActions.first().action!!.invoke()
|
||||
}
|
||||
|
@ -15,7 +15,9 @@ import com.unciv.logic.civilization.managers.ReligionState
|
||||
import com.unciv.logic.map.mapunit.MapUnit
|
||||
import com.unciv.logic.map.tile.Tile
|
||||
import com.unciv.models.ruleset.unique.UniqueType
|
||||
import com.unciv.ui.worldscreen.unit.UnitActions
|
||||
import com.unciv.ui.worldscreen.unit.actions.UnitActions
|
||||
import com.unciv.ui.worldscreen.unit.actions.UnitActionsPillage
|
||||
import com.unciv.ui.worldscreen.unit.actions.UnitActionsUpgrade
|
||||
|
||||
object UnitAutomation {
|
||||
|
||||
@ -124,7 +126,7 @@ object UnitAutomation {
|
||||
if (!Automation.allowSpendingResource(unit.civInfo, upgradedUnit)) return false
|
||||
}
|
||||
|
||||
val upgradeAction = UnitActions.getUpgradeAction(unit)
|
||||
val upgradeAction = UnitActionsUpgrade.getUpgradeAction(unit)
|
||||
?: return false
|
||||
|
||||
upgradeAction.action?.invoke()
|
||||
@ -372,7 +374,7 @@ object UnitAutomation {
|
||||
if (unit.getTile() != tileToPillage)
|
||||
unit.movement.moveToTile(tileToPillage)
|
||||
|
||||
UnitActions.getPillageAction(unit)?.action?.invoke()
|
||||
UnitActionsPillage.getPillageAction(unit)?.action?.invoke()
|
||||
return unit.currentMovement == 0f
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ import com.unciv.logic.map.tile.Tile
|
||||
import com.unciv.models.ruleset.tile.Terrain
|
||||
import com.unciv.models.ruleset.tile.TileImprovement
|
||||
import com.unciv.models.ruleset.unique.UniqueType
|
||||
import com.unciv.ui.worldscreen.unit.UnitActions
|
||||
import com.unciv.ui.worldscreen.unit.actions.UnitActions
|
||||
import com.unciv.utils.Log
|
||||
import com.unciv.utils.debug
|
||||
|
||||
|
@ -26,7 +26,7 @@ import com.unciv.ui.civilopedia.FormattedLine
|
||||
import com.unciv.ui.utils.Fonts
|
||||
import com.unciv.ui.utils.extensions.withItem
|
||||
import com.unciv.ui.utils.extensions.withoutItem
|
||||
import com.unciv.ui.worldscreen.unit.UnitActions
|
||||
import com.unciv.ui.worldscreen.unit.actions.UnitActions
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
|
@ -87,7 +87,8 @@ class TileMap : IsPartOfGameInfoSerialization {
|
||||
val startingLocationsByNation = HashMap<String,HashSet<Tile>>()
|
||||
|
||||
@Transient
|
||||
val continentSizes = HashMap<Int, Int>() // Continent ID, Continent size
|
||||
/** Continent ID to Continent size */
|
||||
val continentSizes = HashMap<Int, Int>()
|
||||
|
||||
//endregion
|
||||
//region Constructors
|
||||
|
@ -1016,15 +1016,6 @@ class MapUnit : IsPartOfGameInfoSerialization {
|
||||
}
|
||||
|
||||
|
||||
fun getPressureAddedFromSpread(): Int {
|
||||
var pressureAdded = baseUnit.religiousStrength.toFloat()
|
||||
|
||||
for (unique in getMatchingUniques(UniqueType.SpreadReligionStrength, checkCivInfoUniques = true))
|
||||
pressureAdded *= unique.params[0].toPercent()
|
||||
|
||||
return pressureAdded.toInt()
|
||||
}
|
||||
|
||||
fun getActionString(action: String): String {
|
||||
val maxActionUses = maxAbilityUses[action]
|
||||
if (abilityUsesLeft[action] == null) return "0/0" // Something went wrong
|
||||
|
@ -16,7 +16,7 @@ import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.civilopedia.CivilopediaScreen.Companion.showReligionInCivilopedia
|
||||
import com.unciv.ui.civilopedia.FormattedLine
|
||||
import com.unciv.ui.utils.extensions.toPercent
|
||||
import com.unciv.ui.worldscreen.unit.UnitActions
|
||||
import com.unciv.ui.worldscreen.unit.actions.UnitActions
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class TileImprovement : RulesetStatsObject() {
|
||||
|
@ -20,7 +20,7 @@ import com.unciv.models.stats.Stats
|
||||
import com.unciv.models.translations.fillPlaceholders
|
||||
import com.unciv.models.translations.hasPlaceholderParameters
|
||||
import com.unciv.ui.utils.MayaCalendar
|
||||
import com.unciv.ui.worldscreen.unit.UnitActions
|
||||
import com.unciv.ui.worldscreen.unit.actions.UnitActionsUpgrade
|
||||
import kotlin.random.Random
|
||||
|
||||
// Buildings, techs, policies, ancient ruins and promotions can have 'triggered' effects
|
||||
@ -377,10 +377,8 @@ object UniqueTriggerActivation {
|
||||
|| unique.params[1].toIntOrNull() == null
|
||||
) return false
|
||||
|
||||
val finalStatAmount =
|
||||
(tileBasedRandom.nextInt(unique.params[0].toInt(), unique.params[1].toInt()) *
|
||||
civInfo.gameInfo.speed.statCostModifiers[stat]!!
|
||||
).toFloat()
|
||||
val finalStatAmount = tileBasedRandom.nextInt(unique.params[0].toInt(), unique.params[1].toInt()) *
|
||||
civInfo.gameInfo.speed.statCostModifiers[stat]!!
|
||||
|
||||
val stats = Stats().add(stat, finalStatAmount)
|
||||
civInfo.addStats(stats)
|
||||
@ -592,7 +590,7 @@ object UniqueTriggerActivation {
|
||||
return true
|
||||
}
|
||||
UniqueType.OneTimeUnitUpgrade -> {
|
||||
val upgradeAction = UnitActions.getFreeUpgradeAction(unit)
|
||||
val upgradeAction = UnitActionsUpgrade.getFreeUpgradeAction(unit)
|
||||
?: return false
|
||||
upgradeAction.action!!()
|
||||
if (notification != null)
|
||||
@ -600,7 +598,7 @@ object UniqueTriggerActivation {
|
||||
return true
|
||||
}
|
||||
UniqueType.OneTimeUnitSpecialUpgrade -> {
|
||||
val upgradeAction = UnitActions.getAncientRuinsUpgradeAction(unit)
|
||||
val upgradeAction = UnitActionsUpgrade.getAncientRuinsUpgradeAction(unit)
|
||||
?: return false
|
||||
upgradeAction.action!!()
|
||||
if (notification != null)
|
||||
|
@ -27,7 +27,7 @@ import com.unciv.ui.utils.extensions.darken
|
||||
import com.unciv.ui.utils.extensions.onClick
|
||||
import com.unciv.ui.utils.extensions.surroundWithCircle
|
||||
import com.unciv.ui.utils.extensions.toLabel
|
||||
import com.unciv.ui.worldscreen.unit.UnitActions
|
||||
import com.unciv.ui.worldscreen.unit.actions.UnitActionsUpgrade
|
||||
import kotlin.math.abs
|
||||
|
||||
/**
|
||||
@ -230,7 +230,7 @@ class UnitOverviewTab(
|
||||
|
||||
// Upgrade column
|
||||
if (unit.upgrade.canUpgrade()) {
|
||||
val unitAction = UnitActions.getUpgradeAction(unit)
|
||||
val unitAction = UnitActionsUpgrade.getUpgradeAction(unit)
|
||||
val enable = unitAction?.action != null
|
||||
val upgradeIcon = ImageGetter.getUnitIcon(unit.upgrade.getUnitToUpgradeTo().name,
|
||||
if (enable) Color.GREEN else Color.GREEN.darken(0.5f))
|
||||
|
@ -65,7 +65,7 @@ import com.unciv.ui.worldscreen.status.MultiplayerStatusButton
|
||||
import com.unciv.ui.worldscreen.status.NextTurnAction
|
||||
import com.unciv.ui.worldscreen.status.NextTurnButton
|
||||
import com.unciv.ui.worldscreen.status.StatusButtons
|
||||
import com.unciv.ui.worldscreen.unit.UnitActionsTable
|
||||
import com.unciv.ui.worldscreen.unit.actions.UnitActionsTable
|
||||
import com.unciv.ui.worldscreen.unit.UnitTable
|
||||
import com.unciv.utils.concurrency.Concurrency
|
||||
import com.unciv.utils.concurrency.launchOnGLThread
|
||||
|
@ -1,10 +1,9 @@
|
||||
package com.unciv.ui.worldscreen.unit
|
||||
package com.unciv.ui.worldscreen.unit.actions
|
||||
|
||||
import com.unciv.Constants
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.logic.automation.unit.UnitAutomation
|
||||
import com.unciv.logic.automation.unit.WorkerAutomation
|
||||
import com.unciv.logic.city.City
|
||||
import com.unciv.logic.civilization.Civilization
|
||||
import com.unciv.logic.civilization.NotificationCategory
|
||||
import com.unciv.logic.civilization.NotificationIcon
|
||||
@ -17,22 +16,17 @@ import com.unciv.models.Counter
|
||||
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.ruleset.unique.StateForConditionals
|
||||
import com.unciv.models.ruleset.unique.UniqueTriggerActivation
|
||||
import com.unciv.models.ruleset.unique.UniqueType
|
||||
import com.unciv.models.stats.Stat
|
||||
import com.unciv.models.stats.Stats
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.pickerscreens.ImprovementPickerScreen
|
||||
import com.unciv.ui.pickerscreens.PromotionPickerScreen
|
||||
import com.unciv.ui.popup.ConfirmPopup
|
||||
import com.unciv.ui.popup.hasOpenPopups
|
||||
import com.unciv.ui.utils.Fonts
|
||||
import com.unciv.ui.utils.extensions.toPercent
|
||||
import com.unciv.ui.worldscreen.WorldScreen
|
||||
import kotlin.math.min
|
||||
import kotlin.random.Random
|
||||
import com.unciv.ui.worldscreen.unit.UnitTable
|
||||
|
||||
object UnitActions {
|
||||
|
||||
@ -57,9 +51,9 @@ object UnitActions {
|
||||
addFortifyActions(actionList, unit, false)
|
||||
|
||||
addPromoteAction(unit, actionList)
|
||||
addUnitUpgradeAction(unit, actionList)
|
||||
UnitActionsUpgrade.addUnitUpgradeAction(unit, actionList)
|
||||
addTransformAction(unit, actionList)
|
||||
addPillageAction(unit, actionList, worldScreen)
|
||||
UnitActionsPillage.addPillageAction(unit, actionList, worldScreen)
|
||||
addParadropAction(unit, actionList)
|
||||
addAirSweepAction(unit, actionList)
|
||||
addSetupAction(unit, actionList)
|
||||
@ -67,11 +61,11 @@ object UnitActions {
|
||||
addBuildingImprovementsAction(unit, actionList, tile, worldScreen, unitTable)
|
||||
addRepairAction(unit, actionList)
|
||||
addCreateWaterImprovements(unit, actionList)
|
||||
addGreatPersonActions(unit, actionList, tile)
|
||||
addFoundReligionAction(unit, actionList)
|
||||
addEnhanceReligionAction(unit, actionList)
|
||||
UnitActionsGreatPerson.addGreatPersonActions(unit, actionList, tile)
|
||||
UnitActionsReligion.addFoundReligionAction(unit, actionList)
|
||||
UnitActionsReligion.addEnhanceReligionAction(unit, actionList)
|
||||
actionList += getImprovementConstructionActions(unit, tile)
|
||||
addActionsWithLimitedUses(unit, actionList, tile)
|
||||
UnitActionsReligion.addActionsWithLimitedUses(unit, actionList, tile)
|
||||
addExplorationActions(unit, actionList)
|
||||
addAutomateBuildingImprovementsAction(unit, actionList)
|
||||
addTriggerUniqueActions(unit, actionList)
|
||||
@ -289,96 +283,6 @@ object UnitActions {
|
||||
)
|
||||
}
|
||||
|
||||
private fun addPillageAction(unit: MapUnit, actionList: ArrayList<UnitAction>, worldScreen: WorldScreen) {
|
||||
val pillageAction = getPillageAction(unit)
|
||||
?: return
|
||||
if (pillageAction.action == null)
|
||||
actionList += UnitAction(UnitActionType.Pillage,
|
||||
title = "${UnitActionType.Pillage} [${unit.currentTile.getImprovementToPillageName()!!}]",
|
||||
action = null)
|
||||
else actionList += UnitAction(type = UnitActionType.Pillage,
|
||||
title = "${UnitActionType.Pillage} [${unit.currentTile.getImprovementToPillageName()!!}]") {
|
||||
if (!worldScreen.hasOpenPopups()) {
|
||||
val pillageText = "Are you sure you want to pillage this [${unit.currentTile.getImprovementToPillageName()!!}]?"
|
||||
ConfirmPopup(
|
||||
UncivGame.Current.worldScreen!!,
|
||||
pillageText,
|
||||
"Pillage",
|
||||
true
|
||||
) {
|
||||
(pillageAction.action)()
|
||||
worldScreen.shouldUpdate = true
|
||||
}.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getPillageAction(unit: MapUnit): UnitAction? {
|
||||
val tile = unit.currentTile
|
||||
if (unit.isCivilian() || !tile.canPillageTile() || tile.getOwner() == unit.civInfo) return null
|
||||
return UnitAction(UnitActionType.Pillage,
|
||||
action = {
|
||||
val pillagedImprovement = unit.currentTile.getImprovementToPillageName()!!
|
||||
val pillageText = "An enemy [${unit.baseUnit.name}] has pillaged our [$pillagedImprovement]"
|
||||
val icon = "ImprovementIcons/$pillagedImprovement"
|
||||
tile.getOwner()?.addNotification(
|
||||
pillageText,
|
||||
tile.position,
|
||||
NotificationCategory.War,
|
||||
icon,
|
||||
NotificationIcon.War,
|
||||
unit.baseUnit.name
|
||||
)
|
||||
|
||||
pillageLooting(tile, unit)
|
||||
tile.setPillaged()
|
||||
if (tile.resource != null) tile.getOwner()?.cache?.updateCivResources() // this might take away a resource
|
||||
tile.getCity()?.updateCitizens = true
|
||||
|
||||
val freePillage = unit.hasUnique(UniqueType.NoMovementToPillage, checkCivInfoUniques = true)
|
||||
if (!freePillage) unit.useMovementPoints(1f)
|
||||
|
||||
unit.healBy(25)
|
||||
}.takeIf { unit.currentMovement > 0 && canPillage(unit, tile) })
|
||||
}
|
||||
|
||||
private fun pillageLooting(tile: Tile, unit: MapUnit) {
|
||||
// Stats objects for reporting pillage results in a notification
|
||||
val pillageYield = Stats()
|
||||
val globalPillageYield = Stats()
|
||||
val toCityPillageYield = Stats()
|
||||
val closestCity = unit.civInfo.cities.minByOrNull { it.getCenterTile().aerialDistanceTo(tile) }
|
||||
val improvement = tile.getImprovementToPillage()!!
|
||||
|
||||
for (unique in improvement.getMatchingUniques(UniqueType.PillageYieldRandom)) {
|
||||
for (stat in unique.stats) {
|
||||
val looted = Random.nextInt((stat.value + 1).toInt()) + Random.nextInt((stat.value + 1).toInt())
|
||||
pillageYield.add(stat.key, looted.toFloat())
|
||||
}
|
||||
}
|
||||
for (unique in improvement.getMatchingUniques(UniqueType.PillageYieldFixed)) {
|
||||
for (stat in unique.stats) {
|
||||
pillageYield.add(stat.key, stat.value)
|
||||
}
|
||||
}
|
||||
|
||||
for (stat in pillageYield) {
|
||||
if (stat.key in Stat.statsWithCivWideField) {
|
||||
unit.civInfo.addStat(stat.key, stat.value.toInt())
|
||||
globalPillageYield[stat.key] += stat.value
|
||||
}
|
||||
else if (closestCity != null) {
|
||||
closestCity.addStat(stat.key, stat.value.toInt())
|
||||
toCityPillageYield[stat.key] += stat.value
|
||||
}
|
||||
}
|
||||
|
||||
val lootNotificationText = if (!toCityPillageYield.isEmpty() && closestCity != null)
|
||||
"We have looted [${toCityPillageYield.toStringWithoutIcons()}] from a [${improvement.name}] which has been sent to [${closestCity.name}]"
|
||||
else "We have looted [${globalPillageYield.toStringWithoutIcons()}] from a [${improvement.name}]"
|
||||
|
||||
unit.civInfo.addNotification(lootNotificationText, tile.position, NotificationCategory.War, "ImprovementIcons/${improvement.name}", NotificationIcon.War)
|
||||
}
|
||||
|
||||
private fun addExplorationActions(unit: MapUnit, actionList: ArrayList<UnitAction>) {
|
||||
if (unit.baseUnit.movesLikeAirUnits()) return
|
||||
@ -389,90 +293,6 @@ object UnitActions {
|
||||
}
|
||||
}
|
||||
|
||||
private fun addUnitUpgradeAction(
|
||||
unit: MapUnit,
|
||||
actionList: ArrayList<UnitAction>
|
||||
) {
|
||||
val upgradeAction = getUpgradeAction(unit)
|
||||
if (upgradeAction != null) actionList += upgradeAction
|
||||
}
|
||||
|
||||
/** Common implementation for [getUpgradeAction], [getFreeUpgradeAction] and [getAncientRuinsUpgradeAction] */
|
||||
private fun getUpgradeAction(
|
||||
unit: MapUnit,
|
||||
isFree: Boolean,
|
||||
isSpecial: Boolean
|
||||
): UnitAction? {
|
||||
if (unit.baseUnit().upgradesTo == null && unit.baseUnit().specialUpgradesTo == null) return null // can't upgrade to anything
|
||||
val unitTile = unit.getTile()
|
||||
val civInfo = unit.civInfo
|
||||
if (!isFree && unitTile.getOwner() != civInfo) return null
|
||||
|
||||
val upgradesTo = unit.baseUnit().upgradesTo
|
||||
val specialUpgradesTo = unit.baseUnit().specialUpgradesTo
|
||||
val upgradedUnit = when {
|
||||
isSpecial && specialUpgradesTo != null -> civInfo.getEquivalentUnit(specialUpgradesTo)
|
||||
(isFree || isSpecial) && upgradesTo != null -> civInfo.getEquivalentUnit(upgradesTo) // Only get DIRECT upgrade
|
||||
else -> unit.upgrade.getUnitToUpgradeTo() // Get EVENTUAL upgrade, all the way up the chain
|
||||
}
|
||||
|
||||
if (!unit.upgrade.canUpgrade(unitToUpgradeTo = upgradedUnit, ignoreRequirements = isFree, ignoreResources = true))
|
||||
return null
|
||||
|
||||
// Check _new_ resource requirements (display only - yes even for free or special upgrades)
|
||||
// Using Counter to aggregate is a bit exaggerated, but - respect the mad modder.
|
||||
val resourceRequirementsDelta = Counter<String>()
|
||||
for ((resource, amount) in unit.baseUnit().getResourceRequirements())
|
||||
resourceRequirementsDelta.add(resource, -amount)
|
||||
for ((resource, amount) in upgradedUnit.getResourceRequirements())
|
||||
resourceRequirementsDelta.add(resource, amount)
|
||||
val newResourceRequirementsString = resourceRequirementsDelta.entries
|
||||
.filter { it.value > 0 }
|
||||
.joinToString { "${it.value} {${it.key}}".tr() }
|
||||
|
||||
val goldCostOfUpgrade = if (isFree) 0 else unit.upgrade.getCostOfUpgrade(upgradedUnit)
|
||||
|
||||
// No string for "FREE" variants, these are never shown to the user.
|
||||
// The free actions are only triggered via OneTimeUnitUpgrade or OneTimeUnitSpecialUpgrade in UniqueTriggerActivation.
|
||||
val title = if (newResourceRequirementsString.isEmpty())
|
||||
"Upgrade to [${upgradedUnit.name}] ([$goldCostOfUpgrade] gold)"
|
||||
else "Upgrade to [${upgradedUnit.name}]\n([$goldCostOfUpgrade] gold, [$newResourceRequirementsString])"
|
||||
|
||||
return UnitAction(UnitActionType.Upgrade,
|
||||
title = title,
|
||||
action = {
|
||||
unit.destroy(destroyTransportedUnit = false)
|
||||
val newUnit = civInfo.units.placeUnitNearTile(unitTile.position, upgradedUnit.name)
|
||||
|
||||
/** We were UNABLE to place the new unit, which means that the unit failed to upgrade!
|
||||
* The only known cause of this currently is "land units upgrading to water units" which fail to be placed.
|
||||
*/
|
||||
if (newUnit == null) {
|
||||
val resurrectedUnit = civInfo.units.placeUnitNearTile(unitTile.position, unit.name)!!
|
||||
unit.copyStatisticsTo(resurrectedUnit)
|
||||
} else { // Managed to upgrade
|
||||
if (!isFree) civInfo.addGold(-goldCostOfUpgrade)
|
||||
unit.copyStatisticsTo(newUnit)
|
||||
newUnit.currentMovement = 0f
|
||||
}
|
||||
}.takeIf {
|
||||
isFree || (
|
||||
unit.civInfo.gold >= goldCostOfUpgrade
|
||||
&& unit.currentMovement > 0
|
||||
&& !unit.isEmbarked()
|
||||
&& unit.upgrade.canUpgrade(unitToUpgradeTo = upgradedUnit)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fun getUpgradeAction(unit: MapUnit) =
|
||||
getUpgradeAction(unit, isFree = false, isSpecial = false)
|
||||
fun getFreeUpgradeAction(unit: MapUnit) =
|
||||
getUpgradeAction(unit, isFree = true, isSpecial = false)
|
||||
fun getAncientRuinsUpgradeAction(unit: MapUnit) =
|
||||
getUpgradeAction(unit, isFree = true, isSpecial = true)
|
||||
|
||||
private fun addTransformAction(
|
||||
unit: MapUnit,
|
||||
actionList: ArrayList<UnitAction>
|
||||
@ -624,195 +444,6 @@ object UnitActions {
|
||||
actionList += getAddInCapitalAction(unit, tile)
|
||||
}
|
||||
|
||||
private fun addGreatPersonActions(unit: MapUnit, actionList: ArrayList<UnitAction>, tile: Tile) {
|
||||
|
||||
if (unit.currentMovement > 0) for (unique in unit.getUniques()) when (unique.type) {
|
||||
UniqueType.CanHurryResearch -> {
|
||||
actionList += UnitAction(UnitActionType.HurryResearch,
|
||||
action = {
|
||||
unit.civInfo.tech.addScience(unit.civInfo.tech.getScienceFromGreatScientist())
|
||||
unit.consume()
|
||||
}.takeIf { unit.civInfo.tech.currentTechnologyName() != null
|
||||
&& !unit.civInfo.tech.currentTechnology()!!.hasUnique(UniqueType.CannotBeHurried) }
|
||||
)
|
||||
}
|
||||
UniqueType.StartGoldenAge -> {
|
||||
val turnsToGoldenAge = unique.params[0].toInt()
|
||||
actionList += UnitAction(UnitActionType.StartGoldenAge,
|
||||
action = {
|
||||
unit.civInfo.goldenAges.enterGoldenAge(turnsToGoldenAge)
|
||||
unit.consume()
|
||||
}.takeIf { unit.currentTile.getOwner() != null && unit.currentTile.getOwner() == unit.civInfo }
|
||||
)
|
||||
}
|
||||
UniqueType.CanSpeedupWonderConstruction -> {
|
||||
val canHurryWonder =
|
||||
if (!tile.isCityCenter()) false
|
||||
else tile.getCity()!!.cityConstructions.isBuildingWonder()
|
||||
&& tile.getCity()!!.cityConstructions.canBeHurried()
|
||||
|
||||
actionList += UnitAction(UnitActionType.HurryWonder,
|
||||
action = {
|
||||
tile.getCity()!!.cityConstructions.apply {
|
||||
//http://civilization.wikia.com/wiki/Great_engineer_(Civ5)
|
||||
addProductionPoints(((300 + 30 * tile.getCity()!!.population.population) * unit.civInfo.gameInfo.speed.productionCostModifier).toInt())
|
||||
constructIfEnough()
|
||||
}
|
||||
|
||||
unit.consume()
|
||||
}.takeIf { canHurryWonder }
|
||||
)
|
||||
}
|
||||
|
||||
UniqueType.CanSpeedupConstruction -> {
|
||||
if (!tile.isCityCenter()) {
|
||||
actionList += UnitAction(UnitActionType.HurryBuilding, action = null)
|
||||
continue
|
||||
}
|
||||
|
||||
val cityConstructions = tile.getCity()!!.cityConstructions
|
||||
val canHurryConstruction = cityConstructions.getCurrentConstruction() is Building
|
||||
&& cityConstructions.canBeHurried()
|
||||
|
||||
//http://civilization.wikia.com/wiki/Great_engineer_(Civ5)
|
||||
val productionPointsToAdd = min(
|
||||
(300 + 30 * tile.getCity()!!.population.population) * unit.civInfo.gameInfo.speed.productionCostModifier,
|
||||
cityConstructions.getRemainingWork(cityConstructions.currentConstructionFromQueue).toFloat() - 1
|
||||
).toInt()
|
||||
if (productionPointsToAdd <= 0) continue
|
||||
|
||||
actionList += UnitAction(UnitActionType.HurryBuilding,
|
||||
title = "Hurry Construction (+[$productionPointsToAdd]⚙)",
|
||||
action = {
|
||||
cityConstructions.apply {
|
||||
addProductionPoints(productionPointsToAdd)
|
||||
constructIfEnough()
|
||||
}
|
||||
|
||||
unit.consume()
|
||||
}.takeIf { canHurryConstruction }
|
||||
)
|
||||
}
|
||||
UniqueType.CanTradeWithCityStateForGoldAndInfluence -> {
|
||||
val canConductTradeMission = tile.owningCity?.civInfo?.isCityState() == true
|
||||
&& tile.owningCity?.civInfo?.isAtWarWith(unit.civInfo) == false
|
||||
val influenceEarned = unique.params[0].toFloat()
|
||||
actionList += UnitAction(UnitActionType.ConductTradeMission,
|
||||
action = {
|
||||
// http://civilization.wikia.com/wiki/Great_Merchant_(Civ5)
|
||||
var goldEarned = (350 + 50 * unit.civInfo.getEraNumber()) * unit.civInfo.gameInfo.speed.goldCostModifier
|
||||
for (goldUnique in unit.civInfo.getMatchingUniques(UniqueType.PercentGoldFromTradeMissions))
|
||||
goldEarned *= goldUnique.params[0].toPercent()
|
||||
unit.civInfo.addGold(goldEarned.toInt())
|
||||
tile.owningCity!!.civInfo.getDiplomacyManager(unit.civInfo).addInfluence(influenceEarned)
|
||||
unit.civInfo.addNotification("Your trade mission to [${tile.owningCity!!.civInfo}] has earned you [${goldEarned}] gold and [$influenceEarned] influence!",
|
||||
NotificationCategory.General, tile.owningCity!!.civInfo.civName, NotificationIcon.Gold, NotificationIcon.Culture)
|
||||
unit.consume()
|
||||
}.takeIf { canConductTradeMission }
|
||||
)
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
private fun addFoundReligionAction(unit: MapUnit, actionList: ArrayList<UnitAction>) {
|
||||
if (!unit.hasUnique(UniqueType.MayFoundReligion)) return
|
||||
if (!unit.civInfo.religionManager.mayFoundReligionAtAll(unit)) return
|
||||
actionList += UnitAction(UnitActionType.FoundReligion,
|
||||
action = getFoundReligionAction(unit).takeIf { unit.civInfo.religionManager.mayFoundReligionNow(unit) }
|
||||
)
|
||||
}
|
||||
|
||||
fun getFoundReligionAction(unit: MapUnit): () -> Unit {
|
||||
return {
|
||||
unit.civInfo.religionManager.foundReligion(unit)
|
||||
unit.consume()
|
||||
}
|
||||
}
|
||||
|
||||
private fun addEnhanceReligionAction(unit: MapUnit, actionList: ArrayList<UnitAction>) {
|
||||
if (!unit.hasUnique(UniqueType.MayEnhanceReligion)) return
|
||||
if (!unit.civInfo.religionManager.mayEnhanceReligionAtAll(unit)) return
|
||||
actionList += UnitAction(UnitActionType.EnhanceReligion,
|
||||
title = "Enhance [${unit.civInfo.religionManager.religion!!.getReligionDisplayName()}]",
|
||||
action = getEnhanceReligionAction(unit).takeIf { unit.civInfo.religionManager.mayEnhanceReligionNow(unit) }
|
||||
)
|
||||
}
|
||||
|
||||
fun getEnhanceReligionAction(unit: MapUnit): () -> Unit {
|
||||
return {
|
||||
unit.civInfo.religionManager.useProphetForEnhancingReligion(unit)
|
||||
unit.consume()
|
||||
}
|
||||
}
|
||||
|
||||
fun addActionsWithLimitedUses(unit: MapUnit, actionList: ArrayList<UnitAction>, tile: Tile) {
|
||||
|
||||
val actionsToAdd = unit.religiousActionsUnitCanDo()
|
||||
if (actionsToAdd.none()) return
|
||||
if (unit.religion == null || unit.civInfo.gameInfo.religions[unit.religion]!!.isPantheon()) return
|
||||
val city = tile.getCity() ?: return
|
||||
for (action in actionsToAdd) {
|
||||
if (!unit.abilityUsesLeft.containsKey(action)) continue
|
||||
if (unit.abilityUsesLeft[action]!! <= 0) continue
|
||||
when (action) {
|
||||
Constants.spreadReligion -> addSpreadReligionActions(unit, actionList, city)
|
||||
Constants.removeHeresy -> addRemoveHeresyActions(unit, actionList, city)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun useActionWithLimitedUses(unit: MapUnit, action: String) {
|
||||
unit.abilityUsesLeft[action] = unit.abilityUsesLeft[action]!! - 1
|
||||
if (unit.abilityUsesLeft[action]!! <= 0) {
|
||||
unit.consume()
|
||||
}
|
||||
}
|
||||
|
||||
private fun addSpreadReligionActions(unit: MapUnit, actionList: ArrayList<UnitAction>, city: City) {
|
||||
if (!unit.civInfo.religionManager.maySpreadReligionAtAll(unit)) return
|
||||
actionList += UnitAction(UnitActionType.SpreadReligion,
|
||||
title = "Spread [${unit.getReligionDisplayName()!!}]",
|
||||
action = {
|
||||
val followersOfOtherReligions = city.religion.getFollowersOfOtherReligionsThan(unit.religion!!)
|
||||
for (unique in unit.getMatchingUniques(UniqueType.StatsWhenSpreading, checkCivInfoUniques = true)) {
|
||||
unit.civInfo.addStat(Stat.valueOf(unique.params[1]), followersOfOtherReligions * unique.params[0].toInt())
|
||||
}
|
||||
city.religion.addPressure(unit.religion!!, unit.getPressureAddedFromSpread())
|
||||
if (unit.hasUnique(UniqueType.RemoveOtherReligions))
|
||||
city.religion.removeAllPressuresExceptFor(unit.religion!!)
|
||||
unit.currentMovement = 0f
|
||||
useActionWithLimitedUses(unit, Constants.spreadReligion)
|
||||
}.takeIf { unit.currentMovement > 0 && unit.civInfo.religionManager.maySpreadReligionNow(unit) }
|
||||
)
|
||||
}
|
||||
|
||||
private fun addRemoveHeresyActions(unit: MapUnit, actionList: ArrayList<UnitAction>, city: City) {
|
||||
if (!unit.civInfo.gameInfo.isReligionEnabled()) return
|
||||
if (city.civInfo != unit.civInfo) return
|
||||
// Only allow the action if the city actually has any foreign religion
|
||||
// This will almost be always due to pressure from cities close-by
|
||||
if (city.religion.getPressures().none { it.key != unit.religion!! }) return
|
||||
actionList += UnitAction(UnitActionType.RemoveHeresy,
|
||||
title = "Remove Heresy",
|
||||
action = {
|
||||
city.religion.removeAllPressuresExceptFor(unit.religion!!)
|
||||
if (city.religion.religionThisIsTheHolyCityOf != null) {
|
||||
val religion = unit.civInfo.gameInfo.religions[city.religion.religionThisIsTheHolyCityOf]!!
|
||||
if (city.religion.religionThisIsTheHolyCityOf != unit.religion && !city.religion.isBlockedHolyCity) {
|
||||
religion.getFounder().addNotification("An [${unit.baseUnit.name}] has removed your religion [${religion.getReligionDisplayName()}] from its Holy City [${city.name}]!", NotificationCategory.Religion)
|
||||
city.religion.isBlockedHolyCity = true
|
||||
} else if (city.religion.religionThisIsTheHolyCityOf == unit.religion && city.religion.isBlockedHolyCity) {
|
||||
religion.getFounder().addNotification("An [${unit.baseUnit.name}] has restored [${city.name}] as the Holy City of your religion [${religion.getReligionDisplayName()}]!", NotificationCategory.Religion)
|
||||
city.religion.isBlockedHolyCity = false
|
||||
}
|
||||
}
|
||||
unit.currentMovement = 0f
|
||||
useActionWithLimitedUses(unit, Constants.removeHeresy)
|
||||
}.takeIf { unit.currentMovement > 0f }
|
||||
)
|
||||
}
|
||||
|
||||
fun getImprovementConstructionActions(unit: MapUnit, tile: Tile): ArrayList<UnitAction> {
|
||||
val finalActions = ArrayList<UnitAction>()
|
||||
val uniquesToCheck = unit.getMatchingUniques(UniqueType.ConstructImprovementConsumingUnit)
|
@ -0,0 +1,112 @@
|
||||
package com.unciv.ui.worldscreen.unit.actions
|
||||
|
||||
import com.unciv.logic.civilization.NotificationCategory
|
||||
import com.unciv.logic.civilization.NotificationIcon
|
||||
import com.unciv.logic.map.mapunit.MapUnit
|
||||
import com.unciv.logic.map.tile.Tile
|
||||
import com.unciv.models.UnitAction
|
||||
import com.unciv.models.UnitActionType
|
||||
import com.unciv.models.ruleset.Building
|
||||
import com.unciv.models.ruleset.unique.UniqueType
|
||||
import com.unciv.ui.utils.extensions.toPercent
|
||||
import kotlin.math.min
|
||||
|
||||
object UnitActionsGreatPerson {
|
||||
|
||||
internal fun addGreatPersonActions(unit: MapUnit, actionList: ArrayList<UnitAction>, tile: Tile) {
|
||||
|
||||
if (unit.currentMovement > 0) for (unique in unit.getUniques()) when (unique.type) {
|
||||
UniqueType.CanHurryResearch -> {
|
||||
actionList += UnitAction(
|
||||
UnitActionType.HurryResearch,
|
||||
action = {
|
||||
unit.civInfo.tech.addScience(unit.civInfo.tech.getScienceFromGreatScientist())
|
||||
unit.consume()
|
||||
}.takeIf { unit.civInfo.tech.currentTechnologyName() != null
|
||||
&& !unit.civInfo.tech.currentTechnology()!!.hasUnique(UniqueType.CannotBeHurried) }
|
||||
)
|
||||
}
|
||||
UniqueType.StartGoldenAge -> {
|
||||
val turnsToGoldenAge = unique.params[0].toInt()
|
||||
actionList += UnitAction(
|
||||
UnitActionType.StartGoldenAge,
|
||||
action = {
|
||||
unit.civInfo.goldenAges.enterGoldenAge(turnsToGoldenAge)
|
||||
unit.consume()
|
||||
}.takeIf { unit.currentTile.getOwner() != null && unit.currentTile.getOwner() == unit.civInfo }
|
||||
)
|
||||
}
|
||||
UniqueType.CanSpeedupWonderConstruction -> {
|
||||
val canHurryWonder =
|
||||
if (!tile.isCityCenter()) false
|
||||
else tile.getCity()!!.cityConstructions.isBuildingWonder()
|
||||
&& tile.getCity()!!.cityConstructions.canBeHurried()
|
||||
|
||||
actionList += UnitAction(
|
||||
UnitActionType.HurryWonder,
|
||||
action = {
|
||||
tile.getCity()!!.cityConstructions.apply {
|
||||
//http://civilization.wikia.com/wiki/Great_engineer_(Civ5)
|
||||
addProductionPoints(((300 + 30 * tile.getCity()!!.population.population) * unit.civInfo.gameInfo.speed.productionCostModifier).toInt())
|
||||
constructIfEnough()
|
||||
}
|
||||
|
||||
unit.consume()
|
||||
}.takeIf { canHurryWonder }
|
||||
)
|
||||
}
|
||||
|
||||
UniqueType.CanSpeedupConstruction -> {
|
||||
if (!tile.isCityCenter()) {
|
||||
actionList += UnitAction(UnitActionType.HurryBuilding, action = null)
|
||||
continue
|
||||
}
|
||||
|
||||
val cityConstructions = tile.getCity()!!.cityConstructions
|
||||
val canHurryConstruction = cityConstructions.getCurrentConstruction() is Building
|
||||
&& cityConstructions.canBeHurried()
|
||||
|
||||
//http://civilization.wikia.com/wiki/Great_engineer_(Civ5)
|
||||
val productionPointsToAdd = min(
|
||||
(300 + 30 * tile.getCity()!!.population.population) * unit.civInfo.gameInfo.speed.productionCostModifier,
|
||||
cityConstructions.getRemainingWork(cityConstructions.currentConstructionFromQueue).toFloat() - 1
|
||||
).toInt()
|
||||
if (productionPointsToAdd <= 0) continue
|
||||
|
||||
actionList += UnitAction(
|
||||
UnitActionType.HurryBuilding,
|
||||
title = "Hurry Construction (+[$productionPointsToAdd]⚙)",
|
||||
action = {
|
||||
cityConstructions.apply {
|
||||
addProductionPoints(productionPointsToAdd)
|
||||
constructIfEnough()
|
||||
}
|
||||
|
||||
unit.consume()
|
||||
}.takeIf { canHurryConstruction }
|
||||
)
|
||||
}
|
||||
UniqueType.CanTradeWithCityStateForGoldAndInfluence -> {
|
||||
val canConductTradeMission = tile.owningCity?.civInfo?.isCityState() == true
|
||||
&& tile.owningCity?.civInfo?.isAtWarWith(unit.civInfo) == false
|
||||
val influenceEarned = unique.params[0].toFloat()
|
||||
actionList += UnitAction(
|
||||
UnitActionType.ConductTradeMission,
|
||||
action = {
|
||||
// http://civilization.wikia.com/wiki/Great_Merchant_(Civ5)
|
||||
var goldEarned = (350 + 50 * unit.civInfo.getEraNumber()) * unit.civInfo.gameInfo.speed.goldCostModifier
|
||||
for (goldUnique in unit.civInfo.getMatchingUniques(UniqueType.PercentGoldFromTradeMissions))
|
||||
goldEarned *= goldUnique.params[0].toPercent()
|
||||
unit.civInfo.addGold(goldEarned.toInt())
|
||||
tile.owningCity!!.civInfo.getDiplomacyManager(unit.civInfo).addInfluence(influenceEarned)
|
||||
unit.civInfo.addNotification("Your trade mission to [${tile.owningCity!!.civInfo}] has earned you [${goldEarned}] gold and [$influenceEarned] influence!",
|
||||
NotificationCategory.General, tile.owningCity!!.civInfo.civName, NotificationIcon.Gold, NotificationIcon.Culture)
|
||||
unit.consume()
|
||||
}.takeIf { canConductTradeMission }
|
||||
)
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,112 @@
|
||||
package com.unciv.ui.worldscreen.unit.actions
|
||||
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.logic.civilization.NotificationCategory
|
||||
import com.unciv.logic.civilization.NotificationIcon
|
||||
import com.unciv.logic.map.mapunit.MapUnit
|
||||
import com.unciv.logic.map.tile.Tile
|
||||
import com.unciv.models.UnitAction
|
||||
import com.unciv.models.UnitActionType
|
||||
import com.unciv.models.ruleset.unique.UniqueType
|
||||
import com.unciv.models.stats.Stat
|
||||
import com.unciv.models.stats.Stats
|
||||
import com.unciv.ui.popup.ConfirmPopup
|
||||
import com.unciv.ui.popup.hasOpenPopups
|
||||
import com.unciv.ui.worldscreen.WorldScreen
|
||||
import kotlin.random.Random
|
||||
|
||||
object UnitActionsPillage {
|
||||
|
||||
fun addPillageAction(unit: MapUnit, actionList: ArrayList<UnitAction>, worldScreen: WorldScreen) {
|
||||
val pillageAction = getPillageAction(unit)
|
||||
?: return
|
||||
if (pillageAction.action == null)
|
||||
actionList += UnitAction(
|
||||
UnitActionType.Pillage,
|
||||
title = "${UnitActionType.Pillage} [${unit.currentTile.getImprovementToPillageName()!!}]",
|
||||
action = null)
|
||||
else actionList += UnitAction(type = UnitActionType.Pillage,
|
||||
title = "${UnitActionType.Pillage} [${unit.currentTile.getImprovementToPillageName()!!}]") {
|
||||
if (!worldScreen.hasOpenPopups()) {
|
||||
val pillageText = "Are you sure you want to pillage this [${unit.currentTile.getImprovementToPillageName()!!}]?"
|
||||
ConfirmPopup(
|
||||
UncivGame.Current.worldScreen!!,
|
||||
pillageText,
|
||||
"Pillage",
|
||||
true
|
||||
) {
|
||||
(pillageAction.action)()
|
||||
worldScreen.shouldUpdate = true
|
||||
}.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun getPillageAction(unit: MapUnit): UnitAction? {
|
||||
val tile = unit.currentTile
|
||||
if (unit.isCivilian() || !tile.canPillageTile() || tile.getOwner() == unit.civInfo) return null
|
||||
return UnitAction(
|
||||
UnitActionType.Pillage,
|
||||
action = {
|
||||
val pillagedImprovement = unit.currentTile.getImprovementToPillageName()!!
|
||||
val pillageText = "An enemy [${unit.baseUnit.name}] has pillaged our [$pillagedImprovement]"
|
||||
val icon = "ImprovementIcons/$pillagedImprovement"
|
||||
tile.getOwner()?.addNotification(
|
||||
pillageText,
|
||||
tile.position,
|
||||
NotificationCategory.War,
|
||||
icon,
|
||||
NotificationIcon.War,
|
||||
unit.baseUnit.name
|
||||
)
|
||||
|
||||
pillageLooting(tile, unit)
|
||||
tile.setPillaged()
|
||||
if (tile.resource != null) tile.getOwner()?.cache?.updateCivResources() // this might take away a resource
|
||||
tile.getCity()?.updateCitizens = true
|
||||
|
||||
val freePillage = unit.hasUnique(UniqueType.NoMovementToPillage, checkCivInfoUniques = true)
|
||||
if (!freePillage) unit.useMovementPoints(1f)
|
||||
|
||||
unit.healBy(25)
|
||||
}.takeIf { unit.currentMovement > 0 && UnitActions.canPillage(unit, tile) })
|
||||
}
|
||||
|
||||
private fun pillageLooting(tile: Tile, unit: MapUnit) {
|
||||
// Stats objects for reporting pillage results in a notification
|
||||
val pillageYield = Stats()
|
||||
val globalPillageYield = Stats()
|
||||
val toCityPillageYield = Stats()
|
||||
val closestCity = unit.civInfo.cities.minByOrNull { it.getCenterTile().aerialDistanceTo(tile) }
|
||||
val improvement = tile.getImprovementToPillage()!!
|
||||
|
||||
for (unique in improvement.getMatchingUniques(UniqueType.PillageYieldRandom)) {
|
||||
for (stat in unique.stats) {
|
||||
val looted = Random.nextInt((stat.value + 1).toInt()) + Random.nextInt((stat.value + 1).toInt())
|
||||
pillageYield.add(stat.key, looted.toFloat())
|
||||
}
|
||||
}
|
||||
for (unique in improvement.getMatchingUniques(UniqueType.PillageYieldFixed)) {
|
||||
for (stat in unique.stats) {
|
||||
pillageYield.add(stat.key, stat.value)
|
||||
}
|
||||
}
|
||||
|
||||
for (stat in pillageYield) {
|
||||
if (stat.key in Stat.statsWithCivWideField) {
|
||||
unit.civInfo.addStat(stat.key, stat.value.toInt())
|
||||
globalPillageYield[stat.key] += stat.value
|
||||
}
|
||||
else if (closestCity != null) {
|
||||
closestCity.addStat(stat.key, stat.value.toInt())
|
||||
toCityPillageYield[stat.key] += stat.value
|
||||
}
|
||||
}
|
||||
|
||||
val lootNotificationText = if (!toCityPillageYield.isEmpty() && closestCity != null)
|
||||
"We have looted [${toCityPillageYield.toStringWithoutIcons()}] from a [${improvement.name}] which has been sent to [${closestCity.name}]"
|
||||
else "We have looted [${globalPillageYield.toStringWithoutIcons()}] from a [${improvement.name}]"
|
||||
|
||||
unit.civInfo.addNotification(lootNotificationText, tile.position, NotificationCategory.War, "ImprovementIcons/${improvement.name}", NotificationIcon.War)
|
||||
}
|
||||
}
|
@ -0,0 +1,127 @@
|
||||
package com.unciv.ui.worldscreen.unit.actions
|
||||
|
||||
import com.unciv.Constants
|
||||
import com.unciv.logic.city.City
|
||||
import com.unciv.logic.civilization.NotificationCategory
|
||||
import com.unciv.logic.map.mapunit.MapUnit
|
||||
import com.unciv.logic.map.tile.Tile
|
||||
import com.unciv.models.UnitAction
|
||||
import com.unciv.models.UnitActionType
|
||||
import com.unciv.models.ruleset.unique.UniqueType
|
||||
import com.unciv.models.stats.Stat
|
||||
import com.unciv.ui.utils.extensions.toPercent
|
||||
|
||||
object UnitActionsReligion {
|
||||
|
||||
|
||||
internal fun addFoundReligionAction(unit: MapUnit, actionList: ArrayList<UnitAction>) {
|
||||
if (!unit.hasUnique(UniqueType.MayFoundReligion)) return
|
||||
if (!unit.civInfo.religionManager.mayFoundReligionAtAll(unit)) return
|
||||
actionList += UnitAction(
|
||||
UnitActionType.FoundReligion,
|
||||
action = getFoundReligionAction(unit).takeIf { unit.civInfo.religionManager.mayFoundReligionNow(unit) }
|
||||
)
|
||||
}
|
||||
|
||||
fun getFoundReligionAction(unit: MapUnit): () -> Unit {
|
||||
return {
|
||||
unit.civInfo.religionManager.foundReligion(unit)
|
||||
unit.consume()
|
||||
}
|
||||
}
|
||||
|
||||
internal fun addEnhanceReligionAction(unit: MapUnit, actionList: ArrayList<UnitAction>) {
|
||||
if (!unit.hasUnique(UniqueType.MayEnhanceReligion)) return
|
||||
if (!unit.civInfo.religionManager.mayEnhanceReligionAtAll(unit)) return
|
||||
actionList += UnitAction(
|
||||
UnitActionType.EnhanceReligion,
|
||||
title = "Enhance [${unit.civInfo.religionManager.religion!!.getReligionDisplayName()}]",
|
||||
action = getEnhanceReligionAction(unit).takeIf { unit.civInfo.religionManager.mayEnhanceReligionNow(unit) }
|
||||
)
|
||||
}
|
||||
|
||||
fun getEnhanceReligionAction(unit: MapUnit): () -> Unit {
|
||||
return {
|
||||
unit.civInfo.religionManager.useProphetForEnhancingReligion(unit)
|
||||
unit.consume()
|
||||
}
|
||||
}
|
||||
|
||||
fun addActionsWithLimitedUses(unit: MapUnit, actionList: ArrayList<UnitAction>, tile: Tile) {
|
||||
|
||||
val actionsToAdd = unit.religiousActionsUnitCanDo()
|
||||
if (actionsToAdd.none()) return
|
||||
if (unit.religion == null || unit.civInfo.gameInfo.religions[unit.religion]!!.isPantheon()) return
|
||||
val city = tile.getCity() ?: return
|
||||
for (action in actionsToAdd) {
|
||||
if (!unit.abilityUsesLeft.containsKey(action)) continue
|
||||
if (unit.abilityUsesLeft[action]!! <= 0) continue
|
||||
when (action) {
|
||||
Constants.spreadReligion -> addSpreadReligionActions(unit, actionList, city)
|
||||
Constants.removeHeresy -> addRemoveHeresyActions(unit, actionList, city)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun useActionWithLimitedUses(unit: MapUnit, action: String) {
|
||||
unit.abilityUsesLeft[action] = unit.abilityUsesLeft[action]!! - 1
|
||||
if (unit.abilityUsesLeft[action]!! <= 0) {
|
||||
unit.consume()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getPressureAddedFromSpread(unit: MapUnit): Int {
|
||||
var pressureAdded = unit.baseUnit.religiousStrength.toFloat()
|
||||
|
||||
for (unique in unit.getMatchingUniques(UniqueType.SpreadReligionStrength, checkCivInfoUniques = true))
|
||||
pressureAdded *= unique.params[0].toPercent()
|
||||
|
||||
return pressureAdded.toInt()
|
||||
}
|
||||
|
||||
private fun addSpreadReligionActions(unit: MapUnit, actionList: ArrayList<UnitAction>, city: City) {
|
||||
if (!unit.civInfo.religionManager.maySpreadReligionAtAll(unit)) return
|
||||
actionList += UnitAction(
|
||||
UnitActionType.SpreadReligion,
|
||||
title = "Spread [${unit.getReligionDisplayName()!!}]",
|
||||
action = {
|
||||
val followersOfOtherReligions = city.religion.getFollowersOfOtherReligionsThan(unit.religion!!)
|
||||
for (unique in unit.getMatchingUniques(UniqueType.StatsWhenSpreading, checkCivInfoUniques = true)) {
|
||||
unit.civInfo.addStat(Stat.valueOf(unique.params[1]), followersOfOtherReligions * unique.params[0].toInt())
|
||||
}
|
||||
city.religion.addPressure(unit.religion!!, getPressureAddedFromSpread(unit))
|
||||
if (unit.hasUnique(UniqueType.RemoveOtherReligions))
|
||||
city.religion.removeAllPressuresExceptFor(unit.religion!!)
|
||||
unit.currentMovement = 0f
|
||||
useActionWithLimitedUses(unit, Constants.spreadReligion)
|
||||
}.takeIf { unit.currentMovement > 0 && unit.civInfo.religionManager.maySpreadReligionNow(unit) }
|
||||
)
|
||||
}
|
||||
|
||||
private fun addRemoveHeresyActions(unit: MapUnit, actionList: ArrayList<UnitAction>, city: City) {
|
||||
if (!unit.civInfo.gameInfo.isReligionEnabled()) return
|
||||
if (city.civInfo != unit.civInfo) return
|
||||
// Only allow the action if the city actually has any foreign religion
|
||||
// This will almost be always due to pressure from cities close-by
|
||||
if (city.religion.getPressures().none { it.key != unit.religion!! }) return
|
||||
actionList += UnitAction(
|
||||
UnitActionType.RemoveHeresy,
|
||||
title = "Remove Heresy",
|
||||
action = {
|
||||
city.religion.removeAllPressuresExceptFor(unit.religion!!)
|
||||
if (city.religion.religionThisIsTheHolyCityOf != null) {
|
||||
val religion = unit.civInfo.gameInfo.religions[city.religion.religionThisIsTheHolyCityOf]!!
|
||||
if (city.religion.religionThisIsTheHolyCityOf != unit.religion && !city.religion.isBlockedHolyCity) {
|
||||
religion.getFounder().addNotification("An [${unit.baseUnit.name}] has removed your religion [${religion.getReligionDisplayName()}] from its Holy City [${city.name}]!", NotificationCategory.Religion)
|
||||
city.religion.isBlockedHolyCity = true
|
||||
} else if (city.religion.religionThisIsTheHolyCityOf == unit.religion && city.religion.isBlockedHolyCity) {
|
||||
religion.getFounder().addNotification("An [${unit.baseUnit.name}] has restored [${city.name}] as the Holy City of your religion [${religion.getReligionDisplayName()}]!", NotificationCategory.Religion)
|
||||
city.religion.isBlockedHolyCity = false
|
||||
}
|
||||
}
|
||||
unit.currentMovement = 0f
|
||||
useActionWithLimitedUses(unit, Constants.removeHeresy)
|
||||
}.takeIf { unit.currentMovement > 0f }
|
||||
)
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package com.unciv.ui.worldscreen.unit
|
||||
package com.unciv.ui.worldscreen.unit.actions
|
||||
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Button
|
||||
@ -21,7 +21,8 @@ class UnitActionsTable(val worldScreen: WorldScreen) : Table() {
|
||||
clear()
|
||||
if (unit == null) return
|
||||
if (!worldScreen.canChangeState) return // No actions when it's not your turn or spectator!
|
||||
for (button in UnitActions.getUnitActions(unit, worldScreen).map { getUnitActionButton(unit, it) })
|
||||
for (button in UnitActions.getUnitActions(unit, worldScreen)
|
||||
.map { getUnitActionButton(unit, it) })
|
||||
add(button).left().padBottom(2f).row()
|
||||
pack()
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
package com.unciv.ui.worldscreen.unit.actions
|
||||
|
||||
import com.unciv.logic.map.mapunit.MapUnit
|
||||
import com.unciv.models.Counter
|
||||
import com.unciv.models.UnitAction
|
||||
import com.unciv.models.UnitActionType
|
||||
import com.unciv.models.translations.tr
|
||||
|
||||
object UnitActionsUpgrade{
|
||||
|
||||
internal fun addUnitUpgradeAction(
|
||||
unit: MapUnit,
|
||||
actionList: ArrayList<UnitAction>
|
||||
) {
|
||||
val upgradeAction = getUpgradeAction(unit)
|
||||
if (upgradeAction != null) actionList += upgradeAction
|
||||
}
|
||||
|
||||
/** Common implementation for [getUpgradeAction], [getFreeUpgradeAction] and [getAncientRuinsUpgradeAction] */
|
||||
private fun getUpgradeAction(
|
||||
unit: MapUnit,
|
||||
isFree: Boolean,
|
||||
isSpecial: Boolean
|
||||
): UnitAction? {
|
||||
if (unit.baseUnit().upgradesTo == null && unit.baseUnit().specialUpgradesTo == null) return null // can't upgrade to anything
|
||||
val unitTile = unit.getTile()
|
||||
val civInfo = unit.civInfo
|
||||
if (!isFree && unitTile.getOwner() != civInfo) return null
|
||||
|
||||
val upgradesTo = unit.baseUnit().upgradesTo
|
||||
val specialUpgradesTo = unit.baseUnit().specialUpgradesTo
|
||||
val upgradedUnit = when {
|
||||
isSpecial && specialUpgradesTo != null -> civInfo.getEquivalentUnit(specialUpgradesTo)
|
||||
(isFree || isSpecial) && upgradesTo != null -> civInfo.getEquivalentUnit(upgradesTo) // Only get DIRECT upgrade
|
||||
else -> unit.upgrade.getUnitToUpgradeTo() // Get EVENTUAL upgrade, all the way up the chain
|
||||
}
|
||||
|
||||
if (!unit.upgrade.canUpgrade(unitToUpgradeTo = upgradedUnit, ignoreRequirements = isFree, ignoreResources = true))
|
||||
return null
|
||||
|
||||
// Check _new_ resource requirements (display only - yes even for free or special upgrades)
|
||||
// Using Counter to aggregate is a bit exaggerated, but - respect the mad modder.
|
||||
val resourceRequirementsDelta = Counter<String>()
|
||||
for ((resource, amount) in unit.baseUnit().getResourceRequirements())
|
||||
resourceRequirementsDelta.add(resource, -amount)
|
||||
for ((resource, amount) in upgradedUnit.getResourceRequirements())
|
||||
resourceRequirementsDelta.add(resource, amount)
|
||||
val newResourceRequirementsString = resourceRequirementsDelta.entries
|
||||
.filter { it.value > 0 }
|
||||
.joinToString { "${it.value} {${it.key}}".tr() }
|
||||
|
||||
val goldCostOfUpgrade = if (isFree) 0 else unit.upgrade.getCostOfUpgrade(upgradedUnit)
|
||||
|
||||
// No string for "FREE" variants, these are never shown to the user.
|
||||
// The free actions are only triggered via OneTimeUnitUpgrade or OneTimeUnitSpecialUpgrade in UniqueTriggerActivation.
|
||||
val title = if (newResourceRequirementsString.isEmpty())
|
||||
"Upgrade to [${upgradedUnit.name}] ([$goldCostOfUpgrade] gold)"
|
||||
else "Upgrade to [${upgradedUnit.name}]\n([$goldCostOfUpgrade] gold, [$newResourceRequirementsString])"
|
||||
|
||||
return UnitAction(
|
||||
UnitActionType.Upgrade,
|
||||
title = title,
|
||||
action = {
|
||||
unit.destroy(destroyTransportedUnit = false)
|
||||
val newUnit = civInfo.units.placeUnitNearTile(unitTile.position, upgradedUnit.name)
|
||||
|
||||
/** We were UNABLE to place the new unit, which means that the unit failed to upgrade!
|
||||
* The only known cause of this currently is "land units upgrading to water units" which fail to be placed.
|
||||
*/
|
||||
|
||||
/** We were UNABLE to place the new unit, which means that the unit failed to upgrade!
|
||||
* The only known cause of this currently is "land units upgrading to water units" which fail to be placed.
|
||||
*/
|
||||
if (newUnit == null) {
|
||||
val resurrectedUnit = civInfo.units.placeUnitNearTile(unitTile.position, unit.name)!!
|
||||
unit.copyStatisticsTo(resurrectedUnit)
|
||||
} else { // Managed to upgrade
|
||||
if (!isFree) civInfo.addGold(-goldCostOfUpgrade)
|
||||
unit.copyStatisticsTo(newUnit)
|
||||
newUnit.currentMovement = 0f
|
||||
}
|
||||
}.takeIf {
|
||||
isFree || (
|
||||
unit.civInfo.gold >= goldCostOfUpgrade
|
||||
&& unit.currentMovement > 0
|
||||
&& !unit.isEmbarked()
|
||||
&& unit.upgrade.canUpgrade(unitToUpgradeTo = upgradedUnit)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fun getUpgradeAction(unit: MapUnit) =
|
||||
getUpgradeAction(unit, isFree = false, isSpecial = false)
|
||||
fun getFreeUpgradeAction(unit: MapUnit) =
|
||||
getUpgradeAction(unit, isFree = true, isSpecial = false)
|
||||
fun getAncientRuinsUpgradeAction(unit: MapUnit) =
|
||||
getUpgradeAction(unit, isFree = true, isSpecial = true)
|
||||
|
||||
}
|
@ -7,7 +7,7 @@ import com.unciv.logic.map.tile.RoadStatus
|
||||
import com.unciv.models.ruleset.BeliefType
|
||||
import com.unciv.models.stats.Stats
|
||||
import com.unciv.testing.GdxTestRunner
|
||||
import com.unciv.ui.worldscreen.unit.UnitActions
|
||||
import com.unciv.ui.worldscreen.unit.actions.UnitActions
|
||||
import org.junit.Assert
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
|
@ -2,7 +2,7 @@ package com.unciv.uniques
|
||||
|
||||
import com.badlogic.gdx.math.Vector2
|
||||
import com.unciv.testing.GdxTestRunner
|
||||
import com.unciv.ui.worldscreen.unit.UnitActions
|
||||
import com.unciv.ui.worldscreen.unit.actions.UnitActions
|
||||
import org.junit.Assert.assertNotNull
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
|
Loading…
x
Reference in New Issue
Block a user