'create improvement' action, <consuming this unit> and <as an action> modifiers

This commit is contained in:
Yair Morgenstern
2023-03-01 16:09:44 +02:00
parent 66faeb0d15
commit ae501c3750
10 changed files with 95 additions and 48 deletions

View File

@ -1599,33 +1599,44 @@
{
"name": "Great Artist",
"unitType": "Civilian",
"uniques": ["Can start an [8]-turn golden age", "Can construct [Landmark]", "Great Person - [Culture]", "Unbuildable", "Uncapturable"],
"uniques": ["Can start an [8]-turn golden age",
"Can instantly construct a [Landmark] improvement <consuming this unit>",
"Great Person - [Culture]", "Unbuildable", "Uncapturable"],
"movement": 2
},
{
"name": "Great Scientist",
"unitType": "Civilian",
"uniques": ["Can hurry technology research", "Can construct [Academy]", "Great Person - [Science]", "Unbuildable", "Uncapturable"],
"uniques": ["Can hurry technology research",
"Can instantly construct a [Academy] improvement <consuming this unit>",
"Great Person - [Science]", "Unbuildable", "Uncapturable"],
"movement": 2
},
{
"name": "Great Merchant",
"unitType": "Civilian",
"uniques": ["Can undertake a trade mission with City-State, giving a large sum of gold and [30] Influence",
"Can construct [Customs house]", "Great Person - [Gold]", "Unbuildable", "Uncapturable"],
"Can instantly construct a [Customs house] improvement <consuming this unit>",
"Great Person - [Gold]", "Unbuildable", "Uncapturable"],
"movement": 2
},
{
"name": "Great Engineer",
"unitType": "Civilian",
"uniques": ["Can speed up construction of a building", "Can construct [Manufactory]", "Great Person - [Production]", "Unbuildable", "Uncapturable"],
"uniques": ["Can speed up construction of a building",
"Can instantly construct a [Manufactory] improvement <consuming this unit>",
"Great Person - [Production]", "Unbuildable", "Uncapturable"],
"movement": 2
},
{
"name": "Great Prophet",
"unitType": "Civilian",
"uniques": ["Can construct [Holy site] <if it hasn't used other actions yet>", "Can [Spread Religion] [4] times",
"Removes other religions when spreading religion", "May found a religion", "May enhance a religion",
"uniques": [
"Can instantly construct a [Holy site] improvement <consuming this unit> <if it hasn't used other actions yet>",
"Can [Spread Religion] [4] times",
"Removes other religions when spreading religion",
"May found a religion",
"May enhance a religion",
"May enter foreign tiles without open borders", "[-1] Sight", "Great Person - [Faith]",
"Unbuildable", "Religious Unit", "Hidden when religion is disabled",
"Takes your religion over the one in their birth city"],
@ -1635,7 +1646,8 @@
{
"name": "Great General",
"unitType": "Civilian",
"uniques": ["Can start an [8]-turn golden age", "[+15]% Strength bonus for [Military] units within [2] tiles", "Can construct [Citadel]",
"uniques": ["Can start an [8]-turn golden age", "[+15]% Strength bonus for [Military] units within [2] tiles",
"Can instantly construct a [Citadel] improvement <consuming this unit>",
"Great Person - [War]", "Unbuildable", "Uncapturable"],
"movement": 2
},
@ -1645,7 +1657,9 @@
"uniqueTo": "Mongolia",
"replaces": "Great General",
"uniques": ["Can start an [8]-turn golden age","[+15]% Strength bonus for [Military] units within [2] tiles",
"All adjacent units heal [+15] HP when healing", "[+15] HP when healing", "Can construct [Citadel]", "Great Person - [War]", "Unbuildable", "Uncapturable"],
"All adjacent units heal [+15] HP when healing", "[+15] HP when healing",
"Can instantly construct a [Citadel] improvement <consuming this unit>",
"Great Person - [War]", "Unbuildable", "Uncapturable"],
"movement": 5
},

View File

@ -380,22 +380,6 @@
"promotions": ["[Mohawk Warrior] ability"],
"attackSound": "metalhit"
},
/*
{
"name": "Swordsman",
"unitType": "Sword",
"movement": 2,
"strength": 14,
"cost": 75,
"requiredTech": "Iron Working",
"upgradesTo": "Longswordsman",
"obsoleteTech": "Gunpowder",
"requiredResource": "Iron",
"hurryCostModifier": 20,
"attackSound": "metalhit"
// Barbarian unique Swordsman. Has same icon and name but slightly different 3d texture
},
*/
// Medieval Era
{
@ -1274,33 +1258,44 @@
{
"name": "Great Artist",
"unitType": "Civilian",
"uniques": ["Can start an [8]-turn golden age", "Can construct [Landmark]", "Great Person - [Culture]", "Unbuildable", "Uncapturable"],
"uniques": ["Can start an [8]-turn golden age",
"Can instantly construct a [Landmark] improvement <consuming this unit>",
"Great Person - [Culture]", "Unbuildable", "Uncapturable"],
"movement": 2
},
{
"name": "Great Scientist",
"unitType": "Civilian",
"uniques": ["Can hurry technology research", "Can construct [Academy]", "Great Person - [Science]", "Unbuildable", "Uncapturable"],
"uniques": ["Can hurry technology research",
"Can instantly construct a [Academy] improvement <consuming this unit>",
"Great Person - [Science]", "Unbuildable", "Uncapturable"],
"movement": 2
},
{
"name": "Great Merchant",
"unitType": "Civilian",
"uniques": ["Can undertake a trade mission with City-State, giving a large sum of gold and [30] Influence",
"Can construct [Customs house]", "Great Person - [Gold]", "Unbuildable", "Uncapturable"],
"Can instantly construct a [Customs house] improvement <consuming this unit>",
"Great Person - [Gold]", "Unbuildable", "Uncapturable"],
"movement": 2
},
{
"name": "Great Engineer",
"unitType": "Civilian",
"uniques": ["Can speed up construction of a building", "Can construct [Manufactory]", "Great Person - [Production]", "Unbuildable", "Uncapturable"],
"uniques": ["Can speed up construction of a building",
"Can instantly construct a [Manufactory] improvement <consuming this unit>",
"Great Person - [Production]", "Unbuildable", "Uncapturable"],
"movement": 2
},
{
"name": "Great Prophet",
"unitType": "Civilian",
"uniques": ["Can construct [Holy site] <if it hasn't used other actions yet>", "Can [Spread Religion] [4] times",
"Removes other religions when spreading religion", "May found a religion", "May enhance a religion",
"uniques": [
"Can instantly construct a [Holy site] improvement <consuming this unit> <if it hasn't used other actions yet>",
"Can [Spread Religion] [4] times",
"Removes other religions when spreading religion",
"May found a religion",
"May enhance a religion",
"May enter foreign tiles without open borders", "[-1] Sight", "Great Person - [Faith]",
"Unbuildable", "Religious Unit", "Hidden when religion is disabled",
"Takes your religion over the one in their birth city"],
@ -1310,7 +1305,8 @@
{
"name": "Great General",
"unitType": "Civilian",
"uniques": ["Can start an [8]-turn golden age", "[+15]% Strength bonus for [Military] units within [2] tiles", "Can construct [Citadel]",
"uniques": ["Can start an [8]-turn golden age", "[+15]% Strength bonus for [Military] units within [2] tiles",
"Can instantly construct a [Citadel] improvement <consuming this unit>",
"Great Person - [War]", "Unbuildable", "Uncapturable"],
"movement": 2
},
@ -1320,7 +1316,9 @@
"uniqueTo": "Mongolia",
"replaces": "Great General",
"uniques": ["Can start an [8]-turn golden age", "[+15]% Strength bonus for [Military] units within [2] tiles",
"All adjacent units heal [+15] HP when healing", "[+15] HP when healing", "Can construct [Citadel]", "Great Person - [War]", "Unbuildable", "Uncapturable"],
"All adjacent units heal [+15] HP when healing", "[+15] HP when healing",
"Can instantly construct a [Citadel] improvement <consuming this unit>",
"Great Person - [War]", "Unbuildable", "Uncapturable"],
"movement": 5
},

View File

@ -248,7 +248,8 @@ object SpecificUnitAutomation {
}
fun automateImprovementPlacer(unit: MapUnit) {
val improvementBuildingUniques = unit.getMatchingUniques(UniqueType.ConstructImprovementConsumingUnit)
val improvementBuildingUniques = unit.getMatchingUniques(UniqueType.ConstructImprovementConsumingUnit) +
unit.getMatchingUniques(UniqueType.ConstructImprovementInstantly)
val improvementName = improvementBuildingUniques.first().params[0]
val improvement = unit.civ.gameInfo.ruleset.tileImprovements[improvementName]

View File

@ -262,7 +262,8 @@ object UnitAutomation {
if (unit.hasUnique(UniqueType.PreventSpreadingReligion) || unit.canDoReligiousAction(Constants.removeHeresy))
return SpecificUnitAutomation.automateInquisitor(unit)
if (unit.hasUnique(UniqueType.ConstructImprovementConsumingUnit))
if (unit.hasUnique(UniqueType.ConstructImprovementConsumingUnit)
|| unit.hasUnique(UniqueType.ConstructImprovementInstantly))
// catch great prophet for civs who can't found/enhance/spread religion
return SpecificUnitAutomation.automateImprovementPlacer(unit) // includes great people plus moddable units

View File

@ -121,7 +121,10 @@ class MapUnitCache(val mapUnit: MapUnit) {
|| mapUnit.hasUnique(UniqueType.CanEnterForeignTilesButLosesReligiousStrength)
hasStrengthBonusInRadiusUnique = mapUnit.hasUnique(UniqueType.StrengthBonusInRadius)
hasCitadelPlacementUnique = mapUnit.getMatchingUniques(UniqueType.ConstructImprovementConsumingUnit)
hasCitadelPlacementUnique = (
mapUnit.getMatchingUniques(UniqueType.ConstructImprovementConsumingUnit)
+ mapUnit.getMatchingUniques(UniqueType.ConstructImprovementInstantly)
)
.mapNotNull { mapUnit.civ.gameInfo.ruleset.tileImprovements[it.params[0]] }
.any { it.hasUnique(UniqueType.TakesOverAdjacentTiles) }
}

View File

@ -167,7 +167,8 @@ class RulesetValidator(val ruleset: Ruleset) {
lines += "${unit.name} contains promotion $promotion which does not exist!"
if (!ruleset.unitTypes.containsKey(unit.unitType) && (ruleset.unitTypes.isNotEmpty() || !vanillaRuleset.unitTypes.containsKey(unit.unitType)))
lines += "${unit.name} is of type ${unit.unitType}, which does not exist!"
for (unique in unit.getMatchingUniques(UniqueType.ConstructImprovementConsumingUnit)) {
for (unique in unit.getMatchingUniques(UniqueType.ConstructImprovementConsumingUnit)
+ unit.getMatchingUniques(UniqueType.ConstructImprovementInstantly)) {
val improvementName = unique.params[0]
if (ruleset.tileImprovements[improvementName]==null) continue // this will be caught in the checkUniques
if ((ruleset.tileImprovements[improvementName] as Stats).none() &&
@ -545,7 +546,7 @@ class RulesetValidator(val ruleset: Ruleset) {
// the 'consume unit' conditional causes a triggerable unique to become a unit action
&& !(uniqueTarget== UniqueTarget.Unit
&& unique.isTriggerable
&& unique.conditionals.any { it.type == UniqueType.ConditionalConsumeUnit }))
&& unique.conditionals.any { it.type == UniqueType.UnitActionConsumeUnit }))
rulesetErrors.add(
"$name's unique \"${unique.text}\" cannot be put on this type of object!",
RulesetErrorSeverity.Warning

View File

@ -13,9 +13,9 @@ import com.unciv.models.ruleset.unique.UniqueTarget
import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.ruleset.unit.BaseUnit
import com.unciv.models.translations.tr
import com.unciv.ui.components.extensions.toPercent
import com.unciv.ui.screens.civilopediascreen.CivilopediaScreen.Companion.showReligionInCivilopedia
import com.unciv.ui.screens.civilopediascreen.FormattedLine
import com.unciv.ui.components.extensions.toPercent
import com.unciv.ui.screens.worldscreen.unit.actions.UnitActions
import kotlin.math.roundToInt
@ -274,7 +274,8 @@ class TileImprovement : RulesetStatsObject() {
private fun getCreatingUnits(ruleset: Ruleset): List<BaseUnit> {
return ruleset.units.values.asSequence()
.filter { unit ->
unit.getMatchingUniques(UniqueType.ConstructImprovementConsumingUnit, StateForConditionals.IgnoreConditionals)
(unit.getMatchingUniques(UniqueType.ConstructImprovementConsumingUnit, StateForConditionals.IgnoreConditionals)
+ unit.getMatchingUniques(UniqueType.ConstructImprovementInstantly))
.any { it.params[0] == name }
}.toList()
}

View File

@ -347,7 +347,11 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
///////////////////////////////////////// region UNIT UNIQUES /////////////////////////////////////////
// Unit action uniques
// Unit actions should look like: "Can {action description}, to allow them to be combined with modifiers
FoundCity("Founds a new city", UniqueTarget.Unit),
ConstructImprovementInstantly("Can instantly construct a [improvementName] improvement", UniqueTarget.Unit),
@Deprecated("as of 4.5.2", ReplaceWith("Can instantly construct a [improvementName] improvement"))
ConstructImprovementConsumingUnit("Can construct [improvementName]", UniqueTarget.Unit),
BuildImprovements("Can build [improvementFilter/terrainFilter] improvements on tiles", UniqueTarget.Unit),
CreateWaterImprovements("May create improvements on water resources", UniqueTarget.Unit),
@ -501,7 +505,10 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags:
///////////////////////////////////////// region UNIT ACTION MODIFIERS /////////////////////////////////////////
ConditionalConsumeUnit("by consuming this unit", UniqueTarget.UnitActionModifier),
UnitActionConsumeUnit("consuming this unit", UniqueTarget.UnitActionModifier),
UnitActionTriggerUnitUnique("as an action", UniqueTarget.UnitActionModifier),
@Deprecated("as of 4.5.2", ReplaceWith("consuming this unit"))
UnitActionConsumeUnitOld("by consuming this unit", UniqueTarget.UnitActionModifier),
// endregion

View File

@ -18,8 +18,10 @@ import com.unciv.models.UncivSound
import com.unciv.models.UnitAction
import com.unciv.models.UnitActionType
import com.unciv.models.ruleset.unique.StateForConditionals
import com.unciv.models.ruleset.unique.Unique
import com.unciv.models.ruleset.unique.UniqueTriggerActivation
import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.translations.removeConditionals
import com.unciv.models.translations.tr
import com.unciv.ui.components.Fonts
import com.unciv.ui.popups.ConfirmPopup
@ -453,7 +455,8 @@ object UnitActions {
fun getImprovementConstructionActions(unit: MapUnit, tile: Tile): ArrayList<UnitAction> {
val finalActions = ArrayList<UnitAction>()
val uniquesToCheck = unit.getMatchingUniques(UniqueType.ConstructImprovementConsumingUnit)
val uniquesToCheck = unit.getMatchingUniques(UniqueType.ConstructImprovementConsumingUnit) +
unit.getMatchingUniques(UniqueType.ConstructImprovementInstantly)
val civResources = unit.civ.getCivResourcesByName()
for (unique in uniquesToCheck) {
@ -474,7 +477,9 @@ object UnitActions {
unitTile.changeImprovement(improvementName)
unitTile.stopWorkingOnImprovement()
improvement.handleImprovementCompletion(unit)
unit.consume()
if (unique.type == UniqueType.ConstructImprovementConsumingUnit) unit.consume()
else activateSideEffects(unit, unique)
}.takeIf {
resourcesAvailable
&& unit.currentMovement > 0f
@ -637,10 +642,11 @@ object UnitActions {
private fun addTriggerUniqueActions(unit: MapUnit, actionList: ArrayList<UnitAction>){
for (unique in unit.getUniques()) {
if (!unique.conditionals.any { it.type == UniqueType.ConditionalConsumeUnit }) continue
val unitAction = UnitAction(type = UnitActionType.TriggerUnique, unique.text){
UniqueTriggerActivation.triggerCivwideUnique(unique, unit.civ)
unit.consume()
if (!unique.conditionals.any { it.type == UniqueType.UnitActionTriggerUnitUnique }) continue
val unitAction = UnitAction(type = UnitActionType.TriggerUnique, unique.text.removeConditionals()){
UniqueTriggerActivation.triggerUnitwideUnique(unique, unit)
activateSideEffects(unit, unique)
}
actionList += unitAction
}
@ -666,4 +672,13 @@ object UnitActions {
}
)
}
fun activateSideEffects(unit: MapUnit, actionUnique: Unique){
for (conditional in actionUnique.conditionals){
when (conditional.type){
UniqueType.UnitActionConsumeUnit -> unit.consume()
else -> unit.useMovementPoints(1f)
}
}
}
}

View File

@ -1039,8 +1039,8 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
??? example "Founds a new city"
Applicable to: Unit
??? example "Can construct [improvementName]"
Example: "Can construct [Trading Post]"
??? example "Can instantly construct a [improvementName] improvement"
Example: "Can instantly construct a [Trading Post] improvement"
Applicable to: Unit
@ -1975,6 +1975,12 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
Applicable to: UnitTriggerCondition
## UnitActionModifier uniques
??? example "&lt;consuming this unit&gt;"
Applicable to: UnitActionModifier
??? example "&lt;as an action&gt;"
Applicable to: UnitActionModifier
??? example "&lt;by consuming this unit&gt;"
Applicable to: UnitActionModifier