New uniques and stuff for mods (#3055)

* "[+1 Gold] for each adjacent [Road]" Roadstatus can be used now in tile improvement uniques

* Added hasViewableResource check to "[stats] from every [Resource]"

* Fixed translation of nation uniques

* Eras with no researchable techs will not appear in dropdown menu in new game options

* Implemented startingUnits, aiMajorCivStartingUnits and aiCityStateStartingUnits fields in difficulty

* reassignRemovedModReferences will also reassign if nation is a City-State in current ruleset
e.g. Venice will be unselected if player unselects Civ5ExpansionMod which has it as playable civ

* "Cannot be purchased" - new unique for non-wonders and units. SS parts have it

* Update template.properties

* Update Difficulty.kt
This commit is contained in:
HadeanLake 2020-08-30 15:48:00 +03:00 committed by GitHub
parent 5e1508e481
commit 15ed1a608b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 65 additions and 30 deletions

View File

@ -908,7 +908,7 @@
"name": "SS Booster", "name": "SS Booster",
"requiredResource": "Aluminum", "requiredResource": "Aluminum",
"requiredTech": "Robotics", "requiredTech": "Robotics",
"uniques": ["Spaceship part"] "uniques": ["Spaceship part", "Cannot be purchased"]
}, },
{ {
"name": "Apollo Program", "name": "Apollo Program",
@ -935,18 +935,18 @@
"name": "SS Cockpit", "name": "SS Cockpit",
"requiredResource": "Aluminum", "requiredResource": "Aluminum",
"requiredTech": "Satellites", "requiredTech": "Satellites",
"uniques": ["Spaceship part"] "uniques": ["Spaceship part", "Cannot be purchased"]
}, },
{ {
"name": "SS Engine", "name": "SS Engine",
"requiredResource": "Aluminum", "requiredResource": "Aluminum",
"requiredTech": "Particle Physics", "requiredTech": "Particle Physics",
"uniques": ["Spaceship part"] "uniques": ["Spaceship part", "Cannot be purchased"]
}, },
{ {
"name": "SS Stasis Chamber", "name": "SS Stasis Chamber",
"requiredResource": "Aluminum", "requiredResource": "Aluminum",
"requiredTech": "Nanotechnology", "requiredTech": "Nanotechnology",
"uniques": ["Spaceship part"] "uniques": ["Spaceship part", "Cannot be purchased"]
} }
] ]

View File

