Get rid of old religion style actions!!! (#10192)

* Giant refactoring - get rid of old religion style actions!!!

* Added special promotion to replace Great Mosque of Djenne ability

* removed double promotion added my mistake

* Added AI recognition of cities with bonus spread religion charges

* Added "disallowed for pantheon" filtering to new unit actions

* merge unit action changes with religion action changes

* Use new invokeUnitAction function for simplicity

* revert inquisitor unique change used for tests

* separate modifier side effects from old-style side effects

* Use canUSe shorthand for clarity
This commit is contained in:
Yair Morgenstern 2023-10-01 09:43:26 +03:00 committed by GitHub
parent b01353eee7
commit 6d6dc51bea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 133 additions and 69 deletions

View File

@ -458,7 +458,8 @@
"greatPersonPoints": {"Great Engineer": 1}, "greatPersonPoints": {"Great Engineer": 1},
"isWonder": true, "isWonder": true,
"uniques": ["Gain a free [Mosque] [in this city]", "Hidden when religion is disabled", "uniques": ["Gain a free [Mosque] [in this city]", "Hidden when religion is disabled",
"[Missionary] units built [in this city] can [Spread Religion] [1] extra times", "[Great Prophet] units built [in this city] can [Spread Religion] [1] extra times"], "All newly-trained [Missionary] units [in this city] receive the [Devout] promotion",
"All newly-trained [Great Prophet] units [in this city] receive the [Devout] promotion"],
"requiredTech": "Theology", "requiredTech": "Theology",
"quote": "'With the magnificence of eternity before us, let time, with all its fluctuations, dwindle into its own littleness.' - Thomas Chalmers" "quote": "'With the magnificence of eternity before us, let time, with all its fluctuations, dwindle into its own littleness.' - Thomas Chalmers"
}, },

View File

