From 35c3f7b191fd459f5b74395f0ad9d2001d8aabd0 Mon Sep 17 00:00:00 2001 From: SomeTroglodyte <63000004+SomeTroglodyte@users.noreply.github.com> Date: Tue, 9 Apr 2024 22:12:07 +0200 Subject: [PATCH] Fix "Connect road" going through Mountains (#11428) * Cache Road/Railroad improvement objects * Fix connect roads planning paths through mountains --- core/src/com/unciv/logic/city/City.kt | 4 ++-- core/src/com/unciv/logic/city/CityStats.kt | 2 +- .../logic/civilization/managers/TechManager.kt | 8 ++++---- core/src/com/unciv/logic/map/MapPathing.kt | 11 ++++------- core/src/com/unciv/models/ruleset/Ruleset.kt | 13 +++++++++++-- .../unciv/ui/screens/worldscreen/WorldMapHolder.kt | 8 +++----- 6 files changed, 25 insertions(+), 21 deletions(-) diff --git a/core/src/com/unciv/logic/city/City.kt b/core/src/com/unciv/logic/city/City.kt index ffb58fec11..f06d456afc 100644 --- a/core/src/com/unciv/logic/city/City.kt +++ b/core/src/com/unciv/logic/city/City.kt @@ -373,11 +373,11 @@ class City : IsPartOfGameInfoSerialization { internal fun tryUpdateRoadStatus() { if (getCenterTile().roadStatus == RoadStatus.None) { - val roadImprovement = RoadStatus.Road.improvement(getRuleset()) + val roadImprovement = getRuleset().roadImprovement if (roadImprovement != null && roadImprovement.techRequired in civ.tech.techsResearched) getCenterTile().roadStatus = RoadStatus.Road } else if (getCenterTile().roadStatus != RoadStatus.Railroad) { - val railroadImprovement = RoadStatus.Railroad.improvement(getRuleset()) + val railroadImprovement = getRuleset().railroadImprovement if (railroadImprovement != null && railroadImprovement.techRequired in civ.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 64a2da6e90..5ad1f498e0 100644 --- a/core/src/com/unciv/logic/city/CityStats.kt +++ b/core/src/com/unciv/logic/city/CityStats.kt @@ -131,7 +131,7 @@ class CityStats(val city: City) { private fun getStatPercentBonusesFromRailroad(): Stats { val stats = Stats() - val railroadImprovement = RoadStatus.Railroad.improvement(city.getRuleset()) + val railroadImprovement = city.getRuleset().railroadImprovement ?: return stats // for mods val techEnablingRailroad = railroadImprovement.techRequired // If we conquered enemy cities connected by railroad, but we don't yet have that tech, diff --git a/core/src/com/unciv/logic/civilization/managers/TechManager.kt b/core/src/com/unciv/logic/civilization/managers/TechManager.kt index 9f360b0e7c..1c093df282 100644 --- a/core/src/com/unciv/logic/civilization/managers/TechManager.kt +++ b/core/src/com/unciv/logic/civilization/managers/TechManager.kt @@ -525,12 +525,12 @@ class TechManager : IsPartOfGameInfoSerialization { } fun getBestRoadAvailable(): RoadStatus { - val railroadImprovement = RoadStatus.Railroad.improvement(getRuleset()) // May not exist in mods - if (railroadImprovement != null && (railroadImprovement.techRequired==null || isResearched(railroadImprovement.techRequired!!))) + val railroadImprovement = getRuleset().railroadImprovement // May not exist in mods + if (railroadImprovement != null && (railroadImprovement.techRequired == null || isResearched(railroadImprovement.techRequired!!))) return RoadStatus.Railroad - val roadImprovement = RoadStatus.Road.improvement(getRuleset()) - if (roadImprovement != null && (roadImprovement.techRequired==null || isResearched(roadImprovement.techRequired!!))) + val roadImprovement = getRuleset().roadImprovement + if (roadImprovement != null && (roadImprovement.techRequired == null || isResearched(roadImprovement.techRequired!!))) return RoadStatus.Road return RoadStatus.None diff --git a/core/src/com/unciv/logic/map/MapPathing.kt b/core/src/com/unciv/logic/map/MapPathing.kt index c0a5892bf3..24934b08da 100644 --- a/core/src/com/unciv/logic/map/MapPathing.kt +++ b/core/src/com/unciv/logic/map/MapPathing.kt @@ -3,7 +3,6 @@ package com.unciv.logic.map import com.unciv.logic.map.mapunit.MapUnit import com.unciv.logic.map.tile.RoadStatus import com.unciv.logic.map.tile.Tile -import com.unciv.models.ruleset.tile.TileImprovement import com.unciv.utils.Log //TODO: Eventually, all path generation in the game should be moved into here. @@ -34,12 +33,13 @@ object MapPathing { return 1f } - fun isValidRoadPathTile(unit: MapUnit, tile: Tile, roadImprovement: TileImprovement): Boolean { + fun isValidRoadPathTile(unit: MapUnit, tile: Tile): Boolean { + val roadImprovement = tile.ruleset.roadImprovement ?: return false return tile.isLand && !tile.isImpassible() && unit.civ.hasExplored(tile) && tile.canCivPassThrough(unit.civ) - && tile.hasRoadConnection(unit.civ, true) || tile.improvementFunctions.canBuildImprovement(roadImprovement, unit.civ) + && (tile.hasRoadConnection(unit.civ, true) || tile.improvementFunctions.canBuildImprovement(roadImprovement, unit.civ)) } /** @@ -53,11 +53,10 @@ object MapPathing { * @return A sequence of tiles representing the path from startTile to endTile, or null if no valid path is found. */ fun getRoadPath(unit: MapUnit, startTile: Tile, endTile: Tile): List?{ - val roadImprovement = RoadStatus.Road.improvement(startTile.ruleset) ?: return null return getPath(unit, startTile, endTile, - { unit, tile -> isValidRoadPathTile(unit, tile, roadImprovement) }, + ::isValidRoadPathTile, ::roadPreferredMovementCost, {_, _, _ -> 0f} ) @@ -106,5 +105,3 @@ object MapPathing { } } - - diff --git a/core/src/com/unciv/models/ruleset/Ruleset.kt b/core/src/com/unciv/models/ruleset/Ruleset.kt index 6d9d6b2f1b..a850187530 100644 --- a/core/src/com/unciv/models/ruleset/Ruleset.kt +++ b/core/src/com/unciv/models/ruleset/Ruleset.kt @@ -5,6 +5,7 @@ import com.unciv.Constants import com.unciv.json.fromJsonFile import com.unciv.json.json import com.unciv.logic.BackwardCompatibility.updateDeprecations +import com.unciv.logic.map.tile.RoadStatus import com.unciv.models.metadata.BaseRuleset import com.unciv.models.ruleset.nation.CityStateType import com.unciv.models.ruleset.nation.Difficulty @@ -48,6 +49,10 @@ class Ruleset { */ var name = "" + /** The list of mods that made up this Ruleset, including the base ruleset. */ + val mods = LinkedHashSet() + + //region Json fields val beliefs = LinkedHashMap() val buildings = LinkedHashMap() val difficulties = LinkedHashMap() @@ -73,7 +78,10 @@ class Ruleset { var cityStateTypes = LinkedHashMap() val personalities = LinkedHashMap() val events = LinkedHashMap() + var modOptions = ModOptions() + //endregion + //region cache fields val greatGeneralUnits by lazy { units.values.filter { it.hasUnique(UniqueType.GreatPersonFromCombat, StateForConditionals.IgnoreConditionals) } } @@ -97,8 +105,9 @@ class Ruleset { }.toSet() } - val mods = LinkedHashSet() - var modOptions = ModOptions() + val roadImprovement by lazy { RoadStatus.Road.improvement(this) } + val railroadImprovement by lazy { RoadStatus.Railroad.improvement(this) } + //endregion fun clone(): Ruleset { val newRuleset = Ruleset() diff --git a/core/src/com/unciv/ui/screens/worldscreen/WorldMapHolder.kt b/core/src/com/unciv/ui/screens/worldscreen/WorldMapHolder.kt index 8d99816a77..1ac4913228 100644 --- a/core/src/com/unciv/ui/screens/worldscreen/WorldMapHolder.kt +++ b/core/src/com/unciv/ui/screens/worldscreen/WorldMapHolder.kt @@ -26,7 +26,6 @@ import com.unciv.logic.map.MapPathing import com.unciv.logic.map.TileMap import com.unciv.logic.map.mapunit.MapUnit import com.unciv.logic.map.mapunit.movement.UnitMovement -import com.unciv.logic.map.tile.RoadStatus import com.unciv.logic.map.tile.Tile import com.unciv.models.UncivSound import com.unciv.models.UnitActionType @@ -731,10 +730,9 @@ class WorldMapHolder( // Z-Layer: 0 // Highlight suitable tiles in road connecting mode if (worldScreen.bottomUnitTable.selectedUnitIsConnectingRoad) { - val roadImprovement = RoadStatus.Road.improvement(unit.currentTile.ruleset) - val validTiles = if (roadImprovement==null) listOf() - else unit.civ.gameInfo.tileMap.tileList.filter { - MapPathing.isValidRoadPathTile(unit, it, roadImprovement) + if (unit.currentTile.ruleset.roadImprovement == null) return + val validTiles = unit.civ.gameInfo.tileMap.tileList.filter { + MapPathing.isValidRoadPathTile(unit, it) } val connectRoadTileOverlayColor = Color.RED for (tile in validTiles) {