Added difficulty settings!
This commit is contained in:
parent
7af1a89913
commit
06c68302ce
14 changed files with 160 additions and 32 deletions
82
android/assets/jsons/Difficulties.json
Normal file
82
android/assets/jsons/Difficulties.json
Normal file
|
@ -0,0 +1,82 @@
|
|||
[
|
||||
{
|
||||
name:"Settler",
|
||||
baseHappiness:15,
|
||||
researchCostModifier:0.9,
|
||||
unhappinessModifier:0.4,
|
||||
aiCityGrowthModifier:1.6, // that is to say it'll take them 1.6 times as long to grow the city
|
||||
aiUnitMaintainanceModifier:1,
|
||||
aiConstructionModifier:0.6, // Replaces "Construction rate" and "Create rate" in original config
|
||||
aiFreeTechs:[]
|
||||
},
|
||||
{
|
||||
name:"Chieftain",
|
||||
baseHappiness:12,
|
||||
researchCostModifier:0.95,
|
||||
unhappinessModifier:0.6,
|
||||
aiCityGrowthModifier:1.3,
|
||||
aiUnitMaintainanceModifier:1,
|
||||
aiConstructionModifier:0.75,
|
||||
aiFreeTechs:[]
|
||||
},
|
||||
{
|
||||
name:"Warlord",
|
||||
baseHappiness:12,
|
||||
researchCostModifier:1,
|
||||
unhappinessModifier:0.75,
|
||||
aiCityGrowthModifier:1.1,
|
||||
aiUnitMaintainanceModifier:1,
|
||||
aiConstructionModifier:0.9,
|
||||
aiFreeTechs:[]
|
||||
},
|
||||
{
|
||||
name:"Prince",
|
||||
baseHappiness:9,
|
||||
researchCostModifier:1,
|
||||
unhappinessModifier:1
|
||||
aiCityGrowthModifier:1,
|
||||
aiUnitMaintainanceModifier:0.85,
|
||||
aiConstructionModifier:1,
|
||||
aiFreeTechs:[]
|
||||
},
|
||||
{
|
||||
name:"King",
|
||||
baseHappiness:9,
|
||||
researchCostModifier:1,
|
||||
unhappinessModifier:1
|
||||
aiCityGrowthModifier:0.9,
|
||||
aiUnitMaintainanceModifier:0.8,
|
||||
aiConstructionModifier:1.15,
|
||||
aiFreeTechs:["Pottery"]
|
||||
},
|
||||
{
|
||||
name:"Emperor",
|
||||
baseHappiness:9,
|
||||
researchCostModifier:1,
|
||||
unhappinessModifier:1
|
||||
aiCityGrowthModifier:0.85,
|
||||
aiUnitMaintainanceModifier:0.75,
|
||||
aiConstructionModifier:1.25,
|
||||
aiFreeTechs:["Pottery","Animal Husbandry"]
|
||||
},
|
||||
{
|
||||
name:"Immortal",
|
||||
baseHappiness:9,
|
||||
researchCostModifier:1,
|
||||
unhappinessModifier:1
|
||||
aiCityGrowthModifier:0.75,
|
||||
aiUnitMaintainanceModifier:0.65,
|
||||
aiConstructionModifier:1.5,
|
||||
aiFreeTechs:["Pottery","Animal Husbandry","Mining"]
|
||||
},
|
||||
{
|
||||
name:"Deity",
|
||||
baseHappiness:9,
|
||||
researchCostModifier:1,
|
||||
unhappinessModifier:1
|
||||
aiCityGrowthModifier:0.6,
|
||||
aiUnitMaintainanceModifier:0.5,
|
||||
aiConstructionModifier:2,
|
||||
aiFreeTechs:["Pottery","Animal Husbandry","Mining","The Wheel"]
|
||||
}
|
||||
]
|
|
@ -21,8 +21,8 @@ android {
|
|||
applicationId "com.unciv.game"
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 26
|
||||
versionCode 105
|
||||
versionName "2.6.7"
|
||||
versionCode 106
|
||||
versionName "2.6.8"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
|
|
|
@ -8,7 +8,7 @@ import com.unciv.models.gamebasics.GameBasics
|
|||
import com.unciv.ui.utils.getRandom
|
||||
|
||||
class GameStarter(){
|
||||
fun startNewGame(mapRadius: Int, numberOfCivs: Int, civilization: String): GameInfo {
|
||||
fun startNewGame(mapRadius: Int, numberOfCivs: Int, civilization: String, difficulty:String): GameInfo {
|
||||
val gameInfo = GameInfo()
|
||||
|
||||
gameInfo.tileMap = TileMap(mapRadius)
|
||||
|
@ -24,7 +24,9 @@ class GameStarter(){
|
|||
|
||||
val freeTiles = gameInfo.tileMap.values.toMutableList().filter { vectorIsWithinNTilesOfEdge(it.position,3)}.toMutableList()
|
||||
val playerPosition = freeTiles.getRandom().position
|
||||
gameInfo.civilizations.add(CivilizationInfo(civilization, playerPosition, gameInfo)) // first one is player civ
|
||||
val playerCiv = CivilizationInfo(civilization, playerPosition, gameInfo)
|
||||
playerCiv.difficulty=difficulty
|
||||
gameInfo.civilizations.add(playerCiv) // first one is player civ
|
||||
|
||||
freeTiles.removeAll(gameInfo.tileMap.getTilesInDistance(playerPosition,6))
|
||||
|
||||
|
@ -33,7 +35,9 @@ class GameStarter(){
|
|||
|
||||
for (civname in GameBasics.Civilizations.keys.filterNot { it=="Barbarians" || it==civilization }.take(numberOfCivs)) {
|
||||
val startingLocation = freeTiles.toList().getRandom().position
|
||||
gameInfo.civilizations.add(CivilizationInfo(civname, startingLocation, gameInfo))
|
||||
val civ = CivilizationInfo(civname, startingLocation, gameInfo)
|
||||
civ.tech.techsResearched.addAll(playerCiv.getDifficulty().aiFreeTechs)
|
||||
gameInfo.civilizations.add(civ)
|
||||
freeTiles.removeAll(gameInfo.tileMap.getTilesInDistance(startingLocation, 6))
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ class UnCivGame : Game() {
|
|||
}
|
||||
|
||||
fun startNewGame(saveTutorialState:Boolean = false) {
|
||||
val newGame = GameStarter().startNewGame(20, 3, "Babylon")
|
||||
val newGame = GameStarter().startNewGame(20, 3, "Babylon","Chieftain")
|
||||
if(saveTutorialState) {
|
||||
newGame.tutorial = gameInfo.tutorial
|
||||
}
|
||||
|
|
|
@ -102,6 +102,9 @@ class CityConstructions {
|
|||
} else
|
||||
currentConstruction = saveCurrentConstruction
|
||||
|
||||
var productionToAdd = cityStats.production
|
||||
if(!cityInfo.civInfo.isPlayerCivilization())
|
||||
productionToAdd *= cityInfo.civInfo.gameInfo.getPlayerCivilization().getDifficulty().aiConstructionModifier
|
||||
addConstruction(Math.round(cityStats.production))
|
||||
val productionCost = construction.getProductionCost(cityInfo.civInfo.policies.adoptedPolicies)
|
||||
if (inProgressConstructions[currentConstruction]!! >= productionCost) {
|
||||
|
|
|
@ -99,8 +99,11 @@ class CityStats {
|
|||
// in order to determine how much food is produced in a city!
|
||||
// -3 happiness per city
|
||||
fun getCityHappiness(): LinkedHashMap<String, Float> {
|
||||
happinessList["Cities"] = -3f
|
||||
val civInfo = cityInfo.civInfo
|
||||
var unhappinessModifier = civInfo.getDifficulty().unhappinessModifier
|
||||
|
||||
happinessList["Cities"] = -3f * unhappinessModifier
|
||||
|
||||
var unhappinessFromCitizens = cityInfo.population.population.toFloat()
|
||||
if (civInfo.policies.isAdopted("Democracy"))
|
||||
unhappinessFromCitizens -= cityInfo.population.getNumberOfSpecialists() * 0.5f
|
||||
|
@ -109,7 +112,7 @@ class CityStats {
|
|||
if (civInfo.policies.isAdopted("Meritocracy"))
|
||||
unhappinessFromCitizens *= 0.95f
|
||||
|
||||
happinessList["Population"] = -unhappinessFromCitizens
|
||||
happinessList["Population"] = -unhappinessFromCitizens * unhappinessModifier
|
||||
|
||||
var happinessFromPolicies = 0f
|
||||
if (civInfo.policies.isAdopted("Aristocracy"))
|
||||
|
|
|
@ -36,8 +36,11 @@ class PopulationManager {
|
|||
|
||||
|
||||
fun getFoodToNextPopulation(): Int {
|
||||
// civ v math,civilization.wikia
|
||||
return 15 + 6 * (population - 1) + Math.floor(Math.pow((population - 1).toDouble(), 1.8)).toInt()
|
||||
// civ v math, civilization.wikia
|
||||
var foodRequired = 15 + 6 * (population - 1) + Math.floor(Math.pow((population - 1).toDouble(), 1.8))
|
||||
if(!cityInfo.civInfo.isPlayerCivilization())
|
||||
foodRequired *= cityInfo.civInfo.gameInfo.getPlayerCivilization().getDifficulty().aiCityGrowthModifier
|
||||
return foodRequired.toInt()
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ import com.unciv.logic.map.MapUnit
|
|||
import com.unciv.logic.map.RoadStatus
|
||||
import com.unciv.logic.map.TileInfo
|
||||
import com.unciv.models.Counter
|
||||
import com.unciv.models.gamebasics.Civilization
|
||||
import com.unciv.models.gamebasics.GameBasics
|
||||
import com.unciv.models.gamebasics.tech.TechEra
|
||||
import com.unciv.models.gamebasics.tile.ResourceType
|
||||
|
@ -19,6 +18,7 @@ import com.unciv.ui.utils.getRandom
|
|||
import com.unciv.ui.utils.tr
|
||||
import kotlin.math.max
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
|
||||
class CivilizationInfo {
|
||||
|
@ -28,6 +28,7 @@ class CivilizationInfo {
|
|||
|
||||
var gold = 0
|
||||
var happiness = 15
|
||||
var difficulty = "Chieftain"
|
||||
var civName = "Babylon"
|
||||
|
||||
var tech = TechManager()
|
||||
|
@ -40,7 +41,8 @@ class CivilizationInfo {
|
|||
var cities = ArrayList<CityInfo>()
|
||||
var exploredTiles = HashSet<Vector2>()
|
||||
|
||||
fun getCivilization(): Civilization {return GameBasics.Civilizations[civName]!!}
|
||||
fun getDifficulty() = GameBasics.Difficulties[difficulty]!!
|
||||
fun getCivilization() = GameBasics.Civilizations[civName]!!
|
||||
|
||||
fun getCapital()=cities.first { it.isCapital() }
|
||||
|
||||
|
@ -97,9 +99,11 @@ class CivilizationInfo {
|
|||
if(policies.isAdopted("Oligarchy")) unitsToPayFor = unitsToPayFor.filterNot { it.getTile().isCityCenter() }
|
||||
val totalPaidUnits = max(0,unitsToPayFor.count()-freeUnits)
|
||||
val gameProgress = gameInfo.turns/400f // as game progresses maintainance cost rises
|
||||
val cost = baseUnitCost*totalPaidUnits*(1+gameProgress)
|
||||
val finalCost = cost.pow(1+gameProgress/3) // Why 3? No reason.
|
||||
return finalCost.toInt()
|
||||
var cost = baseUnitCost*totalPaidUnits*(1+gameProgress)
|
||||
cost = cost.pow(1+gameProgress/3) // Why 3? To spread 1 to 1.33
|
||||
if(!isPlayerCivilization())
|
||||
cost *= gameInfo.getPlayerCivilization().getDifficulty().aiUnitMaintainanceModifier
|
||||
return cost.toInt()
|
||||
}
|
||||
|
||||
private fun getTransportationUpkeep(): Int {
|
||||
|
@ -115,11 +119,11 @@ class CivilizationInfo {
|
|||
}
|
||||
|
||||
// base happiness
|
||||
fun getHappinessForNextTurn(): HashMap<String, Int> {
|
||||
val statMap = HashMap<String,Int>()
|
||||
statMap["Base happiness"] = 15
|
||||
fun getHappinessForNextTurn(): HashMap<String, Float> {
|
||||
val statMap = HashMap<String,Float>()
|
||||
statMap["Base happiness"] = getDifficulty().baseHappiness.toFloat()
|
||||
|
||||
var happinessPerUniqueLuxury = 5
|
||||
var happinessPerUniqueLuxury = 5f
|
||||
if (policies.isAdopted("Protectionism")) happinessPerUniqueLuxury += 1
|
||||
statMap["Luxury resources"]= getCivResources().keys
|
||||
.count { it.resourceType === ResourceType.Luxury } * happinessPerUniqueLuxury
|
||||
|
@ -127,13 +131,13 @@ class CivilizationInfo {
|
|||
for(city in cities){
|
||||
for(keyvalue in city.cityStats.getCityHappiness()){
|
||||
if(statMap.containsKey(keyvalue.key))
|
||||
statMap[keyvalue.key] = statMap[keyvalue.key]!!+keyvalue.value.toInt()
|
||||
else statMap[keyvalue.key] = keyvalue.value.toInt()
|
||||
statMap[keyvalue.key] = statMap[keyvalue.key]!!+keyvalue.value
|
||||
else statMap[keyvalue.key] = keyvalue.value
|
||||
}
|
||||
}
|
||||
|
||||
if (buildingUniques.contains("Provides 1 happiness per social policy"))
|
||||
statMap["Policies"] = policies.getAdoptedPolicies().count { !it.endsWith("Complete") }
|
||||
statMap["Policies"] = policies.getAdoptedPolicies().count { !it.endsWith("Complete") }.toFloat()
|
||||
|
||||
return statMap
|
||||
}
|
||||
|
@ -227,7 +231,7 @@ class CivilizationInfo {
|
|||
getViewableTiles() // adds explored tiles so that the units will be able to perform automated actions better
|
||||
for (city in cities)
|
||||
city.cityStats.update()
|
||||
happiness = getHappinessForNextTurn().values.sum()
|
||||
happiness = getHappinessForNextTurn().values.sum().roundToInt()
|
||||
getCivUnits().forEach { it.startTurn() }
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ class DiplomacyManager() {
|
|||
civInfo=civilizationInfo
|
||||
otherCivName=OtherCivName
|
||||
}
|
||||
|
||||
// var status:DiplomaticStatus = DiplomaticStatus.War
|
||||
var trades = ArrayList<Trade>()
|
||||
|
||||
|
|
|
@ -20,10 +20,9 @@ class TechManager {
|
|||
|
||||
private fun getCurrentTechnology(): Technology = GameBasics.Technologies[currentTechnology()]!!
|
||||
|
||||
fun getAmountResearchedText(): String =
|
||||
if (currentTechnology() == null) ""
|
||||
else "(" + researchOfTech(currentTechnology()!!) + "/" + getCurrentTechnology().cost + ")"
|
||||
|
||||
fun costOfTech(techName: String): Int {
|
||||
return (GameBasics.Technologies[techName]!!.cost * civInfo.getDifficulty().researchCostModifier).toInt()
|
||||
}
|
||||
|
||||
fun currentTechnology(): String? {
|
||||
if (techsToResearch.isEmpty()) return null
|
||||
|
@ -35,8 +34,8 @@ class TechManager {
|
|||
else return 0
|
||||
}
|
||||
|
||||
fun turnsToTech(TechName: String): Int {
|
||||
val remainingScience =GameBasics.Technologies[TechName]!!.cost - researchOfTech(TechName)
|
||||
fun turnsToTech(techName: String): Int {
|
||||
val remainingScience = costOfTech(techName) - researchOfTech(techName)
|
||||
return Math.ceil( remainingScience.toDouble()
|
||||
/ civInfo.getStatsForNextTurn().science).toInt()
|
||||
}
|
||||
|
@ -51,7 +50,7 @@ class TechManager {
|
|||
val currentTechnology = currentTechnology()
|
||||
if (currentTechnology == null) return
|
||||
techsInProgress[currentTechnology] = researchOfTech(currentTechnology) + scienceForNewTurn
|
||||
if (techsInProgress[currentTechnology]!! < getCurrentTechnology().cost)
|
||||
if (techsInProgress[currentTechnology]!! < costOfTech(currentTechnology))
|
||||
return
|
||||
|
||||
val previousEra = civInfo.getEra()
|
||||
|
|
15
core/src/com/unciv/models/gamebasics/Difficulty.kt
Normal file
15
core/src/com/unciv/models/gamebasics/Difficulty.kt
Normal file
|
@ -0,0 +1,15 @@
|
|||
package com.unciv.models.gamebasics
|
||||
|
||||
import com.unciv.models.stats.INamed
|
||||
import java.util.*
|
||||
|
||||
class Difficulty: INamed {
|
||||
override lateinit var name: String
|
||||
var baseHappiness: Int = 0
|
||||
var researchCostModifier:Float = 1f
|
||||
var unhappinessModifier = 1f
|
||||
var aiCityGrowthModifier = 1f
|
||||
var aiUnitMaintainanceModifier = 1f
|
||||
var aiConstructionModifier = 1f
|
||||
var aiFreeTechs = ArrayList<String>()
|
||||
}
|
|
@ -23,6 +23,7 @@ object GameBasics {
|
|||
val UnitPromotions = LinkedHashMap<String, Promotion>()
|
||||
val Civilizations = LinkedHashMap<String, Civilization>()
|
||||
val PolicyBranches = LinkedHashMap<String, PolicyBranch>()
|
||||
val Difficulties = LinkedHashMap<String, Difficulty>()
|
||||
val Tutorials = LinkedHashMap<String, List<String>>()
|
||||
val Translations = Translations(Gdx.files.internal("jsons/Translations.json").readString())
|
||||
|
||||
|
@ -48,6 +49,7 @@ object GameBasics {
|
|||
UnitPromotions += createHashmap(getFromJson(Array<Promotion>::class.java, "UnitPromotions"))
|
||||
PolicyBranches += createHashmap(getFromJson(Array<PolicyBranch>::class.java, "Policies"))
|
||||
Civilizations += createHashmap(getFromJson(Array<Civilization>::class.java, "Civilizations"))
|
||||
Difficulties += createHashmap(getFromJson(Array<Difficulty>::class.java, "Difficulties"))
|
||||
|
||||
// ...Yes. Total Voodoo. I wish I didn't have to do this.
|
||||
val x = LinkedHashMap<String,com.badlogic.gdx.utils.Array<com.badlogic.gdx.utils.Array<String>>>()
|
||||
|
|
|
@ -19,6 +19,7 @@ class NewGameScreen: PickerScreen(){
|
|||
val table = Table()
|
||||
table.skin= skin
|
||||
|
||||
|
||||
table.add("Civilization:".tr())
|
||||
val civSelectBox = SelectBox<String>(skin)
|
||||
val civArray = Array<String>()
|
||||
|
@ -48,6 +49,16 @@ class NewGameScreen: PickerScreen(){
|
|||
enemiesSelectBox.selected=3
|
||||
table.add(enemiesSelectBox).pad(10f).row()
|
||||
|
||||
|
||||
table.add("Difficulty:".tr())
|
||||
val difficultySelectBox = SelectBox<String>(skin)
|
||||
val difficultyArray = Array<String>()
|
||||
GameBasics.Difficulties.keys.forEach{difficultyArray.add(it)}
|
||||
difficultySelectBox.items = difficultyArray
|
||||
difficultySelectBox.selected = "Chieftain"
|
||||
table.add(difficultySelectBox).pad(10f).row()
|
||||
|
||||
|
||||
rightSideButton.enable()
|
||||
rightSideButton.setText("Start game!".tr())
|
||||
rightSideButton.addClickListener {
|
||||
|
@ -57,7 +68,8 @@ class NewGameScreen: PickerScreen(){
|
|||
|
||||
kotlin.concurrent.thread { // Creating a new game can tke a while and we don't want ANRs
|
||||
newGame = GameStarter().startNewGame(
|
||||
worldSizeToRadius[worldSizeSelectBox.selected]!!, enemiesSelectBox.selected, civSelectBox.selected )
|
||||
worldSizeToRadius[worldSizeSelectBox.selected]!!, enemiesSelectBox.selected,
|
||||
civSelectBox.selected, difficultySelectBox.selected )
|
||||
.apply { tutorial=game.gameInfo.tutorial }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,7 +83,7 @@ class WorldScreen : CameraStageBaseScreen() {
|
|||
|
||||
|
||||
fun update() {
|
||||
kotlin.concurrent.thread { civInfo.happiness = civInfo.getHappinessForNextTurn().values.sum() }
|
||||
kotlin.concurrent.thread { civInfo.happiness = civInfo.getHappinessForNextTurn().values.sum().toInt() }
|
||||
|
||||
if (game.gameInfo.tutorial.contains("CityEntered")) {
|
||||
displayTutorials("AfterCityEntered")
|
||||
|
|
Loading…
Reference in a new issue