@ -707,6 +707,10 @@
"name": "Home Sweet Home", // only for Mehal Sefari and subsequent upgrades "name": "Home Sweet Home", // only for Mehal Sefari and subsequent upgrades
"uniques": ["[+30]% Strength decreasing with distance from the capital"] "uniques": ["[+30]% Strength decreasing with distance from the capital"]
}, },
{
"name": "Devout",
"uniques": ["Can Spread Religion <[1] additional time(s)>"]
},
{ {
"name": "[Mohawk Warrior] ability", "name": "[Mohawk Warrior] ability",
"uniques": ["[+33]% Strength <when fighting in [Forest] tiles>", "[+33]% Strength <when fighting in [Jungle] tiles>"] "uniques": ["[+33]% Strength <when fighting in [Forest] tiles>", "[+33]% Strength <when fighting in [Jungle] tiles>"]

View File

@ -1636,7 +1636,7 @@
"unitType": "Civilian", "unitType": "Civilian",
"uniques": [ "uniques": [
"Can instantly construct a [Holy site] improvement <by consuming this unit> <if it hasn't used other actions yet>", "Can instantly construct a [Holy site] improvement <by consuming this unit> <if it hasn't used other actions yet>",
"Can [Spread Religion] [4] times", "Can Spread Religion <[4] times>",
"Removes other religions when spreading religion", "Removes other religions when spreading religion",
"May found a religion", "May found a religion",
"May enhance a religion", "May enhance a religion",
@ -1675,7 +1675,9 @@
{ {
"name": "Missionary", "name": "Missionary",
"unitType": "Civilian", "unitType": "Civilian",
"uniques": ["Can [Spread Religion] [2] times", "May enter foreign tiles without open borders, but loses [250] religious strength each turn it ends there", "uniques": [
"Can Spread Religion <[2] times>",
"May enter foreign tiles without open borders, but loses [250] religious strength each turn it ends there",
"Can be purchased with [Faith] [in all cities in which the majority religion is a major religion]", "Can be purchased with [Faith] [in all cities in which the majority religion is a major religion]",
"[-1] Sight", "Unbuildable", "Religious Unit", "Hidden when religion is disabled"], "[-1] Sight", "Unbuildable", "Religious Unit", "Hidden when religion is disabled"],
"movement": 4, "movement": 4,
@ -1685,8 +1687,8 @@
"name": "Inquisitor", "name": "Inquisitor",
"unitType": "Civilian", "unitType": "Civilian",
"uniques": ["Prevents spreading of religion to the city it is next to", "uniques": ["Prevents spreading of religion to the city it is next to",
"Can [Remove Foreign religions from your own cities] [1] times", "Can remove other religions from cities <in [Friendly] tiles> <once> <after which this unit is consumed>",
"Can be purchased with [Faith] [in all cities in which the majority religion is an enhanced religion]", "Can be purchased with [Faith] [in all cities in which the majority religion is a major religion]",
"[+1] Sight", "Hidden when religion is disabled", "Unbuildable", "Religious Unit" "[+1] Sight", "Hidden when religion is disabled", "Unbuildable", "Religious Unit"
], ],
"movement": 3 "movement": 3

View File

@ -1294,7 +1294,7 @@
"unitType": "Civilian", "unitType": "Civilian",
"uniques": [ "uniques": [
"Can instantly construct a [Holy site] improvement <by consuming this unit> <if it hasn't used other actions yet>", "Can instantly construct a [Holy site] improvement <by consuming this unit> <if it hasn't used other actions yet>",
"Can [Spread Religion] [4] times", "Can Spread Religion <[4] times>",
"Removes other religions when spreading religion", "Removes other religions when spreading religion",
"May found a religion", "May found a religion",
"May enhance a religion", "May enhance a religion",
@ -1333,7 +1333,9 @@
{ {
"name": "Missionary", "name": "Missionary",
"unitType": "Civilian", "unitType": "Civilian",
"uniques": ["Can [Spread Religion] [2] times", "May enter foreign tiles without open borders, but loses [250] religious strength each turn it ends there", "uniques": [
"Can Spread Religion <[2] times>",
"May enter foreign tiles without open borders, but loses [250] religious strength each turn it ends there",
"Can be purchased with [Faith] [in all cities in which the majority religion is a major religion]", "Can be purchased with [Faith] [in all cities in which the majority religion is a major religion]",
"[-1] Sight", "Unbuildable", "Religious Unit", "Hidden when religion is disabled"], "[-1] Sight", "Unbuildable", "Religious Unit", "Hidden when religion is disabled"],
"movement": 4, "movement": 4,
@ -1343,7 +1345,7 @@
"name": "Inquisitor", "name": "Inquisitor",
"unitType": "Civilian", "unitType": "Civilian",
"uniques": ["Prevents spreading of religion to the city it is next to", "uniques": ["Prevents spreading of religion to the city it is next to",
"Can [Remove Foreign religions from your own cities] [1] times", "Can remove other religions from cities <in [Friendly] tiles> <once> <after which this unit is consumed>",
"Can be purchased with [Faith] [in all cities in which the majority religion is an enhanced religion]", "Can be purchased with [Faith] [in all cities in which the majority religion is an enhanced religion]",
"[+1] Sight", "Hidden when religion is disabled", "Unbuildable", "Religious Unit" "[+1] Sight", "Hidden when religion is disabled", "Unbuildable", "Religious Unit"
], ],

View File

@ -2,7 +2,6 @@ package com.unciv.logic.automation.civilization
import com.unciv.Constants import com.unciv.Constants
import com.unciv.logic.city.City import com.unciv.logic.city.City
import com.unciv.models.ruleset.INonPerpetualConstruction
import com.unciv.logic.civilization.Civilization import com.unciv.logic.civilization.Civilization
import com.unciv.logic.civilization.managers.ReligionState import com.unciv.logic.civilization.managers.ReligionState
import com.unciv.logic.map.tile.Tile import com.unciv.logic.map.tile.Tile
@ -41,7 +40,10 @@ object ReligionAutomation {
val citiesWithoutOurReligion = civInfo.cities.filter { it.religion.getMajorityReligion() != civInfo.religionManager.religion!! } val citiesWithoutOurReligion = civInfo.cities.filter { it.religion.getMajorityReligion() != civInfo.religionManager.religion!! }
// The original had a cap at 4 missionaries total, but 1/4 * the number of cities should be more appropriate imo // The original had a cap at 4 missionaries total, but 1/4 * the number of cities should be more appropriate imo
if (citiesWithoutOurReligion.count() > if (citiesWithoutOurReligion.count() >
4 * civInfo.units.getCivUnits().count { it.canDoLimitedAction(Constants.spreadReligion) || it.canDoLimitedAction(Constants.removeHeresy) } 4 * civInfo.units.getCivUnits().count {
it.canDoLimitedAction(Constants.spreadReligion) // OLD
|| it.hasUnique(UniqueType.CanSpreadReligion) // NEW
|| it.canDoLimitedAction(Constants.removeHeresy) }
) { ) {
val (city, pressureDifference) = citiesWithoutOurReligion.map { city -> val (city, pressureDifference) = citiesWithoutOurReligion.map { city ->
city to city.religion.getPressureDeficit(civInfo.religionManager.religion?.name) city to city.religion.getPressureDeficit(civInfo.religionManager.religion?.name)
@ -77,7 +79,10 @@ object ReligionAutomation {
// Todo: buy Great People post industrial era // Todo: buy Great People post industrial era
// Just buy missionaries to spread our religion outside of our civ // Just buy missionaries to spread our religion outside of our civ
if (civInfo.units.getCivUnits().count { it.canDoLimitedAction(Constants.spreadReligion) } < 4) { if (civInfo.units.getCivUnits().count {
it.canDoLimitedAction(Constants.spreadReligion) // OLD
|| it.hasUnique(UniqueType.CanSpreadReligion) // NEW
} < 4) {
buyMissionaryInAnyCity(civInfo) buyMissionaryInAnyCity(civInfo)
return return
} }
@ -103,7 +108,10 @@ object ReligionAutomation {
private fun buyMissionaryInAnyCity(civInfo: Civilization) { private fun buyMissionaryInAnyCity(civInfo: Civilization) {
if (civInfo.religionManager.religionState < ReligionState.Religion) return if (civInfo.religionManager.religionState < ReligionState.Religion) return
var missionaries = civInfo.gameInfo.ruleset.units.values.filter { unit -> var missionaries = civInfo.gameInfo.ruleset.units.values.filter { unit ->
// OLD
unit.getMatchingUniques(UniqueType.CanActionSeveralTimes).filter { it.params[0] == Constants.spreadReligion }.any() unit.getMatchingUniques(UniqueType.CanActionSeveralTimes).filter { it.params[0] == Constants.spreadReligion }.any()
// NEW
|| unit.hasUnique(UniqueType.CanSpreadReligion)
} }
missionaries = missionaries.map { civInfo.getEquivalentUnit(it) } missionaries = missionaries.map { civInfo.getEquivalentUnit(it) }
@ -127,7 +135,12 @@ object ReligionAutomation {
if (validCitiesToBuy.isEmpty()) return if (validCitiesToBuy.isEmpty()) return
val citiesWithBonusCharges = validCitiesToBuy.filter { city -> val citiesWithBonusCharges = validCitiesToBuy.filter { city ->
city.getMatchingUniques(UniqueType.UnitStartingActions).filter { it.params[2] == Constants.spreadReligion }.any() city.getMatchingUniques(UniqueType.UnitStartingActions).any { it.params[2] == Constants.spreadReligion }
|| city.getMatchingUniques(UniqueType.UnitStartingPromotions).any {
val promotionName = it.params[2]
val promotion = city.getRuleset().unitPromotions[promotionName] ?: return@any false
promotion.hasUnique(UniqueType.CanSpreadReligion)
}
} }
val holyCity = validCitiesToBuy.firstOrNull { it.isHolyCityOf(civInfo.religionManager.religion!!.name) } val holyCity = validCitiesToBuy.firstOrNull { it.isHolyCityOf(civInfo.religionManager.religion!!.name) }

View File

@ -11,7 +11,6 @@ import com.unciv.logic.civilization.Civilization
import com.unciv.logic.civilization.diplomacy.DiplomaticModifiers import com.unciv.logic.civilization.diplomacy.DiplomaticModifiers
import com.unciv.logic.map.mapunit.MapUnit import com.unciv.logic.map.mapunit.MapUnit
import com.unciv.logic.map.tile.Tile import com.unciv.logic.map.tile.Tile
import com.unciv.models.UnitAction
import com.unciv.models.UnitActionType import com.unciv.models.UnitActionType
import com.unciv.models.ruleset.Building import com.unciv.models.ruleset.Building
import com.unciv.models.ruleset.unique.LocalUniqueCache import com.unciv.models.ruleset.unique.LocalUniqueCache
@ -341,7 +340,7 @@ object SpecificUnitAutomation {
unit.movement.headTowards(destination) unit.movement.headTowards(destination)
if (unit.getTile() in city.getTiles() && unit.civ.religionManager.maySpreadReligionNow(unit)) { if (unit.getTile() in city.getTiles() && unit.civ.religionManager.maySpreadReligionNow(unit)) {
doReligiousAction(unit, unit.getTile()) UnitActions.invokeUnitAction(unit, UnitActionType.SpreadReligion)
} }
} }
@ -397,7 +396,7 @@ object SpecificUnitAutomation {
unit.movement.headTowards(destination) unit.movement.headTowards(destination)
if (cityToConvert != null && unit.getTile().getCity() == destination.getCity()) { if (cityToConvert != null && unit.getTile().getCity() == destination.getCity()) {
doReligiousAction(unit, destination) UnitActions.invokeUnitAction(unit, UnitActionType.RemoveHeresy)
} }
} }
@ -634,10 +633,4 @@ object SpecificUnitAutomation {
UnitActionsReligion.getEnhanceReligionAction(unit)() UnitActionsReligion.getEnhanceReligionAction(unit)()
} }
private fun doReligiousAction(unit: MapUnit, destination: Tile) {
val religiousActions = ArrayList<UnitAction>()
UnitActionsReligion.addActionsWithLimitedUses(unit, religiousActions, destination)
if (religiousActions.firstOrNull()?.action == null) return
religiousActions.first().action!!.invoke()
}
} }

View File

@ -13,7 +13,7 @@ import com.unciv.models.ruleset.unique.UniqueTriggerActivation
import com.unciv.models.ruleset.unique.UniqueType import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.ruleset.unit.BaseUnit import com.unciv.models.ruleset.unit.BaseUnit
import com.unciv.ui.components.extensions.toPercent import com.unciv.ui.components.extensions.toPercent
import java.lang.Integer.max import com.unciv.ui.screens.worldscreen.unit.actions.UnitActionModifiers
import java.lang.Integer.min import java.lang.Integer.min
import kotlin.random.Random import kotlin.random.Random
@ -445,7 +445,11 @@ class ReligionManager : IsPartOfGameInfoSerialization {
fun maySpreadReligionAtAll(missionary: MapUnit): Boolean { fun maySpreadReligionAtAll(missionary: MapUnit): Boolean {
if (!civInfo.isMajorCiv()) return false // Only major civs if (!civInfo.isMajorCiv()) return false // Only major civs
if (!civInfo.gameInfo.isReligionEnabled()) return false // No religion, no spreading if (!civInfo.gameInfo.isReligionEnabled()) return false // No religion, no spreading
if (!missionary.canDoLimitedAction(Constants.spreadReligion)) return false
val religion = missionary.civ.gameInfo.religions[missionary.religion] ?: return false
if (religion.isPantheon()) return false
if (!missionary.canDoLimitedAction(Constants.spreadReligion)
&& UnitActionModifiers.getUsableUnitActionUniques(missionary, UniqueType.CanSpreadReligion).any()) return false
return true return true
} }

View File

@ -499,6 +499,7 @@ enum class UniqueParameterType(
}, },
/** For untyped "Can [] [] times" unique */ /** For untyped "Can [] [] times" unique */
@Deprecated("As of 4.8.9")
Action("action", Constants.spreadReligion, "An action that a unit can perform. Currently, there are only two actions part of this: 'Spread Religion' and 'Remove Foreign religions from your own cities'", "Religious Action Filters") { Action("action", Constants.spreadReligion, "An action that a unit can perform. Currently, there are only two actions part of this: 'Spread Religion' and 'Remove Foreign religions from your own cities'", "Religious Action Filters") {
private val knownValues = setOf(Constants.spreadReligion, Constants.removeHeresy) private val knownValues = setOf(Constants.spreadReligion, Constants.removeHeresy)
override fun getErrorSeverity( override fun getErrorSeverity(

View File

@ -219,6 +219,7 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
ReligionSpreadDistance("Religion naturally spreads to cities [amount] tiles away", UniqueTarget.Global, UniqueTarget.FollowerBelief), ReligionSpreadDistance("Religion naturally spreads to cities [amount] tiles away", UniqueTarget.Global, UniqueTarget.FollowerBelief),
MayNotGenerateGreatProphet("May not generate great prophet equivalents naturally", UniqueTarget.Global), MayNotGenerateGreatProphet("May not generate great prophet equivalents naturally", UniqueTarget.Global),
FaithCostOfGreatProphetChange("[relativeAmount]% Faith cost of generating Great Prophet equivalents", UniqueTarget.Global), FaithCostOfGreatProphetChange("[relativeAmount]% Faith cost of generating Great Prophet equivalents", UniqueTarget.Global),
@Deprecated("As of 4.8.9", ReplaceWith("All newly-trained [baseUnitFilter] units [cityFilter] receive the [Devout] promotion"))
UnitStartingActions("[baseUnitFilter] units built [cityFilter] can [action] [amount] extra times", UniqueTarget.Global, UniqueTarget.FollowerBelief), UnitStartingActions("[baseUnitFilter] units built [cityFilter] can [action] [amount] extra times", UniqueTarget.Global, UniqueTarget.FollowerBelief),
/// Things you get at the start of the game /// Things you get at the start of the game
@ -326,7 +327,12 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
MayParadrop("May Paradrop up to [amount] tiles from inside friendly territory", UniqueTarget.Unit), MayParadrop("May Paradrop up to [amount] tiles from inside friendly territory", UniqueTarget.Unit),
CanAirsweep("Can perform Air Sweep", UniqueTarget.Unit), CanAirsweep("Can perform Air Sweep", UniqueTarget.Unit),
@Deprecated("As of 4.8.9", ReplaceWith("Can Spread Religion <[amount] times> <after which this unit is consumed>\" OR \"Can remove other religions from cities <in [Friendly] tiles> <once> <after which this unit is consumed>"))
CanActionSeveralTimes("Can [action] [amount] times", UniqueTarget.Unit), CanActionSeveralTimes("Can [action] [amount] times", UniqueTarget.Unit),
CanSpreadReligion("Can Spread Religion", UniqueTarget.Unit),
CanRemoveHeresy("Can remove other religions from cities", UniqueTarget.Unit),
CanSpeedupConstruction("Can speed up construction of a building", UniqueTarget.Unit), CanSpeedupConstruction("Can speed up construction of a building", UniqueTarget.Unit),
CanSpeedupWonderConstruction("Can speed up the construction of a wonder", UniqueTarget.Unit), CanSpeedupWonderConstruction("Can speed up the construction of a wonder", UniqueTarget.Unit),
CanHurryResearch("Can hurry technology research", UniqueTarget.Unit), CanHurryResearch("Can hurry technology research", UniqueTarget.Unit),

View File

@ -8,11 +8,15 @@ import com.unciv.models.translations.tr
import com.unciv.ui.components.Fonts import com.unciv.ui.components.Fonts
object UnitActionModifiers { object UnitActionModifiers {
fun canUse(unit: MapUnit, actionUnique: Unique): Boolean {
val usagesLeft = usagesLeft(unit, actionUnique)
return usagesLeft == null || usagesLeft > 0
}
fun getUsableUnitActionUniques(unit:MapUnit, actionUniqueType: UniqueType) = fun getUsableUnitActionUniques(unit:MapUnit, actionUniqueType: UniqueType) =
unit.getMatchingUniques(actionUniqueType) unit.getMatchingUniques(actionUniqueType)
.filter { it.conditionals.none { it.type == UniqueType.UnitActionExtraLimitedTimes } } .filter { it.conditionals.none { it.type == UniqueType.UnitActionExtraLimitedTimes } }
.filter { usagesLeft(unit, it) != 0 } .filter { canUse(unit, it) }
private fun getMovementPointsToUse(actionUnique: Unique): Int { private fun getMovementPointsToUse(actionUnique: Unique): Int {
val movementCost = actionUnique.conditionals val movementCost = actionUnique.conditionals
@ -44,7 +48,7 @@ object UnitActionModifiers {
} }
/** Returns 'null' if usages are not limited */ /** Returns 'null' if usages are not limited */
fun usagesLeft(unit: MapUnit, actionUnique: Unique): Int?{ private fun usagesLeft(unit: MapUnit, actionUnique: Unique): Int?{
val usagesTotal = getMaxUsages(unit, actionUnique) ?: return null val usagesTotal = getMaxUsages(unit, actionUnique) ?: return null
val usagesSoFar = unit.abilityToTimesUsed[actionUnique.placeholderText] ?: 0 val usagesSoFar = unit.abilityToTimesUsed[actionUnique.placeholderText] ?: 0
return usagesTotal - usagesSoFar return usagesTotal - usagesSoFar

View File

@ -8,6 +8,7 @@ import com.unciv.logic.map.mapunit.MapUnit
import com.unciv.logic.map.tile.Tile import com.unciv.logic.map.tile.Tile
import com.unciv.models.UnitAction import com.unciv.models.UnitAction
import com.unciv.models.UnitActionType import com.unciv.models.UnitActionType
import com.unciv.models.ruleset.unique.Unique
import com.unciv.models.ruleset.unique.UniqueType import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.translations.tr import com.unciv.models.translations.tr
import com.unciv.ui.popups.ConfirmPopup import com.unciv.ui.popups.ConfirmPopup
@ -47,7 +48,8 @@ object UnitActions {
UnitActionsReligion.addFoundReligionAction(unit, actionList) UnitActionsReligion.addFoundReligionAction(unit, actionList)
UnitActionsReligion.addEnhanceReligionAction(unit, actionList) UnitActionsReligion.addEnhanceReligionAction(unit, actionList)
actionList += UnitActionsFromUniques.getImprovementConstructionActions(unit, tile) actionList += UnitActionsFromUniques.getImprovementConstructionActions(unit, tile)
UnitActionsReligion.addActionsWithLimitedUses(unit, actionList, tile) UnitActionsReligion.addSpreadReligionActions(unit, actionList)
UnitActionsReligion.addRemoveHeresyActions(unit, actionList)
UnitActionsFromUniques.addTriggerUniqueActions(unit, actionList) UnitActionsFromUniques.addTriggerUniqueActions(unit, actionList)
UnitActionsFromUniques.addAddInCapitalAction(unit, actionList, tile) UnitActionsFromUniques.addAddInCapitalAction(unit, actionList, tile)
@ -119,7 +121,8 @@ object UnitActions {
type = UnitActionType.SwapUnits, type = UnitActionType.SwapUnits,
isCurrentAction = worldScreen.bottomUnitTable.selectedUnitIsSwapping, isCurrentAction = worldScreen.bottomUnitTable.selectedUnitIsSwapping,
action = { action = {
worldScreen.bottomUnitTable.selectedUnitIsSwapping = !worldScreen.bottomUnitTable.selectedUnitIsSwapping worldScreen.bottomUnitTable.selectedUnitIsSwapping =
!worldScreen.bottomUnitTable.selectedUnitIsSwapping
worldScreen.shouldUpdate = true worldScreen.shouldUpdate = true
} }
) )
@ -163,7 +166,11 @@ object UnitActions {
} }
private fun addFortifyActions(actionList: ArrayList<UnitAction>, unit: MapUnit, showingAdditionalActions: Boolean) { private fun addFortifyActions(
actionList: ArrayList<UnitAction>,
unit: MapUnit,
showingAdditionalActions: Boolean
) {
if (unit.isFortified() && !showingAdditionalActions) { if (unit.isFortified() && !showingAdditionalActions) {
actionList += UnitAction( actionList += UnitAction(
type = if (unit.isActionUntilHealed()) type = if (unit.isActionUntilHealed())
@ -189,11 +196,16 @@ object UnitActions {
action = { unit.fortify() }.takeIf { !isFortified }) action = { unit.fortify() }.takeIf { !isFortified })
} }
private fun addSleepActions(actionList: ArrayList<UnitAction>, unit: MapUnit, showingAdditionalActions: Boolean) { private fun addSleepActions(
actionList: ArrayList<UnitAction>,
unit: MapUnit,
showingAdditionalActions: Boolean
) {
if (unit.isFortified() || unit.canFortify() || unit.currentMovement == 0f) return if (unit.isFortified() || unit.canFortify() || unit.currentMovement == 0f) return
// If this unit is working on an improvement, it cannot sleep // If this unit is working on an improvement, it cannot sleep
if (unit.currentTile.hasImprovementInProgress() if (unit.currentTile.hasImprovementInProgress()
&& unit.canBuildImprovement(unit.currentTile.getTileImprovementInProgress()!!)) return && unit.canBuildImprovement(unit.currentTile.getTileImprovementInProgress()!!)
) return
val isSleeping = unit.isSleeping() val isSleeping = unit.isSleeping()
val isDamaged = unit.health < 100 val isDamaged = unit.health < 100
@ -223,7 +235,10 @@ object UnitActions {
if (recipient.isAtWarWith(unit.civ)) return null // No gifts to enemy CS if (recipient.isAtWarWith(unit.civ)) return null // No gifts to enemy CS
// City States only take military units (and units specifically allowed by uniques) // City States only take military units (and units specifically allowed by uniques)
if (!unit.isMilitary() if (!unit.isMilitary()
&& unit.getMatchingUniques(UniqueType.GainInfluenceWithUnitGiftToCityState, checkCivInfoUniques = true) && unit.getMatchingUniques(
UniqueType.GainInfluenceWithUnitGiftToCityState,
checkCivInfoUniques = true
)
.none { unit.matchesFilter(it.params[1]) } .none { unit.matchesFilter(it.params[1]) }
) return null ) return null
} }
@ -238,7 +253,10 @@ object UnitActions {
val giftAction = { val giftAction = {
if (recipient.isCityState()) { if (recipient.isCityState()) {
for (unique in unit.getMatchingUniques(UniqueType.GainInfluenceWithUnitGiftToCityState, checkCivInfoUniques = true)) { for (unique in unit.getMatchingUniques(
UniqueType.GainInfluenceWithUnitGiftToCityState,
checkCivInfoUniques = true
)) {
if (unit.matchesFilter(unique.params[1])) { if (unit.matchesFilter(unique.params[1])) {
recipient.getDiplomacyManager(unit.civ) recipient.getDiplomacyManager(unit.civ)
.addInfluence(unique.params[0].toFloat() - 5f) .addInfluence(unique.params[0].toFloat() - 5f)
@ -260,7 +278,11 @@ object UnitActions {
return UnitAction(UnitActionType.GiftUnit, action = giftAction) return UnitAction(UnitActionType.GiftUnit, action = giftAction)
} }
private fun addAutomateAction(unit: MapUnit, actionList: ArrayList<UnitAction>, showingAdditionalActions:Boolean) { private fun addAutomateAction(
unit: MapUnit,
actionList: ArrayList<UnitAction>,
showingAdditionalActions: Boolean
) {
// If either of these are true it goes in primary actions, else in additional actions // If either of these are true it goes in primary actions, else in additional actions
if ((unit.hasUnique(UniqueType.AutomationPrimaryAction) || unit.cache.hasUniqueToBuildImprovements) != showingAdditionalActions) if ((unit.hasUnique(UniqueType.AutomationPrimaryAction) || unit.cache.hasUniqueToBuildImprovements) != showingAdditionalActions)
@ -297,5 +319,6 @@ object UnitActions {
} }
) )
} }
}
}

View File

@ -187,7 +187,7 @@ object UnitActionsFromUniques {
// extends an existing unit action // extends an existing unit action
if (unique.conditionals.any { it.type == UniqueType.UnitActionExtraLimitedTimes }) continue if (unique.conditionals.any { it.type == UniqueType.UnitActionExtraLimitedTimes }) continue
if (!unique.isTriggerable) continue if (!unique.isTriggerable) continue
if (UnitActionModifiers.usagesLeft(unit, unique) ==0) continue if (!UnitActionModifiers.canUse(unit, unique)) continue
val baseTitle = if (unique.isOfType(UniqueType.OneTimeEnterGoldenAgeTurns)) val baseTitle = if (unique.isOfType(UniqueType.OneTimeEnterGoldenAgeTurns))
unique.placeholderText.fillPlaceholders( unique.placeholderText.fillPlaceholders(

View File

@ -1,10 +1,8 @@
package com.unciv.ui.screens.worldscreen.unit.actions package com.unciv.ui.screens.worldscreen.unit.actions
import com.unciv.Constants import com.unciv.Constants
import com.unciv.logic.city.City
import com.unciv.logic.civilization.NotificationCategory import com.unciv.logic.civilization.NotificationCategory
import com.unciv.logic.map.mapunit.MapUnit import com.unciv.logic.map.mapunit.MapUnit
import com.unciv.logic.map.tile.Tile
import com.unciv.models.UnitAction import com.unciv.models.UnitAction
import com.unciv.models.UnitActionType import com.unciv.models.UnitActionType
import com.unciv.models.ruleset.unique.UniqueType import com.unciv.models.ruleset.unique.UniqueType
@ -43,22 +41,6 @@ object UnitActionsReligion {
} }
} }
fun addActionsWithLimitedUses(unit: MapUnit, actionList: ArrayList<UnitAction>, tile: Tile) {
val actionsToAdd = unit.limitedActionsUnitCanDo()
if (actionsToAdd.none()) return
if (unit.religion == null || unit.civ.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) { private fun useActionWithLimitedUses(unit: MapUnit, action: String) {
unit.abilityUsesLeft[action] = unit.abilityUsesLeft[action]!! - 1 unit.abilityUsesLeft[action] = unit.abilityUsesLeft[action]!! - 1
if (unit.abilityUsesLeft[action]!! <= 0) { if (unit.abilityUsesLeft[action]!! <= 0) {
@ -75,11 +57,19 @@ object UnitActionsReligion {
return pressureAdded.toInt() return pressureAdded.toInt()
} }
private fun addSpreadReligionActions(unit: MapUnit, actionList: ArrayList<UnitAction>, city: City) { fun addSpreadReligionActions(unit: MapUnit, actionList: ArrayList<UnitAction>) {
if (!unit.civ.religionManager.maySpreadReligionAtAll(unit)) return if (!unit.civ.religionManager.maySpreadReligionAtAll(unit)) return
val city = unit.currentTile.getCity() ?: return
val newStyleUnique = UnitActionModifiers.getUsableUnitActionUniques(unit, UniqueType.CanSpreadReligion).firstOrNull()
val title = if (newStyleUnique != null)
UnitActionModifiers.actionTextWithSideEffects("Spread [${unit.getReligionDisplayName()!!}]", newStyleUnique, unit)
else "Spread [${unit.getReligionDisplayName()!!}]"
actionList += UnitAction( actionList += UnitAction(
UnitActionType.SpreadReligion, UnitActionType.SpreadReligion,
title = "Spread [${unit.getReligionDisplayName()!!}]", title = title,
action = { action = {
val followersOfOtherReligions = city.religion.getFollowersOfOtherReligionsThan(unit.religion!!) val followersOfOtherReligions = city.religion.getFollowersOfOtherReligionsThan(unit.religion!!)
for (unique in unit.getMatchingUniques(UniqueType.StatsWhenSpreading, checkCivInfoUniques = true)) { for (unique in unit.getMatchingUniques(UniqueType.StatsWhenSpreading, checkCivInfoUniques = true)) {
@ -88,21 +78,42 @@ object UnitActionsReligion {
city.religion.addPressure(unit.religion!!, getPressureAddedFromSpread(unit)) city.religion.addPressure(unit.religion!!, getPressureAddedFromSpread(unit))
if (unit.hasUnique(UniqueType.RemoveOtherReligions)) if (unit.hasUnique(UniqueType.RemoveOtherReligions))
city.religion.removeAllPressuresExceptFor(unit.religion!!) city.religion.removeAllPressuresExceptFor(unit.religion!!)
unit.currentMovement = 0f
if (newStyleUnique != null) UnitActionModifiers.activateSideEffects(unit, newStyleUnique)
else {
useActionWithLimitedUses(unit, Constants.spreadReligion) useActionWithLimitedUses(unit, Constants.spreadReligion)
unit.currentMovement = 0f
}
}.takeIf { unit.currentMovement > 0 && unit.civ.religionManager.maySpreadReligionNow(unit) } }.takeIf { unit.currentMovement > 0 && unit.civ.religionManager.maySpreadReligionNow(unit) }
) )
} }
private fun addRemoveHeresyActions(unit: MapUnit, actionList: ArrayList<UnitAction>, city: City) { internal fun addRemoveHeresyActions(unit: MapUnit, actionList: ArrayList<UnitAction>) {
if (!unit.civ.gameInfo.isReligionEnabled()) return if (!unit.civ.gameInfo.isReligionEnabled()) return
val religion = unit.civ.gameInfo.religions[unit.religion] ?: return
if (religion.isPantheon()) return
val city = unit.currentTile.getCity() ?: return
if (city.civ != unit.civ) return if (city.civ != unit.civ) return
// Only allow the action if the city actually has any foreign religion // Only allow the action if the city actually has any foreign religion
// This will almost be always due to pressure from cities close-by // This will almost be always due to pressure from cities close-by
if (city.religion.getPressures().none { it.key != unit.religion!! }) return if (city.religion.getPressures().none { it.key != unit.religion!! }) return
val hasOldStyleAbility = unit.abilityUsesLeft.containsKey(Constants.removeHeresy)
&& unit.abilityUsesLeft[Constants.removeHeresy]!! > 0
val newStyleUnique = UnitActionModifiers.getUsableUnitActionUniques(unit, UniqueType.CanRemoveHeresy).firstOrNull()
val hasNewStyleAbility = newStyleUnique != null
if (!hasOldStyleAbility && !hasNewStyleAbility) return
val title = if (hasNewStyleAbility)
UnitActionModifiers.actionTextWithSideEffects("Remove Heresy", newStyleUnique!!, unit)
else "Remove Heresy"
actionList += UnitAction( actionList += UnitAction(
UnitActionType.RemoveHeresy, UnitActionType.RemoveHeresy,
title = "Remove Heresy", title = title,
action = { action = {
city.religion.removeAllPressuresExceptFor(unit.religion!!) city.religion.removeAllPressuresExceptFor(unit.religion!!)
if (city.religion.religionThisIsTheHolyCityOf != null) { if (city.religion.religionThisIsTheHolyCityOf != null) {
@ -115,8 +126,12 @@ object UnitActionsReligion {
city.religion.isBlockedHolyCity = false city.religion.isBlockedHolyCity = false
} }
} }
unit.currentMovement = 0f
if (hasNewStyleAbility) UnitActionModifiers.activateSideEffects(unit, newStyleUnique!!)
else {
useActionWithLimitedUses(unit, Constants.removeHeresy) useActionWithLimitedUses(unit, Constants.removeHeresy)
unit.currentMovement = 0f
}
}.takeIf { unit.currentMovement > 0f } }.takeIf { unit.currentMovement > 0f }
) )
} }

View File

@ -701,11 +701,6 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: Global Applicable to: Global
??? example "[baseUnitFilter] units built [cityFilter] can [action] [amount] extra times"
Example: "[Melee] units built [in all cities] can [Spread Religion] [3] extra times"
Applicable to: Global, FollowerBelief
??? example "Triggers victory" ??? example "Triggers victory"
Applicable to: Global Applicable to: Global
@ -1142,9 +1137,10 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
??? example "Can perform Air Sweep" ??? example "Can perform Air Sweep"
Applicable to: Unit Applicable to: Unit
??? example "Can [action] [amount] times" ??? example "Can Spread Religion"
Example: "Can [Spread Religion] [3] times" Applicable to: Unit
??? example "Can remove other religions from cities"
Applicable to: Unit Applicable to: Unit
??? example "Can speed up construction of a building" ??? example "Can speed up construction of a building"