Can now specify a mod as a 'base ruleset', and the regular base ruleset will not be added

This means that you can 'start from scratch' and build whatever you want - example "Scenario" in unciv-mod-example repo
Obviously we'll have to change around a lot of things or this to work well, but it's a start
This commit is contained in:
Yair Morgenstern 2020-04-17 14:42:15 +03:00
parent ffe8691df9
commit 4c48cfe4f3
3 changed files with 54 additions and 51 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 429 KiB

After

Width:  |  Height:  |  Size: 429 KiB

View File

@ -53,11 +53,11 @@ class MapUnit {
var action: String? // work, automation, fortifying, I dunno what. var action: String? // work, automation, fortifying, I dunno what.
// getter and setter for compatibility: make sure string-based actions still work // getter and setter for compatibility: make sure string-based actions still work
get() { get() {
val mapUnitActionVal=mapUnitAction val mapUnitActionVal = mapUnitAction
if(mapUnitActionVal is StringAction) if (mapUnitActionVal is StringAction)
return mapUnitActionVal.action return mapUnitActionVal.action
// any other unit action does count as a unit action, thus is not null. The actual logic is not based on an action string, but realized by extending MapUnitAction // any other unit action does count as a unit action, thus is not null. The actual logic is not based on an action string, but realized by extending MapUnitAction
if(mapUnitActionVal!=null) if (mapUnitActionVal != null)
return "" return ""
return null // unit has no action return null // unit has no action
@ -81,14 +81,14 @@ class MapUnit {
//region pure functions //region pure functions
fun clone(): MapUnit { fun clone(): MapUnit {
val toReturn = MapUnit() val toReturn = MapUnit()
toReturn.owner=owner toReturn.owner = owner
toReturn.name=name toReturn.name = name
toReturn.currentMovement=currentMovement toReturn.currentMovement = currentMovement
toReturn.health=health toReturn.health = health
toReturn.action=action toReturn.action = action
toReturn.attacksThisTurn=attacksThisTurn toReturn.attacksThisTurn = attacksThisTurn
toReturn.promotions=promotions.clone() toReturn.promotions = promotions.clone()
toReturn.isTransported=isTransported toReturn.isTransported = isTransported
return toReturn return toReturn
} }
@ -227,7 +227,7 @@ class MapUnit {
} }
fun isInvisible(): Boolean { fun isInvisible(): Boolean {
if(hasUnique("Invisible to others")) if (hasUnique("Invisible to others"))
return true return true
return false return false
} }
@ -304,7 +304,7 @@ class MapUnit {
if(hasUnique("This unit and all others in adjacent tiles heal 5 additional HP. This unit heals 5 additional HP outside of friendly territory.")) healingBonus +=5 if(hasUnique("This unit and all others in adjacent tiles heal 5 additional HP. This unit heals 5 additional HP outside of friendly territory.")) healingBonus +=5
return healingBonus return healingBonus
} }
fun canGarrison() = type.isMilitary() && type.isLandUnit() fun canGarrison() = type.isMilitary() && type.isLandUnit()
//endregion //endregion
@ -324,15 +324,15 @@ class MapUnit {
} }
fun doPreTurnAction() { fun doPreTurnAction() {
if(action==null) return if (action == null) return
val currentTile = getTile() val currentTile = getTile()
if (currentMovement == 0f) return // We've already done stuff this turn, and can't do any more stuff if (currentMovement == 0f) return // We've already done stuff this turn, and can't do any more stuff
val enemyUnitsInWalkingDistance = movement.getDistanceToTiles().keys val enemyUnitsInWalkingDistance = movement.getDistanceToTiles().keys
.filter { it.militaryUnit!=null && civInfo.isAtWarWith(it.militaryUnit!!.civInfo)} .filter { it.militaryUnit != null && civInfo.isAtWarWith(it.militaryUnit!!.civInfo) }
if(enemyUnitsInWalkingDistance.isNotEmpty()) { if (enemyUnitsInWalkingDistance.isNotEmpty()) {
if (mapUnitAction?.shouldStopOnEnemyInSight()==true) if (mapUnitAction?.shouldStopOnEnemyInSight() == true)
mapUnitAction=null mapUnitAction = null
return // Don't you dare move. return // Don't you dare move.
} }
@ -342,18 +342,18 @@ class MapUnit {
val destination = action!!.replace("moveTo ", "").split(",").dropLastWhile { it.isEmpty() }.toTypedArray() val destination = action!!.replace("moveTo ", "").split(",").dropLastWhile { it.isEmpty() }.toTypedArray()
val destinationVector = Vector2(Integer.parseInt(destination[0]).toFloat(), Integer.parseInt(destination[1]).toFloat()) val destinationVector = Vector2(Integer.parseInt(destination[0]).toFloat(), Integer.parseInt(destination[1]).toFloat())
val destinationTile = currentTile.tileMap[destinationVector] val destinationTile = currentTile.tileMap[destinationVector]
if(!movement.canReach(destinationTile)) return // That tile that we were moving towards is now unreachable if (!movement.canReach(destinationTile)) return // That tile that we were moving towards is now unreachable
val gotTo = movement.headTowards(destinationTile) val gotTo = movement.headTowards(destinationTile)
if(gotTo==currentTile) // We didn't move at all if (gotTo == currentTile) // We didn't move at all
return return
if (gotTo.position == destinationVector) action = null if (gotTo.position == destinationVector) action = null
if (currentMovement >0) doPreTurnAction() if (currentMovement > 0) doPreTurnAction()
return return
} }
if (action == Constants.unitActionAutomation) WorkerAutomation(this).automateWorkerAction() if (action == Constants.unitActionAutomation) WorkerAutomation(this).automateWorkerAction()
if(action == Constants.unitActionExplore) UnitAutomation.automatedExplore(this) if (action == Constants.unitActionExplore) UnitAutomation.automatedExplore(this)
} }
private fun doPostTurnAction() { private fun doPostTurnAction() {
@ -370,22 +370,22 @@ class MapUnit {
} }
private fun workOnImprovement() { private fun workOnImprovement() {
val tile=getTile() val tile = getTile()
tile.turnsToImprovement -= 1 tile.turnsToImprovement -= 1
if (tile.turnsToImprovement != 0) return if (tile.turnsToImprovement != 0) return
if(civInfo.isCurrentPlayer()) if (civInfo.isCurrentPlayer())
UncivGame.Current.settings.addCompletedTutorialTask("Construct an improvement") UncivGame.Current.settings.addCompletedTutorialTask("Construct an improvement")
when { when {
tile.improvementInProgress!!.startsWith("Remove") -> { tile.improvementInProgress!!.startsWith("Remove") -> {
val tileImprovement = tile.getTileImprovement() val tileImprovement = tile.getTileImprovement()
if(tileImprovement!=null if (tileImprovement != null
&& tileImprovement.terrainsCanBeBuiltOn.contains(tile.terrainFeature) && tileImprovement.terrainsCanBeBuiltOn.contains(tile.terrainFeature)
&& !tileImprovement.terrainsCanBeBuiltOn.contains(tile.baseTerrain)) { && !tileImprovement.terrainsCanBeBuiltOn.contains(tile.baseTerrain)) {
tile.improvement = null // We removed a terrain (e.g. Forest) and the improvement (e.g. Lumber mill) requires it! tile.improvement = null // We removed a terrain (e.g. Forest) and the improvement (e.g. Lumber mill) requires it!
if (tile.resource!=null) civInfo.updateDetailedCivResources() // unlikely, but maybe a mod makes a resource improvement dependent on a terrain feature 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 (tile.improvementInProgress == "Remove Road" || tile.improvementInProgress == "Remove Railroad")
tile.roadStatus = RoadStatus.None tile.roadStatus = RoadStatus.None
else tile.terrainFeature = null else tile.terrainFeature = null
} }
@ -393,7 +393,7 @@ class MapUnit {
tile.improvementInProgress == "Railroad" -> tile.roadStatus = RoadStatus.Railroad tile.improvementInProgress == "Railroad" -> tile.roadStatus = RoadStatus.Railroad
else -> { else -> {
tile.improvement = tile.improvementInProgress tile.improvement = tile.improvementInProgress
if (tile.resource!=null) civInfo.updateDetailedCivResources() if (tile.resource != null) civInfo.updateDetailedCivResources()
} }
} }
tile.improvementInProgress = null tile.improvementInProgress = null
@ -431,13 +431,13 @@ class MapUnit {
isFriendlyTerritory -> 15 // Allied territory isFriendlyTerritory -> 15 // Allied territory
else -> 5 // Enemy territory else -> 5 // Enemy territory
} }
if (hasUnique("This unit and all others in adjacent tiles heal 5 additional HP. This unit heals 5 additional HP outside of friendly territory.") if (hasUnique("This unit and all others in adjacent tiles heal 5 additional HP. This unit heals 5 additional HP outside of friendly territory.")
&& !isFriendlyTerritory && !isFriendlyTerritory
// Additional healing from medic is only applied when the unit is able to heal // Additional healing from medic is only applied when the unit is able to heal
&& healing > 0) && healing > 0)
healing += 5 healing += 5
return healing return healing
} }
@ -499,9 +499,9 @@ class MapUnit {
// addPromotion requires currentTile to be valid because it accesses ruleset through it // addPromotion requires currentTile to be valid because it accesses ruleset through it
currentTile = tile currentTile = tile
if(!hasUnique("All healing effects doubled") && type.isLandUnit() && type.isMilitary()) if(!hasUnique("All healing effects doubled") && type.isLandUnit() && type.isMilitary()) {
{ val gainDoubleHealPromotion = tile.neighbors
val gainDoubleHealPromotion = tile.neighbors.any{it.containsUnique("Grants Rejuvenation (all healing effects doubled) to adjacent military land units for the rest of the game")} .any { it.containsUnique("Grants Rejuvenation (all healing effects doubled) to adjacent military land units for the rest of the game") }
if (gainDoubleHealPromotion) if (gainDoubleHealPromotion)
promotions.addPromotion("Rejuvenation", true) promotions.addPromotion("Rejuvenation", true)
} }
@ -607,23 +607,24 @@ class MapUnit {
.filter { Random.nextFloat() < ANCIENT_RUIN_MAP_REVEAL_CHANCE } .filter { Random.nextFloat() < ANCIENT_RUIN_MAP_REVEAL_CHANCE }
.map { it.position } .map { it.position }
civInfo.exploredTiles.addAll(tilesToReveal) civInfo.exploredTiles.addAll(tilesToReveal)
civInfo.updateViewableTiles()
civInfo.addNotification("We have found a crudely-drawn map in the ruins!", tile.position, Color.RED) civInfo.addNotification("We have found a crudely-drawn map in the ruins!", tile.position, Color.RED)
} }
(actions.random(tileBasedRandom))() (actions.random(tileBasedRandom))()
} }
fun assignOwner(civInfo:CivilizationInfo, updateCivInfo:Boolean=true){ fun assignOwner(civInfo:CivilizationInfo, updateCivInfo:Boolean=true) {
owner=civInfo.civName owner = civInfo.civName
this.civInfo=civInfo this.civInfo = civInfo
civInfo.addUnit(this,updateCivInfo) civInfo.addUnit(this, updateCivInfo)
} }
fun canIntercept(attackedTile: TileInfo): Boolean { fun canIntercept(attackedTile: TileInfo): Boolean {
if(attacksThisTurn>1) return false if (attacksThisTurn > 1) return false
if(interceptChance()==0) return false if (interceptChance() == 0) return false
if(attacksThisTurn>0 && !hasUnique("1 extra Interception may be made per turn")) return false if (attacksThisTurn > 0 && !hasUnique("1 extra Interception may be made per turn")) return false
if(currentTile.aerialDistanceTo(attackedTile) > baseUnit.interceptRange) return false if (currentTile.aerialDistanceTo(attackedTile) > baseUnit.interceptRange) return false
return true return true
} }
@ -649,13 +650,13 @@ class MapUnit {
} }
fun canTransport(mapUnit: MapUnit): Boolean { fun canTransport(mapUnit: MapUnit): Boolean {
if(!isTransportTypeOf(mapUnit)) return false if (!isTransportTypeOf(mapUnit)) return false
if(owner!=mapUnit.owner) return false if (owner != mapUnit.owner) return false
var unitCapacity = 2 var unitCapacity = 2
unitCapacity += getUniques().count { it == "Can carry 1 extra air unit" } unitCapacity += getUniques().count { it == "Can carry 1 extra air unit" }
if(currentTile.airUnits.filter { it.isTransported }.size>=unitCapacity) return false if (currentTile.airUnits.filter { it.isTransported }.size >= unitCapacity) return false
return true return true
} }

