mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-27 05:46:43 -04:00
City states give gold when met; updates to city state gold gifts (#4435)
* City States now give gold when met * City States can now receive different amounts of gold, and the amount of influence gained from gifts follows the base game * Implemented requested changes * Fixed tests
This commit is contained in:
parent
5925489c0b
commit
253e62de72
@ -137,6 +137,7 @@ Provides [amountOfCulture] culture at 30 Influence =
|
||||
Provides 3 food in capital and 1 food in other cities at 30 Influence =
|
||||
Provides 3 happiness at 30 Influence =
|
||||
Provides land units every 20 turns at 30 Influence =
|
||||
Give a Gift =
|
||||
Gift [giftAmount] gold (+[influenceAmount] influence) =
|
||||
Relationship changes in another [turnsToRelationshipChange] turns =
|
||||
Protected by =
|
||||
@ -407,6 +408,8 @@ You have entered a Golden Age! =
|
||||
[n] sources of [resourceName] revealed, e.g. near [cityName] =
|
||||
A [greatPerson] has been born in [cityName]! =
|
||||
We have encountered [civName]! =
|
||||
[cityStateName] has given us [stats] as a token of goodwill for meeting us =
|
||||
[cityStateName] has given us [stats] as we are the first major civ to meet them =
|
||||
Cannot provide unit upkeep for [unitName] - unit has been disbanded! =
|
||||
[cityName] has grown! =
|
||||
[cityName] is starving! =
|
||||
|
@ -84,7 +84,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.meetCivilization(oldCiv)
|
||||
conqueringCiv.makeCivilizationsMeet(oldCiv)
|
||||
|
||||
oldCiv.getDiplomacyManager(conqueringCiv)
|
||||
.addModifier(DiplomaticModifiers.CapturedOurCities, -aggroGenerated)
|
||||
@ -145,7 +145,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.meetCivilization(foundingCiv)
|
||||
conqueringCiv.makeCivilizationsMeet(foundingCiv)
|
||||
|
||||
if (foundingCiv.isMajorCiv()) {
|
||||
foundingCiv.getDiplomacyManager(conqueringCiv)
|
||||
|
@ -38,7 +38,7 @@ class CivInfoTransientUpdater(val civInfo: CivilizationInfo) {
|
||||
for (entry in viewedCivs) {
|
||||
val metCiv = entry.key
|
||||
if (metCiv == civInfo || metCiv.isBarbarian() || civInfo.diplomacy.containsKey(metCiv.civName)) continue
|
||||
civInfo.meetCivilization(metCiv)
|
||||
civInfo.makeCivilizationsMeet(metCiv)
|
||||
civInfo.addNotification("We have encountered [" + metCiv.civName + "]!", entry.value.position, metCiv.civName, NotificationIcon.Diplomacy)
|
||||
metCiv.addNotification("We have encountered [" + civInfo.civName + "]!", entry.value.position, civInfo.civName, NotificationIcon.Diplomacy)
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ import kotlin.collections.ArrayList
|
||||
import kotlin.collections.HashMap
|
||||
import kotlin.math.roundToInt
|
||||
import kotlin.math.min
|
||||
import kotlin.math.pow
|
||||
|
||||
class CivilizationInfo {
|
||||
|
||||
@ -328,18 +329,40 @@ class CivilizationInfo {
|
||||
return baseUnit
|
||||
}
|
||||
|
||||
fun meetCivilization(otherCiv: CivilizationInfo) {
|
||||
fun makeCivilizationsMeet(otherCiv: CivilizationInfo) {
|
||||
meetCiv(otherCiv)
|
||||
otherCiv.meetCiv(this)
|
||||
}
|
||||
|
||||
private fun meetCiv(otherCiv: CivilizationInfo) {
|
||||
diplomacy[otherCiv.civName] = DiplomacyManager(this, otherCiv.civName)
|
||||
.apply { diplomaticStatus = DiplomaticStatus.Peace }
|
||||
.apply { diplomaticStatus = DiplomaticStatus.Peace }
|
||||
|
||||
otherCiv.popupAlerts.add(PopupAlert(AlertType.FirstContact, civName))
|
||||
|
||||
otherCiv.diplomacy[civName] = DiplomacyManager(otherCiv, civName)
|
||||
.apply { diplomaticStatus = DiplomaticStatus.Peace }
|
||||
popupAlerts.add(PopupAlert(AlertType.FirstContact, otherCiv.civName))
|
||||
|
||||
if (isCurrentPlayer() || otherCiv.isCurrentPlayer())
|
||||
if (isCurrentPlayer())
|
||||
UncivGame.Current.settings.addCompletedTutorialTask("Meet another civilization")
|
||||
|
||||
if (!(isCityState() && otherCiv.isMajorCiv())) return
|
||||
|
||||
val cityStateLocation = if (cities.isEmpty()) null else getCapital().location
|
||||
|
||||
val giftAmount = Stats().add(Stat.Gold, 15f)
|
||||
// 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"
|
||||
if (diplomacy.filter { it.value.otherCiv().isMajorCiv() }.count() == 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, NotificationIcon.Gold)
|
||||
else
|
||||
otherCiv.addNotification(meetString, NotificationIcon.Gold)
|
||||
for (stat in giftAmount.toHashMap().filter { it.value != 0f })
|
||||
otherCiv.addStat(stat.key, stat.value.toInt())
|
||||
|
||||
|
||||
}
|
||||
|
||||
fun discoverNaturalWonder(naturalWonderName: String) {
|
||||
@ -699,11 +722,32 @@ class CivilizationInfo {
|
||||
diplomacyManager.otherCiv().tradeRequests.remove(tradeRequest) // it would be really weird to get a trade request from a dead civ
|
||||
}
|
||||
}
|
||||
|
||||
fun getResearchAgreementCost(): Int {
|
||||
// https://forums.civfanatics.com/resources/research-agreements-bnw.25568/
|
||||
val era = if (getEra() in gameInfo.ruleSet.eras) gameInfo.ruleSet.eras[getEra()]!! else Era()
|
||||
return (era.researchAgreementCost * gameInfo.gameParameters.gameSpeed.modifier).toInt()
|
||||
}
|
||||
|
||||
//////////////////////// Functions specific to City State civilizations ////////////////////////
|
||||
|
||||
fun influenceGainedByGift(cityState: CivilizationInfo, giftAmount: Int): Int {
|
||||
var influenceGained = giftAmount / 10f
|
||||
|
||||
fun influenceGainedByGift(giftAmount: Int): Int {
|
||||
// https://github.com/Gedemon/Civ5-DLL/blob/aa29e80751f541ae04858b6d2a2c7dcca454201e/CvGameCoreDLL_Expansion1/CvMinorCivAI.cpp
|
||||
// line 8681 and below
|
||||
var influenceGained = giftAmount.toFloat().pow(1.01f) / 9.8f
|
||||
val gameProgressApproximate = min(gameInfo.turns / (400f * gameInfo.gameParameters.gameSpeed.modifier), 1f)
|
||||
influenceGained *= 1 - (2/3) * gameProgressApproximate
|
||||
influenceGained *= when (gameInfo.gameParameters.gameSpeed) {
|
||||
GameSpeed.Quick -> 1.25f
|
||||
GameSpeed.Standard -> 1f
|
||||
GameSpeed.Epic -> 0.75f
|
||||
GameSpeed.Marathon -> 0.67f
|
||||
}
|
||||
for (unique in getMatchingUniques("Gifts of Gold to City-States generate []% more Influence"))
|
||||
influenceGained *= 1f + unique.params[0].toFloat() / 100f
|
||||
influenceGained -= influenceGained % 5
|
||||
if (influenceGained < 5f) influenceGained = 5f
|
||||
return influenceGained.toInt()
|
||||
}
|
||||
|
||||
@ -711,17 +755,11 @@ class CivilizationInfo {
|
||||
if (!cityState.isCityState()) throw Exception("You can only gain influence with City-States!")
|
||||
addGold(-giftAmount)
|
||||
cityState.addGold(giftAmount)
|
||||
cityState.getDiplomacyManager(this).influence += influenceGainedByGift(cityState, giftAmount)
|
||||
cityState.getDiplomacyManager(this).influence += influenceGainedByGift(giftAmount)
|
||||
cityState.updateAllyCivForCityState()
|
||||
updateStatsForNextTurn()
|
||||
}
|
||||
|
||||
fun getResearchAgreementCost(): Int {
|
||||
// https://forums.civfanatics.com/resources/research-agreements-bnw.25568/
|
||||
val era = if (getEra() in gameInfo.ruleSet.eras) gameInfo.ruleSet.eras[getEra()]!! else Era()
|
||||
return (era.researchAgreementCost * gameInfo.gameParameters.gameSpeed.modifier).toInt()
|
||||
}
|
||||
|
||||
fun gainMilitaryUnitFromCityState(otherCiv: CivilizationInfo) {
|
||||
val cities = NextTurnAutomation.getClosestCities(this, otherCiv)
|
||||
val city = cities.city1
|
||||
|
@ -107,7 +107,7 @@ class TradeLogic(val ourCivilization:CivilizationInfo, val otherCivilization: Ci
|
||||
}
|
||||
}
|
||||
if (offer.type == TradeType.Introduction)
|
||||
to.meetCivilization(to.gameInfo.getCivilization(offer.name))
|
||||
to.makeCivilizationsMeet(to.gameInfo.getCivilization(offer.name))
|
||||
|
||||
if (offer.type == TradeType.WarDeclaration) {
|
||||
val nameOfCivToDeclareWarOn = offer.name
|
||||
|
@ -29,7 +29,7 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() {
|
||||
|
||||
private val leftSideTable = Table().apply { defaults().pad(10f) }
|
||||
private val rightSideTable = Table()
|
||||
|
||||
|
||||
private fun isNotPlayersTurn() = !UncivGame.Current.worldScreen.isPlayersTurn
|
||||
|
||||
init {
|
||||
@ -92,8 +92,7 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() {
|
||||
return tradeTable
|
||||
}
|
||||
|
||||
|
||||
private fun getCityStateDiplomacyTable(otherCiv: CivilizationInfo): Table {
|
||||
private fun getCityStateDiplomacyTableHeader(otherCiv: CivilizationInfo): Table {
|
||||
val otherCivDiplomacyManager = otherCiv.getDiplomacyManager(viewingCiv)
|
||||
|
||||
val diplomacyTable = Table()
|
||||
@ -144,21 +143,26 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() {
|
||||
friendBonusLabelColor = Color.GRAY
|
||||
|
||||
val friendBonusLabel = friendBonusText.toLabel(friendBonusLabelColor)
|
||||
.apply { setAlignment(Align.center) }
|
||||
.apply { setAlignment(Align.center) }
|
||||
diplomacyTable.add(friendBonusLabel).row()
|
||||
|
||||
return diplomacyTable
|
||||
}
|
||||
|
||||
private fun getCityStateDiplomacyTable(otherCiv: CivilizationInfo): Table {
|
||||
val otherCivDiplomacyManager = otherCiv.getDiplomacyManager(viewingCiv)
|
||||
|
||||
val diplomacyTable = getCityStateDiplomacyTableHeader(otherCiv)
|
||||
|
||||
diplomacyTable.addSeparator()
|
||||
|
||||
val giftAmount = 250
|
||||
val influenceAmount = viewingCiv.influenceGainedByGift(otherCiv, giftAmount)
|
||||
val giftButton = "Gift [$giftAmount] gold (+[$influenceAmount] influence)".toTextButton()
|
||||
giftButton.onClick {
|
||||
viewingCiv.giveGoldGift(otherCiv, giftAmount)
|
||||
updateRightSide(otherCiv)
|
||||
val giveGoldButton = "Give a Gift".toTextButton()
|
||||
giveGoldButton.onClick {
|
||||
rightSideTable.clear()
|
||||
rightSideTable.add(ScrollPane(getGoldGiftTable(otherCiv)))
|
||||
}
|
||||
diplomacyTable.add(giftButton).row()
|
||||
if (viewingCiv.gold < giftAmount || isNotPlayersTurn()) giftButton.disable()
|
||||
|
||||
diplomacyTable.add(giveGoldButton).row()
|
||||
|
||||
if (otherCivDiplomacyManager.diplomaticStatus == DiplomaticStatus.Protector){
|
||||
val revokeProtectionButton = "Revoke Protection".toTextButton()
|
||||
revokeProtectionButton.onClick {
|
||||
@ -216,6 +220,30 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() {
|
||||
|
||||
return diplomacyTable
|
||||
}
|
||||
|
||||
private fun getGoldGiftTable(otherCiv: CivilizationInfo): Table {
|
||||
val diplomacyTable = getCityStateDiplomacyTableHeader(otherCiv)
|
||||
diplomacyTable.addSeparator()
|
||||
|
||||
for (giftAmount in listOf(250, 500, 1000)) {
|
||||
val influenceAmount = viewingCiv.influenceGainedByGift(giftAmount)
|
||||
val giftButton = "Gift [$giftAmount] gold (+[$influenceAmount] influence)".toTextButton()
|
||||
giftButton.onClick {
|
||||
viewingCiv.giveGoldGift(otherCiv, giftAmount)
|
||||
updateRightSide(otherCiv)
|
||||
}
|
||||
diplomacyTable.add(giftButton).row()
|
||||
if (viewingCiv.gold < giftAmount || isNotPlayersTurn()) giftButton.disable()
|
||||
}
|
||||
|
||||
val backButton = "Back".toTextButton()
|
||||
backButton.onClick {
|
||||
rightSideTable.clear()
|
||||
rightSideTable.add(ScrollPane(getCityStateDiplomacyTable(otherCiv)))
|
||||
}
|
||||
diplomacyTable.add(backButton)
|
||||
return diplomacyTable
|
||||
}
|
||||
|
||||
private fun getQuestTable(assignedQuest: AssignedQuest): Table {
|
||||
val questTable = Table()
|
||||
|
@ -518,7 +518,7 @@ object UnitActions {
|
||||
val otherCiv = tile.getOwner()
|
||||
if (otherCiv != null) {
|
||||
// decrease relations for -10 pt/tile
|
||||
if (!otherCiv.knows(unit.civInfo)) otherCiv.meetCivilization(unit.civInfo)
|
||||
if (!otherCiv.knows(unit.civInfo)) otherCiv.makeCivilizationsMeet(unit.civInfo)
|
||||
otherCiv.getDiplomacyManager(unit.civInfo).addModifier(DiplomaticModifiers.StealingTerritory, -10f)
|
||||
civsToNotify.add(otherCiv)
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package com.unciv.logic.civilization.diplomacy
|
||||
|
||||
import com.unciv.logic.GameInfo
|
||||
import com.unciv.logic.civilization.CivilizationInfo
|
||||
import com.unciv.models.ruleset.Nation
|
||||
import com.unciv.testing.GdxTestRunner
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
@ -23,11 +24,14 @@ class DiplomacyManagerTests {
|
||||
|
||||
private fun meetByName(civilization: String, civilizationToMeet: String) {
|
||||
civilizations.getValue(civilization)
|
||||
.meetCivilization(civilizations.getValue(civilizationToMeet))
|
||||
.makeCivilizationsMeet(civilizations.getValue(civilizationToMeet))
|
||||
}
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
// Add nations to test civilizations, as we need them to know that they are major civs
|
||||
civilizations.values.forEach { it.nation = Nation() }
|
||||
|
||||
// Setup the GameInfo mock
|
||||
|
||||
every { mockGameInfo.getCivilization(capture(slot)) } answers { civilizations.getValue(slot.captured) }
|
||||
|
Loading…
x
Reference in New Issue
Block a user