mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-28 14:24:43 -04:00
Competition quests in progress display tied leaders (and your place if you're behind) (#11224)
* Minor Quest/QuestManager linting * Cache Quest and QuestName references and use them * Nicer randomWeighted and fix UniqueType.ResourceWeighting * Integrate @soggerr's #10739 - show tied leaders and your position if you aren't leading * One more lint
This commit is contained in:
parent
31931d3849
commit
d5fda541ad
@ -170,8 +170,10 @@ Ally = Allié
|
|||||||
|
|
||||||
[questName] (+[influenceAmount] influence) = [questName] (+[influenceAmount] influence)
|
[questName] (+[influenceAmount] influence) = [questName] (+[influenceAmount] influence)
|
||||||
[remainingTurns] turns remaining = [remainingTurns] tours restants
|
[remainingTurns] turns remaining = [remainingTurns] tours restants
|
||||||
Current leader is [civInfo] with [amount] [stat] generated. = [civInfo] est actuellement en tête et a généré [amount] [stat].
|
Current leader(s): [leaders] = Actuellement en tête: [leaders]
|
||||||
Current leader is [civInfo] with [amount] Technologies discovered. = [civInfo] est actuellement en tête avec [amount] Technologies découvertes.
|
Current leader(s): [leaders], you: [yourScore] = Ton résultat: [yourScore] est dépassé par: [leaders]
|
||||||
|
# In the two templates above, 'leaders' and 'yourScore' will use the following:
|
||||||
|
[civilizations] with [value] [valueType] = [civilizations] avec [value] [valueType]
|
||||||
|
|
||||||
Demands = Demandes
|
Demands = Demandes
|
||||||
Please don't settle new cities near us. = Veuillez ne pas fonder de villes près de nous.
|
Please don't settle new cities near us. = Veuillez ne pas fonder de villes près de nous.
|
||||||
|
@ -170,8 +170,10 @@ Ally =
|
|||||||
|
|
||||||
[questName] (+[influenceAmount] influence) =
|
[questName] (+[influenceAmount] influence) =
|
||||||
[remainingTurns] turns remaining =
|
[remainingTurns] turns remaining =
|
||||||
Current leader is [civInfo] with [amount] [stat] generated. =
|
Current leader(s): [leaders] =
|
||||||
Current leader is [civInfo] with [amount] Technologies discovered. =
|
Current leader(s): [leaders], you: [yourScore] =
|
||||||
|
# In the two templates above, 'leaders' will be one or more of the following, and 'yourScore' one:
|
||||||
|
[civInfo] with [value] [valueType] =
|
||||||
|
|
||||||
Demands =
|
Demands =
|
||||||
Please don't settle new cities near us. =
|
Please don't settle new cities near us. =
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -57,12 +57,11 @@ object LuxuryResourcePlacementLogic {
|
|||||||
|
|
||||||
// Pick a luxury at random. Weight is reduced if the luxury has been picked before
|
// Pick a luxury at random. Weight is reduced if the luxury has been picked before
|
||||||
val regionConditional = StateForConditionals(region = region)
|
val regionConditional = StateForConditionals(region = region)
|
||||||
val modifiedWeights = candidateLuxuries.map {
|
region.luxury = candidateLuxuries.randomWeighted {
|
||||||
val weightingUnique = it.getMatchingUniques(UniqueType.ResourceWeighting, regionConditional).firstOrNull()
|
val weightingUnique = it.getMatchingUniques(UniqueType.ResourceWeighting, regionConditional).firstOrNull()
|
||||||
val relativeWeight = if (weightingUnique == null) 1f else weightingUnique.params[0].toFloat()
|
val relativeWeight = if (weightingUnique == null) 1f else weightingUnique.params[0].toFloat()
|
||||||
relativeWeight / (1f + amountRegionsWithLuxury[it.name]!!)
|
relativeWeight / (1f + amountRegionsWithLuxury[it.name]!!)
|
||||||
}.shuffled()
|
}.name
|
||||||
region.luxury = candidateLuxuries.randomWeighted(modifiedWeights).name
|
|
||||||
amountRegionsWithLuxury[region.luxury!!] = amountRegionsWithLuxury[region.luxury]!! + 1
|
amountRegionsWithLuxury[region.luxury!!] = amountRegionsWithLuxury[region.luxury]!! + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,15 +149,14 @@ object LuxuryResourcePlacementLogic {
|
|||||||
}
|
}
|
||||||
if (candidateLuxuries.isEmpty()) return@repeat
|
if (candidateLuxuries.isEmpty()) return@repeat
|
||||||
|
|
||||||
val weights = candidateLuxuries.map {
|
val luxury = candidateLuxuries.randomWeighted {
|
||||||
val weightingUnique =
|
val weightingUnique =
|
||||||
it.getMatchingUniques(UniqueType.LuxuryWeightingForCityStates).firstOrNull()
|
it.getMatchingUniques(UniqueType.LuxuryWeightingForCityStates).firstOrNull()
|
||||||
if (weightingUnique == null)
|
if (weightingUnique == null)
|
||||||
1f
|
1f
|
||||||
else
|
else
|
||||||
weightingUnique.params[0].toFloat()
|
weightingUnique.params[0].toFloat()
|
||||||
}
|
}.name
|
||||||
val luxury = candidateLuxuries.randomWeighted(weights).name
|
|
||||||
cityStateLuxuries.add(luxury)
|
cityStateLuxuries.add(luxury)
|
||||||
amountRegionsWithLuxury[luxury] = 1
|
amountRegionsWithLuxury[luxury] = 1
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ object MapRegionResources {
|
|||||||
fallbackTiles.add(tile) // Taken but might be a viable fallback tile
|
fallbackTiles.add(tile) // Taken but might be a viable fallback tile
|
||||||
} else {
|
} else {
|
||||||
// Add a resource to the tile
|
// Add a resource to the tile
|
||||||
val resourceToPlace = possibleResourcesForTile.randomWeighted(possibleResourcesForTile.map { weightings[it] ?: 0f })
|
val resourceToPlace = possibleResourcesForTile.randomWeighted { weightings[it] ?: 0f }
|
||||||
tile.setTileResource(resourceToPlace, majorDeposit)
|
tile.setTileResource(resourceToPlace, majorDeposit)
|
||||||
tileData.placeImpact(impactType, tile, baseImpact + Random.nextInt(randomImpact + 1))
|
tileData.placeImpact(impactType, tile, baseImpact + Random.nextInt(randomImpact + 1))
|
||||||
amountPlaced++
|
amountPlaced++
|
||||||
@ -66,7 +66,7 @@ object MapRegionResources {
|
|||||||
val bestTile = fallbackTiles.minByOrNull { tileData[it.position]!!.impacts[impactType]!! }!!
|
val bestTile = fallbackTiles.minByOrNull { tileData[it.position]!!.impacts[impactType]!! }!!
|
||||||
fallbackTiles.remove(bestTile)
|
fallbackTiles.remove(bestTile)
|
||||||
val possibleResourcesForTile = resourceOptions.filter { it.generatesNaturallyOn(bestTile) }
|
val possibleResourcesForTile = resourceOptions.filter { it.generatesNaturallyOn(bestTile) }
|
||||||
val resourceToPlace = possibleResourcesForTile.randomWeighted(possibleResourcesForTile.map { weightings[it] ?: 0f })
|
val resourceToPlace = possibleResourcesForTile.randomWeighted { weightings[it] ?: 0f }
|
||||||
bestTile.setTileResource(resourceToPlace, majorDeposit)
|
bestTile.setTileResource(resourceToPlace, majorDeposit)
|
||||||
tileData.placeImpact(impactType, bestTile, baseImpact + Random.nextInt(randomImpact + 1))
|
tileData.placeImpact(impactType, bestTile, baseImpact + Random.nextInt(randomImpact + 1))
|
||||||
amountPlaced++
|
amountPlaced++
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package com.unciv.models.ruleset
|
package com.unciv.models.ruleset
|
||||||
|
|
||||||
|
import com.unciv.logic.civilization.Civilization
|
||||||
import com.unciv.models.stats.INamed
|
import com.unciv.models.stats.INamed
|
||||||
import com.unciv.logic.civilization.Civilization // for Kdoc
|
|
||||||
|
|
||||||
enum class QuestName(val value: String) {
|
enum class QuestName(val value: String) {
|
||||||
Route("Route"),
|
Route("Route"),
|
||||||
@ -22,6 +22,10 @@ enum class QuestName(val value: String) {
|
|||||||
DenounceCiv("Denounce Civilization"),
|
DenounceCiv("Denounce Civilization"),
|
||||||
SpreadReligion("Spread Religion"),
|
SpreadReligion("Spread Religion"),
|
||||||
None("")
|
None("")
|
||||||
|
;
|
||||||
|
companion object {
|
||||||
|
fun find(value: String) = values().firstOrNull { it.value == value } ?: None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class QuestType {
|
enum class QuestType {
|
||||||
@ -33,12 +37,14 @@ enum class QuestType {
|
|||||||
// Notes: This is **not** `IsPartOfGameInfoSerialization`, only Ruleset.
|
// Notes: This is **not** `IsPartOfGameInfoSerialization`, only Ruleset.
|
||||||
// Saves contain [QuestManager]s instead, which contain lists of [AssignedQuest] instances.
|
// Saves contain [QuestManager]s instead, which contain lists of [AssignedQuest] instances.
|
||||||
// These are matched to this Quest **by name**.
|
// These are matched to this Quest **by name**.
|
||||||
// Note [name] must match one of the [QuestName] _values_ above for the Quest to have any functionality.
|
|
||||||
class Quest : INamed {
|
class Quest : INamed {
|
||||||
|
|
||||||
/** Unique identifier name of the quest, it is also shown */
|
/** Unique identifier name of the quest, it is also shown.
|
||||||
|
* Must match a [QuestName.value] for the Quest to have any functionality. */
|
||||||
override var name: String = ""
|
override var name: String = ""
|
||||||
|
|
||||||
|
val questNameInstance by lazy { QuestName.find(name) } // lazy only ensures evaluation happens after deserialization, all will be 'triggered'
|
||||||
|
|
||||||
/** Description of the quest shown to players */
|
/** Description of the quest shown to players */
|
||||||
var description: String = ""
|
var description: String = ""
|
||||||
|
|
||||||
|
@ -23,6 +23,13 @@ fun <T> List<T>.randomWeighted(weights: List<Float>, random: Random = Random): T
|
|||||||
return this.last()
|
return this.last()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Get one random element of a given List.
|
||||||
|
*
|
||||||
|
* The probability for each element is proportional to the result of [getWeight] (evaluated only once).
|
||||||
|
*/
|
||||||
|
fun <T> List<T>.randomWeighted(random: Random = Random, getWeight: (T) -> Float): T =
|
||||||
|
randomWeighted(map(getWeight), random)
|
||||||
|
|
||||||
/** Gets a clone of an [ArrayList] with an additional item
|
/** Gets a clone of an [ArrayList] with an additional item
|
||||||
*
|
*
|
||||||
* Solves concurrent modification problems - everyone who had a reference to the previous arrayList can keep using it because it hasn't changed
|
* Solves concurrent modification problems - everyone who had a reference to the previous arrayList can keep using it because it hasn't changed
|
||||||
|
@ -81,7 +81,7 @@ class CityStateDiplomacyTable(private val diplomacyScreen: DiplomacyScreen) {
|
|||||||
val diplomaticMarriageButton = getDiplomaticMarriageButton(otherCiv)
|
val diplomaticMarriageButton = getDiplomaticMarriageButton(otherCiv)
|
||||||
if (diplomaticMarriageButton != null) diplomacyTable.add(diplomaticMarriageButton).row()
|
if (diplomaticMarriageButton != null) diplomacyTable.add(diplomaticMarriageButton).row()
|
||||||
|
|
||||||
for (assignedQuest in otherCiv.questManager.assignedQuests.filter { it.assignee == viewingCiv.civName }) {
|
for (assignedQuest in otherCiv.questManager.getAssignedQuestsFor(viewingCiv.civName)) {
|
||||||
diplomacyTable.addSeparator()
|
diplomacyTable.addSeparator()
|
||||||
diplomacyTable.add(getQuestTable(assignedQuest)).row()
|
diplomacyTable.add(getQuestTable(assignedQuest)).row()
|
||||||
}
|
}
|
||||||
@ -464,8 +464,8 @@ class CityStateDiplomacyTable(private val diplomacyScreen: DiplomacyScreen) {
|
|||||||
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()) {
|
if (quest.isGlobal()) {
|
||||||
val leaderString = viewingCiv.gameInfo.getCivilization(assignedQuest.assigner).questManager.getLeaderStringForQuest(assignedQuest.questName)
|
val leaderString = viewingCiv.gameInfo.getCivilization(assignedQuest.assigner).questManager.getScoreStringForGlobalQuest(assignedQuest)
|
||||||
if (leaderString != "")
|
if (leaderString.isNotEmpty())
|
||||||
questTable.add(leaderString.toLabel()).row()
|
questTable.add(leaderString.toLabel()).row()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,8 +162,7 @@ class WonderInfo {
|
|||||||
private fun knownFromQuest(viewingPlayer: Civilization, name: String): Boolean {
|
private fun knownFromQuest(viewingPlayer: Civilization, name: String): Boolean {
|
||||||
// No, *your* civInfo's QuestManager has no idea about your quests
|
// No, *your* civInfo's QuestManager has no idea about your quests
|
||||||
for (civ in gameInfo.civilizations) {
|
for (civ in gameInfo.civilizations) {
|
||||||
for (quest in civ.questManager.assignedQuests) {
|
for (quest in civ.questManager.getAssignedQuestsFor(viewingPlayer.civName)) {
|
||||||
if (quest.assignee != viewingPlayer.civName) continue
|
|
||||||
if (quest.questName == QuestName.FindNaturalWonder.value && quest.data1 == name)
|
if (quest.questName == QuestName.FindNaturalWonder.value && quest.data1 == name)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user