mirror of
https://github.com/yairm210/Unciv.git
synced 2025-02-04 16:11:46 +07:00
Update ModConstants and start its documentation (#6309)
* Update ModConstants * Update ModConstants - revert Ice, tweak formula * Update ModConstants - comment on predefined MapSizes
This commit is contained in:
parent
88ba48d7f1
commit
e4b0afb7e3
@ -8,6 +8,14 @@ import com.unciv.models.metadata.BaseRuleset
|
||||
import com.unciv.models.ruleset.RulesetCache
|
||||
|
||||
|
||||
/* Predefined Map Sizes - ours are a little lighter than the original values. For reference those are:
|
||||
Civ5Duel(40,24,17),
|
||||
Civ5Tiny(56,36,25),
|
||||
Civ5Small(66,42,30),
|
||||
Civ5Medium(80,52,37),
|
||||
Civ5Large(104,64,47),
|
||||
Civ5Huge(128,80,58),
|
||||
*/
|
||||
enum class MapSize(val radius: Int, val width: Int, val height: Int) {
|
||||
Tiny(10, 23, 15),
|
||||
Small(15, 33, 21),
|
||||
|
@ -148,6 +148,8 @@ class MapGenerator(val ruleset: Ruleset) {
|
||||
val tilesInArea = ArrayList<TileInfo>()
|
||||
val tilesToCheck = ArrayList<TileInfo>()
|
||||
|
||||
val maxLakeSize = ruleset.modOptions.constants.maxLakeSize
|
||||
|
||||
while (waterTiles.isNotEmpty()) {
|
||||
val initialWaterTile = waterTiles.random(randomness.RNG)
|
||||
tilesInArea += initialWaterTile
|
||||
@ -166,7 +168,7 @@ class MapGenerator(val ruleset: Ruleset) {
|
||||
tilesToCheck -= tileWeAreChecking
|
||||
}
|
||||
|
||||
if (tilesInArea.size <= 10) {
|
||||
if (tilesInArea.size <= maxLakeSize) {
|
||||
for (tile in tilesInArea) {
|
||||
tile.baseTerrain = Constants.lakes
|
||||
tile.setTransients()
|
||||
@ -194,8 +196,10 @@ class MapGenerator(val ruleset: Ruleset) {
|
||||
if (map.mapParameters.noRuins || ruinsEquivalents.isEmpty() )
|
||||
return
|
||||
val suitableTiles = map.values.filter { it.isLand && !it.isImpassible() }
|
||||
val locations = randomness.chooseSpreadOutLocations(suitableTiles.size / 50,
|
||||
suitableTiles, map.mapParameters.mapSize.radius)
|
||||
val locations = randomness.chooseSpreadOutLocations(
|
||||
(suitableTiles.size * ruleset.modOptions.constants.ancientRuinCountMultiplier).roundToInt(),
|
||||
suitableTiles,
|
||||
map.mapParameters.mapSize.radius)
|
||||
for (tile in locations)
|
||||
tile.improvement = ruinsEquivalents.keys.random()
|
||||
}
|
||||
@ -512,7 +516,7 @@ class MapGenerator(val ruleset: Ruleset) {
|
||||
val latitudeTemperature = 1.0 - 2.0 * abs(tile.latitude) / tileMap.maxLatitude
|
||||
var temperature = ((latitudeTemperature + randomTemperature) / 2.0)
|
||||
temperature = abs(temperature).pow(1.0 - tileMap.mapParameters.temperatureExtremeness) * temperature.sign
|
||||
if (temperature < -0.8)
|
||||
if (temperature < -0.8f)
|
||||
tile.addTerrainFeature(Constants.ice)
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import com.unciv.models.ruleset.unique.Unique
|
||||
import com.unciv.models.ruleset.unique.UniqueType
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.round
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class NaturalWonderGenerator(val ruleset: Ruleset, val randomness: MapGenerationRandomness) {
|
||||
|
||||
@ -25,8 +26,10 @@ class NaturalWonderGenerator(val ruleset: Ruleset, val randomness: MapGeneration
|
||||
if (tileMap.mapParameters.noNaturalWonders)
|
||||
return
|
||||
val mapRadius = tileMap.mapParameters.mapSize.radius
|
||||
// number of Natural Wonders scales linearly with mapRadius as #wonders = mapRadius * 0.13133208 - 0.56128831
|
||||
val numberToSpawn = round(mapRadius * 0.13133208f - 0.56128831f).toInt()
|
||||
// number of Natural Wonders scales linearly with mapRadius
|
||||
val numberToSpawn = ruleset.modOptions.constants.run {
|
||||
mapRadius * naturalWonderCountMultiplier + naturalWonderCountAddedConstant
|
||||
}.roundToInt()
|
||||
|
||||
val spawned = mutableListOf<Terrain>()
|
||||
val allNaturalWonders = ruleset.terrains.values
|
||||
|
@ -5,21 +5,20 @@ import com.unciv.Constants
|
||||
import com.unciv.logic.map.TileInfo
|
||||
import com.unciv.logic.map.TileMap
|
||||
import com.unciv.models.ruleset.Ruleset
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class RiverGenerator(
|
||||
private val tileMap: TileMap,
|
||||
private val randomness: MapGenerationRandomness,
|
||||
private val ruleset: Ruleset
|
||||
ruleset: Ruleset
|
||||
) {
|
||||
companion object{
|
||||
const val MAP_TILES_PER_RIVER = 100
|
||||
const val MIN_RIVER_LENGTH = 5
|
||||
const val MAX_RIVER_LENGTH = 666 // Do not set < max map radius
|
||||
}
|
||||
private val riverCountMultiplier = ruleset.modOptions.constants.riverCountMultiplier
|
||||
private val minRiverLength = ruleset.modOptions.constants.minRiverLength
|
||||
private val maxRiverLength = ruleset.modOptions.constants.maxRiverLength
|
||||
|
||||
fun spawnRivers() {
|
||||
if (tileMap.values.none { it.isWater }) return
|
||||
val numberOfRivers = tileMap.values.count { it.isLand } / MAP_TILES_PER_RIVER
|
||||
val numberOfRivers = (tileMap.values.count { it.isLand } * riverCountMultiplier).roundToInt()
|
||||
|
||||
var optionalTiles = tileMap.values.asSequence()
|
||||
.filter { it.baseTerrain == Constants.mountain && it.isFarEnoughFromWater() }
|
||||
@ -37,14 +36,14 @@ class RiverGenerator(
|
||||
}
|
||||
|
||||
private fun TileInfo.isFarEnoughFromWater(): Boolean {
|
||||
for (distance in 1 until MIN_RIVER_LENGTH) {
|
||||
for (distance in 1 until minRiverLength) {
|
||||
if (getTilesAtDistance(distance).any { it.isWater }) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun getClosestWaterTile(tile: TileInfo): TileInfo {
|
||||
for (distance in 1..MAX_RIVER_LENGTH) {
|
||||
for (distance in 1..maxRiverLength) {
|
||||
val waterTiles = tile.getTilesAtDistance(distance).filter { it.isWater }
|
||||
if (waterTiles.any())
|
||||
return waterTiles.toList().random(randomness.RNG)
|
||||
@ -59,7 +58,7 @@ class RiverGenerator(
|
||||
var riverCoordinate = RiverCoordinate(initialPosition.position,
|
||||
RiverCoordinate.BottomRightOrLeft.values().random(randomness.RNG))
|
||||
|
||||
for (step in 1..MAX_RIVER_LENGTH) { // Arbitrary max on river length, otherwise this will go in circles - rarely
|
||||
for (step in 1..maxRiverLength) { // Arbitrary max on river length, otherwise this will go in circles - rarely
|
||||
if (riverCoordinate.getAdjacentTiles(tileMap).any { it.isWater }) return
|
||||
val possibleCoordinates = riverCoordinate.getAdjacentPositions(tileMap)
|
||||
if (possibleCoordinates.none()) return // end of the line
|
||||
|
@ -25,11 +25,29 @@ class ModConstants {
|
||||
// unitSupplyBase and unitSupplyPerCity can be found in difficulties.json
|
||||
// unitSupplyBase, unitSupplyPerCity and unitSupplyPerPopulation can also be increased through uniques
|
||||
val unitSupplyPerPopulation = 0.5
|
||||
|
||||
|
||||
// The minimal distance that must be between any two cities, not counting the tiles cities are on
|
||||
// The number is the amount of tiles between two cities, not counting the tiles the cities are on.
|
||||
// e.g. "C__C", where "C" is a tile with a city and "_" is a tile without a city, has a distance of 2.
|
||||
// First constant is for cities on the same landmass, the second is for cities on different continents.
|
||||
val minimalCityDistance = 3
|
||||
val minimalCityDistanceOnDifferentContinents = 2
|
||||
}
|
||||
|
||||
// NaturalWonderGenerator uses these to determine the number of Natural Wonders to spawn for a given map size.
|
||||
// With these values, radius * mul + add gives a 1-2-3-4-5 progression for Unciv predefined map sizes and a 2-3-4-5-6-7 progression for the original Civ5 map sizes.
|
||||
// 0.124 = (Civ5.Huge.getHexagonalRadiusForArea(w*h) - Civ5.Duel.getHexagonalRadiusForArea(w*h)) / 5 (if you do not round in the radius function)
|
||||
// The other constant is empiric to avoid an ugly jump in the progression.
|
||||
val naturalWonderCountMultiplier = 0.124f
|
||||
val naturalWonderCountAddedConstant = 0.1f
|
||||
|
||||
// MapGenerator.spreadAncientRuins: number of ruins = suitable tile count * this
|
||||
val ancientRuinCountMultiplier = 0.02f
|
||||
// MapGenerator.spawnIce: spawn Ice where T < this, with T calculated from temperatureExtremeness, latitude and perlin noise.
|
||||
val spawnIceBelowTemperature = -0.8f
|
||||
// MapGenerator.spawnLakesAndCoasts: Water bodies up to this tile count become Lakes
|
||||
val maxLakeSize = 10
|
||||
// RiverGenerator: river frequency and length bounds
|
||||
val riverCountMultiplier = 0.01f
|
||||
val minRiverLength = 5
|
||||
val maxRiverLength = 666 // Do not set < max map radius
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ Each era can have the following attributes:
|
||||
| unitBaseBuyCost | Integer (≥0) | defaults to 200 | Base cost of buying units with Faith, Food, Science or Culture when no other cost is provided |
|
||||
| startingSettlerCount | Integer (≥0) | defaults to 1 | Amount of settler units that should be spawned when starting a game in this era |
|
||||
| startingSettlerUnit | String | defaults to "Settler" | Name of the unit that should be used for the previous field. Must be in [Units.json](Unit-related-JSON-files.md#unitsjson) |
|
||||
| startingWokerCount | Integer (≥0) | defaults to 0 | Amount of worker units that should be spawned when starting a game in this era |
|
||||
| startingWorkerCount | Integer (≥0) | defaults to 0 | Amount of worker units that should be spawned when starting a game in this era |
|
||||
| startingWorkerUnit | String | defaults to "Worker" | Name of the unit that should be used for the previous field. Must be in [Units.json](Unit-related-JSON-files.md#unitsjson) |
|
||||
| startingMilitaryUnitCount | Integer (≥0) | defaults to 1 | Amount of military units that should be spawned when starting a game in this era |
|
||||
| startingMilitaryUnit | String | defaults to "Warrior" | Name of the unit that should be used for the previous field. Must be in [Units.json](Unit-related-JSON-files.md#unitsjson)|
|
||||
@ -69,7 +69,7 @@ The file can have the following attributes, including the values Unciv sets (no
|
||||
| Attribute | Type | Defaults | Notes |
|
||||
|-----------|------|-----------|-------|
|
||||
| isBaseRuleset | Boolean | false | Differentiates mods that change the vanilla ruleset or replace it |
|
||||
| maxXPfromBarbarians | Integer | 30 | ...as the name says... |
|
||||
| maxXPfromBarbarians | Integer | 30 | *Deprecated*, see [constants](#ModConstants) |
|
||||
| uniques | List | empty | Mod-wide specials, [see here](../Modders/Unique-parameter-types.md#modoptions-uniques) |
|
||||
| techsToRemove | List | empty | List of [Technologies](Civilization-related-JSON-files.md#techsjson) to remove (isBaseRuleset=false only) |
|
||||
| buildingsToRemove | List | empty | List of [Buildings or Wonders](Civilization-related-JSON-files.md#buildingsjson) to remove (isBaseRuleset=false only) |
|
||||
@ -79,6 +79,53 @@ The file can have the following attributes, including the values Unciv sets (no
|
||||
| modUrl | String | empty | Set automatically after download - URL of repository |
|
||||
| author | String | empty | Set automatically after download - Owner of repository |
|
||||
| modSize | Integer | empty | Set automatically after download - kB in entire repository, not sum of default branch files |
|
||||
| constants | Object | empty | see [constants](#ModOptions.constants) |
|
||||
|
||||
### ModConstants
|
||||
Stored in ModOptions.constants, this is a collection of constants used internally in Unciv.
|
||||
|
||||
| Attribute | Type | Defaults | Notes |
|
||||
|-----------|------|-----------|-------|
|
||||
| maxXPfromBarbarians | Int | 30 | [^A] |
|
||||
| cityStrengthBase| Float | 8.0 | [^B] |
|
||||
| cityStrengthPerPop| Float | 0.4 | [^B] |
|
||||
| cityStrengthFromTechsMultiplier| Float | 5.5 | [^B] |
|
||||
| cityStrengthFromTechsExponent| Float | 2.8 | [^B] |
|
||||
| cityStrengthFromTechsFullMultiplier| Float | 1.0 | [^B] |
|
||||
| cityStrengthFromGarrison| Float | 0.2 | [^B] |
|
||||
| unitSupplyPerPopulation| Float | 0.5 | [^C] |
|
||||
| minimalCityDistance| Int | 3 | [^D] |
|
||||
| minimalCityDistanceOnDifferentContinents| Int | 2 | [^D] |
|
||||
| naturalWonderCountMultiplier| Float | 0.124 | [^E] |
|
||||
| naturalWonderCountAddedConstant| Float | 0.1 | [^E] |
|
||||
| ancientRuinCountMultiplier| Float | 0.02 | [^F] |
|
||||
| maxLakeSize| Int | 10 | [^H] |
|
||||
| riverCountMultiplier| Float | 0.01 | [^I] |
|
||||
| minRiverLength| Int | 5 | [^I] |
|
||||
| maxRiverLength| Int | 666 | [^I] |
|
||||
|
||||
[^A]: Max amount of experience that can be gained from combat with barbarians
|
||||
[^B]: Formula for city Strength:
|
||||
Strength = baseStrength + strengthPerPop + strengthFromTiles +
|
||||
((%techs * multiplier) ^ exponent) * fullMultiplier +
|
||||
(garrisonBonus * garrisonUnitStrength * garrisonUnitHealth/100) +
|
||||
defensiveBuildingStrength
|
||||
where %techs is the percentage of techs in the tech tree that are complete
|
||||
If no techs exist in this ruleset, %techs = 0.5 (=50%)
|
||||
[^C]: Formula for Unit Supply:
|
||||
Supply = unitSupplyBase (difficulties.json)
|
||||
unitSupplyPerCity * amountOfCities + (difficulties.json)
|
||||
unitSupplyPerPopulation * amountOfPopulationInAllCities
|
||||
unitSupplyBase and unitSupplyPerCity can be found in difficulties.json
|
||||
unitSupplyBase, unitSupplyPerCity and unitSupplyPerPopulation can also be increased through uniques
|
||||
[^D]: The minimal distance that must be between any two cities, not counting the tiles cities are on
|
||||
The number is the amount of tiles between two cities, not counting the tiles the cities are on.
|
||||
e.g. "C__C", where "C" is a tile with a city and "_" is a tile without a city, has a distance of 2.
|
||||
First constant is for cities on the same landmass, the second is for cities on different continents.
|
||||
[^E]: NaturalWonderGenerator uses these to determine the number of Natural Wonders to spawn for a given map size. The number scales linearly with map radius: #wonders = radius * naturalWonderCountMultiplier + naturalWonderCountAddedConstant. The defaults effectively mean Tiny - 1, Small - 2, Medium - 3, Large - 4, Huge - 5, Custom radius >=109 - all G&K wonders.
|
||||
[^F]: MapGenerator.spreadAncientRuins: number of ruins = suitable tile count * this
|
||||
[^H]: MapGenerator.spawnLakesAndCoasts: Water bodies up to this tile count become Lakes
|
||||
[^I]: RiverGenerator: river frequency and length bounds
|
||||
|
||||
|
||||
## Civilopedia text
|
||||
|
Loading…
Reference in New Issue
Block a user