mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-16 10:49:17 +07:00
City-state allies with most influencing civ. (#1291)
* City-state allies with most influencing civ. * More notifications for alliance. More intense status update. * Fix a crash about lateinit tiles. * More reasonable civInfo.setTransients.
This commit is contained in:

committed by
Yair Morgenstern

parent
2e9b1e6de6
commit
1e403442f7
@ -669,6 +669,15 @@
|
||||
Czech:"Vliv: "
|
||||
}
|
||||
|
||||
"Reach 30 for friendship.":{
|
||||
}
|
||||
|
||||
"Reach highest influence above 60 for alliance.":{
|
||||
}
|
||||
|
||||
"Ally: ":{
|
||||
}
|
||||
|
||||
////// Trade
|
||||
|
||||
"Trade":{
|
||||
|
@ -778,4 +778,9 @@
|
||||
Ukrainian:"[nation]: відмова не будувати міста поруч з нами!"
|
||||
}
|
||||
|
||||
"We have allied with [nation].": {
|
||||
}
|
||||
|
||||
"We have lost alliance with [nation].": {
|
||||
}
|
||||
}
|
||||
|
@ -246,9 +246,9 @@ class GameInfo {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (civInfo in civilizations) civInfo.setNationTransient()
|
||||
for (civInfo in civilizations) civInfo.setTransients()
|
||||
for (civInfo in civilizations) civInfo.updateSightAndResources()
|
||||
|
||||
for (civInfo in civilizations){
|
||||
for(unit in civInfo.getCivUnits())
|
||||
|
@ -125,32 +125,9 @@ class CityInfo {
|
||||
|
||||
for (tileInfo in getTiles().filter { it.resource != null }) {
|
||||
val resource = tileInfo.getTileResource()
|
||||
if (resource.revealedBy!=null && !civInfo.tech.isResearched(resource.revealedBy!!)) continue
|
||||
|
||||
// Even if the improvement exists (we conquered an enemy city or somesuch) or we have a city on it, we won't get the resource until the correct tech is researched
|
||||
if (resource.improvement!=null){
|
||||
val improvement = GameBasics.TileImprovements[resource.improvement!!]!!
|
||||
if(improvement.techRequired!=null && !civInfo.tech.isResearched(improvement.techRequired!!)) continue
|
||||
}
|
||||
|
||||
if (resource.improvement == tileInfo.improvement || tileInfo.isCityCenter()
|
||||
// Per https://gaming.stackexchange.com/questions/53155/do-manufactories-and-customs-houses-sacrifice-the-strategic-or-luxury-resources
|
||||
|| (resource.resourceType==ResourceType.Strategic && tileInfo.containsGreatImprovement())){
|
||||
var amountToAdd = 1
|
||||
if(resource.resourceType == ResourceType.Strategic){
|
||||
amountToAdd = 2
|
||||
if(civInfo.policies.isAdopted("Facism")) amountToAdd*=2
|
||||
if(civInfo.nation.unique=="Strategic Resources provide +1 Production, and Horses, Iron and Uranium Resources provide double quantity"
|
||||
&& resource.name in listOf("Horses","Iron","Uranium"))
|
||||
amountToAdd *= 2
|
||||
if(resource.name=="Oil" && civInfo.nation.unique=="+1 Gold from each Trade Route, Oil resources provide double quantity")
|
||||
amountToAdd *= 2
|
||||
}
|
||||
if(resource.resourceType == ResourceType.Luxury
|
||||
&& containsBuildingUnique("Provides 1 extra copy of each improved luxury resource near this City"))
|
||||
amountToAdd*=2
|
||||
|
||||
cityResources.add(resource, amountToAdd, "Tiles")
|
||||
val amount = getTileResourceAmount(tileInfo)
|
||||
if (amount > 0) {
|
||||
cityResources.add(resource, amount, "Tiles")
|
||||
}
|
||||
|
||||
}
|
||||
@ -163,6 +140,52 @@ class CityInfo {
|
||||
return cityResources
|
||||
}
|
||||
|
||||
fun getCityResourcesForAlly(): ResourceSupplyList {
|
||||
val cityResources = ResourceSupplyList()
|
||||
|
||||
for (tileInfo in getTiles().filter { it.resource != null }) {
|
||||
val resource = tileInfo.getTileResource()
|
||||
val amount = getTileResourceAmount(tileInfo)
|
||||
if (amount > 0) {
|
||||
cityResources.add(resource, amount, "City-States")
|
||||
}
|
||||
}
|
||||
return cityResources
|
||||
}
|
||||
|
||||
fun getTileResourceAmount(tileInfo: TileInfo): Int {
|
||||
if (tileInfo.resource == null) return 0
|
||||
val resource = tileInfo.getTileResource()
|
||||
if (resource.revealedBy!=null && !civInfo.tech.isResearched(resource.revealedBy!!)) return 0
|
||||
|
||||
// Even if the improvement exists (we conquered an enemy city or somesuch) or we have a city on it, we won't get the resource until the correct tech is researched
|
||||
if (resource.improvement!=null){
|
||||
val improvement = GameBasics.TileImprovements[resource.improvement!!]!!
|
||||
if(improvement.techRequired!=null && !civInfo.tech.isResearched(improvement.techRequired!!)) return 0
|
||||
}
|
||||
|
||||
if (resource.improvement == tileInfo.improvement || tileInfo.isCityCenter()
|
||||
// Per https://gaming.stackexchange.com/questions/53155/do-manufactories-and-customs-houses-sacrifice-the-strategic-or-luxury-resources
|
||||
|| (resource.resourceType==ResourceType.Strategic && tileInfo.containsGreatImprovement())){
|
||||
var amountToAdd = 1
|
||||
if(resource.resourceType == ResourceType.Strategic){
|
||||
amountToAdd = 2
|
||||
if(civInfo.policies.isAdopted("Facism")) amountToAdd*=2
|
||||
if(civInfo.nation.unique=="Strategic Resources provide +1 Production, and Horses, Iron and Uranium Resources provide double quantity"
|
||||
&& resource.name in listOf("Horses","Iron","Uranium"))
|
||||
amountToAdd *= 2
|
||||
if(resource.name=="Oil" && civInfo.nation.unique=="+1 Gold from each Trade Route, Oil resources provide double quantity")
|
||||
amountToAdd *= 2
|
||||
}
|
||||
if(resource.resourceType == ResourceType.Luxury
|
||||
&& containsBuildingUnique("Provides 1 extra copy of each improved luxury resource near this City"))
|
||||
amountToAdd*=2
|
||||
|
||||
return amountToAdd
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
fun getBuildingUniques(): List<String> = cityConstructions.getBuiltBuildings().flatMap { it.uniques }
|
||||
fun containsBuildingUnique(unique:String) = cityConstructions.getBuiltBuildings().any { it.uniques.contains(unique) }
|
||||
|
||||
|
@ -25,6 +25,15 @@ class CivInfoTransientUpdater(val civInfo: CivilizationInfo){
|
||||
val neighboringUnownedTiles = ownedTiles.flatMap { it.neighbors.asSequence().filter { it.getOwner()!=civInfo } }
|
||||
newViewableTiles.addAll(neighboringUnownedTiles)
|
||||
newViewableTiles.addAll(civInfo.getCivUnits().asSequence().flatMap { it.viewableTiles.asSequence()})
|
||||
|
||||
if (!civInfo.isCityState()) {
|
||||
for (otherCiv in civInfo.getKnownCivs()) {
|
||||
if (otherCiv.getAllyCiv() == civInfo.civName) {
|
||||
newViewableTiles.addAll(otherCiv.cities.asSequence().flatMap { it.getTiles().asSequence() })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
civInfo.viewableTiles = newViewableTiles // to avoid concurrent modification problems
|
||||
|
||||
val newViewableInvisibleTiles = HashSet<TileInfo>()
|
||||
@ -138,6 +147,17 @@ class CivInfoTransientUpdater(val civInfo: CivilizationInfo){
|
||||
fun updateDetailedCivResources() {
|
||||
val newDetailedCivResources = ResourceSupplyList()
|
||||
for (city in civInfo.cities) newDetailedCivResources.add(city.getCityResources())
|
||||
|
||||
if (!civInfo.isCityState()) {
|
||||
for (otherCiv in civInfo.getKnownCivs()) {
|
||||
if (otherCiv.getAllyCiv() == civInfo.civName) {
|
||||
for (city in otherCiv.cities) {
|
||||
newDetailedCivResources.add(city.getCityResourcesForAlly())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (dip in civInfo.diplomacy.values) newDetailedCivResources.add(dip.resourcesFromTrade())
|
||||
for(resource in civInfo.getCivUnits().mapNotNull { it.baseUnit.requiredResource }.map { GameBasics.TileResources[it]!! })
|
||||
newDetailedCivResources.add(resource,-1,"Units")
|
||||
|
@ -58,6 +58,7 @@ class CivilizationInfo {
|
||||
var diplomacy = HashMap<String, DiplomacyManager>()
|
||||
var notifications = ArrayList<Notification>()
|
||||
val popupAlerts = ArrayList<PopupAlert>()
|
||||
var allyCivName = ""
|
||||
|
||||
//** for trades here, ourOffers is the current civ's offers, and theirOffers is what the requesting civ offers */
|
||||
val tradeRequests = ArrayList<TradeRequest>()
|
||||
@ -87,6 +88,7 @@ class CivilizationInfo {
|
||||
toReturn.goldenAges = goldenAges.clone()
|
||||
toReturn.greatPeople = greatPeople.clone()
|
||||
toReturn.victoryManager = victoryManager.clone()
|
||||
toReturn.allyCivName = allyCivName
|
||||
for (diplomacyManager in diplomacy.values.map { it.clone() })
|
||||
toReturn.diplomacy.put(diplomacyManager.otherCivName, diplomacyManager)
|
||||
toReturn.cities = cities.map { it.clone() }
|
||||
@ -325,6 +327,9 @@ class CivilizationInfo {
|
||||
cityInfo.civInfo = this // must be before the city's setTransients because it depends on the tilemap, that comes from the currentPlayerCivInfo
|
||||
cityInfo.setTransients()
|
||||
}
|
||||
}
|
||||
|
||||
fun updateSightAndResources() {
|
||||
updateViewableTiles()
|
||||
updateHasActiveGreatWall()
|
||||
updateDetailedCivResources()
|
||||
@ -394,6 +399,7 @@ class CivilizationInfo {
|
||||
goldenAges.endTurn(getHappiness())
|
||||
getCivUnits().forEach { it.endTurn() }
|
||||
diplomacy.values.forEach{it.nextTurn()}
|
||||
updateAllyCivForCityState()
|
||||
updateHasActiveGreatWall()
|
||||
}
|
||||
|
||||
@ -459,6 +465,7 @@ class CivilizationInfo {
|
||||
if(!otherCiv.isCityState()) throw Exception("You can only gain influence with city states!")
|
||||
gold -= giftAmount
|
||||
otherCiv.getDiplomacyManager(this).influence += giftAmount/10
|
||||
otherCiv.updateAllyCivForCityState()
|
||||
updateStatsForNextTurn()
|
||||
}
|
||||
|
||||
@ -471,5 +478,36 @@ class CivilizationInfo {
|
||||
addNotification("[${otherCiv.civName}] gave us a [${militaryUnit.name}] as gift near [${city.name}]!", null, Color.GREEN)
|
||||
}
|
||||
|
||||
fun getAllyCiv(): String {
|
||||
return allyCivName
|
||||
}
|
||||
|
||||
fun updateAllyCivForCityState() {
|
||||
var newAllyName = ""
|
||||
if (!isCityState()) return
|
||||
val maxInfluence = diplomacy.filter{ !it.value.otherCiv().isCityState() && !it.value.otherCiv().isDefeated() }.maxBy { it.value.influence }
|
||||
if (maxInfluence != null && maxInfluence.value.influence >= 60) {
|
||||
newAllyName = maxInfluence.key
|
||||
}
|
||||
|
||||
if (allyCivName != newAllyName) {
|
||||
val oldAllyName = allyCivName
|
||||
allyCivName = newAllyName
|
||||
|
||||
if (newAllyName != "") {
|
||||
val newAllyCiv = gameInfo.getCivilization(newAllyName)
|
||||
newAllyCiv.addNotification("We have allied with [${civName}].", Color.GREEN)
|
||||
newAllyCiv.updateViewableTiles()
|
||||
newAllyCiv.updateDetailedCivResources()
|
||||
}
|
||||
if (oldAllyName != "") {
|
||||
val oldAllyCiv = gameInfo.getCivilization(oldAllyName)
|
||||
oldAllyCiv.addNotification("We have lost alliance with [${civName}].", Color.RED)
|
||||
oldAllyCiv.updateViewableTiles()
|
||||
oldAllyCiv.updateDetailedCivResources()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//endregion
|
||||
}
|
||||
|
@ -342,6 +342,22 @@ class DiplomacyManager() {
|
||||
}
|
||||
}
|
||||
otherCivDiplomacy.removeFlag(DiplomacyFlags.DeclarationOfFriendship)
|
||||
if (otherCiv.isCityState()) otherCiv.updateAllyCivForCityState()
|
||||
|
||||
if (!civInfo.isCityState()) {
|
||||
for (thirdCiv in civInfo.getKnownCivs()) {
|
||||
if (thirdCiv.isCityState() && thirdCiv.getAllyCiv() == civInfo.civName && thirdCiv.getDiplomacyManager(otherCiv).canDeclareWar()) {
|
||||
thirdCiv.getDiplomacyManager(otherCiv).declareWar()
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!otherCiv.isCityState()) {
|
||||
for (thirdCiv in otherCiv.getKnownCivs()) {
|
||||
if (thirdCiv.isCityState() && thirdCiv.getAllyCiv() == otherCiv.civName && thirdCiv.getDiplomacyManager(civInfo).canDeclareWar()) {
|
||||
thirdCiv.getDiplomacyManager(civInfo).declareWar()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun makePeace(){
|
||||
|
@ -2,6 +2,7 @@ package com.unciv.models.gamebasics
|
||||
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.unciv.logic.civilization.CityStateType
|
||||
import com.unciv.logic.civilization.CivilizationInfo
|
||||
import com.unciv.models.stats.INamed
|
||||
import com.unciv.ui.utils.colorFromRGB
|
||||
|
||||
|
@ -95,9 +95,25 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() {
|
||||
diplomacyTable.defaults().pad(10f)
|
||||
diplomacyTable.add(otherCiv.getLeaderDisplayName().toLabel(fontSize = 24)).row()
|
||||
diplomacyTable.add(("Type: ".tr() + otherCiv.getCityStateType().toString().tr()).toLabel()).row()
|
||||
diplomacyTable.add(("Influence: ".tr() + otherCivDiplomacyManager.influence.toInt() + "/30").toLabel()).row()
|
||||
|
||||
otherCiv.updateAllyCivForCityState()
|
||||
val ally = otherCiv.getAllyCiv()
|
||||
if (ally != "")
|
||||
{
|
||||
diplomacyTable.add(("Ally: ".tr() + ally!!.tr() + " " + "Influence: ".tr()
|
||||
+ otherCiv.getDiplomacyManager(ally).influence.toString().tr()).toLabel()).row()
|
||||
}
|
||||
val nextLevelString: String
|
||||
if (otherCivDiplomacyManager.influence.toInt() < 30) {
|
||||
nextLevelString = "Reach 30 for friendship."
|
||||
} else if (ally == viewingCiv.civName) {
|
||||
nextLevelString = ""
|
||||
} else {
|
||||
nextLevelString = "Reach highest influence above 60 for alliance."
|
||||
}
|
||||
diplomacyTable.add(getRelationshipTable(otherCivDiplomacyManager)).row()
|
||||
if (nextLevelString != "") {
|
||||
diplomacyTable.add(nextLevelString.tr().toLabel()).row()
|
||||
}
|
||||
|
||||
val friendBonusText = when (otherCiv.getCityStateType()) {
|
||||
CityStateType.Cultured -> ("Provides [" + (3 * (viewingCiv.getEra().ordinal + 1)).toString() + "] culture at [30] Influence").tr()
|
||||
|
Reference in New Issue
Block a user