Made Gold Gifting moddable (#11995)

* Made gold gifting moddable

* Made gold gift degradation moddable

* Removed unused import statement
This commit is contained in:
Oskar Niesen
2024-07-24 08:31:57 -05:00
committed by GitHub
parent 61fe6d0eee
commit 155082471b
6 changed files with 110 additions and 19 deletions

View File

@ -18,6 +18,7 @@ import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.ui.components.extensions.toPercent
import kotlin.math.ceil
import kotlin.math.max
import kotlin.math.roundToInt
import kotlin.math.sign
enum class RelationshipLevel(val color: Color) {
@ -690,18 +691,24 @@ class DiplomacyManager() : IsPartOfGameInfoSerialization {
}
/**
* Resolves adding gifts with negative gold values.
* Resolves the otherCiv giving gifts to this civ with negative gold values.
* Prioritises reducing gifts given to the other civ before increasing our gift value.
* Does not take the gold from either civ's stockpile
* @param gold the amount of gold without inflation, can be negative
* @param isPureGift should be true if the gift was one-sided, or false if it wasn't
*/
fun giftGold(gold: Int) {
fun giftGold(gold: Int, isPureGift: Boolean) {
val currentGold = if (isPureGift)
(gold * civInfo.gameInfo.ruleset.modOptions.constants.goldGiftMultiplier).roundToInt()
else
(gold * civInfo.gameInfo.ruleset.modOptions.constants.goldGiftTradeMultiplier).roundToInt()
val otherGold = otherCivDiplomacy().getGoldGifts()
if (otherGold > gold) {
otherCivDiplomacy().recieveGoldGifts(-gold)
if (otherGold > currentGold) {
otherCivDiplomacy().recieveGoldGifts(-currentGold)
} else {
otherCivDiplomacy().removeModifier(DiplomaticModifiers.GaveUsGifts)
recieveGoldGifts(gold - otherGold)
recieveGoldGifts(currentGold - otherGold)
}
}

View File

@ -294,22 +294,22 @@ object DiplomacyTurnManager {
revertToZero(DiplomaticModifiers.LiberatedCity, 1 / 8f)
if (hasModifier(DiplomaticModifiers.GaveUsGifts)) {
val giftLoss = when {
relationshipLevel() == RelationshipLevel.Ally -> .5f
relationshipLevel() == RelationshipLevel.Friend -> 1f
relationshipLevel() == RelationshipLevel.Favorable -> 1.5f
relationshipLevel() == RelationshipLevel.Ally -> 1f
relationshipLevel() == RelationshipLevel.Friend -> 1.5f
relationshipLevel() == RelationshipLevel.Favorable -> 2f
relationshipLevel() == RelationshipLevel.Neutral -> 2.5f
relationshipLevel() == RelationshipLevel.Competitor -> 5f
relationshipLevel() == RelationshipLevel.Enemy -> 7.5f
relationshipLevel() == RelationshipLevel.Unforgivable -> 10f
else -> 2f // Neutral
}
else -> 2.5f
} * civInfo.gameInfo.ruleset.modOptions.constants.goldGiftDegradationMultiplier
// We should subtract a certain amount from this balanced each turn
// Assuming neutral relations we will subtract the higher of either:
// 2% of the total amount or
// roughly 40 gold per turn (a value of ~.4 without inflation)
// 2.5% of the total amount or roughly 50 gold per turn (a value of ~.5 without inflation)
// This ensures that the amount can be reduced to zero but scales with larger numbers
val amountLost = (getModifier(DiplomaticModifiers.GaveUsGifts).absoluteValue * giftLoss / 100)
.coerceAtLeast(giftLoss / 5)
revertToZero(DiplomaticModifiers.GaveUsGifts, amountLost) // Roughly worth 20 GPT without inflation
revertToZero(DiplomaticModifiers.GaveUsGifts, amountLost)
}
setFriendshipBasedModifier()

View File

@ -159,9 +159,11 @@ class TradeLogic(val ourCivilization: Civilization, val otherCivilization: Civil
val ourGoldValueOfTrade = TradeEvaluation().getTradeAcceptability(currentTrade, ourCivilization, otherCivilization, includeDiplomaticGifts = false)
val theirGoldValueOfTrade = TradeEvaluation().getTradeAcceptability(currentTrade.reverse(), otherCivilization, ourCivilization, includeDiplomaticGifts = false)
if (ourGoldValueOfTrade > theirGoldValueOfTrade) {
ourDiploManager.giftGold(ourGoldValueOfTrade - theirGoldValueOfTrade.coerceAtLeast(0))
val isPureGift = currentTrade.ourOffers.isEmpty()
ourDiploManager.giftGold(ourGoldValueOfTrade - theirGoldValueOfTrade.coerceAtLeast(0), isPureGift)
} else if (theirGoldValueOfTrade > ourGoldValueOfTrade) {
theirDiploManger.giftGold(theirGoldValueOfTrade - ourGoldValueOfTrade.coerceAtLeast(0))
val isPureGift = currentTrade.theirOffers.isEmpty()
theirDiploManger.giftGold(theirGoldValueOfTrade - ourGoldValueOfTrade.coerceAtLeast(0), isPureGift)
}
}

View File

@ -52,6 +52,15 @@ class ModConstants {
var cityWorkRange = 3
var cityExpandRange = 5
// Modifies how much the gold value of a one-sided trade is applied to the gifts diplomatic modifier.
// Eg: One side offers a city, resource or gold for nothing in return.
var goldGiftMultiplier = 1f
// Modifies how much the gold value of a regular trade is applied to the gifts diplomatic modifier.
var goldGiftTradeMultiplier = .8f
// Modifies how quickly the GaveUsGifts dimplomacy modifier runs out. A higher value makes it run out quicker.
// Normally the gifts reduced by ~2.5% per turn depending on the diplomatic relations with the default value.
var goldGiftDegradationMultiplier = 1f
// Constants used to calculate Unit Upgrade gold Cost (can only be modded all-or-nothing)
// This is a data class for one reason only: The equality implementation enables Gdx Json to omit it when default (otherwise only the individual fields are omitted)
data class UnitUpgradeCost(

View File

@ -218,6 +218,9 @@ and city distance in another. In case of conflicts, there is no guarantee which
| baseTurnsUntilRevolt | Int | 4 | [^Q] |
| cityStateElectionTurns | Int | 15 | [^R] |
| maxImprovementTechErasForward | Int | None | [^S] |
| goldGiftMultiplier | Float | 1 | [^T] |
| goldGiftTradeMultiplier | Float | 0.8 | [^U] |
| goldGiftDegradationMultiplier | Float | 1.0 | [^V] |
Legend:
@ -257,6 +260,9 @@ Legend:
- [^Q]: The number of turns before a revolt is spawned
- [^R]: The number of turns between city-state elections
- [^S]: If set, the Improvement picker will silently skip improvements whose tech requirement is more advanced than your current Era + this value. Example: With a 0, Trade posts will not show until the Medieval Era, with a 1 they will already show in the CLassical Era.
- [^T]: The multiplier of the gold value of a one-sided trade to be stored as gifts.
- [^U]: The multiplier of the gold value of a regular trade to be stored as gifts. Set to 0 to disable gold gifting in two-sided trades.
- [^U]: Modifies how quickly the GaveUsGifts dimplomacy modifier runs out. A higher value makes it run out quicker. Normally the gifts reduced by ~2.5% per turn depending on the diplomatic relations with the default value.
#### UnitUpgradeCost

View File

@ -29,6 +29,9 @@ class GoldGiftingTests {
a.diplomacyFunctions.makeCivilizationsMeet(b)
aDiplomacy = a.getDiplomacyManager(b)!!
bDiplomacy = b.getDiplomacyManager(a)!!
a.gameInfo.ruleset.modOptions.constants.goldGiftMultiplier = 1f
a.gameInfo.ruleset.modOptions.constants.goldGiftTradeMultiplier = 1f
a.gameInfo.ruleset.modOptions.constants.goldGiftDegradationMultiplier = 1f
}
@Test
@ -44,7 +47,7 @@ class GoldGiftingTests {
fun `Gold Gift Test` () {
assertEquals(0, aDiplomacy.getGoldGifts())
assertEquals(0, bDiplomacy.getGoldGifts())
aDiplomacy.giftGold(10)
aDiplomacy.giftGold(10, true)
assertTrue(aDiplomacy.getGoldGifts() > 0)
assertEquals(0, bDiplomacy.getGoldGifts())
}
@ -88,8 +91,8 @@ class GoldGiftingTests {
@Test
fun `Gifting gold reduces previous gifts taken` () {
aDiplomacy.giftGold(1000)
bDiplomacy.giftGold(500)
aDiplomacy.giftGold(1000, true)
bDiplomacy.giftGold(500, true)
assertTrue(aDiplomacy.getGoldGifts() > 0)
assertTrue(aDiplomacy.getGoldGifts() < 1000)
assertTrue(bDiplomacy.getGoldGifts() == 0)
@ -134,5 +137,69 @@ class GoldGiftingTests {
assertTrue(TradeEvaluation().getTradeAcceptability(tradeOffer2.currentTrade.reverse(), b,a,true) > 0)
}
@Test
fun `Gold gifted uses pure gold multiplier constant`() {
a.addGold(1000)
a.gameInfo.ruleset.modOptions.constants.goldGiftMultiplier = .5f
a.gameInfo.ruleset.modOptions.constants.goldGiftTradeMultiplier = 0f
val tradeOffer = TradeLogic(a,b)
tradeOffer.currentTrade.ourOffers.add(tradeOffer.ourAvailableOffers.first { it.type == TradeOfferType.Gold })
tradeOffer.acceptTrade()
assertEquals(500, bDiplomacy.getGoldGifts())
}
@Test
fun `Gold gifted uses gold multiplier constant`() {
a.addGold(1000)
b.addGold(500)
a.gameInfo.ruleset.modOptions.constants.goldGiftMultiplier = 0f
a.gameInfo.ruleset.modOptions.constants.goldGiftTradeMultiplier = .5f
val tradeOffer = TradeLogic(a,b)
tradeOffer.currentTrade.ourOffers.add(tradeOffer.ourAvailableOffers.first { it.type == TradeOfferType.Gold })
tradeOffer.currentTrade.theirOffers.add(tradeOffer.theirAvailableOffers.first { it.type == TradeOfferType.Gold })
tradeOffer.acceptTrade()
assertEquals(250, bDiplomacy.getGoldGifts())
}
@Test
fun `Gifted Gold Disapears using gold gift degradation multiplier constant` () {
val c = testGame.addCiv()
c.diplomacyFunctions.makeCivilizationsMeet(a)
val caDiplomacy = c.getDiplomacyManager(a)!!
a.gameInfo.ruleset.modOptions.constants.goldGiftDegradationMultiplier = 1f
aDiplomacy.recieveGoldGifts(100)
caDiplomacy.recieveGoldGifts(100)
assertTrue(aDiplomacy.getGoldGifts() > 0)
assertTrue(caDiplomacy.getGoldGifts() > 0)
aDiplomacy.nextTurn()
a.gameInfo.ruleset.modOptions.constants.goldGiftDegradationMultiplier = 10f
caDiplomacy.nextTurn()
assertTrue(caDiplomacy.getGoldGifts() < aDiplomacy.getGoldGifts())
}
@Test
fun `Gifted Gold doesn't disapear when gold gift degradation multiplier constant is set to 0` () {
a.gameInfo.ruleset.modOptions.constants.goldGiftDegradationMultiplier = 0f
aDiplomacy.recieveGoldGifts(1000)
assertTrue(aDiplomacy.getGoldGifts() > 0)
val gold = aDiplomacy.getGoldGifts()
aDiplomacy.nextTurn()
val gold2 = aDiplomacy.getGoldGifts()
assertTrue(gold == gold2)
}
@Test
fun `Gifted Gold doesn't disapear when gold gift degradation multiplier constant is set to 0 with low gold` () {
a.gameInfo.ruleset.modOptions.constants.goldGiftDegradationMultiplier = 0f
aDiplomacy.recieveGoldGifts(10)
assertTrue(aDiplomacy.getGoldGifts() > 0)
val gold = aDiplomacy.getGoldGifts()
aDiplomacy.nextTurn()
val gold2 = aDiplomacy.getGoldGifts()
assertTrue(gold == gold2)
}
}