diff --git a/android/Images/TechIcons/Railroad.png b/android/Images/TechIcons/Railroads.png similarity index 100% rename from android/Images/TechIcons/Railroad.png rename to android/Images/TechIcons/Railroads.png diff --git a/android/assets/game.atlas b/android/assets/game.atlas index 318afafe8b..a5773b4280 100644 --- a/android/assets/game.atlas +++ b/android/assets/game.atlas @@ -1859,9 +1859,9 @@ TechIcons/Radio orig: 100, 100 offset: 0, 0 index: -1 -TechIcons/Railroad +TechIcons/Railroads rotate: false - xy: 1292, 760 + xy: 1184, 652 size: 100, 100 orig: 100, 100 offset: 0, 0 @@ -2071,14 +2071,14 @@ TileSets/Default/OasisOverlay index: -1 TileSets/Default/Railroad rotate: false - xy: 1184, 652 + xy: 1292, 760 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ImprovementIcons/Railroad rotate: false - xy: 1184, 652 + xy: 1292, 760 size: 100, 100 orig: 100, 100 offset: 0, 0 diff --git a/android/assets/game.png b/android/assets/game.png index ae49008dfb..9695a7feb5 100644 Binary files a/android/assets/game.png and b/android/assets/game.png differ diff --git a/android/assets/jsons/Civ V - Vanilla/Buildings.json b/android/assets/jsons/Civ V - Vanilla/Buildings.json index 089e76129c..7a911fccfd 100644 --- a/android/assets/jsons/Civ V - Vanilla/Buildings.json +++ b/android/assets/jsons/Civ V - Vanilla/Buildings.json @@ -954,7 +954,7 @@ "isWonder": true, "uniques": ["[+1 Happiness, +2 Culture, +3 Gold] from every [Castle]", "Must have an owned [Mountain] within [2] tiles"], - "requiredTech": "Railroad", + "requiredTech": "Railroads", "quote": "'...the location is one of the most beautiful to be found, holy and unapproachable, a worthy temple for the divine friend who has brought salvation and true blessing to the world.' - King Ludwig II of Bavaria" }, // Column 12 diff --git a/android/assets/jsons/Civ V - Vanilla/Techs.json b/android/assets/jsons/Civ V - Vanilla/Techs.json index f23babc801..978991054a 100644 --- a/android/assets/jsons/Civ V - Vanilla/Techs.json +++ b/android/assets/jsons/Civ V - Vanilla/Techs.json @@ -446,7 +446,7 @@ "quote": "'Aeronautics was neither an industry nor a science. It was a miracle.' - Igor Sikorsky" }, { - "name": "Railroad", + "name": "Railroads", "row": 8, "prerequisites": ["Steam Power","Dynamite"], "quote": "'The introduction of so powerful an agent as steam to a carriage on wheels will make a great change in the situation of man.' - Thomas Jefferson" @@ -481,7 +481,7 @@ { "name": "Combustion", "row": 8, - "prerequisites": ["Railroad"], + "prerequisites": ["Railroads"], "quote": "'Any man who can drive safely while kissing a pretty girl is simply not giving the kiss the attention it deserves.' - Albert Einstein" } ] diff --git a/android/assets/jsons/Civ V - Vanilla/TileImprovements.json b/android/assets/jsons/Civ V - Vanilla/TileImprovements.json index 74ef97ee31..f0aa75e63b 100644 --- a/android/assets/jsons/Civ V - Vanilla/TileImprovements.json +++ b/android/assets/jsons/Civ V - Vanilla/TileImprovements.json @@ -110,7 +110,7 @@ { "name": "Railroad", "turnsToBuild": 4, - "techRequired": "Railroad", + "techRequired": "Railroads", "uniques": ["Can be built outside your borders", "Costs [2] gold per turn when in your territory"], "shortcutKey": "R", "civilopediaText": [{text:"Reduces movement cost to ⅒ if the other tile also has a Railroad"}] diff --git a/android/assets/jsons/translations/German.properties b/android/assets/jsons/translations/German.properties index 7b19278c77..abecbf61c5 100644 --- a/android/assets/jsons/translations/German.properties +++ b/android/assets/jsons/translations/German.properties @@ -3496,7 +3496,7 @@ Replaceable Parts = Ersetzbare Teile 'Nothing is particularly hard if you divide it into small jobs.' - Henry Ford = 'Keine Aufgabe ist wirklich schwierig, solange man sie in einzelne Schritte aufteilt.' - Henry Ford Flight = Flug 'Aeronautics was neither an industry nor a science. It was a miracle.' - Igor Sikorsky = 'Die Luftfahrt war weder eine Industrie noch eine Wissenschaft. Es war ein Wunder.' - Igor Sikorsky -Railroad = Eisenbahn +Railroads = Eisenbahn 'The introduction of so powerful an agent as steam to a carriage on wheels will make a great change in the situation of man.' - Thomas Jefferson = 'Die Einführung eines so mächtigen Mittels wie Dampf in einen Wagen auf Rädern wird die Situation des Menschen stark verändern.' - Thomas Jefferson Plastics = Plastik @@ -3659,6 +3659,7 @@ Fort = Festung Costs [amount] gold per turn when in your territory = Kostet [amount] Gold pro Runde innerhalb des eigenen Territoriums Road = Straße +Railroad = Schienen Remove Forest = Wald abholzen diff --git a/core/src/com/unciv/logic/GameInfo.kt b/core/src/com/unciv/logic/GameInfo.kt index af23849fdf..5243f824dc 100644 --- a/core/src/com/unciv/logic/GameInfo.kt +++ b/core/src/com/unciv/logic/GameInfo.kt @@ -248,7 +248,7 @@ class GameInfo { /** * [CivilizationInfo.addNotification][Add a notification] to every civilization that have - * adopted Honor policy and have explored the [tile] where the Barbarian Encampent has spawned. + * adopted Honor policy and have explored the [tile] where the Barbarian Encampment has spawned. */ fun notifyCivsOfBarbarianEncampment(tile: TileInfo) { civilizations.filter { @@ -273,6 +273,14 @@ class GameInfo { throw UncivShowableException("Missing mods: [$missingMods]") } + // compatibility code translating changed tech name "Railroad" - to be deprecated soon + val (oldTechName, newTechName) = "Railroad" to "Railroads" + if (ruleSet.technologies[oldTechName] == null && ruleSet.technologies[newTechName] != null) { + civilizations.forEach { + it.tech.replaceUpdatedTechName(oldTechName, newTechName) + } + } + removeMissingModReferences() tileMap.setTransients(ruleSet) @@ -391,6 +399,7 @@ class GameInfo { * This function can be used for backwards compatibility with older save files when a building * name is changed. */ + @Suppress("unused") // it's OK if there's no deprecation currently needing this private fun changeBuildingNameIfNotInRuleset(cityConstructions: CityConstructions, oldBuildingName: String, newBuildingName: String) { if (ruleSet.buildings.containsKey(oldBuildingName)) return @@ -411,7 +420,24 @@ class GameInfo { cityConstructions.inProgressConstructions.remove(oldBuildingName) } } - + + /** Replace a changed tech name, only temporarily used for breaking ruleset updates */ + private fun TechManager.replaceUpdatedTechName(oldTechName: String, newTechName: String) { + if (oldTechName in techsResearched) { + techsResearched.remove(oldTechName) + techsResearched.add(newTechName) + } + val index = techsToResearch.indexOf(oldTechName) + if (index >= 0) { + techsToResearch[index] = newTechName + } + if (oldTechName in techsInProgress) { + techsInProgress[newTechName] = researchOfTech(oldTechName) + techsInProgress.remove(oldTechName) + } + } + + fun hasReligionEnabled() = gameParameters.religionEnabled || ruleSet.hasReligion() // Temporary function to check whether religion should be used for this game } diff --git a/core/src/com/unciv/logic/city/CityInfo.kt b/core/src/com/unciv/logic/city/CityInfo.kt index 48757cb88d..3e388f60d6 100644 --- a/core/src/com/unciv/logic/city/CityInfo.kt +++ b/core/src/com/unciv/logic/city/CityInfo.kt @@ -498,11 +498,11 @@ class CityInfo { internal fun tryUpdateRoadStatus() { if (getCenterTile().roadStatus == RoadStatus.None) { - val roadImprovement = getRuleset().tileImprovements["Road"] + val roadImprovement = RoadStatus.Road.improvement(getRuleset()) if (roadImprovement != null && roadImprovement.techRequired in civInfo.tech.techsResearched) getCenterTile().roadStatus = RoadStatus.Road } else if (getCenterTile().roadStatus != RoadStatus.Railroad) { - val railroadImprovement = getRuleset().tileImprovements["Railroad"] + val railroadImprovement = RoadStatus.Railroad.improvement(getRuleset()) if (railroadImprovement != null && railroadImprovement.techRequired in civInfo.tech.techsResearched) getCenterTile().roadStatus = RoadStatus.Railroad } diff --git a/core/src/com/unciv/logic/city/CityStats.kt b/core/src/com/unciv/logic/city/CityStats.kt index 1a006e71e2..1fdbedec00 100644 --- a/core/src/com/unciv/logic/city/CityStats.kt +++ b/core/src/com/unciv/logic/city/CityStats.kt @@ -77,12 +77,12 @@ class CityStats { private fun getStatPercentBonusesFromRailroad(): Stats { val stats = Stats() - val railroadImprovement = cityInfo.getRuleset().tileImprovements["Railroad"] - if (railroadImprovement == null) return stats // for mods - val techEnablingRailroad = railroadImprovement.techRequired!! + val railroadImprovement = RoadStatus.Railroad.improvement(cityInfo.getRuleset()) + ?: return stats // for mods + val techEnablingRailroad = railroadImprovement.techRequired // If we conquered enemy cities connected by railroad, but we don't yet have that tech, - // we shouldn't get bonuses, it's as if the tracks aare layed out but we can't operate them. - if (cityInfo.civInfo.tech.isResearched(techEnablingRailroad) + // we shouldn't get bonuses, it's as if the tracks are laid out but we can't operate them. + if ( (techEnablingRailroad == null || cityInfo.civInfo.tech.isResearched(techEnablingRailroad)) && (cityInfo.isCapital() || isConnectedToCapital(RoadStatus.Railroad))) stats.production += 25f return stats @@ -364,8 +364,12 @@ class CityStats { if (cityInfo.civInfo.cities.count() < 2) return false// first city! // Railroad, or harbor from railroad - if (roadType == RoadStatus.Railroad) return cityInfo.isConnectedToCapital { it.any { it.contains("Railroad") } } - else return cityInfo.isConnectedToCapital() + return if (roadType == RoadStatus.Railroad) + cityInfo.isConnectedToCapital { + roadTypes -> + roadTypes.any { it.contains(RoadStatus.Railroad.name) } + } + else cityInfo.isConnectedToCapital() } //endregion @@ -398,7 +402,7 @@ class CityStats { newStatPercentBonusList["Buildings"] = getStatPercentBonusesFromUniques(currentConstruction, localBuildingUniques) .plus(cityInfo.cityConstructions.getStatPercentBonuses()) // This function is to be deprecated but it'll take a while. newStatPercentBonusList["Wonders"] = getStatPercentBonusesFromUniques(currentConstruction, cityInfo.civInfo.getCivWideBuildingUniques()) - newStatPercentBonusList["Railroad"] = getStatPercentBonusesFromRailroad() + newStatPercentBonusList["Railroads"] = getStatPercentBonusesFromRailroad() // Name chosen same as tech, for translation, but theoretically independent newStatPercentBonusList["Resources"] = getStatPercentBonusesFromResources(currentConstruction) newStatPercentBonusList["National ability"] = getStatPercentBonusesFromNationUnique(currentConstruction) newStatPercentBonusList["Puppet City"] = getStatPercentBonusesFromPuppetCity() diff --git a/core/src/com/unciv/logic/civilization/CapitalConnectionsFinder.kt b/core/src/com/unciv/logic/civilization/CapitalConnectionsFinder.kt index 602352f716..506474d81c 100644 --- a/core/src/com/unciv/logic/civilization/CapitalConnectionsFinder.kt +++ b/core/src/com/unciv/logic/civilization/CapitalConnectionsFinder.kt @@ -13,13 +13,14 @@ class CapitalConnectionsFinder(private val civInfo: CivilizationInfo) { private val allCivCities = civInfo.gameInfo.getCities() + private val harbor = "Harbor" // hardcoding at least centralized for this class for now private val road = RoadStatus.Road.name private val railroad = RoadStatus.Railroad.name - private val harborFromRoad = "Harbor-Road" - private val harborFromRailroad = "Harbor-Railroad" + private val harborFromRoad = "$harbor-$road" + private val harborFromRailroad = "$harbor-$railroad" private val ruleset = civInfo.gameInfo.ruleSet - private val theWheelIsResearched = ruleset.tileImprovements.containsKey(road) && civInfo.tech.isResearched(ruleset.tileImprovements[road]!!.techRequired!!) + private val roadIsResearched = ruleset.tileImprovements.containsKey(road) && civInfo.tech.isResearched(ruleset.tileImprovements[road]!!.techRequired!!) private val railroadIsResearched = ruleset.tileImprovements.containsKey(railroad) && civInfo.tech.isResearched(ruleset.tileImprovements[railroad]!!.techRequired!!) init { @@ -42,7 +43,7 @@ class CapitalConnectionsFinder(private val civInfo: CivilizationInfo) { if(mediumsReached.contains("Start") || mediumsReached.contains(railroad) || mediumsReached.contains(harborFromRailroad)) checkRailroad(cityToConnectFrom) // This is only relevant for city connection if there is an unbreaking line from the capital } - if (theWheelIsResearched) { + if (roadIsResearched) { checkRoad(cityToConnectFrom) } } @@ -71,7 +72,7 @@ class CapitalConnectionsFinder(private val civInfo: CivilizationInfo) { private fun checkHarbor(cityToConnectFrom: CityInfo) { check( cityToConnectFrom, - transportType = if(cityToConnectFrom.wasPreviouslyReached("Railroad",null)) harborFromRailroad else harborFromRoad, + transportType = if(cityToConnectFrom.wasPreviouslyReached(railroad,null)) harborFromRailroad else harborFromRoad, overridingTransportType = harborFromRailroad, tileFilter = { tile -> tile.isWater || tile.isCityCenter() }, cityFilter = { city -> city.containsHarbor() } @@ -79,7 +80,7 @@ class CapitalConnectionsFinder(private val civInfo: CivilizationInfo) { } private fun CityInfo.containsHarbor() = - this.cityConstructions.containsBuildingOrEquivalent("Harbor") + this.cityConstructions.containsBuildingOrEquivalent(harbor) private fun check(cityToConnectFrom: CityInfo, transportType: String, diff --git a/core/src/com/unciv/logic/civilization/CivInfoStats.kt b/core/src/com/unciv/logic/civilization/CivInfoStats.kt index 7b2d34a41b..ca4d12b480 100644 --- a/core/src/com/unciv/logic/civilization/CivInfoStats.kt +++ b/core/src/com/unciv/logic/civilization/CivInfoStats.kt @@ -1,7 +1,6 @@ package com.unciv.logic.civilization 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.tile.ResourceType import com.unciv.models.stats.Stat @@ -65,13 +64,7 @@ class CivInfoStats(val civInfo: CivilizationInfo) { if (tile.isCityCenter()) continue if (ignoredTileTypes.any { tile.matchesFilter(it, civInfo) }) continue - val tileUpkeep = - when (tile.roadStatus) { - RoadStatus.Road -> 1 - RoadStatus.Railroad -> 2 - RoadStatus.None -> 0 - } - transportationUpkeep += tileUpkeep + transportationUpkeep += tile.roadStatus.upkeep } } for (unique in civInfo.getMatchingUniques("Maintenance on roads & railroads reduced by []%")) @@ -158,8 +151,10 @@ class CivInfoStats(val civInfo: CivilizationInfo) { .map { it.params[0].toFloat() / 100f }.sum() val luxuriesProvidedByCityStates = - civInfo.getKnownCivs().filter { it.isCityState() && it.getAllyCiv() == civInfo.civName } - .map { it.getCivResources().map { res -> res.resource } }.flatten().distinct().count { it.resourceType === ResourceType.Luxury } + civInfo.getKnownCivs().asSequence() + .filter { it.isCityState() && it.getAllyCiv() == civInfo.civName } + .map { it.getCivResources().map { res -> res.resource } } + .flatten().distinct().count { it.resourceType === ResourceType.Luxury } statMap["City-State Luxuries"] = happinessBonusForCityStateProvidedLuxuries * luxuriesProvidedByCityStates * happinessPerUniqueLuxury diff --git a/core/src/com/unciv/logic/civilization/TechManager.kt b/core/src/com/unciv/logic/civilization/TechManager.kt index c307c47295..415e70c15c 100644 --- a/core/src/com/unciv/logic/civilization/TechManager.kt +++ b/core/src/com/unciv/logic/civilization/TechManager.kt @@ -35,7 +35,7 @@ class TechManager { // UnitMovementAlgorithms.getMovementCostBetweenAdjacentTiles is a close second =) @Transient - var movementSpeedOnRoadsImproved = false + var movementSpeedOnRoads = 1f @Transient var roadsConnectAcrossRivers = false @@ -50,8 +50,7 @@ class TechManager { /** When moving towards a certain tech, the user doesn't have to manually pick every one. */ var techsToResearch = ArrayList() var overflowScience = 0 - private var techsInProgress = HashMap() - fun scienceSpentOnTech(tech: String): Int = if (tech in techsInProgress) techsInProgress[tech]!! else 0 + var techsInProgress = HashMap() /** In civ IV, you can auto-convert a certain percentage of gold in cities to science */ var goldPercentConvertedToScience = 0.6f @@ -109,10 +108,9 @@ class TechManager { return if (techsToResearch.isEmpty()) null else techsToResearch[0] } - private fun researchOfTech(TechName: String?): Int { - return if (techsInProgress.containsKey(TechName)) techsInProgress[TechName]!! else 0 - } - + fun researchOfTech(TechName: String?) = techsInProgress[TechName] ?: 0 + // Was once duplicated as fun scienceSpentOnTech(tech: String): Int + fun remainingScienceToTech(techName: String) = costOfTech(techName) - researchOfTech(techName) fun turnsToTech(techName: String): String { @@ -302,7 +300,7 @@ class TechManager { val text = "[${cities.size}] cities changed production from [$unit] to [${construction.upgradesTo!!}]" civInfo.addNotification(text, locationAction, unit, NotificationIcon.Construction, construction.upgradesTo!!) } else { - val text = "[$unit] has become osbolete and was removed from the queue in [${cities.size}] cities!" + val text = "[$unit] has become obsolete and was removed from the queue in [${cities.size}] cities!" civInfo.addNotification(text, locationAction, NotificationIcon.Construction) } } @@ -365,7 +363,8 @@ class TechManager { unitsCanEmbark = wayfinding || civInfo.hasUnique("Enables embarkation for land units") embarkedUnitsCanEnterOcean = wayfinding || civInfo.hasUnique("Enables embarked units to enter ocean tiles") - movementSpeedOnRoadsImproved = civInfo.hasUnique("Improves movement speed on roads") + movementSpeedOnRoads = if (civInfo.hasUnique("Improves movement speed on roads")) + RoadStatus.Road.movementImproved else RoadStatus.Road.movement roadsConnectAcrossRivers = civInfo.hasUnique("Roads connect tiles across rivers") } diff --git a/core/src/com/unciv/logic/map/MapUnit.kt b/core/src/com/unciv/logic/map/MapUnit.kt index e728650277..3929ef45d0 100644 --- a/core/src/com/unciv/logic/map/MapUnit.kt +++ b/core/src/com/unciv/logic/map/MapUnit.kt @@ -14,7 +14,6 @@ import com.unciv.models.ruleset.tile.TileImprovement import com.unciv.models.ruleset.unit.BaseUnit import com.unciv.models.ruleset.unit.UnitType import java.text.DecimalFormat -import kotlin.math.pow import kotlin.random.Random /** @@ -275,7 +274,7 @@ class MapUnit { && canBuildImprovement(getTile().getTileImprovementInProgress()!!)) return false // unique "Can construct roads" deprecated since 3.15.5 - if (hasUnique("Can construct roads") && currentTile.improvementInProgress == "Road") return false + if (hasUnique("Can construct roads") && currentTile.improvementInProgress == RoadStatus.Road.name) return false // if (isFortified()) return false if (action == Constants.unitActionExplore || isSleeping() @@ -459,6 +458,7 @@ class MapUnit { if (civInfo.isCurrentPlayer()) UncivGame.Current.settings.addCompletedTutorialTask("Construct an improvement") + when { tile.improvementInProgress!!.startsWith("Remove ") -> { val removedFeatureName = tile.improvementInProgress!!.removePrefix("Remove ") @@ -473,9 +473,9 @@ class MapUnit { tile.improvement = null if (tile.resource != null) civInfo.updateDetailedCivResources() // unlikely, but maybe a mod makes a resource improvement dependent on a terrain feature } - if (tile.improvementInProgress == "Remove Road" || tile.improvementInProgress == "Remove Railroad") { + if (RoadStatus.values().any { tile.improvementInProgress == it.removeAction }) tile.roadStatus = RoadStatus.None - } else { + else { val removedFeatureObject = tile.ruleset.terrains[removedFeatureName] if (removedFeatureObject != null && removedFeatureObject.uniques .contains("Provides a one-time Production bonus to the closest city when cut down") @@ -485,8 +485,8 @@ class MapUnit { tile.terrainFeatures.remove(removedFeatureName) } } - tile.improvementInProgress == "Road" -> tile.roadStatus = RoadStatus.Road - tile.improvementInProgress == "Railroad" -> tile.roadStatus = RoadStatus.Railroad + tile.improvementInProgress == RoadStatus.Road.name -> tile.roadStatus = RoadStatus.Road + tile.improvementInProgress == RoadStatus.Railroad.name -> tile.roadStatus = RoadStatus.Railroad else -> { tile.improvement = tile.improvementInProgress if (tile.resource != null) civInfo.updateDetailedCivResources() diff --git a/core/src/com/unciv/logic/map/RoadStatus.kt b/core/src/com/unciv/logic/map/RoadStatus.kt index 37520a56d4..cddb0493ca 100644 --- a/core/src/com/unciv/logic/map/RoadStatus.kt +++ b/core/src/com/unciv/logic/map/RoadStatus.kt @@ -1,18 +1,23 @@ package com.unciv.logic.map -import com.unciv.logic.map.RoadStatus.Railroad -import com.unciv.logic.map.RoadStatus.Road import com.unciv.models.ruleset.Ruleset /** * You can use RoadStatus.name to identify [Road] and [Railroad] * in string-based identification, as done in [improvement]. + * + * Note: Order is important, [ordinal] _is_ compared - please interpret as "roadLevel". */ -enum class RoadStatus { +enum class RoadStatus( + val upkeep: Int = 0, + val movement: Float = 1f, + val movementImproved: Float = 1f, + val removeAction: String? = null +) { None, - Road, - Railroad; + Road (1, 0.5f, 1/3f, "Remove Road"), + Railroad (2, 0.1f, 0.1f, "Remove Railroad"); /** returns null for [None] */ fun improvement(ruleset: Ruleset) = ruleset.tileImprovements[this.name] diff --git a/core/src/com/unciv/logic/map/TileInfo.kt b/core/src/com/unciv/logic/map/TileInfo.kt index 3179427e61..cdc3dd390a 100644 --- a/core/src/com/unciv/logic/map/TileInfo.kt +++ b/core/src/com/unciv/logic/map/TileInfo.kt @@ -406,8 +406,7 @@ open class TileInfo { } -> false // Road improvements can change on tiles with irremovable improvements - nothing else can, though. - improvement.name != RoadStatus.Railroad.name && improvement.name != RoadStatus.Railroad.name - && improvement.name != "Remove Road" && improvement.name != "Remove Railroad" + RoadStatus.values().none { it.name == improvement.name || it.removeAction == improvement.name } && getTileImprovement().let { it != null && it.hasUnique("Irremovable") } -> false // Decide cancelImprovementOrder earlier, otherwise next check breaks it @@ -420,10 +419,8 @@ open class TileInfo { if (filter == "River") return@any !isAdjacentToRiver() else return@any !neighbors.any { neighbor -> neighbor.matchesFilter(filter) } } -> false - improvement.name == "Road" && roadStatus == RoadStatus.None && !isWater -> true - improvement.name == "Railroad" && this.roadStatus != RoadStatus.Railroad && !isWater -> true - improvement.name == "Remove Road" && this.roadStatus == RoadStatus.Road -> true - improvement.name == "Remove Railroad" && this.roadStatus == RoadStatus.Railroad -> true + !isWater && RoadStatus.values().any { it.name == improvement.name && it > roadStatus } -> true + improvement.name == roadStatus.removeAction -> true topTerrain.unbuildable && !improvement.isAllowedOnFeature(topTerrain.name) -> false // DO NOT reverse this &&. isAdjacentToFreshwater() is a lazy which calls a function, and reversing it breaks the tests. improvement.hasUnique("Can also be built on tiles adjacent to fresh water") && isAdjacentToFreshwater -> true diff --git a/core/src/com/unciv/logic/map/UnitMovementAlgorithms.kt b/core/src/com/unciv/logic/map/UnitMovementAlgorithms.kt index ac76f4b02e..0022155c43 100644 --- a/core/src/com/unciv/logic/map/UnitMovementAlgorithms.kt +++ b/core/src/com/unciv/logic/map/UnitMovementAlgorithms.kt @@ -25,16 +25,14 @@ class UnitMovementAlgorithms(val unit:MapUnit) { extraCost += 1 if (from.roadStatus == RoadStatus.Railroad && to.roadStatus == RoadStatus.Railroad) - return 1 / 10f + extraCost + return RoadStatus.Railroad.movement + extraCost val areConnectedByRoad = from.hasConnection(civInfo) && to.hasConnection(civInfo) val areConnectedByRiver = from.isConnectedByRiver(to) if (areConnectedByRoad && (!areConnectedByRiver || civInfo.tech.roadsConnectAcrossRivers)) - { - if (unit.civInfo.tech.movementSpeedOnRoadsImproved) return 1 / 3f + extraCost - else return 1 / 2f + extraCost - } + return unit.civInfo.tech.movementSpeedOnRoads + extraCost + if (unit.ignoresTerrainCost) return 1f + extraCost if (areConnectedByRiver) return 100f // Rivers take the entire turn to cross diff --git a/core/src/com/unciv/models/ruleset/tile/TileImprovement.kt b/core/src/com/unciv/models/ruleset/tile/TileImprovement.kt index c97b8e3b17..57586ac71d 100644 --- a/core/src/com/unciv/models/ruleset/tile/TileImprovement.kt +++ b/core/src/com/unciv/models/ruleset/tile/TileImprovement.kt @@ -1,6 +1,7 @@ package com.unciv.models.ruleset.tile import com.unciv.logic.civilization.CivilizationInfo +import com.unciv.logic.map.RoadStatus import com.unciv.models.ruleset.Ruleset import com.unciv.models.ruleset.Unique import com.unciv.models.stats.NamedStats @@ -72,6 +73,7 @@ class TileImprovement : NamedStats(), ICivilopediaText { fun hasUnique(unique: String) = uniques.contains(unique) fun isGreatImprovement() = hasUnique("Great Improvement") + fun isRoad() = RoadStatus.values().any { it != RoadStatus.None && it.name == this.name } /** * Check: Is this improvement allowed on a [given][name] terrain feature? @@ -93,7 +95,7 @@ class TileImprovement : NamedStats(), ICivilopediaText { return when (filter) { name -> true "All" -> true - "All Road" -> name == "road" || name == "railroad" + "All Road" -> isRoad() "Great Improvement", "Great" -> isGreatImprovement() else -> false } diff --git a/core/src/com/unciv/ui/mapeditor/MapEditorOptionsTable.kt b/core/src/com/unciv/ui/mapeditor/MapEditorOptionsTable.kt index f63a2e4697..a6da51d6f3 100644 --- a/core/src/com/unciv/ui/mapeditor/MapEditorOptionsTable.kt +++ b/core/src/com/unciv/ui/mapeditor/MapEditorOptionsTable.kt @@ -141,8 +141,8 @@ class MapEditorOptionsTable(val mapEditorScreen: MapEditorScreen): Table(CameraS improvementImage.onClick { tileAction = { when (improvement.name) { - "Road" -> it.roadStatus = RoadStatus.Road - "Railroad" -> it.roadStatus = RoadStatus.Railroad + RoadStatus.Road.name -> it.roadStatus = RoadStatus.Road + RoadStatus.Railroad.name -> it.roadStatus = RoadStatus.Railroad else -> it.improvement = improvement.name } } diff --git a/core/src/com/unciv/ui/pickerscreens/TechPickerScreen.kt b/core/src/com/unciv/ui/pickerscreens/TechPickerScreen.kt index 1a7a3b1ad0..264198876f 100644 --- a/core/src/com/unciv/ui/pickerscreens/TechPickerScreen.kt +++ b/core/src/com/unciv/ui/pickerscreens/TechPickerScreen.kt @@ -264,7 +264,7 @@ class TechPickerScreen(internal val civInfo: CivilizationInfo, centerOnTech: Tec } private fun getTechProgressLabel(techs: List): String { - val progress = techs.sumBy { tech -> civTech.scienceSpentOnTech(tech) } + val progress = techs.sumBy { tech -> civTech.researchOfTech(tech) } val techCost = techs.sumBy { tech -> civInfo.tech.costOfTech(tech) } return "(${progress}/${techCost})" } diff --git a/core/src/com/unciv/ui/worldscreen/unit/UnitActions.kt b/core/src/com/unciv/ui/worldscreen/unit/UnitActions.kt index b59556a313..bc68013ec6 100644 --- a/core/src/com/unciv/ui/worldscreen/unit/UnitActions.kt +++ b/core/src/com/unciv/ui/worldscreen/unit/UnitActions.kt @@ -56,7 +56,6 @@ object UnitActions { addSpreadReligionActions(unit, actionList, tile) - addToggleActionsAction(unit, actionList, unitTable) return actionList @@ -76,7 +75,6 @@ object UnitActions { addGiftAction(unit, actionList, tile) - addToggleActionsAction(unit, actionList, unitTable) return actionList diff --git a/core/src/com/unciv/ui/worldscreen/unit/UnitActionsTable.kt b/core/src/com/unciv/ui/worldscreen/unit/UnitActionsTable.kt index 65611f0fe9..2436ed2a85 100644 --- a/core/src/com/unciv/ui/worldscreen/unit/UnitActionsTable.kt +++ b/core/src/com/unciv/ui/worldscreen/unit/UnitActionsTable.kt @@ -8,6 +8,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table import com.unciv.Constants import com.unciv.UncivGame import com.unciv.logic.map.MapUnit +import com.unciv.logic.map.RoadStatus import com.unciv.models.UnitAction import com.unciv.models.translations.equalsPlaceholderText import com.unciv.models.translations.getPlaceholderParameters @@ -60,7 +61,9 @@ class UnitActionsTable(val worldScreen: WorldScreen) : Table() { "Start Golden Age" -> return UnitIconAndKey(ImageGetter.getUnitIcon("Great Artist"), 'g') "Hurry Wonder" -> return UnitIconAndKey(ImageGetter.getUnitIcon("Great Engineer"), 'g') "Conduct Trade Mission" -> return UnitIconAndKey(ImageGetter.getUnitIcon("Great Merchant"), 'g') - "Construct road" -> return UnitIconAndKey(ImageGetter.getImprovementIcon("Road"), 'r') + // Deprecated since 3.15.4 + "Construct road" -> return UnitIconAndKey(ImageGetter.getImprovementIcon(RoadStatus.Road.name), 'r') + // "Paradrop" -> return UnitIconAndKey(ImageGetter.getUnitIcon("Paratrooper"), 'p') "Set up" -> return UnitIconAndKey(ImageGetter.getUnitIcon("Catapult"), 't') "Explore" -> return UnitIconAndKey(ImageGetter.getUnitIcon("Scout"), 'x')