mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-28 06:16:37 -04:00
Quests fixes and additions (#5301)
* enable all quests * implement more quests * weighting for quests * global quests * fixes * fixes * Update template.properties * general string * reviews
This commit is contained in:
parent
e9e0f2c55f
commit
fa813f8f5e
@ -22,12 +22,12 @@
|
|||||||
{
|
{
|
||||||
"name": "Acquire Great Person",
|
"name": "Acquire Great Person",
|
||||||
"description": "Great People can change the course of a Civilization! You will be rewarded for acquiring a new [greatPerson]."
|
"description": "Great People can change the course of a Civilization! You will be rewarded for acquiring a new [greatPerson]."
|
||||||
},/*
|
},
|
||||||
{
|
{
|
||||||
"name": "Conquer City State",
|
"name": "Conquer City State",
|
||||||
"description": "You will be rewarded for conquering the city state of [cityState]!",
|
"description": "It's time to erase the City State of [cityState] from the map. You will be greatly rewarded for conquering them!",
|
||||||
"influence": 80
|
"influence": 80
|
||||||
},*/
|
},
|
||||||
{
|
{
|
||||||
"name": "Find Player",
|
"name": "Find Player",
|
||||||
"description": "You have yet to discover where [civName] set up their cities. You will be rewarded for finding their territories.",
|
"description": "You have yet to discover where [civName] set up their cities. You will be rewarded for finding their territories.",
|
||||||
@ -36,18 +36,17 @@
|
|||||||
{
|
{
|
||||||
"name": "Find Natural Wonder",
|
"name": "Find Natural Wonder",
|
||||||
"description": "Send your best explorers on a quest to discover Natural Wonders. Nobody knows the location of [naturalWonder] yet."
|
"description": "Send your best explorers on a quest to discover Natural Wonders. Nobody knows the location of [naturalWonder] yet."
|
||||||
}
|
},
|
||||||
/* G&K */
|
/* G&K */
|
||||||
/*
|
|
||||||
{
|
{
|
||||||
"name": "Give Gold",
|
"name": "Give Gold",
|
||||||
"description": "We are suffering great poverty, and unless we receive a sum of [250] Gold, it's only a matter of time before we collapse.",
|
"description": "We are suffering great poverty after being robbed by [civName], and unless we receive a sum of Gold, it's only a matter of time before we collapse.",
|
||||||
"influence": 20,
|
"influence": 20,
|
||||||
"duration": 30
|
"duration": 30
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Pledge to Protect",
|
"name": "Pledge to Protect",
|
||||||
"description": "Our peoples deserve to be protected by the likes of you. By signing a Protection Pedging, you'll confirm the bond that ties us.",
|
"description": "We need your protection to stop the aggressions of [civName]. By signing a Pledge of Protection, you'll confirm the bond that ties us.",
|
||||||
"influence": 20,
|
"influence": 20,
|
||||||
"duration": 30
|
"duration": 30
|
||||||
},
|
},
|
||||||
@ -66,7 +65,7 @@
|
|||||||
"minimumCivs": 3
|
"minimumCivs": 3
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Contest Techs",
|
"name": "Contest Technologies",
|
||||||
"description": "The civilization with the largest number of new Technologies researched will gain a reward.",
|
"description": "The civilization with the largest number of new Technologies researched will gain a reward.",
|
||||||
"type": "Global",
|
"type": "Global",
|
||||||
"duration": 30,
|
"duration": 30,
|
||||||
@ -74,7 +73,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Invest",
|
"name": "Invest",
|
||||||
"description": "Our people are rejoycing thanks to a tourism boom. For a certain amount of time, any Gold donation will yeld double the Influence.",
|
"description": "Our people are rejoicing thanks to a tourism boom. For a certain amount of time, any Gold donation will yield [50]% extra Influence.",
|
||||||
"type": "Global",
|
"type": "Global",
|
||||||
"influence": 0,
|
"influence": 0,
|
||||||
"duration": 30,
|
"duration": 30,
|
||||||
@ -82,19 +81,18 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Bully City State",
|
"name": "Bully City State",
|
||||||
"description": ""
|
"description": "We are tired of the pretensions of [cityState]. If someone were to put them in their place by Demanding Tribute from them, they would be rewarded.",
|
||||||
"duration": 30
|
"duration": 30
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Denounce Civilization",
|
"name": "Denounce Civilization",
|
||||||
"description": "",
|
"description": "We have been forced to pay tribute to [civName]! We need you to tell the world of their ill deeds.",
|
||||||
"duration": 30
|
"duration": 30
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Spread Religion",
|
"name": "Spread Religion",
|
||||||
"description": ""
|
"description": "We have heard the tenets of [religionName] and are most curious. Will you send missionaries to teach us about your religion?"
|
||||||
},
|
}
|
||||||
*/
|
|
||||||
/* BNW */
|
/* BNW */
|
||||||
/*
|
/*
|
||||||
{
|
{
|
||||||
|
@ -134,6 +134,8 @@ Ally =
|
|||||||
|
|
||||||
[questName] (+[influenceAmount] influence) =
|
[questName] (+[influenceAmount] influence) =
|
||||||
[remainingTurns] turns remaining =
|
[remainingTurns] turns remaining =
|
||||||
|
Current leader is [civInfo] with [amount] [stat] generated. =
|
||||||
|
Current leader is [civInfo] with [amount] Technologies discovered. =
|
||||||
|
|
||||||
## Diplomatic modifiers
|
## Diplomatic modifiers
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ import kotlin.math.pow
|
|||||||
|
|
||||||
/** Class containing city-state-specific functions */
|
/** Class containing city-state-specific functions */
|
||||||
class CityStateFunctions(val civInfo: CivilizationInfo) {
|
class CityStateFunctions(val civInfo: CivilizationInfo) {
|
||||||
|
|
||||||
/** Attempts to initialize the city state, returning true if successful. */
|
/** Attempts to initialize the city state, returning true if successful. */
|
||||||
fun initCityState(ruleset: Ruleset, startingEra: String, unusedMajorCivs: Collection<String>): Boolean {
|
fun initCityState(ruleset: Ruleset, startingEra: String, unusedMajorCivs: Collection<String>): Boolean {
|
||||||
val cityStateType = ruleset.nations[civInfo.civName]?.cityStateType
|
val cityStateType = ruleset.nations[civInfo.civName]?.cityStateType
|
||||||
@ -55,7 +55,7 @@ class CityStateFunctions(val civInfo: CivilizationInfo) {
|
|||||||
// Unique unit for militaristic city-states
|
// Unique unit for militaristic city-states
|
||||||
if (allPossibleBonuses.any { it.isOfType(UniqueType.CityStateMilitaryUnits) }
|
if (allPossibleBonuses.any { it.isOfType(UniqueType.CityStateMilitaryUnits) }
|
||||||
|| (fallback && cityStateType == CityStateType.Militaristic) // Fallback for badly defined Eras.json
|
|| (fallback && cityStateType == CityStateType.Militaristic) // Fallback for badly defined Eras.json
|
||||||
) {
|
) {
|
||||||
|
|
||||||
val possibleUnits = ruleset.units.values.filter { it.requiredTech != null
|
val possibleUnits = ruleset.units.values.filter { it.requiredTech != null
|
||||||
&& ruleset.eras[ruleset.technologies[it.requiredTech!!]!!.era()]!!.eraNumber > ruleset.eras[startingEra]!!.eraNumber // Not from the start era or before
|
&& ruleset.eras[ruleset.technologies[it.requiredTech!!]!!.era()]!!.eraNumber > ruleset.eras[startingEra]!!.eraNumber // Not from the start era or before
|
||||||
@ -127,6 +127,10 @@ class CityStateFunctions(val civInfo: CivilizationInfo) {
|
|||||||
}
|
}
|
||||||
for (unique in donorCiv.getMatchingUniques("Gifts of Gold to City-States generate []% more Influence"))
|
for (unique in donorCiv.getMatchingUniques("Gifts of Gold to City-States generate []% more Influence"))
|
||||||
influenceGained *= 1f + unique.params[0].toFloat() / 100f
|
influenceGained *= 1f + unique.params[0].toFloat() / 100f
|
||||||
|
|
||||||
|
// Bonus due to "Invest" quests
|
||||||
|
influenceGained *= civInfo.questManager.getInvestmentMultiplier(donorCiv.civName)
|
||||||
|
|
||||||
influenceGained -= influenceGained % 5
|
influenceGained -= influenceGained % 5
|
||||||
if (influenceGained < 5f) influenceGained = 5f
|
if (influenceGained < 5f) influenceGained = 5f
|
||||||
return influenceGained.toInt()
|
return influenceGained.toInt()
|
||||||
@ -137,6 +141,7 @@ class CityStateFunctions(val civInfo: CivilizationInfo) {
|
|||||||
donorCiv.addGold(-giftAmount)
|
donorCiv.addGold(-giftAmount)
|
||||||
civInfo.addGold(giftAmount)
|
civInfo.addGold(giftAmount)
|
||||||
civInfo.getDiplomacyManager(donorCiv).addInfluence(influenceGainedByGift(donorCiv, giftAmount).toFloat())
|
civInfo.getDiplomacyManager(donorCiv).addInfluence(influenceGainedByGift(donorCiv, giftAmount).toFloat())
|
||||||
|
civInfo.questManager.receivedGoldGift(donorCiv)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getProtectorCivs() : List<CivilizationInfo> {
|
fun getProtectorCivs() : List<CivilizationInfo> {
|
||||||
@ -507,6 +512,13 @@ class CityStateFunctions(val civInfo: CivilizationInfo) {
|
|||||||
protector.popupAlerts.add(PopupAlert(AlertType.BulliedProtectedMinor,
|
protector.popupAlerts.add(PopupAlert(AlertType.BulliedProtectedMinor,
|
||||||
bully.civName + "@" + civInfo.civName)) // we need to pass both civs as argument, hence the horrible chimera
|
bully.civName + "@" + civInfo.civName)) // we need to pass both civs as argument, hence the horrible chimera
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set a diplomatic flag so we remember for future quests (and not to give them any)
|
||||||
|
civInfo.getDiplomacyManager(bully).setFlag(DiplomacyFlags.Bullied, 20)
|
||||||
|
|
||||||
|
// Notify all city states that we were bullied (for quests)
|
||||||
|
civInfo.gameInfo.getAliveCityStates()
|
||||||
|
.forEach { it.questManager.cityStateBullied(civInfo, bully) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A city state was attacked. What are its protectors going to do about it??? Also checks for Wary */
|
/** A city state was attacked. What are its protectors going to do about it??? Also checks for Wary */
|
||||||
@ -531,6 +543,8 @@ class CityStateFunctions(val civInfo: CivilizationInfo) {
|
|||||||
continue
|
continue
|
||||||
if (!cityState.knows(attacker)) // Must have met
|
if (!cityState.knows(attacker)) // Must have met
|
||||||
continue
|
continue
|
||||||
|
if (cityState.questManager.wantsDead(civInfo.civName)) // Must not want us dead
|
||||||
|
continue
|
||||||
|
|
||||||
var probability: Int
|
var probability: Int
|
||||||
if (attacker.isMinorCivWarmonger()) {
|
if (attacker.isMinorCivWarmonger()) {
|
||||||
@ -601,6 +615,10 @@ class CityStateFunctions(val civInfo: CivilizationInfo) {
|
|||||||
protector.addNotification("[${attacker.civName}] has destroyed [${civInfo.civName}], whom you had pledged to protect!", attacker.civName,
|
protector.addNotification("[${attacker.civName}] has destroyed [${civInfo.civName}], whom you had pledged to protect!", attacker.civName,
|
||||||
NotificationIcon.Death, civInfo.civName)
|
NotificationIcon.Death, civInfo.civName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notify all city states that we were killed (for quest completion)
|
||||||
|
civInfo.gameInfo.getAliveCityStates()
|
||||||
|
.forEach { it.questManager.cityStateConquered(civInfo, attacker) }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -162,6 +162,9 @@ class CivilizationInfo {
|
|||||||
// For Aggressor, Warmonger status
|
// For Aggressor, Warmonger status
|
||||||
private var numMinorCivsAttacked = 0
|
private var numMinorCivsAttacked = 0
|
||||||
|
|
||||||
|
var totalCultureForContests = 0
|
||||||
|
var totalFaithForContests = 0
|
||||||
|
|
||||||
constructor()
|
constructor()
|
||||||
|
|
||||||
constructor(civName: String) {
|
constructor(civName: String) {
|
||||||
@ -209,6 +212,8 @@ class CivilizationInfo {
|
|||||||
toReturn.hasEverOwnedOriginalCapital = hasEverOwnedOriginalCapital
|
toReturn.hasEverOwnedOriginalCapital = hasEverOwnedOriginalCapital
|
||||||
toReturn.passableImpassables.addAll(passableImpassables)
|
toReturn.passableImpassables.addAll(passableImpassables)
|
||||||
toReturn.numMinorCivsAttacked = numMinorCivsAttacked
|
toReturn.numMinorCivsAttacked = numMinorCivsAttacked
|
||||||
|
toReturn.totalCultureForContests = totalCultureForContests
|
||||||
|
toReturn.totalFaithForContests = totalFaithForContests
|
||||||
return toReturn
|
return toReturn
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -730,6 +735,7 @@ class CivilizationInfo {
|
|||||||
val nextTurnStats = statsForNextTurn
|
val nextTurnStats = statsForNextTurn
|
||||||
|
|
||||||
policies.endTurn(nextTurnStats.culture.toInt())
|
policies.endTurn(nextTurnStats.culture.toInt())
|
||||||
|
totalCultureForContests += nextTurnStats.culture.toInt()
|
||||||
|
|
||||||
if (isCityState())
|
if (isCityState())
|
||||||
questManager.endTurn()
|
questManager.endTurn()
|
||||||
@ -754,6 +760,7 @@ class CivilizationInfo {
|
|||||||
tech.endTurn(nextTurnStats.science.toInt())
|
tech.endTurn(nextTurnStats.science.toInt())
|
||||||
|
|
||||||
religionManager.endTurn(nextTurnStats.faith.toInt())
|
religionManager.endTurn(nextTurnStats.faith.toInt())
|
||||||
|
totalFaithForContests += nextTurnStats.faith.toInt()
|
||||||
|
|
||||||
if (isMajorCiv()) greatPeople.addGreatPersonPoints(getGreatPersonPointsForNextTurn()) // City-states don't get great people!
|
if (isMajorCiv()) greatPeople.addGreatPersonPoints(getGreatPersonPointsForNextTurn()) // City-states don't get great people!
|
||||||
|
|
||||||
@ -861,10 +868,12 @@ class CivilizationInfo {
|
|||||||
|
|
||||||
fun addStat(stat: Stat, amount: Int) {
|
fun addStat(stat: Stat, amount: Int) {
|
||||||
when (stat) {
|
when (stat) {
|
||||||
Stat.Culture -> policies.addCulture(amount)
|
Stat.Culture -> { policies.addCulture(amount)
|
||||||
|
totalCultureForContests += amount }
|
||||||
Stat.Science -> tech.addScience(amount)
|
Stat.Science -> tech.addScience(amount)
|
||||||
Stat.Gold -> addGold(amount)
|
Stat.Gold -> addGold(amount)
|
||||||
Stat.Faith -> religionManager.storedFaith += amount
|
Stat.Faith -> { religionManager.storedFaith += amount
|
||||||
|
totalFaithForContests += amount }
|
||||||
else -> {}
|
else -> {}
|
||||||
// Food and Production wouldn't make sense to be added nationwide
|
// Food and Production wouldn't make sense to be added nationwide
|
||||||
// Happiness cannot be added as it is recalculated again, use a unique instead
|
// Happiness cannot be added as it is recalculated again, use a unique instead
|
||||||
|
@ -4,7 +4,8 @@ import com.badlogic.gdx.math.Vector2
|
|||||||
import com.unciv.Constants
|
import com.unciv.Constants
|
||||||
import com.unciv.UncivGame
|
import com.unciv.UncivGame
|
||||||
import com.unciv.logic.GameInfo
|
import com.unciv.logic.GameInfo
|
||||||
import com.unciv.logic.map.BFS
|
import com.unciv.logic.civilization.diplomacy.DiplomacyFlags
|
||||||
|
import com.unciv.logic.civilization.diplomacy.DiplomaticStatus
|
||||||
import com.unciv.logic.map.TileInfo
|
import com.unciv.logic.map.TileInfo
|
||||||
import com.unciv.models.ruleset.Building
|
import com.unciv.models.ruleset.Building
|
||||||
import com.unciv.models.ruleset.Quest
|
import com.unciv.models.ruleset.Quest
|
||||||
@ -13,7 +14,9 @@ import com.unciv.models.ruleset.tile.ResourceType
|
|||||||
import com.unciv.models.ruleset.tile.TileResource
|
import com.unciv.models.ruleset.tile.TileResource
|
||||||
import com.unciv.models.ruleset.unit.BaseUnit
|
import com.unciv.models.ruleset.unit.BaseUnit
|
||||||
import com.unciv.models.translations.fillPlaceholders
|
import com.unciv.models.translations.fillPlaceholders
|
||||||
|
import com.unciv.models.translations.getPlaceholderParameters
|
||||||
import com.unciv.ui.utils.randomWeighted
|
import com.unciv.ui.utils.randomWeighted
|
||||||
|
import com.unciv.ui.utils.toPercent
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
@ -55,6 +58,18 @@ class QuestManager {
|
|||||||
/** Returns true if [civInfo] have active quests for [challenger] */
|
/** Returns true if [civInfo] have active quests for [challenger] */
|
||||||
fun haveQuestsFor(challenger: CivilizationInfo): Boolean = assignedQuests.any { it.assignee == challenger.civName }
|
fun haveQuestsFor(challenger: CivilizationInfo): Boolean = assignedQuests.any { it.assignee == challenger.civName }
|
||||||
|
|
||||||
|
/** Returns true if [civInfo] has asked anyone to conquer [target] */
|
||||||
|
fun wantsDead(target: String): Boolean = assignedQuests.any { it.questName == QuestName.ConquerCityState.value && it.data1 == target }
|
||||||
|
|
||||||
|
/** Returns the influence multiplier for [donor] from a Investment quest that [civInfo] might have (assumes only one) */
|
||||||
|
fun getInvestmentMultiplier(donor: String): Float {
|
||||||
|
val investmentQuest = assignedQuests.firstOrNull { it.questName == QuestName.Invest.value && it.assignee == donor }
|
||||||
|
return if (investmentQuest == null)
|
||||||
|
1f
|
||||||
|
else
|
||||||
|
investmentQuest.data1.toPercent()
|
||||||
|
}
|
||||||
|
|
||||||
fun clone(): QuestManager {
|
fun clone(): QuestManager {
|
||||||
val toReturn = QuestManager()
|
val toReturn = QuestManager()
|
||||||
toReturn.globalQuestCountdown = globalQuestCountdown
|
toReturn.globalQuestCountdown = globalQuestCountdown
|
||||||
@ -247,6 +262,8 @@ class QuestManager {
|
|||||||
|
|
||||||
for (assignee in assignees) {
|
for (assignee in assignees) {
|
||||||
|
|
||||||
|
val playerReligion = civInfo.gameInfo.religions.values.firstOrNull { it.foundingCivName == assignee.civName && it.isMajorReligion() }
|
||||||
|
|
||||||
var data1 = ""
|
var data1 = ""
|
||||||
var data2 = ""
|
var data2 = ""
|
||||||
|
|
||||||
@ -261,6 +278,17 @@ class QuestManager {
|
|||||||
QuestName.GreatPerson.value -> data1 = getGreatPersonForQuest(assignee)!!.name
|
QuestName.GreatPerson.value -> data1 = getGreatPersonForQuest(assignee)!!.name
|
||||||
QuestName.FindPlayer.value -> data1 = getCivilizationToFindForQuest(assignee)!!.civName
|
QuestName.FindPlayer.value -> data1 = getCivilizationToFindForQuest(assignee)!!.civName
|
||||||
QuestName.FindNaturalWonder.value -> data1 = getNaturalWonderToFindForQuest(assignee)!!
|
QuestName.FindNaturalWonder.value -> data1 = getNaturalWonderToFindForQuest(assignee)!!
|
||||||
|
QuestName.ConquerCityState.value -> data1 = getCityStateTarget(assignee)!!.civName
|
||||||
|
QuestName.BullyCityState.value -> data1 = getCityStateTarget(assignee)!!.civName
|
||||||
|
QuestName.PledgeToProtect.value -> data1 = getMostRecentBully()!!
|
||||||
|
QuestName.GiveGold.value -> data1 = getMostRecentBully()!!
|
||||||
|
QuestName.DenounceCiv.value -> data1 = getMostRecentBully()!!
|
||||||
|
QuestName.SpreadReligion.value -> { data1 = playerReligion!!.getReligionDisplayName() // For display
|
||||||
|
data2 = playerReligion.name } // To check completion
|
||||||
|
QuestName.ContestCulture.value -> data1 = assignee.totalCultureForContests.toString()
|
||||||
|
QuestName.ContestFaith.value -> data1 = assignee.totalFaithForContests.toString()
|
||||||
|
QuestName.ContestTech.value -> data1 = assignee.tech.getNumberOfTechsResearched().toString()
|
||||||
|
QuestName.Invest.value -> data1 = quest.description.getPlaceholderParameters().first()
|
||||||
}
|
}
|
||||||
|
|
||||||
val newQuest = AssignedQuest(
|
val newQuest = AssignedQuest(
|
||||||
@ -294,22 +322,33 @@ class QuestManager {
|
|||||||
return false
|
return false
|
||||||
if (assignedQuests.any { it.assignee == challenger.civName && it.questName == quest.name })
|
if (assignedQuests.any { it.assignee == challenger.civName && it.questName == quest.name })
|
||||||
return false
|
return false
|
||||||
|
if (quest.isIndividual() && civInfo.getDiplomacyManager(challenger).hasFlag(DiplomacyFlags.Bullied))
|
||||||
|
return false
|
||||||
|
|
||||||
|
val mostRecentBully = getMostRecentBully()
|
||||||
|
val playerReligion = civInfo.gameInfo.religions.values.firstOrNull() { it.foundingCivName == challenger.civName && it.isMajorReligion() }?.name
|
||||||
|
|
||||||
return when (quest.name) {
|
return when (quest.name) {
|
||||||
QuestName.ClearBarbarianCamp.value -> getBarbarianEncampmentForQuest() != null
|
QuestName.ClearBarbarianCamp.value -> getBarbarianEncampmentForQuest() != null
|
||||||
QuestName.Route.value -> {
|
QuestName.Route.value -> !challenger.cities.none()
|
||||||
if (challenger.cities.none() || !civInfo.hasEverBeenFriendWith(challenger)
|
&& !civInfo.isCapitalConnectedToCity(challenger.getCapital())
|
||||||
|| civInfo.isCapitalConnectedToCity(challenger.getCapital())) return false
|
// Need to have a city within 7 tiles on the same continent
|
||||||
|
&& challenger.cities.any { it.getCenterTile().aerialDistanceTo(civInfo.getCapital().getCenterTile()) <= 7
|
||||||
val bfs = BFS(civInfo.getCapital().getCenterTile()) { it.isLand && !it.isImpassible() }
|
&& it.getCenterTile().getContinent() == civInfo.getCapital().getCenterTile().getContinent() }
|
||||||
bfs.stepUntilDestination(challenger.getCapital().getCenterTile())
|
QuestName.ConnectResource.value -> getResourceForQuest(challenger) != null
|
||||||
bfs.hasReachedTile(challenger.getCapital().getCenterTile())
|
QuestName.ConstructWonder.value -> getWonderToBuildForQuest(challenger) != null
|
||||||
}
|
QuestName.GreatPerson.value -> getGreatPersonForQuest(challenger) != null
|
||||||
QuestName.ConnectResource.value -> civInfo.hasEverBeenFriendWith(challenger) && getResourceForQuest(challenger) != null
|
QuestName.FindPlayer.value -> getCivilizationToFindForQuest(challenger) != null
|
||||||
QuestName.ConstructWonder.value -> civInfo.hasEverBeenFriendWith(challenger) && getWonderToBuildForQuest(challenger) != null
|
QuestName.FindNaturalWonder.value -> getNaturalWonderToFindForQuest(challenger) != null
|
||||||
QuestName.GreatPerson.value -> civInfo.hasEverBeenFriendWith(challenger) && getGreatPersonForQuest(challenger) != null
|
QuestName.PledgeToProtect.value -> mostRecentBully != null && challenger !in civInfo.getProtectorCivs()
|
||||||
QuestName.FindPlayer.value -> civInfo.hasEverBeenFriendWith(challenger) && getCivilizationToFindForQuest(challenger) != null
|
QuestName.GiveGold.value -> mostRecentBully != null
|
||||||
QuestName.FindNaturalWonder.value -> civInfo.hasEverBeenFriendWith(challenger) && getNaturalWonderToFindForQuest(challenger) != null
|
QuestName.DenounceCiv.value -> mostRecentBully != null && challenger.knows(mostRecentBully)
|
||||||
|
&& !challenger.getDiplomacyManager(mostRecentBully).hasFlag(DiplomacyFlags.Denunciation)
|
||||||
|
&& challenger.getDiplomacyManager(mostRecentBully).diplomaticStatus != DiplomaticStatus.War
|
||||||
|
&& !( challenger.playerType == PlayerType.Human && civInfo.gameInfo.getCivilization(mostRecentBully).playerType == PlayerType.Human)
|
||||||
|
QuestName.SpreadReligion.value -> playerReligion != null && civInfo.getCapital().religion.getMajorityReligion()?.name != playerReligion
|
||||||
|
QuestName.ConquerCityState.value -> getCityStateTarget(challenger) != null && civInfo.cityStatePersonality != CityStatePersonality.Friendly
|
||||||
|
QuestName.BullyCityState.value -> getCityStateTarget(challenger) != null
|
||||||
else -> true
|
else -> true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -324,6 +363,9 @@ class QuestManager {
|
|||||||
QuestName.GreatPerson.value -> assignee.getCivGreatPeople().any { it.baseUnit.getReplacedUnit(civInfo.gameInfo.ruleSet).name == assignedQuest.data1 }
|
QuestName.GreatPerson.value -> assignee.getCivGreatPeople().any { it.baseUnit.getReplacedUnit(civInfo.gameInfo.ruleSet).name == assignedQuest.data1 }
|
||||||
QuestName.FindPlayer.value -> assignee.hasMetCivTerritory(civInfo.gameInfo.getCivilization(assignedQuest.data1))
|
QuestName.FindPlayer.value -> assignee.hasMetCivTerritory(civInfo.gameInfo.getCivilization(assignedQuest.data1))
|
||||||
QuestName.FindNaturalWonder.value -> assignee.naturalWonders.contains(assignedQuest.data1)
|
QuestName.FindNaturalWonder.value -> assignee.naturalWonders.contains(assignedQuest.data1)
|
||||||
|
QuestName.PledgeToProtect.value -> assignee in civInfo.getProtectorCivs()
|
||||||
|
QuestName.DenounceCiv.value -> assignee.getDiplomacyManager(assignedQuest.data1).hasFlag(DiplomacyFlags.Denunciation)
|
||||||
|
QuestName.SpreadReligion.value -> civInfo.getCapital().religion.getMajorityReligion() == civInfo.gameInfo.religions[assignedQuest.data2]
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -335,6 +377,9 @@ class QuestManager {
|
|||||||
QuestName.ClearBarbarianCamp.value -> civInfo.gameInfo.tileMap[assignedQuest.data1.toInt(), assignedQuest.data2.toInt()].improvement != Constants.barbarianEncampment
|
QuestName.ClearBarbarianCamp.value -> civInfo.gameInfo.tileMap[assignedQuest.data1.toInt(), assignedQuest.data2.toInt()].improvement != Constants.barbarianEncampment
|
||||||
QuestName.ConstructWonder.value -> civInfo.gameInfo.getCities().any { it.civInfo != assignee && it.cityConstructions.isBuilt(assignedQuest.data1) }
|
QuestName.ConstructWonder.value -> civInfo.gameInfo.getCities().any { it.civInfo != assignee && it.cityConstructions.isBuilt(assignedQuest.data1) }
|
||||||
QuestName.FindPlayer.value -> civInfo.gameInfo.getCivilization(assignedQuest.data1).isDefeated()
|
QuestName.FindPlayer.value -> civInfo.gameInfo.getCivilization(assignedQuest.data1).isDefeated()
|
||||||
|
QuestName.ConquerCityState.value -> civInfo.gameInfo.getCivilization(assignedQuest.data1).isDefeated()
|
||||||
|
QuestName.BullyCityState.value -> civInfo.gameInfo.getCivilization(assignedQuest.data1).isDefeated()
|
||||||
|
QuestName.DenounceCiv.value -> civInfo.gameInfo.getCivilization(assignedQuest.data1).isDefeated()
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -358,14 +403,29 @@ class QuestManager {
|
|||||||
|
|
||||||
/** Returns the score for the [assignedQuest] */
|
/** Returns the score for the [assignedQuest] */
|
||||||
private fun getScoreForQuest(assignedQuest: AssignedQuest): Int {
|
private fun getScoreForQuest(assignedQuest: AssignedQuest): Int {
|
||||||
@Suppress("UNUSED_VARIABLE") // This is a work in progress
|
|
||||||
val assignee = civInfo.gameInfo.getCivilization(assignedQuest.assignee)
|
val assignee = civInfo.gameInfo.getCivilization(assignedQuest.assignee)
|
||||||
return when (assignedQuest.questName) {
|
return when (assignedQuest.questName) {
|
||||||
// Waiting for contest quests
|
QuestName.ContestCulture.value -> assignee.totalCultureForContests - assignedQuest.data1.toInt()
|
||||||
|
QuestName.ContestFaith.value -> assignee.totalFaithForContests - assignedQuest.data1.toInt()
|
||||||
|
QuestName.ContestTech.value -> assignee.tech.getNumberOfTechsResearched() - assignedQuest.data1.toInt()
|
||||||
else -> 0
|
else -> 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns a string with the leading civ and their score for [questName] */
|
||||||
|
fun getLeaderStringForQuest(questName: String): String {
|
||||||
|
val leadingQuest = assignedQuests.filter { it.questName == questName }.maxByOrNull { getScoreForQuest(it) }
|
||||||
|
if (leadingQuest == null)
|
||||||
|
return ""
|
||||||
|
|
||||||
|
return when (questName){
|
||||||
|
QuestName.ContestCulture.value -> "Current leader is ${leadingQuest.assignee} with ${getScoreForQuest(leadingQuest)} [Culture] generated."
|
||||||
|
QuestName.ContestFaith.value -> "Current leader is ${leadingQuest.assignee} with ${getScoreForQuest(leadingQuest)} [Faith] generated."
|
||||||
|
QuestName.ContestTech.value -> "Current leader is ${leadingQuest.assignee} with ${getScoreForQuest(leadingQuest)} Technologies discovered."
|
||||||
|
else -> ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets notified a barbarian camp in [location] has been cleared by [civInfo].
|
* Gets notified a barbarian camp in [location] has been cleared by [civInfo].
|
||||||
* Since [QuestName.ClearBarbarianCamp] is a global quest, it could have been assigned to
|
* Since [QuestName.ClearBarbarianCamp] is a global quest, it could have been assigned to
|
||||||
@ -383,6 +443,59 @@ class QuestManager {
|
|||||||
assignedQuests.removeAll(matchingQuests)
|
assignedQuests.removeAll(matchingQuests)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets notified the city state [cityState] was just conquered by [attacker].
|
||||||
|
*/
|
||||||
|
fun cityStateConquered(cityState: CivilizationInfo, attacker: CivilizationInfo) {
|
||||||
|
val matchingQuests = assignedQuests.asSequence()
|
||||||
|
.filter { it.questName == QuestName.ConquerCityState.value }
|
||||||
|
.filter { it.data1 == cityState.civName && it.assignee == attacker.civName}
|
||||||
|
|
||||||
|
for (quest in matchingQuests)
|
||||||
|
giveReward(quest)
|
||||||
|
|
||||||
|
assignedQuests.removeAll(matchingQuests)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets notified the city state [cityState] was just bullied by [bully].
|
||||||
|
*/
|
||||||
|
fun cityStateBullied(cityState: CivilizationInfo, bully: CivilizationInfo) {
|
||||||
|
val matchingQuests = assignedQuests.asSequence()
|
||||||
|
.filter { it.questName == QuestName.BullyCityState.value }
|
||||||
|
.filter { it.data1 == cityState.civName && it.assignee == bully.civName}
|
||||||
|
|
||||||
|
for (quest in matchingQuests)
|
||||||
|
giveReward(quest)
|
||||||
|
|
||||||
|
assignedQuests.removeAll(matchingQuests)
|
||||||
|
|
||||||
|
// What idiots haha oh wait that's us
|
||||||
|
if (civInfo == cityState) {
|
||||||
|
// Revoke most quest types from the bully
|
||||||
|
val revokedQuests = assignedQuests.asSequence()
|
||||||
|
.filter { it.isIndividual() || it.questName == QuestName.Invest.value }
|
||||||
|
assignedQuests.removeAll(revokedQuests)
|
||||||
|
if (revokedQuests.count() > 0)
|
||||||
|
bully.addNotification("[${civInfo.civName}] cancelled the quests they had given you because you demanded tribute from them.",
|
||||||
|
DiplomacyAction(civInfo.civName), civInfo.civName, "OtherIcons/Quest")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets notified when given gold by [donorCiv].
|
||||||
|
*/
|
||||||
|
fun receivedGoldGift(donorCiv: CivilizationInfo) {
|
||||||
|
val matchingQuests = assignedQuests.asSequence()
|
||||||
|
.filter { it.questName == QuestName.GiveGold.value }
|
||||||
|
.filter { it.assignee == donorCiv.civName}
|
||||||
|
|
||||||
|
for (quest in matchingQuests)
|
||||||
|
giveReward(quest)
|
||||||
|
|
||||||
|
assignedQuests.removeAll(matchingQuests)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the weight of the [questName], depends on city state trait and personality
|
* Returns the weight of the [questName], depends on city state trait and personality
|
||||||
*/
|
*/
|
||||||
@ -440,6 +553,56 @@ class QuestManager {
|
|||||||
if (trait == CityStateType.Militaristic)
|
if (trait == CityStateType.Militaristic)
|
||||||
weight *= 3f
|
weight *= 3f
|
||||||
}
|
}
|
||||||
|
QuestName.GiveGold.value -> {
|
||||||
|
when (trait) {
|
||||||
|
CityStateType.Militaristic -> weight *= 2f
|
||||||
|
CityStateType.Mercantile -> weight *= 3.5f
|
||||||
|
else -> weight *= 3f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QuestName.PledgeToProtect.value -> {
|
||||||
|
when (trait) {
|
||||||
|
CityStateType.Militaristic -> weight *= 2f
|
||||||
|
CityStateType.Cultured -> weight *= 3.5f
|
||||||
|
else -> weight *= 3f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QuestName.BullyCityState.value -> {
|
||||||
|
when (personality) {
|
||||||
|
CityStatePersonality.Hostile -> weight *= 2f
|
||||||
|
CityStatePersonality.Irrational -> weight *= 1.5f
|
||||||
|
CityStatePersonality.Friendly -> weight *= .3f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QuestName.DenounceCiv.value -> {
|
||||||
|
when (trait) {
|
||||||
|
CityStateType.Religious -> weight *= 2.5f
|
||||||
|
CityStateType.Maritime -> weight *= 2f
|
||||||
|
else -> weight *= 1.5f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QuestName.SpreadReligion.value -> {
|
||||||
|
if (trait == CityStateType.Religious)
|
||||||
|
weight *= 3f
|
||||||
|
}
|
||||||
|
QuestName.ContestCulture.value -> {
|
||||||
|
if (trait == CityStateType.Cultured)
|
||||||
|
weight *= 2f
|
||||||
|
}
|
||||||
|
QuestName.ContestFaith.value -> {
|
||||||
|
when (trait) {
|
||||||
|
CityStateType.Religious -> weight *= 2f
|
||||||
|
else -> weight *= .5f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QuestName.ContestTech.value -> {
|
||||||
|
if (trait == CityStateType.Religious)
|
||||||
|
weight *= .5f
|
||||||
|
}
|
||||||
|
QuestName.Invest.value -> {
|
||||||
|
if (trait == CityStateType.Mercantile)
|
||||||
|
weight *= 1.5f
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return weight
|
return weight
|
||||||
}
|
}
|
||||||
@ -486,11 +649,21 @@ class QuestManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getWonderToBuildForQuest(challenger: CivilizationInfo): Building? {
|
private fun getWonderToBuildForQuest(challenger: CivilizationInfo): Building? {
|
||||||
|
val startingEra = civInfo.gameInfo.ruleSet.eras[civInfo.gameInfo.gameParameters.startingEra]!!
|
||||||
val wonders = civInfo.gameInfo.ruleSet.buildings.values
|
val wonders = civInfo.gameInfo.ruleSet.buildings.values
|
||||||
.filter { building ->
|
.filter { building ->
|
||||||
building.isWonder &&
|
// Buildable wonder
|
||||||
(building.requiredTech == null || challenger.tech.isResearched(building.requiredTech!!)) &&
|
building.isWonder
|
||||||
civInfo.gameInfo.getCities().none { it.cityConstructions.isBuilt(building.name) }
|
&& (building.requiredTech == null || challenger.tech.isResearched(building.requiredTech!!))
|
||||||
|
&& civInfo.gameInfo.getCities().none { it.cityConstructions.isBuilt(building.name) }
|
||||||
|
// Can't be disabled
|
||||||
|
&& building.name !in startingEra.startingObsoleteWonders
|
||||||
|
&& (civInfo.gameInfo.gameParameters.religionEnabled || !building.hasUnique("Hidden when religion is disabled"))
|
||||||
|
// Can't be more than 25% built anywhere
|
||||||
|
&& civInfo.gameInfo.getCities().none {
|
||||||
|
it.cityConstructions.getWorkDone(building.name) * 3 > it.cityConstructions.getRemainingWork(building.name) }
|
||||||
|
// Can't be a unique wonder
|
||||||
|
&& building.uniqueTo == null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wonders.isNotEmpty())
|
if (wonders.isNotEmpty())
|
||||||
@ -545,6 +718,29 @@ class QuestManager {
|
|||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a city-state [CivilizationInfo] that [civInfo] wants to target for hostile quests
|
||||||
|
*/
|
||||||
|
private fun getCityStateTarget(challenger: CivilizationInfo): CivilizationInfo? {
|
||||||
|
val closestProximity = civInfo.gameInfo.getAliveCityStates()
|
||||||
|
.mapNotNull { civInfo.proximity[it.civName] }.filter { it != Proximity.None }.minByOrNull { it.ordinal }
|
||||||
|
|
||||||
|
if (closestProximity == null || closestProximity == Proximity.Distant) // None close enough
|
||||||
|
return null
|
||||||
|
|
||||||
|
val validTargets = civInfo.getKnownCivs().filter { it.isCityState() && challenger.knows(it)
|
||||||
|
&& civInfo.proximity[it.civName] == closestProximity }
|
||||||
|
|
||||||
|
return validTargets.randomOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns a [CivilizationInfo] of the civ that most recently bullied [civInfo].
|
||||||
|
* Note: forgets after 20 turns has passed! */
|
||||||
|
private fun getMostRecentBully(): String? {
|
||||||
|
val bullies = civInfo.diplomacy.values.filter { it.hasFlag(DiplomacyFlags.Bullied)}
|
||||||
|
return bullies.maxByOrNull { it.getFlag(DiplomacyFlags.Bullied) }?.otherCivName
|
||||||
|
}
|
||||||
//endregion
|
//endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,6 +51,7 @@ enum class DiplomacyFlags {
|
|||||||
RememberSidedWithProtectedMinor,
|
RememberSidedWithProtectedMinor,
|
||||||
Denunciation,
|
Denunciation,
|
||||||
WaryOf,
|
WaryOf,
|
||||||
|
Bullied,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class DiplomaticModifiers {
|
enum class DiplomaticModifiers {
|
||||||
|
@ -11,6 +11,15 @@ enum class QuestName(val value: String) {
|
|||||||
ConquerCityState("Conquer City State"),
|
ConquerCityState("Conquer City State"),
|
||||||
FindPlayer("Find Player"),
|
FindPlayer("Find Player"),
|
||||||
FindNaturalWonder("Find Natural Wonder"),
|
FindNaturalWonder("Find Natural Wonder"),
|
||||||
|
GiveGold("Give Gold"),
|
||||||
|
PledgeToProtect("Pledge to Protect"),
|
||||||
|
ContestCulture("Contest Culture"),
|
||||||
|
ContestFaith("Contest Faith"),
|
||||||
|
ContestTech("Contest Technologies"),
|
||||||
|
Invest("Invest"),
|
||||||
|
BullyCityState("Bully City State"),
|
||||||
|
DenounceCiv("Denounce Civilization"),
|
||||||
|
SpreadReligion("Spread Religion"),
|
||||||
None("")
|
None("")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -541,7 +541,10 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() {
|
|||||||
|
|
||||||
val quest: Quest = viewingCiv.gameInfo.ruleSet.quests[assignedQuest.questName]!!
|
val quest: Quest = viewingCiv.gameInfo.ruleSet.quests[assignedQuest.questName]!!
|
||||||
val remainingTurns: Int = assignedQuest.getRemainingTurns()
|
val remainingTurns: Int = assignedQuest.getRemainingTurns()
|
||||||
val title = "[${quest.name}] (+[${quest.influence.toInt()}] influence)"
|
val title = if (quest.influence > 0)
|
||||||
|
"[${quest.name}] (+[${quest.influence.toInt()}] influence)"
|
||||||
|
else
|
||||||
|
quest.name
|
||||||
val description = assignedQuest.getDescription()
|
val description = assignedQuest.getDescription()
|
||||||
|
|
||||||
questTable.add(title.toLabel(fontSize = 24)).row()
|
questTable.add(title.toLabel(fontSize = 24)).row()
|
||||||
@ -549,6 +552,11 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() {
|
|||||||
.width(stage.width / 2).row()
|
.width(stage.width / 2).row()
|
||||||
if (quest.duration > 0)
|
if (quest.duration > 0)
|
||||||
questTable.add("[${remainingTurns}] turns remaining".toLabel()).row()
|
questTable.add("[${remainingTurns}] turns remaining".toLabel()).row()
|
||||||
|
if (quest.isGlobal()) {
|
||||||
|
val leaderString = viewingCiv.gameInfo.getCivilization(assignedQuest.assigner).questManager.getLeaderStringForQuest(assignedQuest.questName)
|
||||||
|
if (leaderString != "")
|
||||||
|
questTable.add(leaderString.toLabel()).row()
|
||||||
|
}
|
||||||
|
|
||||||
questTable.onClick {
|
questTable.onClick {
|
||||||
assignedQuest.onClickAction()
|
assignedQuest.onClickAction()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user