@ -9,6 +9,7 @@
"policyCostModifier": 0.5, "policyCostModifier": 0.5,
"unhappinessModifier": 0.4, "unhappinessModifier": 0.4,
"barbarianBonus": 0.75, "barbarianBonus": 0.75,
"startingUnits": ["Settler", "Warrior"],
"aiCityGrowthModifier": 1.6, // that is to say it'll take them 1.6 times as long to grow the city "aiCityGrowthModifier": 1.6, // that is to say it'll take them 1.6 times as long to grow the city
"aiUnitCostModifier": 1.75, "aiUnitCostModifier": 1.75,
"aiBuildingCostModifier": 1.6, "aiBuildingCostModifier": 1.6,
@ -16,7 +17,8 @@
"aiBuildingMaintenanceModifier": 1, "aiBuildingMaintenanceModifier": 1,
"aiUnitMaintenanceModifier": 1, "aiUnitMaintenanceModifier": 1,
"aiFreeTechs": [], "aiFreeTechs": [],
"aiFreeUnits": [], "aiMajorCivStartingUnits": ["Settler", "Warrior"],
"aiCityStateStartingUnits": ["Settler", "Warrior"],
"aiUnhappinessModifier": 1, "aiUnhappinessModifier": 1,
"aisExchangeTechs": false, "aisExchangeTechs": false,
"turnBarbariansCanEnterPlayerTiles": 10000, "turnBarbariansCanEnterPlayerTiles": 10000,
@ -32,6 +34,7 @@
"policyCostModifier": 0.67, "policyCostModifier": 0.67,
"unhappinessModifier": 0.6, "unhappinessModifier": 0.6,
"barbarianBonus": 0.5, "barbarianBonus": 0.5,
"startingUnits": ["Settler", "Warrior"],
"aiCityGrowthModifier": 1.3, "aiCityGrowthModifier": 1.3,
"aiUnitCostModifier": 1.3, "aiUnitCostModifier": 1.3,
"aiBuildingCostModifier": 1.3, "aiBuildingCostModifier": 1.3,
@ -39,7 +42,8 @@
"aiBuildingMaintenanceModifier": 1, "aiBuildingMaintenanceModifier": 1,
"aiUnitMaintenanceModifier": 1, "aiUnitMaintenanceModifier": 1,
"aiFreeTechs": [], "aiFreeTechs": [],
"aiFreeUnits": [], "aiMajorCivStartingUnits": ["Settler", "Warrior"],
"aiCityStateStartingUnits": ["Settler", "Warrior"],
"aiUnhappinessModifier": 1, "aiUnhappinessModifier": 1,
"aisExchangeTechs": false, "aisExchangeTechs": false,
"turnBarbariansCanEnterPlayerTiles": 60, "turnBarbariansCanEnterPlayerTiles": 60,
@ -55,6 +59,7 @@
"policyCostModifier": 0.85, "policyCostModifier": 0.85,
"unhappinessModifier": 0.75, "unhappinessModifier": 0.75,
"barbarianBonus": 0.4, "barbarianBonus": 0.4,
"startingUnits": ["Settler", "Warrior"],
"aiCityGrowthModifier": 1.1, "aiCityGrowthModifier": 1.1,
"aiUnitCostModifier": 1.1, "aiUnitCostModifier": 1.1,
"aiBuildingCostModifier": 1.1, "aiBuildingCostModifier": 1.1,
@ -62,7 +67,8 @@
"aiBuildingMaintenanceModifier": 1, "aiBuildingMaintenanceModifier": 1,
"aiUnitMaintenanceModifier": 1, "aiUnitMaintenanceModifier": 1,
"aiFreeTechs": [], "aiFreeTechs": [],
"aiFreeUnits": [], "aiMajorCivStartingUnits": ["Settler", "Warrior"],
"aiCityStateStartingUnits": ["Settler", "Warrior"],
"aiUnhappinessModifier": 1, "aiUnhappinessModifier": 1,
"aisExchangeTechs": false, "aisExchangeTechs": false,
"turnBarbariansCanEnterPlayerTiles": 20, "turnBarbariansCanEnterPlayerTiles": 20,
@ -78,6 +84,7 @@
"policyCostModifier": 1, "policyCostModifier": 1,
"unhappinessModifier": 1, "unhappinessModifier": 1,
"barbarianBonus": 0.33, "barbarianBonus": 0.33,
"startingUnits": ["Settler", "Warrior"],
"aiCityGrowthModifier": 1, "aiCityGrowthModifier": 1,
"aiUnitCostModifier": 1, "aiUnitCostModifier": 1,
"aiBuildingCostModifier": 1, "aiBuildingCostModifier": 1,
@ -85,7 +92,8 @@
"aiBuildingMaintenanceModifier": 1, "aiBuildingMaintenanceModifier": 1,
"aiUnitMaintenanceModifier": 0.85, "aiUnitMaintenanceModifier": 0.85,
"aiFreeTechs": [], "aiFreeTechs": [],
"aiFreeUnits": [], "aiMajorCivStartingUnits": ["Settler", "Warrior"],
"aiCityStateStartingUnits": ["Settler", "Warrior"],
"aiUnhappinessModifier": 1, "aiUnhappinessModifier": 1,
"aisExchangeTechs": true, "aisExchangeTechs": true,
"turnBarbariansCanEnterPlayerTiles": 0, "turnBarbariansCanEnterPlayerTiles": 0,
@ -101,6 +109,7 @@
"policyCostModifier": 1, "policyCostModifier": 1,
"unhappinessModifier": 1, "unhappinessModifier": 1,
"barbarianBonus": 0.25, "barbarianBonus": 0.25,
"startingUnits": ["Settler", "Warrior"],
"aiCityGrowthModifier": 0.9, "aiCityGrowthModifier": 0.9,
"aiUnitCostModifier": 0.85, "aiUnitCostModifier": 0.85,
"aiBuildingCostModifier": 0.85, "aiBuildingCostModifier": 0.85,
@ -108,7 +117,8 @@
"aiBuildingMaintenanceModifier": 0.85, "aiBuildingMaintenanceModifier": 0.85,
"aiUnitMaintenanceModifier": 0.8, "aiUnitMaintenanceModifier": 0.8,
"aiFreeTechs": ["Pottery"], "aiFreeTechs": ["Pottery"],
"aiFreeUnits": ["Warrior"], "aiMajorCivStartingUnits": ["Settler", "Warrior", "Warrior"],
"aiCityStateStartingUnits": ["Settler", "Warrior"],
"aiUnhappinessModifier": 0.9, "aiUnhappinessModifier": 0.9,
"aisExchangeTechs": true, "aisExchangeTechs": true,
"turnBarbariansCanEnterPlayerTiles": 0, "turnBarbariansCanEnterPlayerTiles": 0,
@ -124,6 +134,7 @@
"policyCostModifier": 1, "policyCostModifier": 1,
"unhappinessModifier": 1, "unhappinessModifier": 1,
"barbarianBonus": 0.2, "barbarianBonus": 0.2,
"startingUnits": ["Settler", "Warrior"],
"aiCityGrowthModifier": 0.85, "aiCityGrowthModifier": 0.85,
"aiUnitCostModifier": 0.8, "aiUnitCostModifier": 0.8,
"aiBuildingCostModifier": 0.8, "aiBuildingCostModifier": 0.8,
@ -131,7 +142,8 @@
"aiBuildingMaintenanceModifier": 0.8, "aiBuildingMaintenanceModifier": 0.8,
"aiUnitMaintenanceModifier": 0.75, "aiUnitMaintenanceModifier": 0.75,
"aiFreeTechs": ["Pottery","Animal Husbandry"], "aiFreeTechs": ["Pottery","Animal Husbandry"],
"aiFreeUnits": ["Warrior", "Scout"], "aiMajorCivStartingUnits": ["Settler", "Warrior", "Warrior", "Scout"],
"aiCityStateStartingUnits": ["Settler", "Warrior"],
"aiUnhappinessModifier": 0.85, "aiUnhappinessModifier": 0.85,
"aisExchangeTechs": true, "aisExchangeTechs": true,
"turnBarbariansCanEnterPlayerTiles": 0, "turnBarbariansCanEnterPlayerTiles": 0,
@ -147,6 +159,7 @@
"policyCostModifier": 1, "policyCostModifier": 1,
"unhappinessModifier": 1, "unhappinessModifier": 1,
"barbarianBonus": 0.1, "barbarianBonus": 0.1,
"startingUnits": ["Settler", "Warrior"],
"aiCityGrowthModifier": 0.75, "aiCityGrowthModifier": 0.75,
"aiUnitCostModifier": 0.65, "aiUnitCostModifier": 0.65,
"aiBuildingCostModifier": 0.65, "aiBuildingCostModifier": 0.65,
@ -154,7 +167,8 @@
"aiBuildingMaintenanceModifier": 0.65, "aiBuildingMaintenanceModifier": 0.65,
"aiUnitMaintenanceModifier": 0.65, "aiUnitMaintenanceModifier": 0.65,
"aiFreeTechs": ["Pottery","Animal Husbandry","Mining"], "aiFreeTechs": ["Pottery","Animal Husbandry","Mining"],
"aiFreeUnits": ["Warrior", "Warrior", "Worker", "Scout"], "aiMajorCivStartingUnits": ["Settler", "Warrior", "Warrior", "Warrior", "Worker", "Scout"],
"aiCityStateStartingUnits": ["Settler", "Warrior"],
"aiUnhappinessModifier": 0.75, "aiUnhappinessModifier": 0.75,
"aisExchangeTechs": true, "aisExchangeTechs": true,
"turnBarbariansCanEnterPlayerTiles": 0, "turnBarbariansCanEnterPlayerTiles": 0,
@ -170,6 +184,7 @@
"policyCostModifier": 1, "policyCostModifier": 1,
"unhappinessModifier": 1, "unhappinessModifier": 1,
"barbarianBonus": 0, "barbarianBonus": 0,
"startingUnits": ["Settler", "Warrior"],
"aiCityGrowthModifier": 0.6, "aiCityGrowthModifier": 0.6,
"aiUnitCostModifier": 0.5, "aiUnitCostModifier": 0.5,
"aiBuildingCostModifier": 0.5, "aiBuildingCostModifier": 0.5,
@ -177,7 +192,8 @@
"aiBuildingMaintenanceModifier": 0.5, "aiBuildingMaintenanceModifier": 0.5,
"aiUnitMaintenanceModifier": 0.5, "aiUnitMaintenanceModifier": 0.5,
"aiFreeTechs": ["Pottery","Animal Husbandry","Mining","The Wheel"], "aiFreeTechs": ["Pottery","Animal Husbandry","Mining","The Wheel"],
"aiFreeUnits": ["Settler", "Warrior", "Warrior", "Worker", "Worker", "Scout"], "aiMajorCivStartingUnits": ["Settler", "Warrior", "Settler", "Warrior", "Warrior", "Worker", "Worker", "Scout"],
"aiCityStateStartingUnits": ["Settler", "Warrior"],
"aiUnhappinessModifier": 0.6, "aiUnhappinessModifier": 0.6,
"aisExchangeTechs": true, "aisExchangeTechs": true,
"turnBarbariansCanEnterPlayerTiles": 0, "turnBarbariansCanEnterPlayerTiles": 0,

