mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-14 01:39:40 +07:00
Implemented "Don't settle cities near us", which goes both ways - a good basis for further demands (#831)
This commit is contained in:
@ -126,7 +126,7 @@
|
||||
Portuguese:"Dessa vez não."
|
||||
}
|
||||
|
||||
"Excellent!":{ // AI statement after we accept a trade they proposed, and when we meet a city state
|
||||
"Excellent!":{ // AI statement after we accept a trade they proposed, and when we meet a city state, and our response when they agree to our diplomatic demand
|
||||
Italian:"Eccellente!"
|
||||
Simplified_Chinese:"好极了!和和气气才是生财之道。"
|
||||
French:"Excellent!"
|
||||
@ -358,8 +358,18 @@
|
||||
French:"Vous avez dénoncé nos ennemies"
|
||||
}
|
||||
|
||||
// Demands
|
||||
"Demands":{}
|
||||
"Please don't settle new cities near us.":{}
|
||||
"Very well, we shall look for new lands to settle.":{}
|
||||
"We shall do as we please.":{}
|
||||
|
||||
"You betrayed your promise to not settle cities near us":{}
|
||||
|
||||
"You refused to stop settling cities near us":{}
|
||||
|
||||
"We noticed your new city near our borders, despite your promise. This will have....implications.":{}
|
||||
|
||||
|
||||
////// Trade
|
||||
|
||||
|
@ -147,7 +147,8 @@ class GameInfo {
|
||||
for (civ in civilizations.filter { !it.isBarbarianCivilization() && !it.isDefeated() }) {
|
||||
allResearchedTechs.retainAll(civ.tech.techsResearched)
|
||||
}
|
||||
val unitList = GameBasics.Units.values.filter { !it.unitType.isCivilian() && it.uniqueTo == null }
|
||||
val unitList = GameBasics.Units.values
|
||||
.filter { !it.unitType.isCivilian() && it.uniqueTo == null }
|
||||
.filter{ allResearchedTechs.contains(it.requiredTech)
|
||||
&& (it.obsoleteTech == null || !allResearchedTechs.contains(it.obsoleteTech!!)) }
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.unciv.logic.automation
|
||||
|
||||
import com.unciv.Constants
|
||||
import com.unciv.logic.city.CityInfo
|
||||
import com.unciv.logic.civilization.*
|
||||
import com.unciv.logic.civilization.diplomacy.DiplomacyFlags
|
||||
import com.unciv.logic.civilization.diplomacy.DiplomaticModifiers
|
||||
@ -22,6 +21,7 @@ class NextTurnAutomation{
|
||||
offerPeaceTreaty(civInfo)
|
||||
exchangeTechs(civInfo)
|
||||
exchangeLuxuries(civInfo)
|
||||
issueRequests(civInfo)
|
||||
}
|
||||
|
||||
chooseTechToResearch(civInfo)
|
||||
@ -36,6 +36,7 @@ class NextTurnAutomation{
|
||||
civInfo.popupAlerts.clear() // AIs don't care about popups.
|
||||
}
|
||||
|
||||
|
||||
private fun buyBuildingOrUnit(civInfo: CivilizationInfo) {
|
||||
//allow AI spending money to purchase building & unit
|
||||
for (city in civInfo.cities.sortedByDescending{ it.population.population }) {
|
||||
@ -349,17 +350,30 @@ class NextTurnAutomation{
|
||||
}
|
||||
|
||||
|
||||
fun onCitySettledNearBorders(civInfo: CivilizationInfo, newCity: CityInfo){
|
||||
val diplomacyManager = civInfo.getDiplomacyManager(newCity.civInfo)
|
||||
if(diplomacyManager.hasFlag(DiplomacyFlags.IgnoreThemSettlingNearUs)) return
|
||||
if(diplomacyManager.hasFlag(DiplomacyFlags.AgreedToNotSettleNearUs)){
|
||||
newCity.civInfo.popupAlerts.add(PopupAlert(AlertType.CitySettledNearOtherCivDespiteOurPromise, civInfo.civName))
|
||||
diplomacyManager.setFlag(DiplomacyFlags.IgnoreThemSettlingNearUs,200)
|
||||
diplomacyManager.setModifier(DiplomaticModifiers.BetrayedPromiseToNotSettleCitiesNearUs,-20f)
|
||||
}
|
||||
else{
|
||||
newCity.civInfo.popupAlerts.add(PopupAlert(AlertType.CitySettledNearOtherCiv, civInfo.civName))
|
||||
private fun issueRequests(civInfo: CivilizationInfo) {
|
||||
for(otherCiv in civInfo.getKnownCivs().filter { it.isMajorCiv() }){
|
||||
val diploManager = civInfo.getDiplomacyManager(otherCiv)
|
||||
if(diploManager.hasFlag(DiplomacyFlags.SettledCitiesNearUs))
|
||||
onCitySettledNearBorders(civInfo,otherCiv)
|
||||
}
|
||||
}
|
||||
|
||||
fun onCitySettledNearBorders(civInfo: CivilizationInfo, otherCiv:CivilizationInfo){
|
||||
val diplomacyManager = civInfo.getDiplomacyManager(otherCiv)
|
||||
when {
|
||||
diplomacyManager.hasFlag(DiplomacyFlags.IgnoreThemSettlingNearUs) -> {}
|
||||
diplomacyManager.hasFlag(DiplomacyFlags.AgreedToNotSettleNearUs) -> {
|
||||
otherCiv.popupAlerts.add(PopupAlert(AlertType.CitySettledNearOtherCivDespiteOurPromise, civInfo.civName))
|
||||
diplomacyManager.setFlag(DiplomacyFlags.IgnoreThemSettlingNearUs,200)
|
||||
diplomacyManager.setModifier(DiplomaticModifiers.BetrayedPromiseToNotSettleCitiesNearUs,-20f)
|
||||
}
|
||||
else -> {
|
||||
val threatLevel = Automation().threatAssessment(civInfo,otherCiv)
|
||||
if(threatLevel<ThreatLevel.High) // don't piss them off for no reason please.
|
||||
otherCiv.popupAlerts.add(PopupAlert(AlertType.CitySettledNearOtherCiv, civInfo.civName))
|
||||
}
|
||||
}
|
||||
diplomacyManager.removeFlag(DiplomacyFlags.SettledCitiesNearUs)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package com.unciv.logic.automation
|
||||
import com.unciv.UnCivGame
|
||||
import com.unciv.logic.civilization.CivilizationInfo
|
||||
import com.unciv.logic.civilization.GreatPersonManager
|
||||
import com.unciv.logic.civilization.diplomacy.DiplomacyFlags
|
||||
import com.unciv.logic.map.MapUnit
|
||||
import com.unciv.logic.map.TileInfo
|
||||
import com.unciv.models.stats.Stats
|
||||
@ -81,7 +82,15 @@ class SpecificUnitAutomation{
|
||||
if(unit.getTile().militaryUnit==null) return // Don't move until you're accompanied by a military unit
|
||||
|
||||
val tilesNearCities = unit.civInfo.gameInfo.civilizations.flatMap { it.cities }
|
||||
.flatMap { it.getCenterTile().getTilesInDistance(3) }.toHashSet()
|
||||
.flatMap {
|
||||
val distanceAwayFromCity =
|
||||
if (it.civInfo.knows(unit.civInfo.civName)
|
||||
&& it.civInfo.getDiplomacyManager(unit.civInfo).hasFlag(DiplomacyFlags.WeAgreedNotToSettleNearThem))
|
||||
6
|
||||
else 3
|
||||
it.getCenterTile().getTilesInDistance(distanceAwayFromCity)
|
||||
}
|
||||
.toHashSet()
|
||||
|
||||
// This is to improve performance - instead of ranking each tile in the area up to 19 times, do it once.
|
||||
val nearbyTileRankings = unit.getTile().getTilesInDistance(7)
|
||||
|
@ -4,6 +4,7 @@ import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.math.Vector2
|
||||
import com.unciv.Constants
|
||||
import com.unciv.logic.civilization.CivilizationInfo
|
||||
import com.unciv.logic.civilization.diplomacy.DiplomacyFlags
|
||||
import com.unciv.logic.map.RoadStatus
|
||||
import com.unciv.logic.map.TileInfo
|
||||
import com.unciv.logic.map.TileMap
|
||||
@ -39,7 +40,7 @@ class CityInfo {
|
||||
var hasSoldBuildingThisTurn = false
|
||||
|
||||
constructor() // for json parsing, we need to have a default constructor
|
||||
constructor(civInfo: CivilizationInfo, cityLocation: Vector2) {
|
||||
constructor(civInfo: CivilizationInfo, cityLocation: Vector2) { // new city!
|
||||
this.civInfo = civInfo
|
||||
this.location = cityLocation
|
||||
setTransients()
|
||||
@ -78,6 +79,15 @@ class CityInfo {
|
||||
workedTiles = hashSetOf() //reassign 1st working tile
|
||||
population.autoAssignPopulation()
|
||||
cityStats.update()
|
||||
|
||||
val citiesWithin6Tiles = civInfo.gameInfo.civilizations.filter { it.isMajorCiv() && it!=civInfo }
|
||||
.flatMap { it.cities }
|
||||
.filter { it.getCenterTile().arialDistanceTo(getCenterTile()) <= 6 }
|
||||
val civsWithCloseCities = citiesWithin6Tiles.map { it.civInfo }.distinct()
|
||||
.filter { it.exploredTiles.contains(location) }
|
||||
for(otherCiv in civsWithCloseCities)
|
||||
otherCiv.getDiplomacyManager(civInfo).setFlag(DiplomacyFlags.SettledCitiesNearUs,30)
|
||||
|
||||
}
|
||||
|
||||
//region pure functions
|
||||
|
@ -29,7 +29,9 @@ enum class DiplomacyFlags{
|
||||
DeclarationOfFriendship,
|
||||
Denunceation,
|
||||
BorderConflict,
|
||||
SettledCitiesNearUs,
|
||||
AgreedToNotSettleNearUs,
|
||||
WeAgreedNotToSettleNearThem,
|
||||
IgnoreThemSettlingNearUs
|
||||
}
|
||||
|
||||
@ -41,6 +43,7 @@ enum class DiplomaticModifiers{
|
||||
BetrayedDeclarationOfFriendship,
|
||||
Denunciation,
|
||||
DenouncedOurAllies,
|
||||
RefusedToNotSettleCitiesNearUs,
|
||||
BetrayedPromiseToNotSettleCitiesNearUs,
|
||||
|
||||
YearsOfPeace,
|
||||
@ -48,7 +51,8 @@ enum class DiplomaticModifiers{
|
||||
DeclarationOfFriendship,
|
||||
DeclaredFriendshipWithOurAllies,
|
||||
DenouncedOurEnemies,
|
||||
OpenBorders
|
||||
OpenBorders,
|
||||
FulfilledPromiseToNotSettleCitiesNearUs
|
||||
}
|
||||
|
||||
class DiplomacyManager() {
|
||||
@ -241,7 +245,10 @@ class DiplomacyManager() {
|
||||
revertToZero(DiplomaticModifiers.DeclaredWarOnUs,1/8f) // this disappears real slow - it'll take 160 turns to really forget, this is war declaration we're talking about
|
||||
revertToZero(DiplomaticModifiers.WarMongerer,1/2f) // warmongering gives a big negative boost when it happens but they're forgotten relatively quickly, like WWII amirite
|
||||
revertToZero(DiplomaticModifiers.CapturedOurCities,1/4f) // if you captured our cities, though, that's harder to forget
|
||||
revertToZero(DiplomaticModifiers.BetrayedDeclarationOfFriendship,1/2f) // if you captured our cities, though, that's harder to forget
|
||||
revertToZero(DiplomaticModifiers.BetrayedDeclarationOfFriendship,1/8f) // That's a bastardly thing to do
|
||||
revertToZero(DiplomaticModifiers.RefusedToNotSettleCitiesNearUs,1/4f)
|
||||
revertToZero(DiplomaticModifiers.BetrayedPromiseToNotSettleCitiesNearUs,1/8f) // That's a bastardly thing to do
|
||||
|
||||
if(!hasFlag(DiplomacyFlags.DeclarationOfFriendship))
|
||||
revertToZero(DiplomaticModifiers.DeclarationOfFriendship, 1/2f) //decreases slowly and will revert to full if it is declared later
|
||||
|
||||
@ -249,6 +256,8 @@ class DiplomacyManager() {
|
||||
flagsCountdown[flag] = flagsCountdown[flag]!! - 1
|
||||
if(flagsCountdown[flag]==0) {
|
||||
flagsCountdown.remove(flag)
|
||||
if(flag==DiplomacyFlags.AgreedToNotSettleNearUs.name)
|
||||
addModifier(DiplomaticModifiers.FulfilledPromiseToNotSettleCitiesNearUs,10f)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,8 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
|
||||
import com.unciv.Constants
|
||||
import com.unciv.UnCivGame
|
||||
import com.unciv.logic.automation.Automation
|
||||
import com.unciv.logic.automation.ThreatLevel
|
||||
import com.unciv.logic.civilization.CityStateType
|
||||
import com.unciv.logic.civilization.CivilizationInfo
|
||||
import com.unciv.logic.civilization.diplomacy.DiplomacyFlags
|
||||
@ -78,10 +80,10 @@ class DiplomacyScreen:CameraStageBaseScreen() {
|
||||
}
|
||||
}
|
||||
|
||||
fun updateRightSide(civ: CivilizationInfo){
|
||||
fun updateRightSide(otherCiv: CivilizationInfo){
|
||||
rightSideTable.clear()
|
||||
if(civ.isCityState()) rightSideTable.add(getCityStateDiplomacyTable(civ))
|
||||
else rightSideTable.add(getMajorCivDiplomacyTable(civ))
|
||||
if(otherCiv.isCityState()) rightSideTable.add(getCityStateDiplomacyTable(otherCiv))
|
||||
else rightSideTable.add(getMajorCivDiplomacyTable(otherCiv))
|
||||
}
|
||||
|
||||
fun setTrade(civ: CivilizationInfo): TradeTable {
|
||||
@ -209,7 +211,7 @@ class DiplomacyScreen:CameraStageBaseScreen() {
|
||||
val declareFriendshipButton = TextButton("Declare Friendship ([30] turns)".tr(),skin)
|
||||
declareFriendshipButton.onClick {
|
||||
diplomacyManager.signDeclarationOfFriendship()
|
||||
setRightSideFlavorText(otherCiv,"May our nations forever remain united!".tr(),"Indeed!".tr())
|
||||
setRightSideFlavorText(otherCiv,"May our nations forever remain united!","Indeed!")
|
||||
}
|
||||
diplomacyTable.add(declareFriendshipButton).row()
|
||||
}
|
||||
@ -219,7 +221,7 @@ class DiplomacyScreen:CameraStageBaseScreen() {
|
||||
val denounceButton = TextButton("Denounce ([30] turns)".tr(),skin)
|
||||
denounceButton.onClick {
|
||||
diplomacyManager.denounce()
|
||||
setRightSideFlavorText(otherCiv,"We will remember this.".tr(),"Very well.".tr())
|
||||
setRightSideFlavorText(otherCiv,"We will remember this.","Very well.")
|
||||
}
|
||||
diplomacyTable.add(denounceButton).row()
|
||||
}
|
||||
@ -228,6 +230,12 @@ class DiplomacyScreen:CameraStageBaseScreen() {
|
||||
diplomacyTable.add(declareWarButton).row()
|
||||
}
|
||||
|
||||
val demandsButton = TextButton("Demands".tr(),skin)
|
||||
demandsButton.onClick {
|
||||
rightSideTable.clear();
|
||||
rightSideTable.add(getDemandsTable(currentPlayerCiv,otherCiv))
|
||||
}
|
||||
diplomacyTable.add(demandsButton).row()
|
||||
|
||||
diplomacyTable.add(getRelationshipTable(otherCivDiplomacyManager)).row()
|
||||
|
||||
@ -248,6 +256,8 @@ class DiplomacyScreen:CameraStageBaseScreen() {
|
||||
DenouncedOurAllies -> "You have denounced our allies"
|
||||
DenouncedOurEnemies -> "You have denounced our enemies"
|
||||
BetrayedPromiseToNotSettleCitiesNearUs -> "You betrayed your promise to not settle cities near us"
|
||||
RefusedToNotSettleCitiesNearUs -> "You refused to stop settling cities near us"
|
||||
FulfilledPromiseToNotSettleCitiesNearUs -> "You fulfilled your promise to stop settling cities near us!"
|
||||
}
|
||||
text = text.tr() + " "
|
||||
if (modifier.value > 0) text += "+"
|
||||
@ -260,6 +270,23 @@ class DiplomacyScreen:CameraStageBaseScreen() {
|
||||
return diplomacyTable
|
||||
}
|
||||
|
||||
private fun getDemandsTable(currentPlayerCiv: CivilizationInfo, otherCiv: CivilizationInfo): Table {
|
||||
val demandsTable = Table()
|
||||
demandsTable.defaults().pad(10f)
|
||||
val dontSettleCitiesButton = TextButton("Please don't settle new cities near us.".tr(),skin)
|
||||
dontSettleCitiesButton.onClick {
|
||||
val threatLevel = Automation().threatAssessment(otherCiv,currentPlayerCiv)
|
||||
if(threatLevel>ThreatLevel.Medium){
|
||||
setRightSideFlavorText(otherCiv,"Very well, we shall look for new lands to settle.","Excellent!")
|
||||
otherCiv.getDiplomacyManager(currentPlayerCiv).setFlag(DiplomacyFlags.WeAgreedNotToSettleNearThem,100)
|
||||
}
|
||||
else setRightSideFlavorText(otherCiv,"We shall do as we please.","Very well.")
|
||||
}
|
||||
demandsTable.add(dontSettleCitiesButton).row()
|
||||
demandsTable.add(TextButton("Close".tr(),skin).onClick { updateRightSide(otherCiv) })
|
||||
return demandsTable
|
||||
}
|
||||
|
||||
fun getRelationshipTable(otherCivDiplomacyManager: DiplomacyManager): Table {
|
||||
val relationshipTable = Table()
|
||||
|
||||
@ -305,7 +332,7 @@ class DiplomacyScreen:CameraStageBaseScreen() {
|
||||
diplomacyTable.addSeparator()
|
||||
diplomacyTable.add(flavorText.toLabel()).row()
|
||||
|
||||
val responseButton = TextButton(response,skin)
|
||||
val responseButton = TextButton(response.tr(),skin)
|
||||
responseButton.onClick { updateRightSide(otherCiv) }
|
||||
diplomacyTable.add(responseButton)
|
||||
|
||||
|
@ -4,17 +4,24 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
|
||||
import com.unciv.logic.civilization.AlertType
|
||||
import com.unciv.logic.civilization.PopupAlert
|
||||
import com.unciv.logic.civilization.diplomacy.DiplomacyFlags
|
||||
import com.unciv.logic.civilization.diplomacy.DiplomaticModifiers
|
||||
import com.unciv.models.gamebasics.Nation
|
||||
import com.unciv.models.gamebasics.tr
|
||||
import com.unciv.ui.utils.addSeparator
|
||||
import com.unciv.ui.utils.onClick
|
||||
import com.unciv.ui.utils.toLabel
|
||||
import com.unciv.ui.worldscreen.optionstable.PopupTable
|
||||
import kotlin.random.Random
|
||||
|
||||
class AlertPopup(val worldScreen: WorldScreen, val popupAlert: PopupAlert): PopupTable(worldScreen){
|
||||
fun getCloseButton(text:String): TextButton {
|
||||
fun getCloseButton(text: String, action: (() -> Unit)?=null): TextButton {
|
||||
val button = TextButton(text.tr(), skin)
|
||||
button.onClick { close(); worldScreen.shouldUpdate=true }
|
||||
button.onClick {
|
||||
if(action!=null) action()
|
||||
worldScreen.shouldUpdate=true
|
||||
close()
|
||||
}
|
||||
return button
|
||||
}
|
||||
|
||||
@ -47,7 +54,6 @@ class AlertPopup(val worldScreen: WorldScreen, val popupAlert: PopupAlert): Popu
|
||||
val translatedNation = civ.getTranslatedNation()
|
||||
if (civ.isCityState()) {
|
||||
addLeaderName(translatedNation)
|
||||
val cityStateType = civ.getCityStateType()
|
||||
addGoodSizedLabel("We have encountered the City-State of [${translatedNation.getNameTranslation()}]!").row()
|
||||
add(getCloseButton("Excellent!"))
|
||||
} else {
|
||||
@ -74,7 +80,26 @@ class AlertPopup(val worldScreen: WorldScreen, val popupAlert: PopupAlert): Popu
|
||||
responseTable.add(getCloseButton("Never!"))
|
||||
add(responseTable)
|
||||
}
|
||||
|
||||
AlertType.CitySettledNearOtherCiv -> {
|
||||
val otherciv= worldScreen.gameInfo.getCivilization(popupAlert.value)
|
||||
val otherCivDiploManager = otherciv.getDiplomacyManager(worldScreen.currentPlayerCiv)
|
||||
val translatedNation = otherciv.getTranslatedNation()
|
||||
addLeaderName(translatedNation)
|
||||
addGoodSizedLabel("Please don't settle new cities near us.").row()
|
||||
add(getCloseButton("Very well, we shall look for new lands to settle."){
|
||||
otherCivDiploManager.setFlag(DiplomacyFlags.AgreedToNotSettleNearUs,100+ Random.nextInt(-20,20))
|
||||
}).row()
|
||||
add(getCloseButton("We shall do as we please.") {
|
||||
otherCivDiploManager.addModifier(DiplomaticModifiers.RefusedToNotSettleCitiesNearUs,-10f)
|
||||
}).row()
|
||||
}
|
||||
AlertType.CitySettledNearOtherCivDespiteOurPromise -> {
|
||||
val otherciv= worldScreen.gameInfo.getCivilization(popupAlert.value)
|
||||
val translatedNation = otherciv.getTranslatedNation()
|
||||
addLeaderName(translatedNation)
|
||||
addGoodSizedLabel("We noticed your new city near our borders, despite your promise. This will have....implications.").row()
|
||||
add(getCloseButton("Very well."))
|
||||
}
|
||||
}
|
||||
open()
|
||||
isOpen = true
|
||||
|
Reference in New Issue
Block a user