mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-26 23:58:43 +07:00
chore: Moved diplomacy functions to DiplomacyFunctions
This commit is contained in:
@ -167,7 +167,7 @@ class MainMenuScreen: BaseScreen(), RecreateOnResize {
|
||||
}
|
||||
|
||||
val multiplayerTable = getMenuButton("Multiplayer", "OtherIcons/Multiplayer", 'm')
|
||||
{ game.pushScreen(MultiplayerScreen(this)) }
|
||||
{ game.pushScreen(MultiplayerScreen()) }
|
||||
column2.add(multiplayerTable).row()
|
||||
|
||||
val mapEditorScreenTable = getMenuButton("Map editor", "OtherIcons/MapEditor", 'e')
|
||||
|
@ -683,12 +683,12 @@ object NextTurnAutomation {
|
||||
}
|
||||
|
||||
private fun offerResearchAgreement(civInfo: CivilizationInfo) {
|
||||
if (!civInfo.canSignResearchAgreement()) return // don't waste your time
|
||||
if (!civInfo.diplomacyFunctions.canSignResearchAgreement()) return // don't waste your time
|
||||
|
||||
val canSignResearchAgreementCiv = civInfo.getKnownCivs()
|
||||
.asSequence()
|
||||
.filter {
|
||||
civInfo.canSignResearchAgreementsWith(it)
|
||||
civInfo.diplomacyFunctions.canSignResearchAgreementsWith(it)
|
||||
&& !civInfo.getDiplomacyManager(it).hasFlag(DiplomacyFlags.DeclinedResearchAgreement)
|
||||
}
|
||||
.sortedByDescending { it.stats.statsForNextTurn.science }
|
||||
@ -752,12 +752,12 @@ object NextTurnAutomation {
|
||||
val theirCity = closestCities.city2
|
||||
|
||||
if (civInfo.units.getCivUnits().filter { it.isMilitary() }.none {
|
||||
val damageRecievedWhenAttacking =
|
||||
val damageReceivedWhenAttacking =
|
||||
BattleDamage.calculateDamageToAttacker(
|
||||
MapUnitCombatant(it),
|
||||
CityCombatant(theirCity)
|
||||
)
|
||||
damageRecievedWhenAttacking < 100
|
||||
damageReceivedWhenAttacking < 100
|
||||
})
|
||||
return 0 // You don't have any units that can attack this city without dying, don't declare war.
|
||||
|
||||
|
@ -174,7 +174,7 @@ class CityInfoConquestFunctions(val city: CityInfo){
|
||||
// How can you conquer a city but not know the civ you conquered it from?!
|
||||
// I don't know either, but some of our players have managed this, and crashed their game!
|
||||
if (!conqueringCiv.knows(oldCiv))
|
||||
conqueringCiv.makeCivilizationsMeet(oldCiv)
|
||||
conqueringCiv.diplomacyFunctions.makeCivilizationsMeet(oldCiv)
|
||||
|
||||
oldCiv.getDiplomacyManager(conqueringCiv)
|
||||
.addModifier(DiplomaticModifiers.CapturedOurCities, -aggroGenerated)
|
||||
@ -246,7 +246,7 @@ class CityInfoConquestFunctions(val city: CityInfo){
|
||||
|
||||
// In order to get "plus points" in Diplomacy, you have to establish diplomatic relations if you haven't yet
|
||||
if (!conqueringCiv.knows(foundingCiv))
|
||||
conqueringCiv.makeCivilizationsMeet(foundingCiv)
|
||||
conqueringCiv.diplomacyFunctions.makeCivilizationsMeet(foundingCiv)
|
||||
|
||||
if (foundingCiv.isMajorCiv()) {
|
||||
foundingCiv.getDiplomacyManager(conqueringCiv)
|
||||
@ -299,7 +299,7 @@ class CityInfoConquestFunctions(val city: CityInfo){
|
||||
removeBuildingsOnMoveToCiv(oldCiv)
|
||||
|
||||
// Place palace for newCiv if this is the only city they have
|
||||
// This needs to happen _before_ free buildings are added, as somtimes these should
|
||||
// This needs to happen _before_ free buildings are added, as sometimes these should
|
||||
// only be placed in the capital, and then there needs to be a capital.
|
||||
if (newCivInfo.cities.size == 1) {
|
||||
newCivInfo.moveCapitalTo(this)
|
||||
|
@ -12,8 +12,8 @@ import com.unciv.logic.automation.unit.WorkerAutomation
|
||||
import com.unciv.logic.city.CityInfo
|
||||
import com.unciv.logic.civilization.diplomacy.CityStateFunctions
|
||||
import com.unciv.logic.civilization.diplomacy.CityStatePersonality
|
||||
import com.unciv.logic.civilization.diplomacy.DiplomacyFlags
|
||||
import com.unciv.logic.civilization.diplomacy.DiplomacyManager
|
||||
import com.unciv.logic.civilization.diplomacy.DiplomacyFunctions
|
||||
import com.unciv.logic.civilization.diplomacy.DiplomaticStatus
|
||||
import com.unciv.logic.civilization.managers.EspionageManager
|
||||
import com.unciv.logic.civilization.managers.GoldenAgeManager
|
||||
@ -48,10 +48,8 @@ import com.unciv.models.ruleset.unique.UniqueType
|
||||
import com.unciv.models.ruleset.unique.getMatchingUniques
|
||||
import com.unciv.models.ruleset.unit.BaseUnit
|
||||
import com.unciv.models.stats.Stat
|
||||
import com.unciv.models.stats.Stats
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.utils.extensions.toPercent
|
||||
import com.unciv.ui.utils.extensions.withItem
|
||||
import com.unciv.ui.victoryscreen.RankingType
|
||||
import java.util.*
|
||||
import kotlin.math.max
|
||||
@ -91,6 +89,9 @@ class CivilizationInfo : IsPartOfGameInfoSerialization {
|
||||
@Transient
|
||||
val units = UnitManager(this)
|
||||
|
||||
@Transient
|
||||
var diplomacyFunctions = DiplomacyFunctions(this)
|
||||
|
||||
@Transient
|
||||
var viewableTiles = setOf<TileInfo>()
|
||||
|
||||
@ -328,39 +329,25 @@ class CivilizationInfo : IsPartOfGameInfoSerialization {
|
||||
fun knows(otherCivName: String) = diplomacy.containsKey(otherCivName)
|
||||
fun knows(otherCiv: CivilizationInfo) = knows(otherCiv.civName)
|
||||
|
||||
/** A sorted Sequence of all other civs we know (excluding barbarians and spectators) */
|
||||
fun getKnownCivsSorted(includeCityStates: Boolean = true, includeDefeated: Boolean = false) =
|
||||
gameInfo.civilizations.asSequence()
|
||||
.filterNot {
|
||||
it == this ||
|
||||
it.isBarbarian() || it.isSpectator() ||
|
||||
!this.knows(it) ||
|
||||
(!includeDefeated && it.isDefeated()) ||
|
||||
(!includeCityStates && it.isCityState())
|
||||
}
|
||||
.sortedWith(
|
||||
compareByDescending<CivilizationInfo> { it.isMajorCiv() }
|
||||
.thenBy (UncivGame.Current.settings.getCollatorFromLocale()) { it.civName.tr() }
|
||||
)
|
||||
fun getCapital() = cities.firstOrNull { it.isCapital() }
|
||||
fun isHuman() = playerType == PlayerType.Human
|
||||
fun isAI() = playerType == PlayerType.AI
|
||||
fun isOneCityChallenger() = (
|
||||
playerType == PlayerType.Human &&
|
||||
gameInfo.gameParameters.oneCityChallenge)
|
||||
fun isOneCityChallenger() = playerType == PlayerType.Human && gameInfo.gameParameters.oneCityChallenge
|
||||
|
||||
fun isCurrentPlayer() = gameInfo.currentPlayerCiv == this
|
||||
fun isMajorCiv() = nation.isMajorCiv()
|
||||
fun isMinorCiv() = nation.isCityState() || nation.isBarbarian()
|
||||
fun isCityState(): Boolean = nation.isCityState()
|
||||
fun isBarbarian() = nation.isBarbarian()
|
||||
fun isSpectator() = nation.isSpectator()
|
||||
fun isCityState(): Boolean = nation.isCityState()
|
||||
fun isAlive(): Boolean = !isDefeated()
|
||||
|
||||
@delegate:Transient
|
||||
val cityStateType: CityStateType by lazy { gameInfo.ruleSet.cityStateTypes[nation.cityStateType!!]!! }
|
||||
var cityStatePersonality: CityStatePersonality = CityStatePersonality.Neutral
|
||||
var cityStateResource: String? = null
|
||||
var cityStateUniqueUnit: String? = null // Unique unit for militaristic city state. Might still be null if there are no appropriate units
|
||||
fun isMajorCiv() = nation.isMajorCiv()
|
||||
fun isMinorCiv() = nation.isCityState() || nation.isBarbarian()
|
||||
fun isAlive(): Boolean = !isDefeated()
|
||||
|
||||
|
||||
fun hasMetCivTerritory(otherCiv: CivilizationInfo): Boolean = otherCiv.getCivTerritory().any { hasExplored(it) }
|
||||
fun getCompletedPolicyBranchesCount(): Int = policies.adoptedPolicies.count { Policy.isBranchCompleteByName(it) }
|
||||
@ -400,7 +387,6 @@ class CivilizationInfo : IsPartOfGameInfoSerialization {
|
||||
|
||||
fun getHappiness() = stats.happiness
|
||||
|
||||
|
||||
fun getCivResources(): ResourceSupplyList = summarizedCivResources
|
||||
|
||||
// Preserves some origins for resources so we can separate them for trades
|
||||
@ -509,6 +495,7 @@ class CivilizationInfo : IsPartOfGameInfoSerialization {
|
||||
?: throw UncivShowableException("Unit $baseUnitName doesn't seem to exist!")
|
||||
return getEquivalentUnit(baseUnit)
|
||||
}
|
||||
|
||||
fun getEquivalentUnit(baseUnit: BaseUnit): BaseUnit {
|
||||
if (baseUnit.replaces != null)
|
||||
return getEquivalentUnit(baseUnit.replaces!!) // Equivalent of unique unit is the equivalent of the replaced unit
|
||||
@ -519,56 +506,6 @@ class CivilizationInfo : IsPartOfGameInfoSerialization {
|
||||
return baseUnit
|
||||
}
|
||||
|
||||
fun makeCivilizationsMeet(otherCiv: CivilizationInfo, warOnContact: Boolean = false) {
|
||||
meetCiv(otherCiv, warOnContact)
|
||||
otherCiv.meetCiv(this, warOnContact)
|
||||
}
|
||||
|
||||
private fun meetCiv(otherCiv: CivilizationInfo, warOnContact: Boolean = false) {
|
||||
diplomacy[otherCiv.civName] = DiplomacyManager(this, otherCiv.civName)
|
||||
.apply { diplomaticStatus = DiplomaticStatus.Peace }
|
||||
|
||||
if (!otherCiv.isSpectator())
|
||||
otherCiv.popupAlerts.add(PopupAlert(AlertType.FirstContact, civName))
|
||||
|
||||
if (isCurrentPlayer())
|
||||
UncivGame.Current.settings.addCompletedTutorialTask("Meet another civilization")
|
||||
|
||||
if (!(isCityState() && otherCiv.isMajorCiv())) return
|
||||
if (warOnContact || otherCiv.isMinorCivAggressor()) return // No gift if they are bad people, or we are just about to be at war
|
||||
|
||||
val cityStateLocation = if (cities.isEmpty()) null else getCapital()!!.location
|
||||
|
||||
val giftAmount = Stats(gold = 15f)
|
||||
val faithAmount = Stats(faith = 4f)
|
||||
// Later, religious city-states will also gift gold, making this the better implementation
|
||||
// For now, it might be overkill though.
|
||||
var meetString = "[${civName}] has given us [${giftAmount}] as a token of goodwill for meeting us"
|
||||
val religionMeetString = "[${civName}] has also given us [${faithAmount}]"
|
||||
if (diplomacy.filter { it.value.otherCiv().isMajorCiv() }.size == 1) {
|
||||
giftAmount.timesInPlace(2f)
|
||||
meetString = "[${civName}] has given us [${giftAmount}] as we are the first major civ to meet them"
|
||||
}
|
||||
if (cityStateLocation != null)
|
||||
otherCiv.addNotification(meetString, cityStateLocation, NotificationCategory.Diplomacy, NotificationIcon.Gold)
|
||||
else
|
||||
otherCiv.addNotification(meetString, NotificationCategory.Diplomacy, NotificationIcon.Gold)
|
||||
|
||||
if (otherCiv.isCityState() && otherCiv.cityStateFunctions.canProvideStat(Stat.Faith)){
|
||||
otherCiv.addNotification(religionMeetString, NotificationCategory.Diplomacy, NotificationIcon.Faith)
|
||||
|
||||
for ((key, value) in faithAmount)
|
||||
otherCiv.addStat(key, value.toInt())
|
||||
}
|
||||
for ((key, value) in giftAmount)
|
||||
otherCiv.addStat(key, value.toInt())
|
||||
|
||||
if (cities.isNotEmpty())
|
||||
otherCiv.exploredTiles = otherCiv.exploredTiles.withItem(getCapital()!!.location)
|
||||
|
||||
questManager.justMet(otherCiv) // Include them in war with major pseudo-quest
|
||||
}
|
||||
|
||||
override fun toString(): String = civName // for debug
|
||||
|
||||
/**
|
||||
@ -587,31 +524,10 @@ class CivilizationInfo : IsPartOfGameInfoSerialization {
|
||||
|
||||
fun getEraNumber(): Int = getEra().eraNumber
|
||||
|
||||
fun isAtWarWith(otherCiv: CivilizationInfo): Boolean {
|
||||
return when {
|
||||
otherCiv == this -> false
|
||||
otherCiv.isBarbarian() || isBarbarian() -> true
|
||||
else -> {
|
||||
val diplomacyManager = diplomacy[otherCiv.civName]
|
||||
?: return false // not encountered yet
|
||||
return diplomacyManager.diplomaticStatus == DiplomaticStatus.War
|
||||
}
|
||||
}
|
||||
}
|
||||
fun isAtWarWith(otherCiv: CivilizationInfo) = diplomacyFunctions.isAtWarWith(otherCiv)
|
||||
|
||||
fun isAtWar() = diplomacy.values.any { it.diplomaticStatus == DiplomaticStatus.War && !it.otherCiv().isDefeated() }
|
||||
|
||||
fun getEnemyMovementPenalty(enemyUnit: MapUnit): Float {
|
||||
if (enemyMovementPenaltyUniques != null && enemyMovementPenaltyUniques!!.any()) {
|
||||
return enemyMovementPenaltyUniques!!.sumOf {
|
||||
if (it.type!! == UniqueType.EnemyLandUnitsSpendExtraMovement
|
||||
&& enemyUnit.matchesFilter(it.params[0]))
|
||||
it.params[1].toInt()
|
||||
else 0
|
||||
}.toFloat()
|
||||
}
|
||||
return 0f // should not reach this point
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a civilization caption suitable for greetings including player type info:
|
||||
@ -623,34 +539,13 @@ class CivilizationInfo : IsPartOfGameInfoSerialization {
|
||||
val online = gameInfo.gameParameters.isOnlineMultiplayer
|
||||
return nation.getLeaderDisplayName().tr() +
|
||||
when {
|
||||
!online && !severalHumans ->
|
||||
"" // offline single player will know everybody else is AI
|
||||
playerType == PlayerType.AI ->
|
||||
" (" + "AI".tr() + ")"
|
||||
online ->
|
||||
" (" + "Human".tr() + " - " + "Multiplayer".tr() + ")"
|
||||
else ->
|
||||
" (" + "Human".tr() + " - " + "Hotseat".tr() + ")"
|
||||
!online && !severalHumans -> "" // offline single player will know everybody else is AI
|
||||
playerType == PlayerType.AI -> " (${"AI".tr()})"
|
||||
online -> " (${"Human".tr()} - ${"Multiplayer".tr()})"
|
||||
else -> " (${"Human".tr()} - ${"Hotseat".tr()})"
|
||||
}
|
||||
}
|
||||
|
||||
fun canSignResearchAgreement(): Boolean {
|
||||
if (!isMajorCiv()) return false
|
||||
if (!hasUnique(UniqueType.EnablesResearchAgreements)) return false
|
||||
if (gameInfo.ruleSet.technologies.values
|
||||
.none { tech.canBeResearched(it.name) && !tech.isResearched(it.name) }) return false
|
||||
return true
|
||||
}
|
||||
|
||||
fun canSignResearchAgreementsWith(otherCiv: CivilizationInfo): Boolean {
|
||||
val diplomacyManager = getDiplomacyManager(otherCiv)
|
||||
val cost = getResearchAgreementCost()
|
||||
return canSignResearchAgreement() && otherCiv.canSignResearchAgreement()
|
||||
&& diplomacyManager.hasFlag(DiplomacyFlags.DeclarationOfFriendship)
|
||||
&& !diplomacyManager.hasFlag(DiplomacyFlags.ResearchAgreement)
|
||||
&& !diplomacyManager.otherCivDiplomacy().hasFlag(DiplomacyFlags.ResearchAgreement)
|
||||
&& gold >= cost && otherCiv.gold >= cost
|
||||
}
|
||||
|
||||
fun getStatForRanking(category: RankingType): Int {
|
||||
return if (isDefeated()) 0
|
||||
@ -687,9 +582,6 @@ class CivilizationInfo : IsPartOfGameInfoSerialization {
|
||||
return sum
|
||||
}
|
||||
|
||||
fun hasTechOrPolicy(techOrPolicyName: String) =
|
||||
tech.isResearched(techOrPolicyName) || policies.isAdopted(techOrPolicyName)
|
||||
|
||||
fun isMinorCivAggressor() = numMinorCivsAttacked >= 2
|
||||
fun isMinorCivWarmonger() = numMinorCivsAttacked >= 4
|
||||
|
||||
|
@ -257,7 +257,7 @@ class CityStateFunctions(val civInfo: CivilizationInfo) {
|
||||
civInfo.getDiplomacyManager(newEnemy).declareWar()
|
||||
else if (!civInfo.knows(newEnemy)) {
|
||||
// We have to meet first
|
||||
civInfo.makeCivilizationsMeet(newEnemy, warOnContact = true)
|
||||
civInfo.diplomacyFunctions.makeCivilizationsMeet(newEnemy, warOnContact = true)
|
||||
civInfo.getDiplomacyManager(newEnemy).declareWar()
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,119 @@
|
||||
package com.unciv.logic.civilization.diplomacy
|
||||
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.logic.civilization.AlertType
|
||||
import com.unciv.logic.civilization.CivilizationInfo
|
||||
import com.unciv.logic.civilization.NotificationCategory
|
||||
import com.unciv.logic.civilization.NotificationIcon
|
||||
import com.unciv.logic.civilization.PopupAlert
|
||||
import com.unciv.models.ruleset.unique.UniqueType
|
||||
import com.unciv.models.stats.Stat
|
||||
import com.unciv.models.stats.Stats
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.utils.extensions.withItem
|
||||
|
||||
class DiplomacyFunctions(val civInfo:CivilizationInfo){
|
||||
|
||||
/** A sorted Sequence of all other civs we know (excluding barbarians and spectators) */
|
||||
fun getKnownCivsSorted(includeCityStates: Boolean = true, includeDefeated: Boolean = false) =
|
||||
civInfo.gameInfo.civilizations.asSequence()
|
||||
.filterNot {
|
||||
it == civInfo ||
|
||||
it.isBarbarian() ||
|
||||
it.isSpectator() ||
|
||||
!civInfo.knows(it) ||
|
||||
!includeDefeated && it.isDefeated() ||
|
||||
!includeCityStates && it.isCityState()
|
||||
}
|
||||
.sortedWith(
|
||||
compareByDescending<CivilizationInfo> { it.isMajorCiv() }
|
||||
.thenBy (UncivGame.Current.settings.getCollatorFromLocale()) { it.civName.tr() }
|
||||
)
|
||||
|
||||
|
||||
fun makeCivilizationsMeet(otherCiv: CivilizationInfo, warOnContact: Boolean = false) {
|
||||
meetCiv(otherCiv, warOnContact)
|
||||
otherCiv.diplomacyFunctions.meetCiv(civInfo, warOnContact)
|
||||
}
|
||||
|
||||
fun meetCiv(otherCiv: CivilizationInfo, warOnContact: Boolean = false) {
|
||||
civInfo.diplomacy[otherCiv.civName] = DiplomacyManager(civInfo, otherCiv.civName)
|
||||
.apply { diplomaticStatus = DiplomaticStatus.Peace }
|
||||
|
||||
if (!otherCiv.isSpectator())
|
||||
otherCiv.popupAlerts.add(PopupAlert(AlertType.FirstContact, civInfo.civName))
|
||||
|
||||
if (civInfo.isCurrentPlayer())
|
||||
UncivGame.Current.settings.addCompletedTutorialTask("Meet another civilization")
|
||||
|
||||
|
||||
if (civInfo.isCityState() && otherCiv.isMajorCiv()) {
|
||||
if (warOnContact || otherCiv.isMinorCivAggressor()) return // No gift if they are bad people, or we are just about to be at war
|
||||
|
||||
val cityStateLocation = if (civInfo.cities.isEmpty()) null else civInfo.getCapital()!!.location
|
||||
|
||||
val giftAmount = Stats(gold = 15f)
|
||||
val faithAmount = Stats(faith = 4f)
|
||||
// Later, religious city-states will also gift gold, making this the better implementation
|
||||
// For now, it might be overkill though.
|
||||
var meetString = "[${civInfo.civName}] has given us [${giftAmount}] as a token of goodwill for meeting us"
|
||||
val religionMeetString = "[${civInfo.civName}] has also given us [${faithAmount}]"
|
||||
if (civInfo.diplomacy.filter { it.value.otherCiv().isMajorCiv() }.size == 1) {
|
||||
giftAmount.timesInPlace(2f)
|
||||
meetString = "[${civInfo.civName}] has given us [${giftAmount}] as we are the first major civ to meet them"
|
||||
}
|
||||
if (cityStateLocation != null)
|
||||
otherCiv.addNotification(meetString, cityStateLocation, NotificationCategory.Diplomacy, NotificationIcon.Gold)
|
||||
else
|
||||
otherCiv.addNotification(meetString, NotificationCategory.Diplomacy, NotificationIcon.Gold)
|
||||
|
||||
if (otherCiv.isCityState() && otherCiv.cityStateFunctions.canProvideStat(Stat.Faith)){
|
||||
otherCiv.addNotification(religionMeetString, NotificationCategory.Diplomacy, NotificationIcon.Faith)
|
||||
|
||||
for ((key, value) in faithAmount)
|
||||
otherCiv.addStat(key, value.toInt())
|
||||
}
|
||||
for ((key, value) in giftAmount)
|
||||
otherCiv.addStat(key, value.toInt())
|
||||
|
||||
if (civInfo.cities.isNotEmpty())
|
||||
otherCiv.exploredTiles = otherCiv.exploredTiles.withItem(civInfo.getCapital()!!.location)
|
||||
|
||||
civInfo.questManager.justMet(otherCiv) // Include them in war with major pseudo-quest
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun isAtWarWith(otherCiv: CivilizationInfo): Boolean {
|
||||
return when {
|
||||
otherCiv == civInfo -> false
|
||||
otherCiv.isBarbarian() || civInfo.isBarbarian() -> true
|
||||
else -> {
|
||||
val diplomacyManager = civInfo.diplomacy[otherCiv.civName]
|
||||
?: return false // not encountered yet
|
||||
return diplomacyManager.diplomaticStatus == DiplomaticStatus.War
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun canSignResearchAgreement(): Boolean {
|
||||
if (!civInfo.isMajorCiv()) return false
|
||||
if (!civInfo.hasUnique(UniqueType.EnablesResearchAgreements)) return false
|
||||
if (civInfo.gameInfo.ruleSet.technologies.values
|
||||
.none { civInfo.tech.canBeResearched(it.name) && !civInfo.tech.isResearched(it.name) }) return false
|
||||
return true
|
||||
}
|
||||
|
||||
fun canSignResearchAgreementsWith(otherCiv: CivilizationInfo): Boolean {
|
||||
val diplomacyManager = civInfo.getDiplomacyManager(otherCiv)
|
||||
val cost = civInfo.getResearchAgreementCost()
|
||||
return canSignResearchAgreement() && otherCiv.diplomacyFunctions.canSignResearchAgreement()
|
||||
&& diplomacyManager.hasFlag(DiplomacyFlags.DeclarationOfFriendship)
|
||||
&& !diplomacyManager.hasFlag(DiplomacyFlags.ResearchAgreement)
|
||||
&& !diplomacyManager.otherCivDiplomacy().hasFlag(DiplomacyFlags.ResearchAgreement)
|
||||
&& civInfo.gold >= cost && otherCiv.gold >= cost
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -665,7 +665,7 @@ class DiplomacyManager() : IsPartOfGameInfoSerialization {
|
||||
thirdCiv.getDiplomacyManager(civAtWarWith).declareWar(true)
|
||||
else if (!thirdCiv.knows(civAtWarWith)) {
|
||||
// Our city state ally has not met them yet, so they have to meet first
|
||||
thirdCiv.makeCivilizationsMeet(civAtWarWith, warOnContact = true)
|
||||
thirdCiv.diplomacyFunctions.makeCivilizationsMeet(civAtWarWith, warOnContact = true)
|
||||
thirdCiv.getDiplomacyManager(civAtWarWith).declareWar(true)
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ class CivInfoTransientCache(val civInfo: CivilizationInfo) {
|
||||
for (entry in viewedCivs) {
|
||||
val metCiv = entry.key
|
||||
if (metCiv == civInfo || metCiv.isBarbarian() || civInfo.diplomacy.containsKey(metCiv.civName)) continue
|
||||
civInfo.makeCivilizationsMeet(metCiv)
|
||||
civInfo.diplomacyFunctions.makeCivilizationsMeet(metCiv)
|
||||
civInfo.addNotification("We have encountered [${metCiv.civName}]!",
|
||||
entry.value.position,
|
||||
NotificationCategory.Diplomacy, metCiv.civName,
|
||||
|
@ -2,8 +2,8 @@ package com.unciv.logic.map
|
||||
|
||||
import com.badlogic.gdx.math.Vector2
|
||||
import com.unciv.Constants
|
||||
import com.unciv.logic.map.HexMath.getDistance
|
||||
import com.unciv.logic.civilization.CivilizationInfo
|
||||
import com.unciv.logic.map.HexMath.getDistance
|
||||
import com.unciv.models.helpers.UnitMovementMemoryType
|
||||
import com.unciv.models.ruleset.unique.UniqueType
|
||||
|
||||
@ -11,6 +11,18 @@ class UnitMovementAlgorithms(val unit: MapUnit) {
|
||||
|
||||
private val pathfindingCache = PathfindingCache(unit)
|
||||
|
||||
fun getEnemyMovementPenalty(civInfo:CivilizationInfo, enemyUnit: MapUnit): Float {
|
||||
if (civInfo.enemyMovementPenaltyUniques != null && civInfo.enemyMovementPenaltyUniques!!.any()) {
|
||||
return civInfo.enemyMovementPenaltyUniques!!.sumOf {
|
||||
if (it.type!! == UniqueType.EnemyLandUnitsSpendExtraMovement
|
||||
&& enemyUnit.matchesFilter(it.params[0]))
|
||||
it.params[1].toInt()
|
||||
else 0
|
||||
}.toFloat()
|
||||
}
|
||||
return 0f // should not reach this point
|
||||
}
|
||||
|
||||
// This function is called ALL THE TIME and should be as time-optimal as possible!
|
||||
private fun getMovementCostBetweenAdjacentTiles(
|
||||
from: TileInfo,
|
||||
@ -36,7 +48,7 @@ class UnitMovementAlgorithms(val unit: MapUnit) {
|
||||
toOwner != null &&
|
||||
toOwner.hasActiveEnemyMovementPenalty &&
|
||||
civInfo.isAtWarWith(toOwner)
|
||||
) toOwner.getEnemyMovementPenalty(unit) else 0f
|
||||
) getEnemyMovementPenalty(toOwner, unit) else 0f
|
||||
|
||||
if (from.getUnpillagedRoad() == RoadStatus.Railroad && to.getUnpillagedRoad() == RoadStatus.Railroad)
|
||||
return RoadStatus.Railroad.movement + extraCost
|
||||
|
@ -120,7 +120,7 @@ class TradeLogic(val ourCivilization:CivilizationInfo, val otherCivilization: Ci
|
||||
}
|
||||
}
|
||||
if (offer.type == TradeType.Introduction)
|
||||
to.makeCivilizationsMeet(to.gameInfo.getCivilization(offer.name))
|
||||
to.diplomacyFunctions.makeCivilizationsMeet(to.gameInfo.getCivilization(offer.name))
|
||||
if (offer.type == TradeType.WarDeclaration) {
|
||||
val nameOfCivToDeclareWarOn = offer.name
|
||||
from.getDiplomacyManager(nameOfCivToDeclareWarOn).declareWar()
|
||||
|
@ -232,8 +232,6 @@ class Ruleset {
|
||||
allRulesetObjects() + sequenceOf(modOptions)
|
||||
|
||||
fun load(folderHandle: FileHandle) {
|
||||
val gameBasicsStartTime = System.currentTimeMillis()
|
||||
|
||||
val modOptionsFile = folderHandle.child("ModOptions.json")
|
||||
if (modOptionsFile.exists()) {
|
||||
try {
|
||||
|
@ -271,7 +271,7 @@ class Unique(val text: String, val sourceObjectType: UniqueTarget? = null, val s
|
||||
UniqueType.ConditionalFirstCivToResearch -> sourceObjectType == UniqueTarget.Tech
|
||||
&& state.civInfo != null
|
||||
&& state.civInfo.gameInfo.civilizations.none {
|
||||
it != state.civInfo && it.isMajorCiv() && it.hasTechOrPolicy(sourceObjectName!!)
|
||||
it != state.civInfo && it.isMajorCiv() && (it.tech.isResearched(sourceObjectName!!) || it.policies.isAdopted(sourceObjectName))
|
||||
}
|
||||
|
||||
else -> false
|
||||
|
@ -10,14 +10,13 @@ import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.pickerscreens.PickerScreen
|
||||
import com.unciv.ui.popup.Popup
|
||||
import com.unciv.ui.popup.ToastPopup
|
||||
import com.unciv.ui.utils.BaseScreen
|
||||
import com.unciv.ui.utils.extensions.disable
|
||||
import com.unciv.ui.utils.extensions.enable
|
||||
import com.unciv.ui.utils.extensions.onClick
|
||||
import com.unciv.ui.utils.extensions.toTextButton
|
||||
import com.unciv.ui.utils.AutoScrollPane as ScrollPane
|
||||
|
||||
class MultiplayerScreen(previousScreen: BaseScreen) : PickerScreen() {
|
||||
class MultiplayerScreen : PickerScreen() {
|
||||
private var selectedGame: OnlineMultiplayerGame? = null
|
||||
|
||||
private val editButtonText = "Game settings"
|
||||
|
@ -7,7 +7,6 @@ import com.unciv.models.metadata.GameSettings
|
||||
import com.unciv.ui.utils.BaseScreen
|
||||
import com.unciv.ui.utils.UncivSlider
|
||||
import com.unciv.ui.utils.extensions.toLabel
|
||||
import com.unciv.ui.worldscreen.WorldScreen
|
||||
|
||||
fun gameplayTab(
|
||||
optionsPopup: OptionsPopup
|
||||
@ -45,10 +44,14 @@ fun gameplayTab(
|
||||
optionsPopup.addCheckbox(this, "Order trade offers by amount", settings.orderTradeOffersByAmount) { settings.orderTradeOffersByAmount = it }
|
||||
optionsPopup.addCheckbox(this, "Ask for confirmation when pressing next turn", settings.confirmNextTurn) { settings.confirmNextTurn = it }
|
||||
|
||||
addNotificationLogMaxTurnsSlider(this, settings, UncivGame.Current.worldScreen, optionsPopup.selectBoxMinWidth)
|
||||
addNotificationLogMaxTurnsSlider(this, settings, optionsPopup.selectBoxMinWidth)
|
||||
}
|
||||
|
||||
private fun addNotificationLogMaxTurnsSlider(table: Table, settings: GameSettings, screen: BaseScreen?, selectBoxMinWidth: Float) {
|
||||
private fun addNotificationLogMaxTurnsSlider(
|
||||
table: Table,
|
||||
settings: GameSettings,
|
||||
selectBoxMinWidth: Float
|
||||
) {
|
||||
table.add("Notifications log max turns".toLabel()).left().fillX()
|
||||
|
||||
val minimapSlider = UncivSlider(
|
||||
|
@ -9,11 +9,11 @@ import com.badlogic.gdx.scenes.scene2d.ui.TextButton
|
||||
import com.badlogic.gdx.utils.Align
|
||||
import com.unciv.Constants
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.logic.map.HexMath
|
||||
import com.unciv.logic.civilization.CivilizationInfo
|
||||
import com.unciv.logic.civilization.diplomacy.DiplomacyFlags
|
||||
import com.unciv.logic.civilization.diplomacy.DiplomaticStatus
|
||||
import com.unciv.logic.civilization.diplomacy.RelationshipLevel
|
||||
import com.unciv.logic.map.HexMath
|
||||
import com.unciv.models.ruleset.Policy.PolicyBranchType
|
||||
import com.unciv.ui.images.ImageGetter
|
||||
import com.unciv.ui.trade.DiplomacyScreen
|
||||
@ -262,8 +262,8 @@ class GlobalPoliticsOverviewTable (
|
||||
!it.isSpectator() && !it.isBarbarian() && (persistableData.includeCityStates || !it.isCityState())
|
||||
}
|
||||
undefeatedCivs = sequenceOf(viewingPlayer) +
|
||||
viewingPlayer.getKnownCivsSorted(persistableData.includeCityStates)
|
||||
defeatedCivs = viewingPlayer.getKnownCivsSorted(persistableData.includeCityStates, true)
|
||||
viewingPlayer.diplomacyFunctions.getKnownCivsSorted(persistableData.includeCityStates)
|
||||
defeatedCivs = viewingPlayer.diplomacyFunctions.getKnownCivsSorted(persistableData.includeCityStates, true)
|
||||
.filter { it.isDefeated() }
|
||||
|
||||
clear()
|
||||
|
@ -83,7 +83,7 @@ class PickerPane(
|
||||
/** Return a button for picker screens that display a list of big buttons with icons and labels. */
|
||||
fun getPickerOptionButton(icon: Actor, label: String): Button {
|
||||
return IconTextButton(label, icon).apply {
|
||||
iconCell!!.size(pickerOptionIconSize).pad(10f)
|
||||
iconCell.size(pickerOptionIconSize).pad(10f)
|
||||
labelCell.pad(10f)
|
||||
}
|
||||
}
|
||||
|
@ -211,7 +211,7 @@ class PolicyPickerScreen(val worldScreen: WorldScreen, civInfo: CivilizationInfo
|
||||
topTable.row()
|
||||
|
||||
val branches = viewingCiv.gameInfo.ruleSet.policyBranches
|
||||
var rowChangeCount = Int.MAX_VALUE
|
||||
val rowChangeCount: Int
|
||||
|
||||
// estimate how many branch boxes fit using average size (including pad)
|
||||
// TODO If we'd want to use scene2d correctly, this is supposed to happen inside an overridden layout() method
|
||||
@ -220,9 +220,7 @@ class PolicyPickerScreen(val worldScreen: WorldScreen, civInfo: CivilizationInfo
|
||||
if (numBranchesY > 1.5f) {
|
||||
val numRows = if (numBranchesY < 2.9f) 2 else (numBranchesY + 0.1f).toInt()
|
||||
rowChangeCount = (branches.size + numRows - 1) / numRows
|
||||
} else {
|
||||
rowChangeCount = branches.size
|
||||
}
|
||||
} else rowChangeCount = branches.size
|
||||
|
||||
|
||||
// Actually create and distribute the policy branches
|
||||
|
@ -8,7 +8,6 @@ import com.badlogic.gdx.utils.Align
|
||||
import com.unciv.Constants
|
||||
import com.unciv.UncivGame
|
||||
import com.unciv.logic.civilization.AlertType
|
||||
import com.unciv.logic.civilization.managers.AssignedQuest
|
||||
import com.unciv.logic.civilization.CivilizationInfo
|
||||
import com.unciv.logic.civilization.PopupAlert
|
||||
import com.unciv.logic.civilization.diplomacy.DiplomacyFlags
|
||||
@ -17,6 +16,7 @@ import com.unciv.logic.civilization.diplomacy.DiplomaticModifiers
|
||||
import com.unciv.logic.civilization.diplomacy.DiplomaticModifiers.*
|
||||
import com.unciv.logic.civilization.diplomacy.DiplomaticStatus
|
||||
import com.unciv.logic.civilization.diplomacy.RelationshipLevel
|
||||
import com.unciv.logic.civilization.managers.AssignedQuest
|
||||
import com.unciv.logic.trade.Trade
|
||||
import com.unciv.logic.trade.TradeLogic
|
||||
import com.unciv.logic.trade.TradeOffer
|
||||
@ -113,7 +113,7 @@ class DiplomacyScreen(
|
||||
|
||||
var selectCivY = 0f
|
||||
|
||||
for (civ in viewingCiv.getKnownCivsSorted()) {
|
||||
for (civ in viewingCiv.diplomacyFunctions.getKnownCivsSorted()) {
|
||||
if (civ == selectCiv) {
|
||||
selectCivY = leftSideTable.prefHeight
|
||||
}
|
||||
@ -665,7 +665,7 @@ class DiplomacyScreen(
|
||||
diplomacyTable.add(getDeclareFriendshipButton(otherCiv)).row()
|
||||
|
||||
|
||||
if (viewingCiv.canSignResearchAgreementsWith(otherCiv))
|
||||
if (viewingCiv.diplomacyFunctions.canSignResearchAgreementsWith(otherCiv))
|
||||
diplomacyTable.add(getResearchAgreementButton(otherCiv)).row()
|
||||
|
||||
if (!diplomacyManager.hasFlag(DiplomacyFlags.Denunciation)
|
||||
|
@ -884,7 +884,7 @@ object UnitActions {
|
||||
val otherCiv = tile.getOwner()
|
||||
if (otherCiv != null) {
|
||||
// decrease relations for -10 pt/tile
|
||||
if (!otherCiv.knows(unit.civInfo)) otherCiv.makeCivilizationsMeet(unit.civInfo)
|
||||
if (!otherCiv.knows(unit.civInfo)) otherCiv.diplomacyFunctions.makeCivilizationsMeet(unit.civInfo)
|
||||
otherCiv.getDiplomacyManager(unit.civInfo).addModifier(DiplomaticModifiers.StealingTerritory, -10f)
|
||||
civsToNotify.add(otherCiv)
|
||||
}
|
||||
@ -989,7 +989,7 @@ object UnitActions {
|
||||
.addModifier(DiplomaticModifiers.GaveUsUnits, 5f)
|
||||
|
||||
if (recipient.isCityState() && unit.isGreatPerson())
|
||||
unit.destroy() // City states dont get GPs
|
||||
unit.destroy() // City states don't get GPs
|
||||
else
|
||||
unit.gift(recipient)
|
||||
UncivGame.Current.worldScreen!!.shouldUpdate = true
|
||||
|
@ -25,7 +25,7 @@ class DiplomacyManagerTests {
|
||||
|
||||
private fun meetByName(civilization: String, civilizationToMeet: String) {
|
||||
civilizations.getValue(civilization)
|
||||
.makeCivilizationsMeet(civilizations.getValue(civilizationToMeet))
|
||||
.diplomacyFunctions.makeCivilizationsMeet(civilizations.getValue(civilizationToMeet))
|
||||
}
|
||||
|
||||
@Before
|
||||
|
@ -80,7 +80,7 @@ class SerializationTests {
|
||||
|
||||
// Ensure some diplomacy objects are instantiated
|
||||
val otherCiv = game.getCivilization("Greece")
|
||||
civ.makeCivilizationsMeet(otherCiv)
|
||||
civ.diplomacyFunctions.makeCivilizationsMeet(otherCiv)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -383,7 +383,7 @@ class GlobalUniquesTests {
|
||||
val cityStateTile = game.getTile(Vector2(0f, 1f))
|
||||
@Suppress("UNUSED_VARIABLE")
|
||||
val cityStateCity = game.addCity(cityState, cityStateTile, true)
|
||||
civInfo.makeCivilizationsMeet(cityState)
|
||||
civInfo.diplomacyFunctions.makeCivilizationsMeet(cityState)
|
||||
cityState.getDiplomacyManager(civInfo).addInfluence(100f)
|
||||
|
||||
city.cityStats.update()
|
||||
|
Reference in New Issue
Block a user