mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-09 23:39:40 +07:00
Game can deal gracefully wth mods removing certain units and technologies
This commit is contained in:
@ -262,35 +262,7 @@ class GameInfo {
|
|||||||
throw UncivShowableException("Missing mods: [$missingMods]")
|
throw UncivShowableException("Missing mods: [$missingMods]")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mods can change, leading to things on the map that are no longer defined in the mod.
|
removeMissingModReferences()
|
||||||
// So we remove them so the game doesn't crash when it tries to access them.
|
|
||||||
for (tile in tileMap.values) {
|
|
||||||
if (tile.resource != null && !ruleSet.tileResources.containsKey(tile.resource!!))
|
|
||||||
tile.resource = null
|
|
||||||
if (tile.improvement != null && !ruleSet.tileImprovements.containsKey(tile.improvement!!)
|
|
||||||
&& !tile.improvement!!.startsWith("StartingLocation ")) // To not remove the starting locations in GameStarter.startNewGame()
|
|
||||||
tile.improvement = null
|
|
||||||
|
|
||||||
for (unit in tile.getUnits())
|
|
||||||
for (promotion in unit.promotions.promotions.toList())
|
|
||||||
if (!ruleSet.unitPromotions.containsKey(promotion))
|
|
||||||
unit.promotions.promotions.remove(promotion)
|
|
||||||
|
|
||||||
for (city in civilizations.asSequence().flatMap { it.cities.asSequence() }) {
|
|
||||||
for (building in city.cityConstructions.builtBuildings.toHashSet())
|
|
||||||
if (!ruleSet.buildings.containsKey(building))
|
|
||||||
city.cityConstructions.builtBuildings.remove(building)
|
|
||||||
|
|
||||||
// Remove invalid buildings or units from the queue - don't just check buildings and units because it might be a special construction as well
|
|
||||||
for (construction in city.cityConstructions.constructionQueue.toList()) {
|
|
||||||
if (!ruleSet.buildings.containsKey(construction) && !ruleSet.units.containsKey(construction)
|
|
||||||
&& !PerpetualConstruction.perpetualConstructionsMap.containsKey(construction))
|
|
||||||
city.cityConstructions.constructionQueue.remove(construction)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
tileMap.setTransients(ruleSet)
|
tileMap.setTransients(ruleSet)
|
||||||
|
|
||||||
@ -347,6 +319,46 @@ class GameInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Mods can change, leading to things on the map that are no longer defined in the mod.
|
||||||
|
// So we remove them so the game doesn't crash when it tries to access them.
|
||||||
|
private fun removeMissingModReferences() {
|
||||||
|
for (tile in tileMap.values) {
|
||||||
|
if (tile.resource != null && !ruleSet.tileResources.containsKey(tile.resource!!))
|
||||||
|
tile.resource = null
|
||||||
|
if (tile.improvement != null && !ruleSet.tileImprovements.containsKey(tile.improvement!!)
|
||||||
|
&& !tile.improvement!!.startsWith("StartingLocation ")) // To not remove the starting locations in GameStarter.startNewGame()
|
||||||
|
tile.improvement = null
|
||||||
|
|
||||||
|
for (unit in tile.getUnits()) {
|
||||||
|
if (!ruleSet.units.containsKey(unit.name)) tile.removeUnit(unit)
|
||||||
|
|
||||||
|
for (promotion in unit.promotions.promotions.toList())
|
||||||
|
if (!ruleSet.unitPromotions.containsKey(promotion))
|
||||||
|
unit.promotions.promotions.remove(promotion)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for (city in civilizations.asSequence().flatMap { it.cities.asSequence() }) {
|
||||||
|
for (building in city.cityConstructions.builtBuildings.toHashSet())
|
||||||
|
if (!ruleSet.buildings.containsKey(building))
|
||||||
|
city.cityConstructions.builtBuildings.remove(building)
|
||||||
|
|
||||||
|
// Remove invalid buildings or units from the queue - don't just check buildings and units because it might be a special construction as well
|
||||||
|
for (construction in city.cityConstructions.constructionQueue.toList()) {
|
||||||
|
if (!ruleSet.buildings.containsKey(construction) && !ruleSet.units.containsKey(construction)
|
||||||
|
&& !PerpetualConstruction.perpetualConstructionsMap.containsKey(construction))
|
||||||
|
city.cityConstructions.constructionQueue.remove(construction)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (civinfo in civilizations) {
|
||||||
|
for (tech in civinfo.tech.techsResearched.toList())
|
||||||
|
if (!ruleSet.technologies.containsKey(tech))
|
||||||
|
civinfo.tech.techsResearched.remove(tech)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun changeBuildingName(cityConstructions: CityConstructions, oldBuildingName: String, newBuildingName: String) {
|
private fun changeBuildingName(cityConstructions: CityConstructions, oldBuildingName: String, newBuildingName: String) {
|
||||||
if (cityConstructions.builtBuildings.contains(oldBuildingName)) {
|
if (cityConstructions.builtBuildings.contains(oldBuildingName)) {
|
||||||
cityConstructions.builtBuildings.remove(oldBuildingName)
|
cityConstructions.builtBuildings.remove(oldBuildingName)
|
||||||
|
@ -18,6 +18,7 @@ import kotlin.math.min
|
|||||||
class TechManager {
|
class TechManager {
|
||||||
@Transient
|
@Transient
|
||||||
lateinit var civInfo: CivilizationInfo
|
lateinit var civInfo: CivilizationInfo
|
||||||
|
/** This is the Transient list of Technologies */
|
||||||
@Transient
|
@Transient
|
||||||
var researchedTechnologies = ArrayList<Technology>()
|
var researchedTechnologies = ArrayList<Technology>()
|
||||||
@Transient
|
@Transient
|
||||||
@ -42,6 +43,7 @@ class TechManager {
|
|||||||
/** For calculating Great Scientist yields - see https://civilization.fandom.com/wiki/Great_Scientist_(Civ5) */
|
/** For calculating Great Scientist yields - see https://civilization.fandom.com/wiki/Great_Scientist_(Civ5) */
|
||||||
var scienceOfLast8Turns = IntArray(8) { 0 }
|
var scienceOfLast8Turns = IntArray(8) { 0 }
|
||||||
var scienceFromResearchAgreements = 0
|
var scienceFromResearchAgreements = 0
|
||||||
|
/** This is the lit of strings, which is serialized */
|
||||||
var techsResearched = HashSet<String>()
|
var techsResearched = HashSet<String>()
|
||||||
|
|
||||||
/** When moving towards a certain tech, the user doesn't have to manually pick every one. */
|
/** When moving towards a certain tech, the user doesn't have to manually pick every one. */
|
||||||
|
@ -495,13 +495,7 @@ class MapUnit {
|
|||||||
.forEach { unit -> unit.destroy() }
|
.forEach { unit -> unit.destroy() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun removeFromTile() {
|
fun removeFromTile() = currentTile.removeUnit(this)
|
||||||
when {
|
|
||||||
type.isAirUnit() -> currentTile.airUnits.remove(this)
|
|
||||||
type.isCivilian() -> getTile().civilianUnit = null
|
|
||||||
else -> getTile().militaryUnit = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun moveThroughTile(tile: TileInfo) {
|
fun moveThroughTile(tile: TileInfo) {
|
||||||
if (tile.improvement == Constants.ancientRuins && civInfo.isMajorCiv())
|
if (tile.improvement == Constants.ancientRuins && civInfo.isMajorCiv())
|
||||||
|
@ -483,7 +483,19 @@ open class TileInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun stripUnits() {
|
fun stripUnits() {
|
||||||
for (unit in this.getUnits()) unit.removeFromTile()
|
for (unit in this.getUnits()) removeUnit(unit)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** If the unit isn't in the ruleset we can't even know what type of unit this is! So check each place
|
||||||
|
* This works with no transients so can be called from gameInfo.setTransients with no fear
|
||||||
|
*/
|
||||||
|
fun removeUnit(mapUnit: MapUnit){
|
||||||
|
when {
|
||||||
|
airUnits.contains(mapUnit) -> airUnits.remove(mapUnit)
|
||||||
|
civilianUnit == mapUnit -> civilianUnit = null
|
||||||
|
else -> militaryUnit = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun startWorkingOnImprovement(improvement: TileImprovement, civInfo: CivilizationInfo) {
|
fun startWorkingOnImprovement(improvement: TileImprovement, civInfo: CivilizationInfo) {
|
||||||
|
Reference in New Issue
Block a user