View File

@ -38,6 +38,7 @@ Requires a [buildingName] in all cities =
Requires a [buildingName] in this city = Requires a [buildingName] in this city =
Consumes 1 [resource] = Consumes 1 [resource] =
Required tech: [requiredTech] = Required tech: [requiredTech] =
Cannot be purchased =
Current construction = Current construction =
Construction queue = Construction queue =

View File

@ -156,18 +156,19 @@ object GameStarter {
fun placeNearStartingPosition(unitName: String) { fun placeNearStartingPosition(unitName: String) {
civ.placeUnitNearTile(startingLocation.position, unitName) civ.placeUnitNearTile(startingLocation.position, unitName)
} }
placeNearStartingPosition(Constants.settler)
val warriorEquivalent = getWarriorEquivalent(civ) val warriorEquivalent = getWarriorEquivalent(civ)
if(warriorEquivalent!=null) placeNearStartingPosition(warriorEquivalent) val startingUnits = when {
civ.isPlayerCivilization() -> gameInfo.getDifficulty().startingUnits
civ.isMajorCiv() -> gameInfo.getDifficulty().aiMajorCivStartingUnits
else -> gameInfo.getDifficulty().aiCityStateStartingUnits
}
if (!civ.isPlayerCivilization() && civ.isMajorCiv()) { for (unit in startingUnits) {
for (unit in gameInfo.getDifficulty().aiFreeUnits) {
val unitToAdd = if (unit == "Warrior") warriorEquivalent else unit val unitToAdd = if (unit == "Warrior") warriorEquivalent else unit
if (unitToAdd != null) placeNearStartingPosition(unitToAdd) if (unitToAdd != null) placeNearStartingPosition(unitToAdd)
} }
} }
} }
}
private fun getStartingLocations(civs: List<CivilizationInfo>, tileMap: TileMap): HashMap<CivilizationInfo, TileInfo> { private fun getStartingLocations(civs: List<CivilizationInfo>, tileMap: TileMap): HashMap<CivilizationInfo, TileInfo> {
var landTiles = tileMap.values var landTiles = tileMap.values

View File

@ -184,7 +184,7 @@ open class TileInfo {
for (unique in cityWideUniques + civWideUniques) { for (unique in cityWideUniques + civWideUniques) {
val tileType = unique.params[1] val tileType = unique.params[1]
if (baseTerrain == tileType || terrainFeature == tileType if (baseTerrain == tileType || terrainFeature == tileType
|| resource == tileType || (resource == tileType && hasViewableResource(observingCiv))
|| (tileType == "Water" && isWater) || (tileType == "Water" && isWater)
|| (tileType == "Strategic resource" && hasViewableResource(observingCiv) && getTileResource().resourceType == ResourceType.Strategic) || (tileType == "Strategic resource" && hasViewableResource(observingCiv) && getTileResource().resourceType == ResourceType.Strategic)
|| (tileType == "Water resource" && isWater && hasViewableResource(observingCiv)) || (tileType == "Water resource" && isWater && hasViewableResource(observingCiv))
@ -258,7 +258,8 @@ open class TileInfo {
if (unique.placeholderText == "[] for each adjacent []") { if (unique.placeholderText == "[] for each adjacent []") {
val adjacent = unique.params[1] val adjacent = unique.params[1]
val numberOfBonuses = neighbors.count { it.improvement == adjacent val numberOfBonuses = neighbors.count { it.improvement == adjacent
|| it.baseTerrain==adjacent || it.terrainFeature==adjacent } || it.baseTerrain==adjacent || it.terrainFeature==adjacent
|| it.roadStatus.name==adjacent}
stats.add(Stats.parse(unique.params[0]).times(numberOfBonuses.toFloat())) stats.add(Stats.parse(unique.params[0]).times(numberOfBonuses.toFloat()))
} }

View File

@ -177,7 +177,7 @@ class Building : NamedStats(), IConstruction {
} }
override fun canBePurchased(): Boolean { override fun canBePurchased(): Boolean {
return !isWonder && !isNationalWonder && ("Spaceship part" !in uniques) return !isWonder && !isNationalWonder && ("Cannot be purchased" !in uniques)
} }

View File

@ -1,5 +1,6 @@
package com.unciv.models.ruleset package com.unciv.models.ruleset
import com.unciv.Constants
import com.unciv.models.stats.INamed import com.unciv.models.stats.INamed
import com.unciv.models.translations.tr import com.unciv.models.translations.tr
import java.util.* import java.util.*
@ -15,6 +16,7 @@ class Difficulty: INamed {
var policyCostModifier:Float = 1f var policyCostModifier:Float = 1f
var unhappinessModifier:Float = 1f var unhappinessModifier:Float = 1f
var barbarianBonus:Float = 0f var barbarianBonus:Float = 0f
var startingUnits = ArrayList<String>()
var aiCityGrowthModifier:Float = 1f var aiCityGrowthModifier:Float = 1f
var aiUnitCostModifier:Float = 1f var aiUnitCostModifier:Float = 1f
@ -23,11 +25,23 @@ class Difficulty: INamed {
var aiBuildingMaintenanceModifier:Float = 1f var aiBuildingMaintenanceModifier:Float = 1f
var aiUnitMaintenanceModifier = 1f var aiUnitMaintenanceModifier = 1f
var aiFreeTechs = ArrayList<String>() var aiFreeTechs = ArrayList<String>()
@Deprecated("Deprecated as of 3.10.4. Use aiMajorCivStartingUnits instead")
var aiFreeUnits = ArrayList<String>() var aiFreeUnits = ArrayList<String>()
var aiMajorCivStartingUnits = ArrayList<String>()
var aiCityStateStartingUnits = ArrayList<String>()
var aiUnhappinessModifier = 1f var aiUnhappinessModifier = 1f
var turnBarbariansCanEnterPlayerTiles = 0 var turnBarbariansCanEnterPlayerTiles = 0
var clearBarbarianCampReward = 25 var clearBarbarianCampReward = 25
init {
// For compatibility with old mods that use deprecated var aiFreeUnits and do not have startingUnits, aiCityStateStartingUnits, aiMajorCivStartingUnits
if (startingUnits.isEmpty()) {
startingUnits.add(Constants.settler)
startingUnits.add("Warrior")
aiCityStateStartingUnits.addAll(startingUnits)
aiMajorCivStartingUnits.addAll(startingUnits + aiFreeUnits)
}
}
fun getDescription(): String { fun getDescription(): String {
val lines = ArrayList<String>() val lines = ArrayList<String>()
@ -40,6 +54,7 @@ class Difficulty: INamed {
lines += " - {Policy cost modifier}: $policyCostModifier" lines += " - {Policy cost modifier}: $policyCostModifier"
lines += " - {Unhappiness modifier}: $unhappinessModifier" lines += " - {Unhappiness modifier}: $unhappinessModifier"
lines += " - {Bonus vs. Barbarians}: $barbarianBonus" lines += " - {Bonus vs. Barbarians}: $barbarianBonus"
// lines += " - {Starting units}: $startingUnits"
lines += "" lines += ""
lines += "AI settings" lines += "AI settings"
lines += " - {AI city growth modifier}: $aiCityGrowthModifier" lines += " - {AI city growth modifier}: $aiCityGrowthModifier"
@ -49,7 +64,8 @@ class Difficulty: INamed {
lines += " - {AI building maintenance modifier}: $aiBuildingMaintenanceModifier" lines += " - {AI building maintenance modifier}: $aiBuildingMaintenanceModifier"
lines += " - {AI unit maintenance modifier}: $aiUnitMaintenanceModifier" lines += " - {AI unit maintenance modifier}: $aiUnitMaintenanceModifier"
// lines += " - {AI free techs}: $aiFreeTechs" // lines += " - {AI free techs}: $aiFreeTechs"
// lines += " - {AI free units}: $aiFreeUnits" // lines += " - {AI major civilizations starting units}: $aiMajorCivStartingUnits"
// lines += " - {AI city-state starting units}: $aiCityStateStartingUnits"
lines += " - {AI unhappiness modifier}: $aiUnhappinessModifier" lines += " - {AI unhappiness modifier}: $aiUnhappinessModifier"
lines += "" lines += ""
lines += "{Turns until barbarians enter player tiles}: $turnBarbariansCanEnterPlayerTiles" lines += "{Turns until barbarians enter player tiles}: $turnBarbariansCanEnterPlayerTiles"

View File

@ -92,7 +92,7 @@ class Nation : INamed {
} }
if (uniqueName != "") textList += uniqueName.tr() + ":" if (uniqueName != "") textList += uniqueName.tr() + ":"
textList += " " + uniques.joinToString(", ").tr() textList += " " + uniques.joinToString(", ") { it.tr() }
textList += "" textList += ""
if (startBias.isNotEmpty()) { if (startBias.isNotEmpty()) {
@ -103,7 +103,7 @@ class Nation : INamed {
addUniqueUnitsText(textList, ruleset) addUniqueUnitsText(textList, ruleset)
addUniqueImprovementsText(textList, ruleset) addUniqueImprovementsText(textList, ruleset)
return textList.joinToString("\n").tr().trim() return textList.joinToString("\n")
} }
private fun addUniqueBuildingsText(textList: ArrayList<String>, ruleset: Ruleset) { private fun addUniqueBuildingsText(textList: ArrayList<String>, ruleset: Ruleset) {

View File

@ -89,7 +89,7 @@ class BaseUnit : INamed, IConstruction {
return unit return unit
} }
override fun canBePurchased() = true override fun canBePurchased() = "Cannot be purchased" !in uniques
override fun getProductionCost(civInfo: CivilizationInfo): Int { override fun getProductionCost(civInfo: CivilizationInfo): Int {
var productionCost = cost.toFloat() var productionCost = cost.toFloat()

View File

@ -133,7 +133,7 @@ class GameOptionsTable(val previousScreen: IPreviousScreen, val updatePlayerPick
private fun Table.addEraSelectBox() { private fun Table.addEraSelectBox() {
if (ruleset.technologies.isEmpty()) return // scenario with no techs if (ruleset.technologies.isEmpty()) return // scenario with no techs
val eras = ruleset.technologies.values.map { it.era() }.distinct() val eras = ruleset.technologies.values.filter { !it.uniques.contains("Starting tech") }.map { it.era() }.distinct()
addSelectBox("{Starting Era}:", eras, gameParameters.startingEra) addSelectBox("{Starting Era}:", eras, gameParameters.startingEra)
{ gameParameters.startingEra = it } { gameParameters.startingEra = it }
} }

View File

@ -93,7 +93,7 @@ class PlayerPickerTable(val previousScreen: IPreviousScreen, var gameParameters:
*/ */
private fun reassignRemovedModReferences() { private fun reassignRemovedModReferences() {
for (player in gameParameters.players) { for (player in gameParameters.players) {
if (!previousScreen.ruleset.nations.containsKey(player.chosenCiv)) if (!previousScreen.ruleset.nations.containsKey(player.chosenCiv) || previousScreen.ruleset.nations[player.chosenCiv]!!.isCityState())
player.chosenCiv = Constants.random player.chosenCiv = Constants.random
} }
} }