mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-13 17:28:57 +07:00
Resolved #3384 - Civ uniques now take all researched tech uniques!
This commit is contained in:
@ -102,7 +102,7 @@ class CityStats {
|
|||||||
private fun getStatPercentBonusesFromComputers(): Stats {
|
private fun getStatPercentBonusesFromComputers(): Stats {
|
||||||
val stats = Stats()
|
val stats = Stats()
|
||||||
|
|
||||||
if (cityInfo.civInfo.tech.getTechUniques().contains("+10% science and production in all cities")) {
|
if (cityInfo.civInfo.hasUnique("+10% science and production in all cities")) {
|
||||||
stats.production += 10f
|
stats.production += 10f
|
||||||
stats.science += 10f
|
stats.science += 10f
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ open class PerpetualConstruction(override var name: String, val description: Str
|
|||||||
const val CONVERSION_RATE: Int = 4
|
const val CONVERSION_RATE: Int = 4
|
||||||
val science = object : PerpetualConstruction("Science", "Convert production to science at a rate of [rate] to 1") {
|
val science = object : PerpetualConstruction("Science", "Convert production to science at a rate of [rate] to 1") {
|
||||||
override fun isBuildable(cityConstructions: CityConstructions): Boolean {
|
override fun isBuildable(cityConstructions: CityConstructions): Boolean {
|
||||||
return cityConstructions.cityInfo.civInfo.tech.getTechUniques().contains("Enables conversion of city production to science")
|
return cityConstructions.cityInfo.civInfo.hasUnique("Enables conversion of city production to science")
|
||||||
}
|
}
|
||||||
override fun getProductionTooltip(cityInfo: CityInfo): String {
|
override fun getProductionTooltip(cityInfo: CityInfo): String {
|
||||||
return "\r\n${(cityInfo.cityStats.currentCityStats.production / getConversionRate(cityInfo)).roundToInt()}/${Fonts.turn}"
|
return "\r\n${(cityInfo.cityStats.currentCityStats.production / getConversionRate(cityInfo)).roundToInt()}/${Fonts.turn}"
|
||||||
@ -41,7 +41,7 @@ open class PerpetualConstruction(override var name: String, val description: Str
|
|||||||
}
|
}
|
||||||
val gold = object : PerpetualConstruction("Gold", "Convert production to gold at a rate of $CONVERSION_RATE to 1") {
|
val gold = object : PerpetualConstruction("Gold", "Convert production to gold at a rate of $CONVERSION_RATE to 1") {
|
||||||
override fun isBuildable(cityConstructions: CityConstructions): Boolean {
|
override fun isBuildable(cityConstructions: CityConstructions): Boolean {
|
||||||
return cityConstructions.cityInfo.civInfo.tech.getTechUniques().contains("Enables conversion of city production to gold")
|
return cityConstructions.cityInfo.civInfo.hasUnique("Enables conversion of city production to gold")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val idle = object : PerpetualConstruction("Nothing", "The city will not produce anything.") {
|
val idle = object : PerpetualConstruction("Nothing", "The city will not produce anything.") {
|
||||||
|
@ -11,7 +11,6 @@ import com.unciv.logic.city.CityInfo
|
|||||||
import com.unciv.logic.civilization.diplomacy.DiplomacyFlags
|
import com.unciv.logic.civilization.diplomacy.DiplomacyFlags
|
||||||
import com.unciv.logic.civilization.diplomacy.DiplomacyManager
|
import com.unciv.logic.civilization.diplomacy.DiplomacyManager
|
||||||
import com.unciv.logic.civilization.diplomacy.DiplomaticStatus
|
import com.unciv.logic.civilization.diplomacy.DiplomaticStatus
|
||||||
import com.unciv.logic.civilization.diplomacy.RelationshipLevel
|
|
||||||
import com.unciv.logic.map.MapUnit
|
import com.unciv.logic.map.MapUnit
|
||||||
import com.unciv.logic.map.TileInfo
|
import com.unciv.logic.map.TileInfo
|
||||||
import com.unciv.logic.trade.TradeEvaluation
|
import com.unciv.logic.trade.TradeEvaluation
|
||||||
@ -34,6 +33,7 @@ class CivilizationInfo {
|
|||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
lateinit var gameInfo: GameInfo
|
lateinit var gameInfo: GameInfo
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
lateinit var nation: Nation
|
lateinit var nation: Nation
|
||||||
|
|
||||||
@ -44,8 +44,10 @@ class CivilizationInfo {
|
|||||||
*/
|
*/
|
||||||
@Transient
|
@Transient
|
||||||
private var units = listOf<MapUnit>()
|
private var units = listOf<MapUnit>()
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
var viewableTiles = setOf<TileInfo>()
|
var viewableTiles = setOf<TileInfo>()
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
var viewableInvisibleUnitsTiles = setOf<TileInfo>()
|
var viewableInvisibleUnitsTiles = setOf<TileInfo>()
|
||||||
|
|
||||||
@ -56,14 +58,18 @@ class CivilizationInfo {
|
|||||||
/** This is for performance since every movement calculation depends on this, see MapUnit comment */
|
/** This is for performance since every movement calculation depends on this, see MapUnit comment */
|
||||||
@Transient
|
@Transient
|
||||||
var hasActiveGreatWall = false
|
var hasActiveGreatWall = false
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
var statsForNextTurn = Stats()
|
var statsForNextTurn = Stats()
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
var happinessForNextTurn = 0
|
var happinessForNextTurn = 0
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
var detailedCivResources = ResourceSupplyList()
|
var detailedCivResources = ResourceSupplyList()
|
||||||
|
|
||||||
var playerType = PlayerType.AI
|
var playerType = PlayerType.AI
|
||||||
|
|
||||||
/** Used in online multiplayer for human players */
|
/** Used in online multiplayer for human players */
|
||||||
var playerId = ""
|
var playerId = ""
|
||||||
var gold = 0
|
var gold = 0
|
||||||
@ -223,7 +229,8 @@ class CivilizationInfo {
|
|||||||
fun getMatchingUniques(uniqueTemplate: String): Sequence<Unique> {
|
fun getMatchingUniques(uniqueTemplate: String): Sequence<Unique> {
|
||||||
return nation.uniqueObjects.asSequence().filter { it.placeholderText == uniqueTemplate } +
|
return nation.uniqueObjects.asSequence().filter { it.placeholderText == uniqueTemplate } +
|
||||||
cities.asSequence().flatMap { it.cityConstructions.builtBuildingUniqueMap.getUniques(uniqueTemplate).asSequence() } +
|
cities.asSequence().flatMap { it.cityConstructions.builtBuildingUniqueMap.getUniques(uniqueTemplate).asSequence() } +
|
||||||
policies.policyUniques.getUniques(uniqueTemplate)
|
policies.policyUniques.getUniques(uniqueTemplate) +
|
||||||
|
tech.getTechUniques()
|
||||||
}
|
}
|
||||||
|
|
||||||
//region Units
|
//region Units
|
||||||
@ -365,7 +372,7 @@ class CivilizationInfo {
|
|||||||
|
|
||||||
fun canSignResearchAgreement(): Boolean {
|
fun canSignResearchAgreement(): Boolean {
|
||||||
if (!isMajorCiv()) return false
|
if (!isMajorCiv()) return false
|
||||||
if (!tech.getTechUniques().contains("Enables Research agreements")) return false
|
if (!hasUnique("Enables Research agreements")) return false
|
||||||
if (gameInfo.ruleSet.technologies.values
|
if (gameInfo.ruleSet.technologies.values
|
||||||
.none { tech.canBeResearched(it.name) && !tech.isResearched(it.name) }) return false
|
.none { tech.canBeResearched(it.name) && !tech.isResearched(it.name) }) return false
|
||||||
return true
|
return true
|
||||||
|
@ -2,7 +2,6 @@ package com.unciv.logic.civilization
|
|||||||
|
|
||||||
|
|
||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
import com.unciv.Constants
|
|
||||||
import com.unciv.logic.map.MapSize
|
import com.unciv.logic.map.MapSize
|
||||||
import com.unciv.logic.map.RoadStatus
|
import com.unciv.logic.map.RoadStatus
|
||||||
import com.unciv.models.ruleset.Unique
|
import com.unciv.models.ruleset.Unique
|
||||||
@ -17,18 +16,26 @@ import kotlin.math.max
|
|||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
class TechManager {
|
class TechManager {
|
||||||
@Transient lateinit var civInfo: CivilizationInfo
|
@Transient
|
||||||
@Transient var researchedTechnologies = ArrayList<Technology>()
|
lateinit var civInfo: CivilizationInfo
|
||||||
@Transient private var researchedTechUniques = ArrayList<String>()
|
@Transient
|
||||||
|
var researchedTechnologies = ArrayList<Technology>()
|
||||||
|
@Transient
|
||||||
|
private var researchedTechUniques = ArrayList<Unique>()
|
||||||
|
|
||||||
// MapUnit.canPassThrough is the most called function in the game, and having these extremey specific booleans is or way of improving the time cost
|
// MapUnit.canPassThrough is the most called function in the game, and having these extremey specific booleans is or way of improving the time cost
|
||||||
@Transient var wayfinding = false
|
@Transient
|
||||||
@Transient var unitsCanEmbark = false
|
var wayfinding = false
|
||||||
@Transient var embarkedUnitsCanEnterOcean = false
|
@Transient
|
||||||
|
var unitsCanEmbark = false
|
||||||
|
@Transient
|
||||||
|
var embarkedUnitsCanEnterOcean = false
|
||||||
|
|
||||||
// UnitMovementAlgorithms.getMovementCostBetweenAdjacentTiles is a close second =)
|
// UnitMovementAlgorithms.getMovementCostBetweenAdjacentTiles is a close second =)
|
||||||
@Transient var movementSpeedOnRoadsImproved = false
|
@Transient
|
||||||
@Transient var roadsConnectAcrossRivers = false
|
var movementSpeedOnRoadsImproved = false
|
||||||
|
@Transient
|
||||||
|
var roadsConnectAcrossRivers = false
|
||||||
|
|
||||||
var freeTechs = 0
|
var freeTechs = 0
|
||||||
|
|
||||||
@ -167,7 +174,7 @@ class TechManager {
|
|||||||
private fun scienceFromResearchAgreements(): Int {
|
private fun scienceFromResearchAgreements(): Int {
|
||||||
// https://forums.civfanatics.com/resources/research-agreements-bnw.25568/
|
// https://forums.civfanatics.com/resources/research-agreements-bnw.25568/
|
||||||
var researchAgreementModifier = 0.5f
|
var researchAgreementModifier = 0.5f
|
||||||
for(unique in civInfo.getMatchingUniques("Science gained from research agreements +50%"))
|
for (unique in civInfo.getMatchingUniques("Science gained from research agreements +50%"))
|
||||||
researchAgreementModifier += 0.25f
|
researchAgreementModifier += 0.25f
|
||||||
return (scienceFromResearchAgreements / 3 * researchAgreementModifier).toInt()
|
return (scienceFromResearchAgreements / 3 * researchAgreementModifier).toInt()
|
||||||
}
|
}
|
||||||
@ -194,7 +201,7 @@ class TechManager {
|
|||||||
addScience(finalScienceToAdd)
|
addScience(finalScienceToAdd)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addScience(scienceGet : Int) {
|
fun addScience(scienceGet: Int) {
|
||||||
val currentTechnology = currentTechnologyName()
|
val currentTechnology = currentTechnologyName()
|
||||||
if (currentTechnology == null) return
|
if (currentTechnology == null) return
|
||||||
techsInProgress[currentTechnology] = researchOfTech(currentTechnology) + scienceGet
|
techsInProgress[currentTechnology] = researchOfTech(currentTechnology) + scienceGet
|
||||||
@ -225,7 +232,7 @@ class TechManager {
|
|||||||
techsToResearch.remove(techName)
|
techsToResearch.remove(techName)
|
||||||
researchedTechnologies = researchedTechnologies.withItem(newTech)
|
researchedTechnologies = researchedTechnologies.withItem(newTech)
|
||||||
for (unique in newTech.uniques) {
|
for (unique in newTech.uniques) {
|
||||||
researchedTechUniques = researchedTechUniques.withItem(unique)
|
researchedTechUniques = researchedTechUniques.withItem(Unique(unique))
|
||||||
UniqueTriggerActivation.triggerCivwideUnique(Unique(unique), civInfo)
|
UniqueTriggerActivation.triggerCivwideUnique(Unique(unique), civInfo)
|
||||||
}
|
}
|
||||||
updateTransientBooleans()
|
updateTransientBooleans()
|
||||||
@ -277,12 +284,11 @@ class TechManager {
|
|||||||
if (constructionName in obsoleteUnits) {
|
if (constructionName in obsoleteUnits) {
|
||||||
val text = "[$constructionName] has been obsolete and will be removed from construction queue in [${city.name}]!"
|
val text = "[$constructionName] has been obsolete and will be removed from construction queue in [${city.name}]!"
|
||||||
civInfo.addNotification(text, city.location, Color.BROWN)
|
civInfo.addNotification(text, city.location, Color.BROWN)
|
||||||
}
|
} else city.cityConstructions.constructionQueue.add(newConstructionName)
|
||||||
else city.cityConstructions.constructionQueue.add(newConstructionName)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unique in civInfo.getMatchingUniques("Receive free [] when you discover []")) {
|
for (unique in civInfo.getMatchingUniques("Receive free [] when you discover []")) {
|
||||||
if (unique.params[1] != techName) continue
|
if (unique.params[1] != techName) continue
|
||||||
civInfo.addUnit(unique.params[0])
|
civInfo.addUnit(unique.params[0])
|
||||||
}
|
}
|
||||||
@ -290,17 +296,17 @@ class TechManager {
|
|||||||
|
|
||||||
fun setTransients() {
|
fun setTransients() {
|
||||||
researchedTechnologies.addAll(techsResearched.map { getRuleset().technologies[it]!! })
|
researchedTechnologies.addAll(techsResearched.map { getRuleset().technologies[it]!! })
|
||||||
researchedTechUniques.addAll(researchedTechnologies.flatMap { it.uniques })
|
researchedTechUniques.addAll(researchedTechnologies.asSequence().flatMap { it.uniques.asSequence() }.map { Unique(it) })
|
||||||
updateTransientBooleans()
|
updateTransientBooleans()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateTransientBooleans() {
|
fun updateTransientBooleans() {
|
||||||
wayfinding = civInfo.hasUnique("Can embark and move over Coasts and Oceans immediately")
|
wayfinding = civInfo.hasUnique("Can embark and move over Coasts and Oceans immediately")
|
||||||
unitsCanEmbark = wayfinding || researchedTechUniques.contains("Enables embarkation for land units")
|
unitsCanEmbark = wayfinding || civInfo.hasUnique("Enables embarkation for land units")
|
||||||
|
|
||||||
embarkedUnitsCanEnterOcean = wayfinding || researchedTechUniques.contains("Enables embarked units to enter ocean tiles")
|
embarkedUnitsCanEnterOcean = wayfinding || civInfo.hasUnique("Enables embarked units to enter ocean tiles")
|
||||||
movementSpeedOnRoadsImproved = researchedTechUniques.contains("Improves movement speed on roads")
|
movementSpeedOnRoadsImproved = civInfo.hasUnique("Improves movement speed on roads")
|
||||||
roadsConnectAcrossRivers = researchedTechUniques.contains("Roads connect tiles across rivers")
|
roadsConnectAcrossRivers = civInfo.hasUnique("Roads connect tiles across rivers")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getBestRoadAvailable(): RoadStatus {
|
fun getBestRoadAvailable(): RoadStatus {
|
||||||
@ -308,7 +314,7 @@ class TechManager {
|
|||||||
if (roadImprovement == null || !isResearched(roadImprovement.techRequired!!)) return RoadStatus.None
|
if (roadImprovement == null || !isResearched(roadImprovement.techRequired!!)) return RoadStatus.None
|
||||||
|
|
||||||
val railroadImprovement = RoadStatus.Railroad.improvement(getRuleset())
|
val railroadImprovement = RoadStatus.Railroad.improvement(getRuleset())
|
||||||
val canBuildRailroad = railroadImprovement!=null && isResearched(railroadImprovement.techRequired!!)
|
val canBuildRailroad = railroadImprovement != null && isResearched(railroadImprovement.techRequired!!)
|
||||||
|
|
||||||
return if (canBuildRailroad) RoadStatus.Railroad else RoadStatus.Road
|
return if (canBuildRailroad) RoadStatus.Railroad else RoadStatus.Road
|
||||||
}
|
}
|
||||||
|
@ -234,7 +234,7 @@ class MapUnit {
|
|||||||
|
|
||||||
fun getEmbarkedMovement(): Int {
|
fun getEmbarkedMovement(): Int {
|
||||||
var movement = 2
|
var movement = 2
|
||||||
movement += civInfo.tech.getTechUniques().count { it == "Increases embarked movement +1" }
|
movement += civInfo.getMatchingUniques("Increases embarked movement +1").count()
|
||||||
if (civInfo.hasUnique("+1 Movement for all embarked units")) movement += 1
|
if (civInfo.hasUnique("+1 Movement for all embarked units")) movement += 1
|
||||||
return movement
|
return movement
|
||||||
}
|
}
|
||||||
|
@ -8,11 +8,11 @@ import com.unciv.models.ruleset.ModOptionsConstants
|
|||||||
import com.unciv.models.ruleset.tile.ResourceType
|
import com.unciv.models.ruleset.tile.ResourceType
|
||||||
import com.unciv.models.translations.tr
|
import com.unciv.models.translations.tr
|
||||||
|
|
||||||
class TradeLogic(val ourCivilization:CivilizationInfo, val otherCivilization: CivilizationInfo){
|
class TradeLogic(val ourCivilization:CivilizationInfo, val otherCivilization: CivilizationInfo) {
|
||||||
|
|
||||||
/** Contains everything we could offer the other player, whether we've actually offered it or not */
|
/** Contains everything we could offer the other player, whether we've actually offered it or not */
|
||||||
val ourAvailableOffers = getAvailableOffers(ourCivilization,otherCivilization)
|
val ourAvailableOffers = getAvailableOffers(ourCivilization, otherCivilization)
|
||||||
val theirAvailableOffers = getAvailableOffers(otherCivilization,ourCivilization)
|
val theirAvailableOffers = getAvailableOffers(otherCivilization, ourCivilization)
|
||||||
val currentTrade = Trade()
|
val currentTrade = Trade()
|
||||||
|
|
||||||
fun getAvailableOffers(civInfo: CivilizationInfo, otherCivilization: CivilizationInfo): TradeOffersList {
|
fun getAvailableOffers(civInfo: CivilizationInfo, otherCivilization: CivilizationInfo): TradeOffersList {
|
||||||
@ -21,16 +21,16 @@ class TradeLogic(val ourCivilization:CivilizationInfo, val otherCivilization: Ci
|
|||||||
if (civInfo.isAtWarWith(otherCivilization))
|
if (civInfo.isAtWarWith(otherCivilization))
|
||||||
offers.add(TradeOffer(Constants.peaceTreaty, TradeType.Treaty))
|
offers.add(TradeOffer(Constants.peaceTreaty, TradeType.Treaty))
|
||||||
|
|
||||||
if(!otherCivilization.getDiplomacyManager(civInfo).hasOpenBorders
|
if (!otherCivilization.getDiplomacyManager(civInfo).hasOpenBorders
|
||||||
&& !otherCivilization.isCityState()
|
&& !otherCivilization.isCityState()
|
||||||
&& civInfo.tech.getTechUniques().contains("Enables Open Borders agreements")
|
&& civInfo.hasUnique("Enables Open Borders agreements")
|
||||||
&& otherCivilization.tech.getTechUniques().contains("Enables Open Borders agreements")) {
|
&& otherCivilization.hasUnique("Enables Open Borders agreements")) {
|
||||||
offers.add(TradeOffer(Constants.openBorders, TradeType.Agreement))
|
offers.add(TradeOffer(Constants.openBorders, TradeType.Agreement))
|
||||||
}
|
}
|
||||||
|
|
||||||
for(entry in civInfo.getCivResources()
|
for (entry in civInfo.getCivResources()
|
||||||
.filterNot { it.resource.resourceType == ResourceType.Bonus }) {
|
.filterNot { it.resource.resourceType == ResourceType.Bonus }) {
|
||||||
val resourceTradeType = if(entry.resource.resourceType== ResourceType.Luxury) TradeType.Luxury_Resource
|
val resourceTradeType = if (entry.resource.resourceType == ResourceType.Luxury) TradeType.Luxury_Resource
|
||||||
else TradeType.Strategic_Resource
|
else TradeType.Strategic_Resource
|
||||||
offers.add(TradeOffer(entry.resource.name, resourceTradeType, entry.amount))
|
offers.add(TradeOffer(entry.resource.name, resourceTradeType, entry.amount))
|
||||||
}
|
}
|
||||||
@ -116,5 +116,4 @@ class TradeLogic(val ourCivilization:CivilizationInfo, val otherCivilization: Ci
|
|||||||
transferTrade(ourCivilization, otherCivilization, currentTrade)
|
transferTrade(ourCivilization, otherCivilization, currentTrade)
|
||||||
transferTrade(otherCivilization, ourCivilization, currentTrade.reverse())
|
transferTrade(otherCivilization, ourCivilization, currentTrade.reverse())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -653,7 +653,7 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
|
|||||||
}
|
}
|
||||||
displayTutorial(Tutorial.ApolloProgram) { viewingCiv.hasUnique("Enables construction of Spaceship parts") }
|
displayTutorial(Tutorial.ApolloProgram) { viewingCiv.hasUnique("Enables construction of Spaceship parts") }
|
||||||
displayTutorial(Tutorial.SiegeUnits) { viewingCiv.getCivUnits().any { it.type == UnitType.Siege } }
|
displayTutorial(Tutorial.SiegeUnits) { viewingCiv.getCivUnits().any { it.type == UnitType.Siege } }
|
||||||
displayTutorial(Tutorial.Embarking) { viewingCiv.tech.getTechUniques().contains("Enables embarkation for land units") }
|
displayTutorial(Tutorial.Embarking) { viewingCiv.hasUnique("Enables embarkation for land units") }
|
||||||
displayTutorial(Tutorial.NaturalWonders) { viewingCiv.naturalWonders.size > 0 }
|
displayTutorial(Tutorial.NaturalWonders) { viewingCiv.naturalWonders.size > 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user