mirror of
https://github.com/yairm210/Unciv.git
synced 2025-02-02 12:24:15 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
55bed3bf30
@ -6,6 +6,7 @@ import com.unciv.logic.civilization.NotificationIcon
|
||||
import com.unciv.logic.map.TileInfo
|
||||
import com.unciv.logic.map.TileMap
|
||||
import com.unciv.models.metadata.GameSpeed
|
||||
import com.unciv.models.ruleset.unique.UniqueType
|
||||
import java.util.*
|
||||
import kotlin.collections.HashMap
|
||||
import kotlin.math.max
|
||||
@ -210,7 +211,7 @@ class Encampment {
|
||||
|| it.isCityCenter()
|
||||
|| it.getFirstUnit() != null
|
||||
|| (it.isWater && !canSpawnBoats)
|
||||
|| (it.hasUnique("Fresh water") && it.isWater) // No Lakes
|
||||
|| (it.hasUnique(UniqueType.FreshWater) && it.isWater) // No Lakes
|
||||
}
|
||||
if (validTiles.isEmpty()) return false
|
||||
|
||||
|
@ -704,13 +704,13 @@ object Battle {
|
||||
tile.turnsToImprovement = 0
|
||||
tile.roadStatus = RoadStatus.None
|
||||
if (tile.isLand && !tile.isImpassible() && !tile.terrainFeatures.contains("Fallout")) {
|
||||
if (tile.terrainFeatures.any { attacker.getCivInfo().gameInfo.ruleSet.terrains[it]!!.uniques.contains("Resistant to nukes") }) {
|
||||
if (tile.terrainFeatures.any { attacker.getCivInfo().gameInfo.ruleSet.terrains[it]!!.hasUnique(UniqueType.ResistsNukes) }) {
|
||||
if (Random().nextFloat() < 0.25f) {
|
||||
tile.terrainFeatures.removeAll { attacker.getCivInfo().gameInfo.ruleSet.terrains[it]!!.uniques.contains("Can be destroyed by nukes") }
|
||||
tile.terrainFeatures.removeAll { attacker.getCivInfo().gameInfo.ruleSet.terrains[it]!!.hasUnique(UniqueType.DestroyableByNukes) }
|
||||
tile.terrainFeatures.add("Fallout")
|
||||
}
|
||||
} else if (Random().nextFloat() < 0.5f) {
|
||||
tile.terrainFeatures.removeAll { attacker.getCivInfo().gameInfo.ruleSet.terrains[it]!!.uniques.contains("Can be destroyed by nukes") }
|
||||
tile.terrainFeatures.removeAll { attacker.getCivInfo().gameInfo.ruleSet.terrains[it]!!.hasUnique(UniqueType.DestroyableByNukes) }
|
||||
tile.terrainFeatures.add("Fallout")
|
||||
}
|
||||
}
|
||||
@ -767,13 +767,13 @@ object Battle {
|
||||
tile.turnsToImprovement = 0
|
||||
tile.roadStatus = RoadStatus.None
|
||||
if (tile.isLand && !tile.isImpassible() && !tile.terrainFeatures.contains("Fallout")) {
|
||||
if (tile.terrainFeatures.any { attacker.getCivInfo().gameInfo.ruleSet.terrains[it]!!.uniques.contains("Resistant to nukes") }) {
|
||||
if (tile.terrainFeatures.any { attacker.getCivInfo().gameInfo.ruleSet.terrains[it]!!.hasUnique(UniqueType.ResistsNukes) }) {
|
||||
if (Random().nextFloat() < 0.25f) {
|
||||
tile.terrainFeatures.removeAll { attacker.getCivInfo().gameInfo.ruleSet.terrains[it]!!.uniques.contains("Can be destroyed by nukes") }
|
||||
tile.terrainFeatures.removeAll { attacker.getCivInfo().gameInfo.ruleSet.terrains[it]!!.hasUnique(UniqueType.DestroyableByNukes) }
|
||||
tile.terrainFeatures.add("Fallout")
|
||||
}
|
||||
} else if (Random().nextFloat() < 0.5f) {
|
||||
tile.terrainFeatures.removeAll { attacker.getCivInfo().gameInfo.ruleSet.terrains[it]!!.uniques.contains("Can be destroyed by nukes") }
|
||||
tile.terrainFeatures.removeAll { attacker.getCivInfo().gameInfo.ruleSet.terrains[it]!!.hasUnique(UniqueType.DestroyableByNukes) }
|
||||
tile.terrainFeatures.add("Fallout")
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import com.unciv.logic.city.CityInfo
|
||||
import com.unciv.logic.civilization.CivilizationInfo
|
||||
import com.unciv.logic.map.TileInfo
|
||||
import com.unciv.models.UncivSound
|
||||
import com.unciv.models.ruleset.unique.UniqueType
|
||||
import com.unciv.models.ruleset.unit.UnitType
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.roundToInt
|
||||
@ -39,9 +40,8 @@ class CityCombatant(val city: CityInfo) : ICombatant {
|
||||
var strength = 8f
|
||||
strength += (city.population.population / 5) * 2 // Each 5 pop gives 2 defence
|
||||
val cityTile = city.getCenterTile()
|
||||
for (unique in cityTile.getAllTerrains().flatMap { it.uniqueObjects })
|
||||
if (unique.placeholderText == "[] Strength for cities built on this terrain")
|
||||
strength += unique.params[0].toInt()
|
||||
for (unique in cityTile.getAllTerrains().flatMap { it.getMatchingUniques(UniqueType.GrantsCityStrength) })
|
||||
strength += unique.params[0].toInt()
|
||||
// as tech progresses so does city strength
|
||||
val techCount = getCivInfo().gameInfo.ruleSet.technologies.count()
|
||||
val techsPercentKnown: Float = if (techCount > 0) city.civInfo.tech.techsResearched.count().toFloat() / techCount else 0.5f // for mods with no tech
|
||||
|
@ -294,6 +294,7 @@ class CityStateFunctions(val civInfo: CivilizationInfo) {
|
||||
city.moveToCiv(otherCiv)
|
||||
city.isPuppet = true // Human players get a popup that allows them to annex instead
|
||||
city.foundingCiv = "" // This is no longer a city-state
|
||||
city.isOriginalCapital = false // It's now an ordinary city and can be razed in later conquests
|
||||
}
|
||||
civInfo.destroy()
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.unciv.logic.civilization
|
||||
|
||||
import com.badlogic.gdx.math.Vector2
|
||||
import com.unciv.Constants
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.logic.GameInfo
|
||||
import com.unciv.logic.UncivShowableException
|
||||
@ -343,7 +342,7 @@ class CivilizationInfo {
|
||||
cities.asSequence().flatMap {
|
||||
city ->
|
||||
if (cityItIsFor != null && city == cityItIsFor)
|
||||
city.getAllUniquesWithNonLocalEffects().filter { it.params.none { param -> param == "in other cities" } }
|
||||
city.getAllUniquesWithNonLocalEffects().filter { it.params.none { param -> param == "in other cities" || param == "in all cities" } }
|
||||
else city.getAllUniquesWithNonLocalEffects()
|
||||
}
|
||||
|
||||
@ -714,7 +713,7 @@ class CivilizationInfo {
|
||||
|
||||
passThroughImpassableUnlocked = passableImpassables.isNotEmpty()
|
||||
// Cache whether this civ gets nonstandard terrain damage for performance reasons.
|
||||
nonStandardTerrainDamage = getMatchingUniques("Units ending their turn on [] tiles take [] damage")
|
||||
nonStandardTerrainDamage = getMatchingUniques(UniqueType.DamagesContainingUnits)
|
||||
.any { gameInfo.ruleSet.terrains[it.params[0]]!!.damagePerTurn != it.params[1].toInt() }
|
||||
|
||||
// Cache the last era each resource is used for buildings or units respectively for AI building evaluation
|
||||
|
@ -614,9 +614,7 @@ class MapUnit {
|
||||
tile.roadStatus = RoadStatus.None
|
||||
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")
|
||||
) {
|
||||
if (removedFeatureObject != null && removedFeatureObject.hasUnique(UniqueType.ProductionBonusWhenRemoved)) {
|
||||
tryProvideProductionToClosestCity(removedFeatureName)
|
||||
}
|
||||
tile.terrainFeatures.remove(removedFeatureName)
|
||||
@ -1006,7 +1004,7 @@ class MapUnit {
|
||||
|
||||
fun getDamageFromTerrain(tile: TileInfo = currentTile): Int {
|
||||
if (civInfo.nonStandardTerrainDamage) {
|
||||
for (unique in getMatchingUniques("Units ending their turn on [] tiles take [] damage")) {
|
||||
for (unique in getMatchingUniques(UniqueType.DamagesContainingUnits)) {
|
||||
if (unique.params[0] in tile.getAllTerrains().map { it.name }) {
|
||||
return unique.params[1].toInt() // Use the damage from the unique
|
||||
}
|
||||
|
@ -436,7 +436,7 @@ open class TileInfo {
|
||||
&& getTileImprovement().let { it != null && it.hasUnique("Irremovable") } -> false
|
||||
|
||||
// Terrain blocks most improvements
|
||||
getAllTerrains().any { it.getMatchingUniques("Only [] improvements may be built on this tile")
|
||||
getAllTerrains().any { it.getMatchingUniques(UniqueType.RestrictedBuildableImprovements)
|
||||
.any { unique -> !improvement.matchesFilter(unique.params[0]) } } -> false
|
||||
|
||||
// Decide cancelImprovementOrder earlier, otherwise next check breaks it
|
||||
@ -630,6 +630,17 @@ open class TileInfo {
|
||||
FormattedLine("{$resource} ($resourceAmount)", link="Resource/$resource")
|
||||
else
|
||||
FormattedLine(resource!!, link="Resource/$resource")
|
||||
if (resource != null && viewingCiv != null && hasViewableResource(viewingCiv)) {
|
||||
val tileImprovement = ruleset.tileImprovements[getTileResource().improvement]
|
||||
if (tileImprovement?.techRequired != null
|
||||
&& !viewingCiv.tech.isResearched(tileImprovement.techRequired!!)) {
|
||||
lineList += FormattedLine(
|
||||
"Requires [${tileImprovement.techRequired}]",
|
||||
link="Technology/${tileImprovement.techRequired}",
|
||||
color= "#FAA"
|
||||
)
|
||||
}
|
||||
}
|
||||
if (naturalWonder != null)
|
||||
lineList += FormattedLine(naturalWonder!!, link="Terrain/$naturalWonder")
|
||||
if (roadStatus !== RoadStatus.None && !isCityCenter())
|
||||
|
@ -317,14 +317,17 @@ class TileMap {
|
||||
This can all be summed up as "I can see c if a>b || c>b || (a==b && b !blocks same-elevation view)"
|
||||
*/
|
||||
|
||||
val containsViewableNeighborThatCanSeeOver = cTile.neighbors.any {
|
||||
bNeighbor: TileInfo ->
|
||||
val containsViewableNeighborThatCanSeeOver = cTile.neighbors.any { bNeighbor: TileInfo ->
|
||||
val bNeighborHeight = bNeighbor.height
|
||||
viewableTiles.contains(bNeighbor) && (
|
||||
currentTileHeight > bNeighborHeight // a>b
|
||||
|| cTileHeight > bNeighborHeight // c>b
|
||||
|| currentTileHeight == bNeighborHeight // a==b
|
||||
&& !bNeighbor.hasUnique("Blocks line-of-sight from tiles at same elevation"))
|
||||
viewableTiles.contains(bNeighbor)
|
||||
&& (
|
||||
currentTileHeight > bNeighborHeight // a>b
|
||||
|| cTileHeight > bNeighborHeight // c>b
|
||||
|| (
|
||||
currentTileHeight == bNeighborHeight // a==b
|
||||
&& !bNeighbor.hasUnique(UniqueType.BlocksLineOfSightAtSameElevation)
|
||||
)
|
||||
)
|
||||
}
|
||||
if (containsViewableNeighborThatCanSeeOver) tilesToAddInDistanceI.add(cTile)
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import com.unciv.models.ruleset.Ruleset
|
||||
import com.unciv.models.ruleset.tile.ResourceType
|
||||
import com.unciv.models.ruleset.tile.Terrain
|
||||
import com.unciv.models.ruleset.tile.TerrainType
|
||||
import com.unciv.models.ruleset.unique.UniqueType
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.max
|
||||
import kotlin.math.pow
|
||||
@ -223,9 +224,11 @@ class MapGenerator(val ruleset: Ruleset) {
|
||||
* [MapParameters.elevationExponent] favors high elevation
|
||||
*/
|
||||
private fun raiseMountainsAndHills(tileMap: TileMap) {
|
||||
val mountain = ruleset.terrains.values.firstOrNull { it.uniques.contains("Occurs in chains at high elevations") }?.name
|
||||
val hill = ruleset.terrains.values.firstOrNull { it.uniques.contains("Occurs in groups around high elevations") }?.name
|
||||
val flat = ruleset.terrains.values.firstOrNull { !it.impassable && it.type == TerrainType.Land && !it.uniques.contains("Rough Terrain") }?.name
|
||||
val mountain = ruleset.terrains.values.firstOrNull { it.hasUnique(UniqueType.OccursInChains) }?.name
|
||||
val hill = ruleset.terrains.values.firstOrNull { it.hasUnique(UniqueType.OccursInGroups) }?.name
|
||||
val flat = ruleset.terrains.values.firstOrNull {
|
||||
!it.impassable && it.type == TerrainType.Land && !it.hasUnique(UniqueType.RoughTerrain)
|
||||
}?.name
|
||||
|
||||
if (flat == null) {
|
||||
println("Ruleset seems to contain no flat terrain - can't generate heightmap")
|
||||
@ -358,12 +361,11 @@ class MapGenerator(val ruleset: Ruleset) {
|
||||
val tempFrom: Float, val tempTo: Float,
|
||||
val humidFrom: Float, val humidTo: Float
|
||||
)
|
||||
// List is OK here as it's only sequentially scanned
|
||||
val limitsMap: List<TerrainOccursRange> =
|
||||
// List is OK here as it's only sequentially scanned
|
||||
ruleset.terrains.values.flatMap { terrain ->
|
||||
terrain.uniqueObjects.filter {
|
||||
it.placeholderText == "Occurs at temperature between [] and [] and humidity between [] and []"
|
||||
}.map { unique ->
|
||||
ruleset.terrains.values.flatMap { terrain ->
|
||||
terrain.getMatchingUniques(UniqueType.TileGenerationConditions)
|
||||
.map { unique ->
|
||||
TerrainOccursRange(terrain,
|
||||
unique.params[0].toFloat(), unique.params[1].toFloat(),
|
||||
unique.params[2].toFloat(), unique.params[3].toFloat())
|
||||
@ -432,7 +434,7 @@ class MapGenerator(val ruleset: Ruleset) {
|
||||
*/
|
||||
private fun spawnRareFeatures(tileMap: TileMap) {
|
||||
val rareFeatures = ruleset.terrains.values.filter {
|
||||
it.type == TerrainType.TerrainFeature && it.uniques.contains("Rare feature")
|
||||
it.type == TerrainType.TerrainFeature && it.hasUnique(UniqueType.RareFeature)
|
||||
}
|
||||
for (tile in tileMap.values.asSequence().filter { it.terrainFeatures.isEmpty() }) {
|
||||
if (randomness.RNG.nextDouble() <= tileMap.mapParameters.rareFeaturesRichness) {
|
||||
|
@ -40,7 +40,8 @@ class Terrain : RulesetStatsObject() {
|
||||
@Transient
|
||||
var damagePerTurn = 0
|
||||
|
||||
fun isRough(): Boolean = uniques.contains("Rough terrain")
|
||||
// Shouldn't this just be a lazy property so it's automatically cached?
|
||||
fun isRough(): Boolean = hasUnique(UniqueType.RoughTerrain)
|
||||
|
||||
/** Tests base terrains, features and natural wonders whether they should be treated as Land/Water.
|
||||
* Currently only used for civilopedia display, as other code can test the tile itself.
|
||||
@ -141,8 +142,6 @@ class Terrain : RulesetStatsObject() {
|
||||
}
|
||||
|
||||
fun setTransients() {
|
||||
damagePerTurn = uniqueObjects.sumOf {
|
||||
if (it.placeholderText == "Units ending their turn on this terrain take [] damage") it.params[0].toInt() else 0
|
||||
}
|
||||
damagePerTurn = getMatchingUniques(UniqueType.DamagesContainingUnits).sumOf { it.params[0].toInt() }
|
||||
}
|
||||
}
|
||||
|
@ -261,16 +261,33 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget) {
|
||||
// The "Except [terrainFilter]" could theoretically be implemented with a conditional
|
||||
NaturalWonderConvertNeighborsExcept("Neighboring tiles except [baseTerrain] will convert to [baseTerrain]", UniqueTarget.Terrain),
|
||||
|
||||
DamagesContainingUnits("Units ending their turn on this terrain take [amount] damage", UniqueTarget.Terrain),
|
||||
TerrainGrantsPromotion("Grants [promotion] ([comment]) to adjacent [mapUnitFilter] units for the rest of the game", UniqueTarget.Terrain),
|
||||
GrantsCityStrength("[amount] Strength for cities built on this terrain", UniqueTarget.Terrain),
|
||||
ProductionBonusWhenRemoved("Provides a one-time Production bonus to the closest city when cut down", UniqueTarget.Terrain),
|
||||
|
||||
TileProvidesYieldWithoutPopulation("Tile provides yield without assigned population", UniqueTarget.Terrain, UniqueTarget.Improvement),
|
||||
NullifyYields("Nullifies all other stats this tile provides", UniqueTarget.Terrain),
|
||||
RestrictedBuildableImprovements("Only [improvementFilter] improvements may be built on this tile", UniqueTarget.Terrain),
|
||||
|
||||
BlocksLineOfSightAtSameElevation("Blocks line-of-sight from tiles at same elevation", UniqueTarget.Terrain),
|
||||
VisibilityElevation("Has an elevation of [amount] for visibility calculations", UniqueTarget.Terrain),
|
||||
|
||||
NoNaturalGeneration("Doesn't generate naturally", UniqueTarget.Terrain),
|
||||
|
||||
TileGenerationConditions("Occurs at temperature between [amount] and [amount] and humidity between [amount] and [amount]", UniqueTarget.Terrain),
|
||||
OccursInChains("Occurs in chains at high elevations", UniqueTarget.Terrain),
|
||||
OccursInGroups("Occurs in groups around high elevations", UniqueTarget.Terrain),
|
||||
RareFeature("Rare feature", UniqueTarget.Terrain),
|
||||
|
||||
ResistsNukes("Resistant to nukes", UniqueTarget.Terrain),
|
||||
DestroyableByNukes("Can be destroyed by nukes", UniqueTarget.Terrain),
|
||||
|
||||
FreshWater("Fresh water", UniqueTarget.Terrain),
|
||||
RoughTerrain("Rough terrain", UniqueTarget.Terrain),
|
||||
|
||||
// Resource uniques
|
||||
OverrideDepositAmountOnTileFilter("Deposits in [tileFilter] tiles always provide [amount] resources", UniqueTarget.Resource),
|
||||
|
||||
|
||||
///////////////////////////////////////// CONDITIONALS /////////////////////////////////////////
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user