mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-04 15:27:50 +07:00
Moddable game speeds (#6856)
* Move GameSpeed definition to JSON files * Add game speeds civilopedia page
This commit is contained in:

committed by
GitHub

parent
06198f2e2c
commit
c922f134e6
BIN
android/Images/OtherIcons/Timer.png
Normal file
BIN
android/Images/OtherIcons/Timer.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.6 KiB |
113
android/assets/jsons/Civ V - Gods & Kings/Speeds.json
Normal file
113
android/assets/jsons/Civ V - Gods & Kings/Speeds.json
Normal file
@ -0,0 +1,113 @@
|
||||
[
|
||||
{
|
||||
"name": "Quick",
|
||||
"modifier": 0.67,
|
||||
"productionCostModifier": 0.67,
|
||||
"goldCostModifier": 0.67,
|
||||
"scienceCostModifier": 0.67,
|
||||
"cultureCostModifier": 0.67,
|
||||
"faithCostModifier": 0.67,
|
||||
"improvementBuildLengthModifier": 0.67,
|
||||
"barbarianModifier": 0.67,
|
||||
"goldGiftModifier": 1.25,
|
||||
"cityStateTributeScalingInterval": 5.0,
|
||||
"goldenAgeLengthModifier": 0.80,
|
||||
"religiousPressureAdjacentCity": 9,
|
||||
"peaceDealDuration": 10,
|
||||
"dealDuration": 25,
|
||||
"startYear": -4000,
|
||||
"turns": [
|
||||
{"yearsPerTurn": 60, "untilTurn": 50},
|
||||
{"yearsPerTurn": 40, "untilTurn": 80},
|
||||
{"yearsPerTurn": 30, "untilTurn": 100},
|
||||
{"yearsPerTurn": 20, "untilTurn": 130},
|
||||
{"yearsPerTurn": 10, "untilTurn": 155},
|
||||
{"yearsPerTurn": 5, "untilTurn": 195},
|
||||
{"yearsPerTurn": 2, "untilTurn": 260},
|
||||
{"yearsPerTurn": 1, "untilTurn": 330}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Standard",
|
||||
"modifier": 1.0,
|
||||
"productionCostModifier": 1.0,
|
||||
"goldCostModifier": 1.0,
|
||||
"scienceCostModifier": 1.0,
|
||||
"cultureCostModifier": 1.0,
|
||||
"faithCostModifier": 1.0,
|
||||
"improvementBuildLengthModifier": 1.0,
|
||||
"barbarianModifier": 1.0,
|
||||
"goldGiftModifier": 1.0,
|
||||
"cityStateTributeScalingInterval": 6.5,
|
||||
"goldenAgeLengthModifier": 1.0,
|
||||
"religiousPressureAdjacentCity": 6,
|
||||
"peaceDealDuration": 10,
|
||||
"dealDuration": 30,
|
||||
"startYear": -4000,
|
||||
"turns": [
|
||||
{"yearsPerTurn": 40, "untilTurn": 75},
|
||||
{"yearsPerTurn": 25, "untilTurn": 135},
|
||||
{"yearsPerTurn": 20, "untilTurn": 160},
|
||||
{"yearsPerTurn": 10, "untilTurn": 210},
|
||||
{"yearsPerTurn": 5, "untilTurn": 270},
|
||||
{"yearsPerTurn": 2, "untilTurn": 320},
|
||||
{"yearsPerTurn": 1, "untilTurn": 440},
|
||||
{"yearsPerTurn": 0.5, "untilTurn": 500}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Epic",
|
||||
"modifier": 1.5,
|
||||
"productionCostModifier": 1.5,
|
||||
"goldCostModifier": 1.5,
|
||||
"scienceCostModifier": 1.5,
|
||||
"cultureCostModifier": 1.5,
|
||||
"faithCostModifier": 1.5,
|
||||
"improvementBuildLengthModifier": 1.5,
|
||||
"barbarianModifier": 1.5,
|
||||
"goldGiftModifier": 0.75,
|
||||
"cityStateTributeScalingInterval": 14.0,
|
||||
"goldenAgeLengthModifier": 1.25,
|
||||
"religiousPressureAdjacentCity": 4,
|
||||
"peaceDealDuration": 15,
|
||||
"dealDuration": 45,
|
||||
"startYear": -4000,
|
||||
"turns": [
|
||||
{"yearsPerTurn": 25, "untilTurn": 140},
|
||||
{"yearsPerTurn": 15, "untilTurn": 230},
|
||||
{"yearsPerTurn": 10, "untilTurn": 270},
|
||||
{"yearsPerTurn": 5, "untilTurn": 360},
|
||||
{"yearsPerTurn": 2, "untilTurn": 430},
|
||||
{"yearsPerTurn": 1, "untilTurn": 530},
|
||||
{"yearsPerTurn": 0.5, "untilTurn": 750}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Marathon",
|
||||
"modifier": 3.0,
|
||||
"productionCostModifier": 3.0,
|
||||
"goldCostModifier": 3.0,
|
||||
"scienceCostModifier": 3.0,
|
||||
"cultureCostModifier": 3.0,
|
||||
"faithCostModifier": 3.0,
|
||||
"improvementBuildLengthModifier": 3.0,
|
||||
"barbarianModifier": 4.0,
|
||||
"goldGiftModifier": 0.67,
|
||||
"cityStateTributeScalingInterval": 32.0,
|
||||
"goldenAgeLengthModifier": 2.0,
|
||||
"religiousPressureAdjacentCity": 2,
|
||||
"peaceDealDuration": 30,
|
||||
"dealDuration": 90,
|
||||
"startYear": -4000,
|
||||
"turns": [
|
||||
{"yearsPerTurn": 15, "untilTurn": 100},
|
||||
{"yearsPerTurn": 10, "untilTurn": 400},
|
||||
{"yearsPerTurn": 5, "untilTurn": 570},
|
||||
{"yearsPerTurn": 2, "untilTurn": 771},
|
||||
{"yearsPerTurn": 1, "untilTurn": 900},
|
||||
{"yearsPerTurn": 0.5, "untilTurn": 1080},
|
||||
{"yearsPerTurn": 0.25, "untilTurn": 1344},
|
||||
{"yearsPerTurn": 0.083333, "untilTurn": 1500}
|
||||
]
|
||||
}
|
||||
]
|
113
android/assets/jsons/Civ V - Vanilla/Speeds.json
Normal file
113
android/assets/jsons/Civ V - Vanilla/Speeds.json
Normal file
@ -0,0 +1,113 @@
|
||||
[
|
||||
{
|
||||
"name": "Quick",
|
||||
"modifier": 0.67,
|
||||
"productionCostModifier": 0.67,
|
||||
"goldCostModifier": 0.67,
|
||||
"scienceCostModifier": 0.67,
|
||||
"cultureCostModifier": 0.67,
|
||||
"faithCostModifier": 0.67,
|
||||
"improvementBuildLengthModifier": 0.67,
|
||||
"barbarianModifier": 0.67,
|
||||
"goldGiftModifier": 1.25,
|
||||
"cityStateTributeScalingInterval": 5.0,
|
||||
"goldenAgeLengthModifier": 0.80,
|
||||
"religiousPressureAdjacentCity": 9,
|
||||
"peaceDealDuration": 10,
|
||||
"dealDuration": 25,
|
||||
"startYear": -4000,
|
||||
"turns": [
|
||||
{"yearsPerTurn": 60, "untilTurn": 50},
|
||||
{"yearsPerTurn": 40, "untilTurn": 80},
|
||||
{"yearsPerTurn": 30, "untilTurn": 100},
|
||||
{"yearsPerTurn": 20, "untilTurn": 130},
|
||||
{"yearsPerTurn": 10, "untilTurn": 155},
|
||||
{"yearsPerTurn": 5, "untilTurn": 195},
|
||||
{"yearsPerTurn": 2, "untilTurn": 260},
|
||||
{"yearsPerTurn": 1, "untilTurn": 330}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Standard",
|
||||
"modifier": 1.0,
|
||||
"productionCostModifier": 1.0,
|
||||
"goldCostModifier": 1.0,
|
||||
"scienceCostModifier": 1.0,
|
||||
"cultureCostModifier": 1.0,
|
||||
"faithCostModifier": 1.0,
|
||||
"improvementBuildLengthModifier": 1.0,
|
||||
"barbarianModifier": 1.0,
|
||||
"goldGiftModifier": 1.0,
|
||||
"cityStateTributeScalingInterval": 6.5,
|
||||
"goldenAgeLengthModifier": 1.0,
|
||||
"religiousPressureAdjacentCity": 6,
|
||||
"peaceDealDuration": 10,
|
||||
"dealDuration": 30,
|
||||
"startYear": -4000,
|
||||
"turns": [
|
||||
{"yearsPerTurn": 40, "untilTurn": 75},
|
||||
{"yearsPerTurn": 25, "untilTurn": 135},
|
||||
{"yearsPerTurn": 20, "untilTurn": 160},
|
||||
{"yearsPerTurn": 10, "untilTurn": 210},
|
||||
{"yearsPerTurn": 5, "untilTurn": 270},
|
||||
{"yearsPerTurn": 2, "untilTurn": 320},
|
||||
{"yearsPerTurn": 1, "untilTurn": 440},
|
||||
{"yearsPerTurn": 0.5, "untilTurn": 500}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Epic",
|
||||
"modifier": 1.5,
|
||||
"productionCostModifier": 1.5,
|
||||
"goldCostModifier": 1.5,
|
||||
"scienceCostModifier": 1.5,
|
||||
"cultureCostModifier": 1.5,
|
||||
"faithCostModifier": 1.5,
|
||||
"improvementBuildLengthModifier": 1.5,
|
||||
"barbarianModifier": 1.5,
|
||||
"goldGiftModifier": 0.75,
|
||||
"cityStateTributeScalingInterval": 14.0,
|
||||
"goldenAgeLengthModifier": 1.25,
|
||||
"religiousPressureAdjacentCity": 4,
|
||||
"peaceDealDuration": 15,
|
||||
"dealDuration": 45,
|
||||
"startYear": -4000,
|
||||
"turns": [
|
||||
{"yearsPerTurn": 25, "untilTurn": 140},
|
||||
{"yearsPerTurn": 15, "untilTurn": 230},
|
||||
{"yearsPerTurn": 10, "untilTurn": 270},
|
||||
{"yearsPerTurn": 5, "untilTurn": 360},
|
||||
{"yearsPerTurn": 2, "untilTurn": 430},
|
||||
{"yearsPerTurn": 1, "untilTurn": 530},
|
||||
{"yearsPerTurn": 0.5, "untilTurn": 750}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Marathon",
|
||||
"modifier": 3.0,
|
||||
"productionCostModifier": 3.0,
|
||||
"goldCostModifier": 3.0,
|
||||
"scienceCostModifier": 3.0,
|
||||
"cultureCostModifier": 3.0,
|
||||
"faithCostModifier": 3.0,
|
||||
"improvementBuildLengthModifier": 3.0,
|
||||
"barbarianModifier": 4.0,
|
||||
"goldGiftModifier": 0.67,
|
||||
"cityStateTributeScalingInterval": 32.0,
|
||||
"goldenAgeLengthModifier": 2.0,
|
||||
"religiousPressureAdjacentCity": 2,
|
||||
"peaceDealDuration": 30,
|
||||
"dealDuration": 90,
|
||||
"startYear": -4000,
|
||||
"turns": [
|
||||
{"yearsPerTurn": 15, "untilTurn": 100},
|
||||
{"yearsPerTurn": 10, "untilTurn": 400},
|
||||
{"yearsPerTurn": 5, "untilTurn": 570},
|
||||
{"yearsPerTurn": 2, "untilTurn": 771},
|
||||
{"yearsPerTurn": 1, "untilTurn": 900},
|
||||
{"yearsPerTurn": 0.5, "untilTurn": 1080},
|
||||
{"yearsPerTurn": 0.25, "untilTurn": 1344},
|
||||
{"yearsPerTurn": 0.083333, "untilTurn": 1500}
|
||||
]
|
||||
}
|
||||
]
|
@ -1321,6 +1321,22 @@ Eras =
|
||||
Embarked strength: [amount]† =
|
||||
Base unit buy cost: [amount]¤ =
|
||||
Research agreement cost: [amount]¤ =
|
||||
Game Speeds =
|
||||
General speed modifier: [amount]%⏳ =
|
||||
Production cost modifier: [amount]%⚙ =
|
||||
Gold cost modifier: [amount]%¤ =
|
||||
Science cost modifier: [amount]%⍾ =
|
||||
Culture cost modifier: [amount]%♪ =
|
||||
Faith cost modifier: [amount]%☮ =
|
||||
Improvement build length modifier: [amount]%⏳ =
|
||||
Diplomatic deal duration: [amount] turns⏳ =
|
||||
Gold gift influence gain modifier: [amount]%¤ =
|
||||
City-state tribute scaling interval: [amount] turns⏳ =
|
||||
Barbarian spawn modifier: [amount]%† =
|
||||
Golden age length modifier: [amount]%⌣ =
|
||||
Adjacent city religious pressure: [amount]☮ =
|
||||
Peace deal duration: [amount] turns⏳ =
|
||||
Start year: [comment] =
|
||||
Pillaging this improvement yields [stats] =
|
||||
Pillaging this improvement yields approximately [stats] =
|
||||
|
||||
|
@ -6,7 +6,6 @@ import com.unciv.json.HashMapVector2
|
||||
import com.unciv.logic.civilization.NotificationIcon
|
||||
import com.unciv.logic.map.TileInfo
|
||||
import com.unciv.logic.map.TileMap
|
||||
import com.unciv.models.metadata.GameSpeed
|
||||
import com.unciv.models.ruleset.unique.UniqueType
|
||||
import com.unciv.ui.utils.extensions.randomWeighted
|
||||
import java.util.*
|
||||
@ -288,12 +287,6 @@ class Encampment() {
|
||||
// Quicker if this camp has already spawned units
|
||||
countdown -= min(3, spawnedUnits)
|
||||
|
||||
countdown *= when (gameInfo.gameParameters.gameSpeed) {
|
||||
GameSpeed.Quick -> 67
|
||||
GameSpeed.Standard -> 100
|
||||
GameSpeed.Epic -> 150
|
||||
GameSpeed.Marathon -> 400 // sic!
|
||||
}
|
||||
countdown /= 100
|
||||
countdown = (countdown * gameInfo.speed.barbarianModifier).toInt()
|
||||
}
|
||||
}
|
||||
|
@ -16,12 +16,12 @@ import com.unciv.logic.map.TileInfo
|
||||
import com.unciv.logic.map.TileMap
|
||||
import com.unciv.models.Religion
|
||||
import com.unciv.models.metadata.GameParameters
|
||||
import com.unciv.models.metadata.GameSpeed
|
||||
import com.unciv.models.ruleset.*
|
||||
import com.unciv.models.ruleset.unique.UniqueType
|
||||
import com.unciv.ui.audio.MusicMood
|
||||
import com.unciv.ui.audio.MusicTrackChooserFlags
|
||||
import java.util.*
|
||||
import kotlin.NoSuchElementException
|
||||
|
||||
|
||||
class GameInfo {
|
||||
@ -55,6 +55,9 @@ class GameInfo {
|
||||
@Transient
|
||||
lateinit var difficultyObject: Difficulty // Since this is static game-wide, and was taking a large part of nextTurn
|
||||
|
||||
@Transient
|
||||
lateinit var speed: Speed
|
||||
|
||||
@Transient
|
||||
lateinit var currentPlayerCiv: CivilizationInfo // this is called thousands of times, no reason to search for it with a find{} every time
|
||||
|
||||
@ -152,40 +155,20 @@ class GameInfo {
|
||||
}
|
||||
|
||||
private fun getEquivalentTurn(): Int {
|
||||
val totalTurns = 500f * gameParameters.gameSpeed.modifier
|
||||
val totalTurns = speed.numTotalTurns()
|
||||
val startPercent = ruleSet.eras[gameParameters.startingEra]!!.startPercent
|
||||
return turns + ((totalTurns * startPercent).toInt() / 100)
|
||||
}
|
||||
private class YearsToTurn(
|
||||
// enum class with lists for each value group potentially more efficient?
|
||||
val toTurn: Int,
|
||||
val yearInterval: Float
|
||||
) {
|
||||
companion object {
|
||||
// Best to initialize these once only
|
||||
val marathon = listOf(YearsToTurn(100, 15f), YearsToTurn(400, 10f), YearsToTurn(570, 5f), YearsToTurn(771, 2f), YearsToTurn(900, 1f), YearsToTurn(1080, 0.5f), YearsToTurn(1344, 0.25f), YearsToTurn(1500, 0.083333f))
|
||||
val epic = listOf(YearsToTurn(140, 25f), YearsToTurn(230, 15f), YearsToTurn(270, 10f), YearsToTurn(360, 5f), YearsToTurn(430, 2f), YearsToTurn(530, 1f), YearsToTurn(1500, 0.5f))
|
||||
val standard = listOf(YearsToTurn(75, 40f), YearsToTurn(135, 25f), YearsToTurn(160, 20f), YearsToTurn(210, 10f), YearsToTurn(270, 5f), YearsToTurn(320, 2f), YearsToTurn(440, 1f), YearsToTurn(500, 0.5f))
|
||||
val quick = listOf(YearsToTurn(50, 60f), YearsToTurn(80, 40f), YearsToTurn(100, 30f), YearsToTurn(130, 20f), YearsToTurn(155, 10f), YearsToTurn(195, 5f), YearsToTurn(260, 2f), YearsToTurn(310, 1f))
|
||||
fun getList(gameSpeed: GameSpeed) = when (gameSpeed) {
|
||||
GameSpeed.Marathon -> marathon
|
||||
GameSpeed.Epic -> epic
|
||||
GameSpeed.Standard -> standard
|
||||
GameSpeed.Quick -> quick
|
||||
}
|
||||
}
|
||||
return turns + (totalTurns * startPercent / 100)
|
||||
}
|
||||
|
||||
fun getYear(turnOffset: Int = 0): Int {
|
||||
val turn = getEquivalentTurn() + turnOffset
|
||||
val yearToTurnList = YearsToTurn.getList(gameParameters.gameSpeed)
|
||||
var year: Float = -4000f
|
||||
val yearsToTurn = speed.yearsPerTurn
|
||||
var year = speed.startYear
|
||||
var i = 0
|
||||
var yearsPerTurn: Float
|
||||
|
||||
// if macros are ever added to kotlin, this is one hell of a place for em'
|
||||
while (i < turn) {
|
||||
yearsPerTurn = yearToTurnList.firstOrNull { i < it.toTurn }?.yearInterval ?: 0.5f
|
||||
yearsPerTurn = (yearsToTurn.firstOrNull { i < it.untilTurn }?.yearInterval ?: yearsToTurn.last().yearInterval)
|
||||
year += yearsPerTurn
|
||||
++i
|
||||
}
|
||||
@ -431,6 +414,8 @@ class GameInfo {
|
||||
|
||||
difficultyObject = ruleSet.difficulties[difficulty]!!
|
||||
|
||||
speed = ruleSet.speeds[gameParameters.speed]!!
|
||||
|
||||
for (religion in religions.values) religion.setTransients(this)
|
||||
|
||||
for (civInfo in civilizations) civInfo.setTransients()
|
||||
|
@ -46,6 +46,11 @@ object GameStarter {
|
||||
val ruleset = RulesetCache.getComplexRuleset(gameInfo.gameParameters)
|
||||
val mapGen = MapGenerator(ruleset)
|
||||
|
||||
// Make sure that a valid game speed is loaded (catches a base ruleset not using the default game speed)
|
||||
if (!ruleset.speeds.containsKey(gameSetupInfo.gameParameters.speed)) {
|
||||
gameSetupInfo.gameParameters.speed = ruleset.speeds.keys.first()
|
||||
}
|
||||
|
||||
if (gameSetupInfo.mapParameters.name != "") runAndMeasure("loadMap") {
|
||||
tileMap = MapSaver.loadMap(gameSetupInfo.mapFile!!)
|
||||
// Don't override the map parameters - this can include if we world wrap or not!
|
||||
@ -202,8 +207,8 @@ object GameStarter {
|
||||
val startingEra = gameInfo.gameParameters.startingEra
|
||||
val era = ruleSet.eras[startingEra]!!
|
||||
for (civInfo in gameInfo.civilizations.filter { !it.isBarbarian() }) {
|
||||
civInfo.addGold((era.startingGold * gameInfo.gameParameters.gameSpeed.modifier).toInt())
|
||||
civInfo.policies.addCulture((era.startingCulture * gameInfo.gameParameters.gameSpeed.modifier).toInt())
|
||||
civInfo.addGold((era.startingGold * gameInfo.speed.goldCostModifier).toInt())
|
||||
civInfo.policies.addCulture((era.startingCulture * gameInfo.speed.cultureCostModifier).toInt())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -193,19 +193,18 @@ object Automation {
|
||||
if (civInfo.isCityState() || civInfo.isBarbarian())
|
||||
return false
|
||||
|
||||
// If there are no barbarians we are not afraid
|
||||
if (civInfo.gameInfo.gameParameters.noBarbarians)
|
||||
return false
|
||||
return false // If there are no barbarians we are not afraid
|
||||
|
||||
// Very late in the game we are not afraid
|
||||
if (civInfo.gameInfo.turns > 200 * civInfo.gameInfo.gameParameters.gameSpeed.modifier)
|
||||
return false
|
||||
val speed = civInfo.gameInfo.speed
|
||||
if (civInfo.gameInfo.turns > 200 * speed.barbarianModifier)
|
||||
return false // Very late in the game we are not afraid
|
||||
|
||||
var multiplier = if (civInfo.gameInfo.gameParameters.ragingBarbarians) 1.3f
|
||||
else 1f // We're slightly more afraid of raging barbs
|
||||
|
||||
// Past the early game we are less afraid
|
||||
if (civInfo.gameInfo.turns > 120 * civInfo.gameInfo.gameParameters.gameSpeed.modifier * multiplier)
|
||||
if (civInfo.gameInfo.turns > 120 * speed.barbarianModifier * multiplier)
|
||||
multiplier /= 2
|
||||
|
||||
// If we have a lot of, or no cities we are not afraid
|
||||
|
@ -4,7 +4,6 @@ import com.unciv.Constants
|
||||
import com.unciv.logic.civilization.NotificationIcon
|
||||
import com.unciv.models.Counter
|
||||
import com.unciv.models.Religion
|
||||
import com.unciv.models.metadata.GameSpeed
|
||||
import com.unciv.models.ruleset.unique.Unique
|
||||
import com.unciv.models.ruleset.unique.UniqueType
|
||||
import com.unciv.ui.utils.extensions.toPercent
|
||||
@ -23,14 +22,7 @@ class CityInfoReligionManager {
|
||||
private val followers: Counter<String> = Counter()
|
||||
|
||||
@delegate:Transient
|
||||
private val pressureFromAdjacentCities: Int by lazy {
|
||||
when (cityInfo.civInfo.gameInfo.gameParameters.gameSpeed) {
|
||||
GameSpeed.Quick -> 9
|
||||
GameSpeed.Standard -> 6
|
||||
GameSpeed.Epic -> 4
|
||||
GameSpeed.Marathon -> 2
|
||||
}
|
||||
}
|
||||
private val pressureFromAdjacentCities: Int by lazy { cityInfo.civInfo.gameInfo.speed.religiousPressureAdjacentCity }
|
||||
|
||||
var religionThisIsTheHolyCityOf: String? = null
|
||||
|
||||
|
@ -3,7 +3,6 @@ package com.unciv.logic.civilization
|
||||
import com.unciv.Constants
|
||||
import com.unciv.logic.automation.NextTurnAutomation
|
||||
import com.unciv.logic.civilization.diplomacy.*
|
||||
import com.unciv.models.metadata.GameSpeed
|
||||
import com.unciv.models.ruleset.Ruleset
|
||||
import com.unciv.models.ruleset.tile.ResourceSupplyList
|
||||
import com.unciv.models.ruleset.unique.Unique
|
||||
@ -134,14 +133,10 @@ class CityStateFunctions(val civInfo: CivilizationInfo) {
|
||||
// https://github.com/Gedemon/Civ5-DLL/blob/aa29e80751f541ae04858b6d2a2c7dcca454201e/CvGameCoreDLL_Expansion1/CvMinorCivAI.cpp
|
||||
// line 8681 and below
|
||||
var influenceGained = giftAmount.toFloat().pow(1.01f) / 9.8f
|
||||
val gameProgressApproximate = min(civInfo.gameInfo.turns / (400f * civInfo.gameInfo.gameParameters.gameSpeed.modifier), 1f)
|
||||
val speed = civInfo.gameInfo.speed
|
||||
val gameProgressApproximate = min(civInfo.gameInfo.turns / (400f * speed.modifier), 1f)
|
||||
influenceGained *= 1 - (2/3f) * gameProgressApproximate
|
||||
influenceGained *= when (civInfo.gameInfo.gameParameters.gameSpeed) {
|
||||
GameSpeed.Quick -> 1.25f
|
||||
GameSpeed.Standard -> 1f
|
||||
GameSpeed.Epic -> 0.75f
|
||||
GameSpeed.Marathon -> 0.67f
|
||||
}
|
||||
influenceGained *= speed.goldGiftModifier
|
||||
for (unique in donorCiv.getMatchingUniques(UniqueType.CityStateGoldGiftsProvideMoreInfluence))
|
||||
influenceGained *= 1f + unique.params[0].toFloat() / 100f
|
||||
|
||||
@ -273,7 +268,7 @@ class CityStateFunctions(val civInfo: CivilizationInfo) {
|
||||
|
||||
fun getDiplomaticMarriageCost(): Int {
|
||||
// https://github.com/Gedemon/Civ5-DLL/blob/master/CvGameCoreDLL_Expansion1/CvMinorCivAI.cpp, line 7812
|
||||
var cost = (500 * civInfo.gameInfo.gameParameters.gameSpeed.modifier).toInt()
|
||||
var cost = (500 * civInfo.gameInfo.speed.goldCostModifier).toInt()
|
||||
// Plus disband value of all units
|
||||
for (unit in civInfo.getCivUnits()) {
|
||||
cost += unit.baseUnit.getDisbandGold(civInfo)
|
||||
@ -393,18 +388,8 @@ class CityStateFunctions(val civInfo: CivilizationInfo) {
|
||||
|
||||
fun goldGainedByTribute(): Int {
|
||||
// These values are close enough, linear increase throughout the game
|
||||
var gold = when (civInfo.gameInfo.gameParameters.gameSpeed) {
|
||||
GameSpeed.Quick -> 60
|
||||
GameSpeed.Standard -> 50
|
||||
GameSpeed.Epic -> 35
|
||||
GameSpeed.Marathon -> 30
|
||||
}
|
||||
val turnsToIncrement = when (civInfo.gameInfo.gameParameters.gameSpeed) {
|
||||
GameSpeed.Quick -> 5f
|
||||
GameSpeed.Standard -> 6.5f
|
||||
GameSpeed.Epic -> 14f
|
||||
GameSpeed.Marathon -> 32f
|
||||
}
|
||||
var gold = (10 * civInfo.gameInfo.speed.goldGiftModifier).toInt() * 5 // rounding down to nearest 5
|
||||
val turnsToIncrement = civInfo.gameInfo.speed.cityStateTributeScalingInterval
|
||||
gold += 5 * (civInfo.gameInfo.turns / turnsToIncrement).toInt()
|
||||
|
||||
return gold
|
||||
|
@ -3,7 +3,6 @@ package com.unciv.logic.civilization
|
||||
import com.unciv.Constants
|
||||
import com.unciv.logic.civilization.diplomacy.RelationshipLevel
|
||||
import com.unciv.logic.map.RoadStatus
|
||||
import com.unciv.models.metadata.BASE_GAME_DURATION_TURNS
|
||||
import com.unciv.models.ruleset.BeliefType
|
||||
import com.unciv.models.ruleset.Policy
|
||||
import com.unciv.models.ruleset.tile.ResourceType
|
||||
@ -62,7 +61,7 @@ class CivInfoStats(val civInfo: CivilizationInfo) {
|
||||
val numberOfUnitsToPayFor = max(0.0, costsToPay.asSequence().drop(freeUnits).sumOf { it.toDouble() } ).toFloat()
|
||||
|
||||
// as game progresses Maintenance cost rises
|
||||
val turnLimit = BASE_GAME_DURATION_TURNS * civInfo.gameInfo.gameParameters.gameSpeed.modifier
|
||||
val turnLimit = civInfo.gameInfo.speed.numTotalTurns().toFloat()
|
||||
val gameProgress = min(civInfo.gameInfo.turns / turnLimit, 1f)
|
||||
|
||||
var cost = baseUnitCost * numberOfUnitsToPayFor * (1 + gameProgress)
|
||||
|
@ -1025,7 +1025,7 @@ class CivilizationInfo {
|
||||
fun removeFlag(flag: String) = flagsCountdown.remove(flag)
|
||||
fun hasFlag(flag: String) = flagsCountdown.contains(flag)
|
||||
|
||||
fun getTurnsBetweenDiplomaticVotes() = (15 * gameInfo.gameParameters.gameSpeed.modifier).toInt() // Dunno the exact calculation, hidden in Lua files
|
||||
fun getTurnsBetweenDiplomaticVotes() = (15 * gameInfo.speed.modifier).toInt() // Dunno the exact calculation, hidden in Lua files
|
||||
|
||||
fun getTurnsTillNextDiplomaticVote() = flagsCountdown[CivFlags.TurnsTillNextDiplomaticVote.name]
|
||||
|
||||
@ -1115,7 +1115,7 @@ class CivilizationInfo {
|
||||
}
|
||||
|
||||
private fun getTurnsBeforeRevolt() =
|
||||
((4 + Random().nextInt(3)) * max(gameInfo.gameParameters.gameSpeed.modifier, 1f)).toInt()
|
||||
((4 + Random().nextInt(3)) * max(gameInfo.speed.modifier, 1f)).toInt()
|
||||
|
||||
/** Modify gold by a given amount making sure it does neither overflow nor underflow.
|
||||
* @param delta the amount to add (can be negative)
|
||||
@ -1265,7 +1265,7 @@ class CivilizationInfo {
|
||||
fun getResearchAgreementCost(): Int {
|
||||
// https://forums.civfanatics.com/resources/research-agreements-bnw.25568/
|
||||
return (
|
||||
getEra().researchAgreementCost * gameInfo.gameParameters.gameSpeed.modifier
|
||||
getEra().researchAgreementCost * gameInfo.speed.goldCostModifier
|
||||
).toInt()
|
||||
}
|
||||
|
||||
@ -1367,7 +1367,7 @@ class CivilizationInfo {
|
||||
|
||||
fun receiveGoldGift(donorCiv: CivilizationInfo, giftAmount: Int) =
|
||||
cityStateFunctions.receiveGoldGift(donorCiv, giftAmount)
|
||||
fun turnsForGreatPersonFromCityState(): Int = ((37 + Random().nextInt(7)) * gameInfo.gameParameters.gameSpeed.modifier).toInt()
|
||||
fun turnsForGreatPersonFromCityState(): Int = ((37 + Random().nextInt(7)) * gameInfo.speed.modifier).toInt()
|
||||
|
||||
fun getProtectorCivs() = cityStateFunctions.getProtectorCivs()
|
||||
fun addProtectorCiv(otherCiv: CivilizationInfo) = cityStateFunctions.addProtectorCiv(otherCiv)
|
||||
|
@ -29,7 +29,7 @@ class GoldenAgeManager {
|
||||
var turnsToGoldenAge = unmodifiedNumberOfTurns.toFloat()
|
||||
for (unique in civInfo.getMatchingUniques(UniqueType.GoldenAgeLength))
|
||||
turnsToGoldenAge *= unique.params[0].toPercent()
|
||||
turnsToGoldenAge *= civInfo.gameInfo.gameParameters.gameSpeed.modifier
|
||||
turnsToGoldenAge *= civInfo.gameInfo.speed.goldenAgeLengthModifier
|
||||
turnsLeftForCurrentGoldenAge += turnsToGoldenAge.toInt()
|
||||
civInfo.addNotification("You have entered a Golden Age!", "StatIcons/Happiness")
|
||||
civInfo.popupAlerts.add(PopupAlert(AlertType.GoldenAge, ""))
|
||||
|
@ -144,7 +144,7 @@ class PolicyManager {
|
||||
for (unique in civInfo.getMatchingUniques(UniqueType.LessPolicyCostFromCities)) cityModifier *= 1 - unique.params[0].toFloat() / 100
|
||||
for (unique in civInfo.getMatchingUniques(UniqueType.LessPolicyCost)) policyCultureCost *= unique.params[0].toPercent()
|
||||
if (civInfo.isPlayerCivilization()) policyCultureCost *= civInfo.getDifficulty().policyCostModifier
|
||||
policyCultureCost *= civInfo.gameInfo.gameParameters.gameSpeed.modifier
|
||||
policyCultureCost *= civInfo.gameInfo.speed.cultureCostModifier
|
||||
val cost: Int = (policyCultureCost * (1 + cityModifier)).roundToInt()
|
||||
return cost - (cost % 5)
|
||||
}
|
||||
|
@ -144,7 +144,7 @@ class QuestManager {
|
||||
else
|
||||
GLOBAL_QUEST_MIN_TURNS_BETWEEN + Random.nextInt(GLOBAL_QUEST_RAND_TURNS_BETWEEN)
|
||||
|
||||
globalQuestCountdown = (countdown * civInfo.gameInfo.gameParameters.gameSpeed.modifier).toInt()
|
||||
globalQuestCountdown = (countdown * civInfo.gameInfo.speed.modifier).toInt()
|
||||
}
|
||||
|
||||
private fun seedIndividualQuestsCountdown() {
|
||||
@ -164,7 +164,7 @@ class QuestManager {
|
||||
else
|
||||
INDIVIDUAL_QUEST_MIN_TURNS_BETWEEN + Random.nextInt(INDIVIDUAL_QUEST_RAND_TURNS_BETWEEN)
|
||||
|
||||
individualQuestCountdown[challenger.civName] = (countdown * civInfo.gameInfo.gameParameters.gameSpeed.modifier).toInt()
|
||||
individualQuestCountdown[challenger.civName] = (countdown * civInfo.gameInfo.speed.modifier).toInt()
|
||||
}
|
||||
|
||||
private fun tryStartNewGlobalQuest() {
|
||||
@ -905,7 +905,7 @@ class AssignedQuest(val questName: String = "",
|
||||
fun doesExpire(): Boolean = gameInfo.ruleSet.quests[questName]!!.duration > 0
|
||||
fun isExpired(): Boolean = doesExpire() && getRemainingTurns() == 0
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
fun getDuration(): Int = (gameInfo.gameParameters.gameSpeed.modifier * gameInfo.ruleSet.quests[questName]!!.duration).toInt()
|
||||
fun getDuration(): Int = (gameInfo.speed.modifier * gameInfo.ruleSet.quests[questName]!!.duration).toInt()
|
||||
fun getRemainingTurns(): Int = max(0, (assignedOnTurn + getDuration()) - gameInfo.turns)
|
||||
|
||||
fun getDescription(): String {
|
||||
|
@ -110,7 +110,7 @@ class ReligionManager {
|
||||
|
||||
var faithCost =
|
||||
(200 + 100 * greatProphetsEarned * (greatProphetsEarned + 1) / 2f) *
|
||||
civInfo.gameInfo.gameParameters.gameSpeed.modifier
|
||||
civInfo.gameInfo.speed.faithCostModifier
|
||||
|
||||
for (unique in civInfo.getMatchingUniques(UniqueType.FaithCostOfGreatProphetChange))
|
||||
faithCost *= unique.params[0].toPercent()
|
||||
|
@ -86,7 +86,7 @@ class TechManager {
|
||||
var techCost = getRuleset().technologies[techName]!!.cost.toFloat()
|
||||
if (civInfo.isPlayerCivilization())
|
||||
techCost *= civInfo.getDifficulty().researchCostModifier
|
||||
techCost *= civInfo.gameInfo.gameParameters.gameSpeed.modifier
|
||||
techCost *= civInfo.gameInfo.speed.scienceCostModifier
|
||||
val techsResearchedKnownCivs = civInfo.getKnownCivs()
|
||||
.count { it.isMajorCiv() && it.tech.isResearched(techName) }
|
||||
val undefeatedCivs = civInfo.gameInfo.civilizations
|
||||
@ -132,13 +132,13 @@ class TechManager {
|
||||
val tech = getRuleset().technologies[techName]!!
|
||||
if (tech.uniqueObjects.any { it.type == UniqueType.OnlyAvailableWhen && !it.conditionalsApply(civInfo) })
|
||||
return false
|
||||
|
||||
|
||||
if (tech.getMatchingUniques(UniqueType.IncompatibleWith).any { isResearched(it.params[0]) })
|
||||
return false
|
||||
|
||||
|
||||
if (isResearched(tech.name) && !tech.isContinuallyResearchable())
|
||||
return false
|
||||
|
||||
|
||||
return tech.prerequisites.all { isResearched(it) }
|
||||
}
|
||||
|
||||
@ -167,7 +167,7 @@ class TechManager {
|
||||
|
||||
fun getScienceFromGreatScientist(): Int {
|
||||
// https://civilization.fandom.com/wiki/Great_Scientist_(Civ5)
|
||||
return (scienceOfLast8Turns.sum() * civInfo.gameInfo.gameParameters.gameSpeed.modifier).toInt()
|
||||
return (scienceOfLast8Turns.sum() * civInfo.gameInfo.speed.scienceCostModifier).toInt()
|
||||
}
|
||||
|
||||
private fun addCurrentScienceToScienceOfLast8Turns() {
|
||||
|
@ -959,10 +959,15 @@ class MapUnit {
|
||||
|
||||
val gainedStats = Stats()
|
||||
for (unique in civInfo.getMatchingUniques(UniqueType.ProvidesGoldWheneverGreatPersonExpended)) {
|
||||
gainedStats.gold += (100 * civInfo.gameInfo.gameParameters.gameSpeed.modifier).toInt()
|
||||
gainedStats.gold += (100 * civInfo.gameInfo.speed.goldCostModifier).toInt()
|
||||
}
|
||||
for (unique in civInfo.getMatchingUniques(UniqueType.ProvidesStatsWheneverGreatPersonExpended)) {
|
||||
gainedStats.add(unique.stats)
|
||||
val uniqueStats = unique.stats
|
||||
val speedModifiers = civInfo.gameInfo.speed.statCostModifiers
|
||||
for (stat in uniqueStats) {
|
||||
uniqueStats[stat.key] = stat.value * speedModifiers[stat.key]!!
|
||||
}
|
||||
gainedStats.add(uniqueStats)
|
||||
}
|
||||
|
||||
if (gainedStats.isEmpty()) return
|
||||
@ -1030,7 +1035,7 @@ class MapUnit {
|
||||
.forEach { it.questManager.barbarianCampCleared(civInfo, tile.position) }
|
||||
|
||||
var goldGained =
|
||||
civInfo.getDifficulty().clearBarbarianCampReward * civInfo.gameInfo.gameParameters.gameSpeed.modifier
|
||||
civInfo.getDifficulty().clearBarbarianCampReward * civInfo.gameInfo.speed.goldCostModifier
|
||||
if (civInfo.hasUnique(UniqueType.TripleGoldFromEncampmentsAndCities))
|
||||
goldGained *= 3f
|
||||
|
||||
|
@ -118,7 +118,7 @@ class TradeEvaluation {
|
||||
|
||||
TradeType.Technology -> // Currently unused
|
||||
return (sqrt(civInfo.gameInfo.ruleSet.technologies[offer.name]!!.cost.toDouble())
|
||||
* civInfo.gameInfo.gameParameters.gameSpeed.modifier).toInt() * 20
|
||||
* civInfo.gameInfo.speed.scienceCostModifier).toInt() * 20
|
||||
TradeType.Introduction -> return introductionValue(civInfo.gameInfo.ruleSet)
|
||||
TradeType.WarDeclaration -> {
|
||||
val civToDeclareWarOn = civInfo.gameInfo.getCivilization(offer.name)
|
||||
|
@ -2,7 +2,7 @@ package com.unciv.logic.trade
|
||||
|
||||
import com.unciv.Constants
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.models.metadata.GameSpeed
|
||||
import com.unciv.models.ruleset.Speed
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.utils.Fonts
|
||||
import com.unciv.logic.trade.TradeType.TradeTypeNumberType
|
||||
@ -13,13 +13,12 @@ data class TradeOffer(val name: String, val type: TradeType, var amount: Int = 1
|
||||
name: String,
|
||||
type: TradeType,
|
||||
amount: Int = 1,
|
||||
gameSpeed: GameSpeed = UncivGame.Current.gameInfo!!.gameParameters.gameSpeed
|
||||
speed: Speed = UncivGame.Current.gameInfo!!.speed
|
||||
) : this(name, type, amount, duration = -1) {
|
||||
duration = when {
|
||||
type.isImmediate -> -1 // -1 for offers that are immediate (e.g. gold transfer)
|
||||
name == Constants.peaceTreaty -> 10
|
||||
gameSpeed == GameSpeed.Quick -> 25
|
||||
else -> (30 * gameSpeed.modifier).toInt()
|
||||
name == Constants.peaceTreaty -> speed.peaceDealDuration
|
||||
else -> speed.dealDuration
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,9 +6,9 @@ class ModConstants {
|
||||
var maxXPfromBarbarians = 30
|
||||
|
||||
// Formula for city Strength:
|
||||
// Strength = baseStrength + strengthPerPop + strengthFromTiles +
|
||||
// ((%techs * multiplier) ^ exponent) * fullMultiplier +
|
||||
// (garrisonBonus * garrisonUnitStrength * garrisonUnitHealth/100) +
|
||||
// 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%)
|
||||
@ -18,10 +18,10 @@ class ModConstants {
|
||||
var cityStrengthFromTechsExponent = 2.8
|
||||
var cityStrengthFromTechsFullMultiplier = 1.0
|
||||
var cityStrengthFromGarrison = 0.2
|
||||
|
||||
|
||||
// Formula for Unit Supply:
|
||||
// Supply = unitSupplyBase (difficulties.json)
|
||||
// unitSupplyPerCity * amountOfCities + (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
|
||||
@ -38,7 +38,7 @@ class ModConstants {
|
||||
class UnitUpgradeCost {
|
||||
val base = 10f
|
||||
val perProduction = 2f
|
||||
val eraMultiplier = 0f // 0.3 in Civ5 cpp sources but 0 in xml
|
||||
val eraMultiplier = 0f // 0.3 in Civ5 cpp sources but 0 in xml
|
||||
val exponent = 1f
|
||||
val roundTo = 5
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.unciv.models.metadata
|
||||
|
||||
import com.unciv.logic.civilization.PlayerType
|
||||
import com.unciv.models.ruleset.Speed
|
||||
|
||||
enum class BaseRuleset(val fullName:String){
|
||||
Civ_V_Vanilla("Civ V - Vanilla"),
|
||||
@ -9,7 +10,7 @@ enum class BaseRuleset(val fullName:String){
|
||||
|
||||
class GameParameters { // Default values are the default new game
|
||||
var difficulty = "Prince"
|
||||
var gameSpeed = GameSpeed.Standard
|
||||
var speed = Speed.DEFAULT
|
||||
var players = ArrayList<Player>().apply {
|
||||
add(Player().apply { playerType = PlayerType.Human })
|
||||
for (i in 1..3) add(Player())
|
||||
@ -22,20 +23,20 @@ class GameParameters { // Default values are the default new game
|
||||
var godMode = false
|
||||
var nuclearWeaponsEnabled = true
|
||||
var religionEnabled = false
|
||||
|
||||
var victoryTypes: ArrayList<String> = arrayListOf()
|
||||
|
||||
var victoryTypes: ArrayList<String> = arrayListOf()
|
||||
var startingEra = "Ancient era"
|
||||
|
||||
var isOnlineMultiplayer = false
|
||||
var baseRuleset: String = BaseRuleset.Civ_V_GnK.fullName
|
||||
var mods = LinkedHashSet<String>()
|
||||
|
||||
|
||||
var maxTurns = 500
|
||||
|
||||
fun clone(): GameParameters {
|
||||
val parameters = GameParameters()
|
||||
parameters.difficulty = difficulty
|
||||
parameters.gameSpeed = gameSpeed
|
||||
parameters.speed = speed
|
||||
parameters.players = ArrayList(players)
|
||||
parameters.numberOfCityStates = numberOfCityStates
|
||||
parameters.noBarbarians = noBarbarians
|
||||
@ -54,7 +55,7 @@ class GameParameters { // Default values are the default new game
|
||||
|
||||
// For debugging and GameStarter console output
|
||||
override fun toString() = sequence {
|
||||
yield("$difficulty $gameSpeed $startingEra")
|
||||
yield("$difficulty $speed $startingEra")
|
||||
yield("${players.count { it.playerType == PlayerType.Human }} ${PlayerType.Human}")
|
||||
yield("${players.count { it.playerType == PlayerType.AI }} ${PlayerType.AI}")
|
||||
yield("$numberOfCityStates CS")
|
||||
@ -69,8 +70,8 @@ class GameParameters { // Default values are the default new game
|
||||
yield(baseRuleset)
|
||||
yield(if (mods.isEmpty()) "no mods" else mods.joinToString(",", "mods=(", ")", 6) )
|
||||
}.joinToString(prefix = "(", postfix = ")")
|
||||
|
||||
|
||||
fun getModsAndBaseRuleset(): HashSet<String> {
|
||||
return mods.toHashSet().apply { add(baseRuleset) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +0,0 @@
|
||||
package com.unciv.models.metadata
|
||||
|
||||
const val BASE_GAME_DURATION_TURNS = 500f
|
||||
|
||||
/** Game speed
|
||||
*
|
||||
* @param modifier cost modifier
|
||||
* */
|
||||
enum class GameSpeed(val modifier: Float) {
|
||||
Quick(0.67f),
|
||||
Standard(1f),
|
||||
Epic(1.5f),
|
||||
Marathon(3f);
|
||||
}
|
@ -354,7 +354,7 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
|
||||
civInfo.gameInfo.getDifficulty().aiBuildingCostModifier
|
||||
}
|
||||
|
||||
productionCost *= civInfo.gameInfo.gameParameters.gameSpeed.modifier
|
||||
productionCost *= civInfo.gameInfo.speed.productionCostModifier
|
||||
return productionCost.toInt()
|
||||
}
|
||||
|
||||
|
@ -84,6 +84,7 @@ class Ruleset {
|
||||
val buildings = LinkedHashMap<String, Building>()
|
||||
val difficulties = LinkedHashMap<String, Difficulty>()
|
||||
val eras = LinkedHashMap<String, Era>()
|
||||
val speeds = LinkedHashMap<String, Speed>()
|
||||
var globalUniques = GlobalUniques()
|
||||
val nations = LinkedHashMap<String, Nation>()
|
||||
val policies = LinkedHashMap<String, Policy>()
|
||||
@ -123,6 +124,7 @@ class Ruleset {
|
||||
for (buildingToRemove in ruleset.modOptions.buildingsToRemove) buildings.remove(buildingToRemove)
|
||||
difficulties.putAll(ruleset.difficulties)
|
||||
eras.putAll(ruleset.eras)
|
||||
speeds.putAll(ruleset.speeds)
|
||||
globalUniques = GlobalUniques().apply { uniques.addAll(globalUniques.uniques); uniques.addAll(ruleset.globalUniques.uniques) }
|
||||
nations.putAll(ruleset.nations)
|
||||
for (nationToRemove in ruleset.modOptions.nationsToRemove) nations.remove(nationToRemove)
|
||||
@ -152,6 +154,7 @@ class Ruleset {
|
||||
buildings.clear()
|
||||
difficulties.clear()
|
||||
eras.clear()
|
||||
speeds.clear()
|
||||
globalUniques = GlobalUniques()
|
||||
mods.clear()
|
||||
nations.clear()
|
||||
@ -176,6 +179,7 @@ class Ruleset {
|
||||
buildings.values.asSequence() +
|
||||
//difficulties is only INamed
|
||||
eras.values.asSequence() +
|
||||
speeds.values.asSequence() +
|
||||
sequenceOf(globalUniques) +
|
||||
nations.values.asSequence() +
|
||||
policies.values.asSequence() +
|
||||
@ -245,6 +249,11 @@ class Ruleset {
|
||||
// Using map{} sidesteps this problem
|
||||
eras.map { it.value }.withIndex().forEach { it.value.eraNumber = it.index }
|
||||
|
||||
val speedsFile = folderHandle.child("Speeds.json")
|
||||
if (speedsFile.exists()) {
|
||||
speeds += createHashmap(json().fromJsonFile(Array<Speed>::class.java, speedsFile))
|
||||
}
|
||||
|
||||
val unitTypesFile = folderHandle.child("UnitTypes.json")
|
||||
if (unitTypesFile.exists()) unitTypes += createHashmap(json().fromJsonFile(Array<UnitType>::class.java, unitTypesFile))
|
||||
|
||||
@ -343,6 +352,10 @@ class Ruleset {
|
||||
if (victories.isEmpty()) {
|
||||
victories.putAll(RulesetCache.getVanillaRuleset().victories)
|
||||
}
|
||||
|
||||
if (speeds.isEmpty()) {
|
||||
speeds.putAll(RulesetCache.getVanillaRuleset().speeds)
|
||||
}
|
||||
}
|
||||
|
||||
debug("Loading ruleset - %sms", System.currentTimeMillis() - gameBasicsStartTime)
|
||||
@ -795,6 +808,13 @@ class Ruleset {
|
||||
checkUniques(era, lines, rulesetSpecific, forOptionsPopup)
|
||||
}
|
||||
|
||||
for (speed in speeds.values) {
|
||||
if (speed.modifier < 0f)
|
||||
lines += "Negative speed modifier for game speed ${speed.name}"
|
||||
if (speed.yearsPerTurn.isEmpty())
|
||||
lines += "Empty turn increment list for game speed ${speed.name}"
|
||||
}
|
||||
|
||||
for (belief in beliefs.values) {
|
||||
checkUniques(belief, lines, rulesetSpecific, forOptionsPopup)
|
||||
}
|
||||
|
83
core/src/com/unciv/models/ruleset/Speed.kt
Normal file
83
core/src/com/unciv/models/ruleset/Speed.kt
Normal file
@ -0,0 +1,83 @@
|
||||
package com.unciv.models.ruleset
|
||||
|
||||
import com.unciv.models.ruleset.unique.UniqueTarget
|
||||
import com.unciv.models.stats.Stat
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.civilopedia.FormattedLine
|
||||
import com.unciv.ui.utils.Fonts
|
||||
import kotlin.math.abs
|
||||
|
||||
class Speed : RulesetObject() {
|
||||
var modifier: Float = 1f
|
||||
var goldCostModifier: Float = modifier
|
||||
var productionCostModifier: Float = modifier
|
||||
var scienceCostModifier: Float = modifier
|
||||
var cultureCostModifier: Float = modifier
|
||||
var faithCostModifier: Float = modifier
|
||||
var goldGiftModifier: Float = modifier
|
||||
var cityStateTributeScalingInterval: Float = 6.5f
|
||||
var barbarianModifier: Float = modifier
|
||||
var improvementBuildLengthModifier: Float = modifier
|
||||
var goldenAgeLengthModifier: Float = modifier
|
||||
var religiousPressureAdjacentCity: Int = 6
|
||||
var peaceDealDuration: Int = 10
|
||||
var dealDuration: Int = 30
|
||||
var startYear: Float = -4000f
|
||||
var turns: ArrayList<HashMap<String, Float>> = ArrayList()
|
||||
|
||||
val yearsPerTurn: ArrayList<YearsPerTurn> by lazy {
|
||||
ArrayList<YearsPerTurn>().apply {
|
||||
turns.forEach { this.add(YearsPerTurn(it["yearsPerTurn"]!!, it["untilTurn"]!!.toInt())) }
|
||||
}
|
||||
}
|
||||
|
||||
val statCostModifiers: HashMap<Stat, Float> by lazy {
|
||||
HashMap<Stat, Float>().apply {
|
||||
this[Stat.Faith] = 1f;
|
||||
this[Stat.Production] = productionCostModifier;
|
||||
this[Stat.Gold] = goldCostModifier;
|
||||
this[Stat.Science] = scienceCostModifier;
|
||||
this[Stat.Faith] = faithCostModifier;
|
||||
this[Stat.Happiness] = 1f;
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val DEFAULT: String = "Quick"
|
||||
const val DEFAULTFORSIMULATION: String = "Standard"
|
||||
}
|
||||
|
||||
override fun getUniqueTarget(): UniqueTarget = UniqueTarget.Speed
|
||||
|
||||
override fun makeLink(): String = "GameSpeed/$name"
|
||||
override fun getCivilopediaTextHeader() = FormattedLine(name, header = 2)
|
||||
override fun getCivilopediaTextLines(ruleset: Ruleset) = sequence {
|
||||
yield(FormattedLine("General speed modifier: [${modifier * 100}]%${Fonts.turn}"))
|
||||
yield(FormattedLine("Production cost modifier: [${productionCostModifier * 100}]%${Fonts.production}"))
|
||||
yield(FormattedLine("Gold cost modifier: [${goldCostModifier * 100}]%${Fonts.gold}"))
|
||||
yield(FormattedLine("Science cost modifier: [${scienceCostModifier * 100}]%${Fonts.science}"))
|
||||
yield(FormattedLine("Culture cost modifier: [${cultureCostModifier * 100}]%${Fonts.culture}"))
|
||||
yield(FormattedLine("Faith cost modifier: [${faithCostModifier * 100}]%${Fonts.faith}"))
|
||||
yield(FormattedLine("Improvement build length modifier: [${improvementBuildLengthModifier * 100}]%${Fonts.turn}"))
|
||||
yield(FormattedLine("Diplomatic deal duration: [$dealDuration] turns${Fonts.turn}"))
|
||||
yield(FormattedLine("Gold gift influence gain modifier: [${goldGiftModifier * 100}]%${Fonts.gold}"))
|
||||
yield(FormattedLine("City-state tribute scaling interval: [${cityStateTributeScalingInterval}] turns${Fonts.turn}"))
|
||||
yield(FormattedLine("Barbarian spawn modifier: [${barbarianModifier * 100}]%${Fonts.strength}"))
|
||||
yield(FormattedLine("Golden age length modifier: [${goldenAgeLengthModifier * 100}]%${Fonts.happiness}"))
|
||||
yield(FormattedLine("Adjacent city religious pressure: [$religiousPressureAdjacentCity]${Fonts.faith}"))
|
||||
yield(FormattedLine("Peace deal duration: [$peaceDealDuration] turns${Fonts.turn}"))
|
||||
yield(FormattedLine("Start year: " + ("[${abs(startYear).toInt()}] " + (if (startYear < 0) "BC" else "AD")).tr()))
|
||||
}.toList()
|
||||
|
||||
fun numTotalTurns(): Int = yearsPerTurn.last().untilTurn
|
||||
}
|
||||
|
||||
class YearsPerTurn {
|
||||
var yearInterval: Float = 0f
|
||||
var untilTurn: Int = 0
|
||||
|
||||
constructor(yearsPerTurn: Float, turnsPerIncrement: Int) {
|
||||
this.yearInterval = yearsPerTurn
|
||||
this.untilTurn = turnsPerIncrement
|
||||
}
|
||||
}
|
@ -31,7 +31,7 @@ class TileImprovement : RulesetStatsObject() {
|
||||
fun getTurnsToBuild(civInfo: CivilizationInfo, unit: MapUnit): Int {
|
||||
val state = StateForConditionals(civInfo, unit = unit)
|
||||
return unit.getMatchingUniques(UniqueType.TileImprovementTime, state, checkCivInfoUniques = true)
|
||||
.fold(turnsToBuild.toFloat() * civInfo.gameInfo.gameParameters.gameSpeed.modifier) { it, unique ->
|
||||
.fold(turnsToBuild.toFloat() * civInfo.gameInfo.speed.improvementBuildLengthModifier) { it, unique ->
|
||||
it * unique.params[0].toPercent()
|
||||
}.roundToInt()
|
||||
.coerceAtLeast(1)
|
||||
|
@ -339,7 +339,7 @@ object UniqueTriggerActivation {
|
||||
|
||||
val foundStatAmount =
|
||||
(tileBasedRandom.nextInt(unique.params[0].toInt(), unique.params[1].toInt()) *
|
||||
civInfo.gameInfo.gameParameters.gameSpeed.modifier
|
||||
civInfo.gameInfo.speed.statCostModifiers[stat]!!
|
||||
).toInt()
|
||||
|
||||
civInfo.addStat(
|
||||
|
@ -20,6 +20,7 @@ enum class UniqueTarget(val inheritsFrom: UniqueTarget? = null) {
|
||||
// Civilization-specific
|
||||
Nation(Global),
|
||||
Era(Global),
|
||||
Speed(Global),
|
||||
Tech(Global),
|
||||
Policy(Global),
|
||||
FounderBelief(Global),
|
||||
|
@ -253,7 +253,7 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction {
|
||||
civInfo.getDifficulty().unitCostModifier
|
||||
else
|
||||
civInfo.gameInfo.getDifficulty().aiUnitCostModifier
|
||||
productionCost *= civInfo.gameInfo.gameParameters.gameSpeed.modifier
|
||||
productionCost *= civInfo.gameInfo.speed.productionCostModifier
|
||||
return productionCost.toInt()
|
||||
}
|
||||
|
||||
|
@ -456,6 +456,7 @@ object TranslationFileWriter {
|
||||
"Buildings" -> emptyArray<Building>().javaClass
|
||||
"Difficulties" -> emptyArray<Difficulty>().javaClass
|
||||
"Eras" -> emptyArray<Era>().javaClass
|
||||
"Speeds" -> emptyArray<Speed>().javaClass
|
||||
"GlobalUniques" -> GlobalUniques().javaClass
|
||||
"Nations" -> emptyArray<Nation>().javaClass
|
||||
"Policies" -> emptyArray<PolicyBranch>().javaClass
|
||||
|
@ -188,6 +188,11 @@ enum class CivilopediaCategories (
|
||||
getImage = null,
|
||||
KeyCharAndCode('D'),
|
||||
"OtherIcons/Tyrannosaurus"
|
||||
),
|
||||
Speed ("Speeds", false,
|
||||
getImage = null,
|
||||
KeyCharAndCode('S'),
|
||||
"OtherIcons/Timer"
|
||||
);
|
||||
|
||||
fun getByOffset(offset: Int) = values()[(ordinal + count + offset) % count]
|
||||
|
@ -213,6 +213,7 @@ class CivilopediaScreen(
|
||||
CivilopediaCategories.Belief -> (ruleset.beliefs.values.asSequence() +
|
||||
Belief.getCivilopediaReligionEntry(ruleset)).toList()
|
||||
CivilopediaCategories.Era -> ruleset.eras.values
|
||||
CivilopediaCategories.Speed -> ruleset.speeds.values
|
||||
}
|
||||
|
||||
for (loopCategory in CivilopediaCategories.values()) {
|
||||
|
@ -1,13 +1,8 @@
|
||||
package com.unciv.ui.newgamescreen
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.CheckBox
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Label
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.logic.civilization.CityStateType
|
||||
import com.unciv.logic.multiplayer.OnlineMultiplayer
|
||||
import com.unciv.models.metadata.GameSpeed
|
||||
import com.unciv.models.ruleset.RulesetCache
|
||||
import com.unciv.models.ruleset.unique.UniqueType
|
||||
import com.unciv.models.translations.tr
|
||||
@ -15,7 +10,6 @@ import com.unciv.ui.audio.MusicMood
|
||||
import com.unciv.ui.audio.MusicTrackChooserFlags
|
||||
import com.unciv.ui.images.ImageGetter
|
||||
import com.unciv.ui.multiplayer.MultiplayerHelpers
|
||||
import com.unciv.ui.popup.Popup
|
||||
import com.unciv.ui.popup.ToastPopup
|
||||
import com.unciv.ui.utils.BaseScreen
|
||||
import com.unciv.ui.utils.UncivSlider
|
||||
@ -224,8 +218,8 @@ class GameOptionsTable(
|
||||
}
|
||||
|
||||
private fun Table.addGameSpeedSelectBox() {
|
||||
addSelectBox("{Game Speed}:", GameSpeed.values().map { it.name }, gameParameters.gameSpeed.name)
|
||||
{ gameParameters.gameSpeed = GameSpeed.valueOf(it); null }
|
||||
addSelectBox("{Game Speed}:", ruleset.speeds.values.map { it.name }, gameParameters.speed)
|
||||
{ gameParameters.speed = it; null }
|
||||
}
|
||||
|
||||
private fun Table.addEraSelectBox() {
|
||||
|
@ -518,7 +518,7 @@ object UnitActions {
|
||||
action = {
|
||||
tile.getCity()!!.cityConstructions.apply {
|
||||
//http://civilization.wikia.com/wiki/Great_engineer_(Civ5)
|
||||
addProductionPoints(((300 + 30 * tile.getCity()!!.population.population) * unit.civInfo.gameInfo.gameParameters.gameSpeed.modifier).toInt())
|
||||
addProductionPoints(((300 + 30 * tile.getCity()!!.population.population) * unit.civInfo.gameInfo.speed.productionCostModifier).toInt())
|
||||
constructIfEnough()
|
||||
}
|
||||
|
||||
@ -539,7 +539,7 @@ object UnitActions {
|
||||
|
||||
//http://civilization.wikia.com/wiki/Great_engineer_(Civ5)
|
||||
val productionPointsToAdd = min(
|
||||
(300 + 30 * tile.getCity()!!.population.population) * unit.civInfo.gameInfo.gameParameters.gameSpeed.modifier,
|
||||
(300 + 30 * tile.getCity()!!.population.population) * unit.civInfo.gameInfo.speed.productionCostModifier,
|
||||
cityConstructions.getRemainingWork(cityConstructions.currentConstructionFromQueue).toFloat() - 1
|
||||
).toInt()
|
||||
if (productionPointsToAdd <= 0) continue
|
||||
@ -563,7 +563,7 @@ object UnitActions {
|
||||
actionList += UnitAction(UnitActionType.ConductTradeMission,
|
||||
action = {
|
||||
// http://civilization.wikia.com/wiki/Great_Merchant_(Civ5)
|
||||
var goldEarned = (350 + 50 * unit.civInfo.getEraNumber()) * unit.civInfo.gameInfo.gameParameters.gameSpeed.modifier
|
||||
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())
|
||||
|
@ -11,12 +11,12 @@ import com.unciv.logic.map.MapSize
|
||||
import com.unciv.logic.map.MapSizeNew
|
||||
import com.unciv.models.metadata.GameParameters
|
||||
import com.unciv.models.metadata.GameSettings
|
||||
import com.unciv.models.metadata.GameSpeed
|
||||
import com.unciv.models.metadata.Player
|
||||
import com.unciv.models.ruleset.RulesetCache
|
||||
import com.unciv.models.simulation.Simulation
|
||||
import com.unciv.models.tilesets.TileSetCache
|
||||
import com.unciv.models.metadata.GameSetupInfo
|
||||
import com.unciv.models.ruleset.Speed
|
||||
import kotlin.time.ExperimentalTime
|
||||
|
||||
internal object ConsoleLauncher {
|
||||
@ -69,7 +69,7 @@ internal object ConsoleLauncher {
|
||||
private fun getGameParameters(civilization1: String, civilization2: String): GameParameters {
|
||||
return GameParameters().apply {
|
||||
difficulty = "Chieftain"
|
||||
gameSpeed = GameSpeed.Quick
|
||||
speed = Speed.DEFAULT
|
||||
noBarbarians = true
|
||||
players = ArrayList<Player>().apply {
|
||||
add(Player().apply {
|
||||
|
@ -698,6 +698,50 @@ Unless otherwise specified, all the following are from [the Noun Project](https:
|
||||
- [Santa beard vector](https://www.freepik.com/free-vector/positive-santa-ringing-bell-waving-hand_3636285.htm) by katemangostar
|
||||
- [Funny christmas vector](https://www.freepik.com/free-vector/snowman-wearing-santa-hat-scarf-mittens_3636292.htm) by katemangostar
|
||||
|
||||
- [Circle](https://thenounproject.com/term/circle/1841891/) By Aybige
|
||||
- [Arrow](https://thenounproject.com/term/arrow/18123/) By Joe Mortell for movement
|
||||
- [Swap](https://thenounproject.com/search/?q=swap&i=1259600) By iconomania for swapping units
|
||||
- [Connection](https://thenounproject.com/search/?q=connection&i=1521886) By Travis Avery
|
||||
- [Skull](https://thenounproject.com/search/?q=Skull&i=1030702) By Vladimir Belochkin for disbanding units
|
||||
- [Crosshair](https://thenounproject.com/search/?q=crosshairs&i=916030) By Bakunetsu Kaito for selecting enemies to attack
|
||||
- [City](https://thenounproject.com/search/?q=city&i=571332) By Felix Westphal
|
||||
- [Fire](https://thenounproject.com/search/?q=Fire&i=96564) By Lloyd Humphreys for "city being razed" icon
|
||||
- [Sleep](https://thenounproject.com/search/?q=sleep&i=1760085) By Saeful Muslim
|
||||
- [Banner](https://thenounproject.com/term/banner/866282/) By Emir Palavan for embarked units
|
||||
- [Arrow](https://thenounproject.com/term/arrow/18123/) By uzeir syarief for moving between idle units
|
||||
- [Replace](https://thenounproject.com/search/?q=replace&i=17858) By Mike Rowe for switching tiles between cities
|
||||
- [Resistance](https://thenounproject.com/term/revolution/1315305/) By HeadsOfBirds
|
||||
- [Viking Hat](https://thenounproject.com/search/?q=pillage&i=185405) By my name is mud for pillaging improvements
|
||||
- [Aim](https://thenounproject.com/search/?q=aim&i=2034920) By Kaviashri for ranged strength
|
||||
- [Capitol](https://thenounproject.com/search/?q=capitol&i=160031) By Loren Klein for City-States
|
||||
- [Aircraft](https://thenounproject.com/search/?q=aircraft&i=1629000) By Tom Fricker for aircraft icon in city button
|
||||
- [radar scan](https://thenounproject.com/search/?q=range&i=1500234) By icon 54 for Range
|
||||
- [short range radar](https://thenounproject.com/search/?q=air%20range&i=2612731) by Vectors Point for Intercept range
|
||||
- [Puppet](https://thenounproject.com/search/?q=puppet&i=285735) By Ben Davis for puppeted cities
|
||||
- [City](https://thenounproject.com/search/?q=city&i=1765370) By Muhajir ila Robbi in the Icon center
|
||||
- [Lock](https://thenounproject.com/search/?q=lock&i=3217613) by Vadim Solomakhin for locked tiles
|
||||
- [Hourglass](https://thenounproject.com/search/?q=hourglass&i=142268) by I Create Stuff for the 'Turn' icon
|
||||
- [Shield](https://thenounproject.com/search/?q=shield&i=813568) by Gregor Cresnar for Religious Strength
|
||||
- [skill sword flame](https://thenounproject.com/term/skill-sword-flame/2360212/) by Maxicons) for Remove Heresy
|
||||
- [Pencil](https://thenounproject.com/search/?q=pencil&i=4195852) by Muhamad Aldi Maulana for Enter Text Prompt Button / Pencil
|
||||
- [Parchment](https://thenounproject.com/term/parchment/1516378/) by hans draiman for Cultured City-States
|
||||
- [connection](https://thenounproject.com/term/connection/1365233/) by Popular for Mercantile City-States
|
||||
- [crossed sword](https://thenounproject.com/term/crossed-sword/2427559/) by ProSymbols for Militaristic City-States
|
||||
- [ship helm](https://thenounproject.com/term/ship-helm/2170591/) by Vectors Market for Maritime City-States
|
||||
- [Magnifying Glass](https://thenounproject.com/term/magnifying-glass/1311/) by John Caserta for Mod filter
|
||||
- [tick](https://thenounproject.com/term/tick/3968142/) by Adrien Coquet on Nation picker
|
||||
- [people](https://thenounproject.com/term/people/458671) by Wilson Joseph as base for Civilopedia category Nations
|
||||
- [Mountains ](https://thenounproject.com/term/mountains/15616/) by Andrew J. Young as base for Civilopedia category Terrains
|
||||
- [File:Maya.svg](https://en.wikipedia.org/wiki/File:Maya.svg) for Mayan numerals
|
||||
- [East side of stela C, Quirigua](https://en.wikipedia.org/wiki/File:East_side_of_stela_C,_Quirigua.PNG) for Mayan calendar symbols
|
||||
- [Footprints](https://thenounproject.com/icon/footprints-1393611/) by Abdul Wahhab for movement overlay toggle, slightly modified. Currently unused.
|
||||
- Arrows.svg by Intralexical (@will-ca), CC0.
|
||||
- [favor](https://thenounproject.com/icon/favor-1029350/) by MICHAEL G BROWN for WLTK marker on City Overview
|
||||
- [Party](https://thenounproject.com/icon/party-1784941/) by Adrien Coquet for WLTK header on City Overview
|
||||
- [Party](https://thenounproject.com/icon/party-2955155/) by Lars Meiertoberens as additional WLKT decoration
|
||||
- [turn right](https://thenounproject.com/icon/turn-right-1920867/) by Alice Design for Resource Overview
|
||||
- [Tyrannosaurus Rex](https://thenounproject.com/icon/tyrannosaurus-rex-4130976/) by Amethyst Studio for Civilopedia Eras header
|
||||
- [Timer](https://www.flaticon.com/free-icons/timer) created by Gregor Cresnar Premium - Flaticon
|
||||
|
||||
### Main menu
|
||||
|
||||
|
@ -60,6 +60,43 @@ Each era can have the following attributes:
|
||||
| settlerBuildings | List of Strings | defaults to none | Buildings that should automatically be built whenever a city is settled when starting a game in this era |
|
||||
| startingObsoleteWonders | List of Strings | defaults to none | Wonders (and technically buildings) that should be impossible to built when starting a game in this era. Used in the base game to remove all wonders older than 2 era's |
|
||||
|
||||
## Speeds.json
|
||||
|
||||
[Link to original](https://github.com/yairm210/Unciv/tree/master/android/assets/jsons/Civ%20V%20-%20Gods%20&%20Kings/Speeds.json)
|
||||
|
||||
This file should contain all the speeds you want to use in your mod.
|
||||
|
||||
Each speed can have the following attributes:
|
||||
|
||||
| Attribute | Type | Optional | Notes |
|
||||
| --------- | ---- | -------- | ----- |
|
||||
| name | String | required | Name of the speed |
|
||||
| modifier | Float (≥0) | defaults to 1.0 | Overall game speed modifier |
|
||||
| productionCostModifier | Float (≥0) | defaults to the value of `modifier` | Scales production cost of units and buildings |
|
||||
| goldCostModifier | Float (≥0) | defaults to the value of `modifier` | Scales gold costs |
|
||||
| scienceCostModifier | Float (≥0) | defaults to the value of `modifier` | Scales science costs |
|
||||
| cultureCostModifier | Float (≥0) | defaults to the value of `modifier` | Scales culture costs |
|
||||
| faithCostModifier | Float (≥0) | defaults to the value of `modifier` | Scales faith costs |
|
||||
| improvementBuildLengthModifier | Float (≥0) | defaults to the value of `modifier` | Scales the time it takes for a worker to build tile improvements |
|
||||
| barbarianModifier | Float (≥0) | defaults to the value of `modifier` | Scales the time between barbarian spawns |
|
||||
| goldGiftModifier | Float (≥0) | defaults to the value of `modifier` | Scales the influence gained from gifting gold to city-states |
|
||||
| cityStateTributeScalingInterval | Float (≥0) | defaults to 6.5 | The number of turns it takes for the amount of gold a player demands from city-states to increase by 5 gold |
|
||||
| goldenAgeLengthModifier | Float (≥0) | defaults to the value of `modifier` | Scales the length of golden ages |
|
||||
| religiousPressureAdjacentCity | Integer (≥0) | defaults to 6 | Defines how much religious pressure a city exerts on nearby cities |
|
||||
| peaceDealDuration | Integer (≥0) | defaults to 10 | The number of turns a peace deal lasts |
|
||||
| dealDuration | Integer (≥0) | defaults to 30 | The number of turns a non-peace deal (research agreement, open borders, etc.) lasts |
|
||||
| startYear | Float | defaults to -4000 | The start year of the game (negative is BC/BCE) |
|
||||
| turns | List of HashMaps | required | The amount of time passed between turns ("yearsPerTurn") and the range of turn numbers ("untilTurn") that this duration applies to |
|
||||
|
||||
The below code is an example of a valid "turns" definition and it specifies that the first 50 turns of a game last for 60 years each, then the next 30 turns (and any played after the 80th) last for 40 years each.
|
||||
|
||||
```json
|
||||
"turns": [
|
||||
{"yearsPerTurn": 60, "untilTurn": 50},
|
||||
{"yearsPerTurn": 40, "untilTurn": 80}
|
||||
]
|
||||
```
|
||||
|
||||
## ModOptions.json
|
||||
|
||||
<!-- [Link to original](https://github.com/yairm210/Unciv/tree/master/android/assets/jsons/Civ%20V%20-%20Gods%20&%20Kings/ModOptions.json) -->
|
||||
@ -185,13 +222,13 @@ Currently the following milestones are supported:
|
||||
| --------- | ----------- |
|
||||
| Build [building] | Build the building [building] in any city |
|
||||
| Anyone build [building] | Anyone must build the building [building] for all players to have this milestone |
|
||||
| Add all [comment] in capital | Add all units in the `requiredSpaceshipParts` field of this victory to the capital |
|
||||
| Add all [comment] in capital | Add all units in the `requiredSpaceshipParts` field of this victory to the capital |
|
||||
| Destroy all players | You must be the only major civilization with any cities left |
|
||||
| Capture all capitals | Capture all the original capitals of major civilizations in the game |
|
||||
| Complete [amount] Policy branches | Fully complete at least [amount] policy branches |
|
||||
| Win diplomatic vote | At any point in the game win a diplomatic vote (UN). You may lose afterwards and still retain this milestone |
|
||||
| Become the world religion | Have your religion be the majority religion in a majority of cities of all major civs |
|
||||
| Have highest score after max turns | Basically time victory. Enables the 'max turn' slider and calculates score when that amount is reached |
|
||||
| Have highest score after max turns | Basically time victory. Enables the 'max turn' slider and calculates score when that amount is reached |
|
||||
|
||||
|
||||
## Civilopedia text
|
||||
|
@ -7,10 +7,7 @@ import com.unciv.logic.city.CityInfo
|
||||
import com.unciv.logic.civilization.CivilizationInfo
|
||||
import com.unciv.logic.civilization.diplomacy.DiplomacyManager
|
||||
import com.unciv.logic.civilization.diplomacy.DiplomaticStatus
|
||||
import com.unciv.models.ruleset.Difficulty
|
||||
import com.unciv.models.ruleset.Nation
|
||||
import com.unciv.models.ruleset.Ruleset
|
||||
import com.unciv.models.ruleset.RulesetCache
|
||||
import com.unciv.models.ruleset.*
|
||||
import com.unciv.models.ruleset.unit.BaseUnit
|
||||
import com.unciv.testing.GdxTestRunner
|
||||
import org.junit.Assert
|
||||
@ -35,10 +32,11 @@ class UnitMovementAlgorithmsTests {
|
||||
civInfo.tech.techsResearched.addAll(ruleSet.technologies.keys)
|
||||
civInfo.tech.embarkedUnitsCanEnterOcean = true
|
||||
civInfo.tech.unitsCanEmbark = true
|
||||
civInfo.nation = Nation().apply { name = "My nation" }
|
||||
civInfo.gameInfo = GameInfo()
|
||||
civInfo.gameInfo.ruleSet = ruleSet
|
||||
civInfo.gameInfo.difficultyObject = Difficulty()
|
||||
civInfo.gameInfo.speed = ruleSet.speeds[Speed.DEFAULTFORSIMULATION]!!
|
||||
civInfo.nation = Nation().apply { name = "My nation" }
|
||||
civInfo.gameInfo.civilizations.add(civInfo)
|
||||
unit.civInfo = civInfo
|
||||
unit.owner = civInfo.civName
|
||||
|
@ -39,6 +39,7 @@ class TestGame {
|
||||
ruleset = RulesetCache[BaseRuleset.Civ_V_GnK.fullName]!!
|
||||
gameInfo.ruleSet = ruleset
|
||||
gameInfo.difficultyObject = ruleset.difficulties["Prince"]!!
|
||||
gameInfo.speed = ruleset.speeds[Speed.DEFAULTFORSIMULATION]!!
|
||||
|
||||
// Create a tilemap, needed for city centers
|
||||
gameInfo.tileMap = TileMap(1, ruleset, false)
|
||||
|
Reference in New Issue
Block a user