View File

@ -15,6 +15,7 @@ import com.unciv.models.stats.INamed
import kotlin.collections.set import kotlin.collections.set
class ModOptions { class ModOptions {
var isBaseRuleset = false
var techsToRemove = HashSet<String>() var techsToRemove = HashSet<String>()
var buildingsToRemove = HashSet<String>() var buildingsToRemove = HashSet<String>()
var unitsToRemove = HashSet<String>() var unitsToRemove = HashSet<String>()
@ -194,12 +195,13 @@ object RulesetCache :HashMap<String,Ruleset>() {
fun getComplexRuleset(mods: LinkedHashSet<String>): Ruleset { fun getComplexRuleset(mods: LinkedHashSet<String>): Ruleset {
val newRuleset = Ruleset() val newRuleset = Ruleset()
newRuleset.add(getBaseRuleset()) val loadedMods = mods.filter { containsKey(it) }.map { this[it]!! }
for (mod in mods) if (loadedMods.none { it.modOptions.isBaseRuleset })
if (containsKey(mod)) { newRuleset.add(getBaseRuleset())
newRuleset.add(this[mod]!!) for (mod in loadedMods.sortedByDescending { it.modOptions.isBaseRuleset }) {
newRuleset.mods += mod newRuleset.add(mod)
} newRuleset.mods += mod.name
}
newRuleset.updateBuildingCosts() // only after we've added all the mods can we calculate the building costs newRuleset.updateBuildingCosts() // only after we've added all the mods can we calculate the building costs
return newRuleset return newRuleset