Changed notification to accept multiple icons, like in Civ VI - this allows for more informative iconography

This commit is contained in:
Yair Morgenstern 2021-03-19 15:11:47 +02:00
parent 50d5b0d7ce
commit 4c260ca954
12 changed files with 54 additions and 56 deletions

View File

@ -9,15 +9,11 @@ import com.unciv.logic.city.PerpetualConstruction
import com.unciv.logic.civilization.*
import com.unciv.logic.map.TileInfo
import com.unciv.logic.map.TileMap
import com.unciv.logic.trade.TradeOffer
import com.unciv.logic.trade.TradeType
import com.unciv.models.metadata.GameParameters
import com.unciv.models.ruleset.Difficulty
import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.RulesetCache
import com.unciv.models.ruleset.Specialist
import java.util.*
import kotlin.collections.ArrayList
class UncivShowableException(missingMods: String) : Exception(missingMods)
@ -171,11 +167,11 @@ class GameInfo {
if (tiles.size < 3) {
for (tile in tiles) {
val unitName = tile.militaryUnit!!.name
thisPlayer.addNotification("An enemy [$unitName] was spotted $inOrNear our territory", tile.position, NotificationType.War)
thisPlayer.addNotification("An enemy [$unitName] was spotted $inOrNear our territory", tile.position, NotificationIcon.War)
}
} else {
val positions = tiles.map { it.position }
thisPlayer.addNotification("[${positions.size}] enemy units were spotted $inOrNear our territory", NotificationType.War, LocationAction(positions))
thisPlayer.addNotification("[${positions.size}] enemy units were spotted $inOrNear our territory", LocationAction(positions), NotificationIcon.War)
}
}

View File

@ -1,12 +1,11 @@
package com.unciv.logic.automation
import com.badlogic.gdx.graphics.Color
import com.unciv.Constants
import com.unciv.UncivGame
import com.unciv.logic.city.CityConstructions
import com.unciv.logic.city.PerpetualConstruction
import com.unciv.logic.civilization.CityAction
import com.unciv.logic.civilization.NotificationType
import com.unciv.logic.civilization.NotificationIcon
import com.unciv.logic.civilization.PlayerType
import com.unciv.logic.map.BFS
import com.unciv.models.ruleset.Building
@ -87,7 +86,7 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
// Nobody can plan 30 turns ahead, I don't care how cost-efficient you are.
else theChosenOne = relativeCostEffectiveness.minBy { it.remainingWork }!!.choice
civInfo.addNotification("Work has started on [$theChosenOne]", NotificationType.Construction, CityAction(cityInfo.location))
civInfo.addNotification("Work has started on [$theChosenOne]", CityAction(cityInfo.location), NotificationIcon.Construction)
cityConstructions.currentConstructionFromQueue = theChosenOne
}

View File

@ -6,7 +6,7 @@ import com.unciv.UncivGame
import com.unciv.logic.city.CityInfo
import com.unciv.logic.civilization.AlertType
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.civilization.NotificationType
import com.unciv.logic.civilization.NotificationIcon
import com.unciv.logic.civilization.PopupAlert
import com.unciv.logic.civilization.diplomacy.DiplomaticModifiers
import com.unciv.logic.map.RoadStatus
@ -174,7 +174,7 @@ object Battle {
else " [" + defender.getName() + "]"
else " our [" + defender.getName() + "]"
val notificationString = attackerString + whatHappenedString + defenderString
defender.getCivInfo().addNotification(notificationString, attackedTile.position, NotificationType.War)
defender.getCivInfo().addNotification(notificationString, attackedTile.position, NotificationIcon.War)
}
}
@ -289,7 +289,7 @@ object Battle {
private fun conquerCity(city: CityInfo, attacker: ICombatant) {
val attackerCiv = attacker.getCivInfo()
attackerCiv.addNotification("We have conquered the city of [${city.name}]!", city.location, NotificationType.War)
attackerCiv.addNotification("We have conquered the city of [${city.name}]!", city.location, NotificationIcon.War)
city.getCenterTile().apply {
if (militaryUnit != null) militaryUnit!!.destroy()
@ -335,7 +335,7 @@ object Battle {
val capturedUnit = defender.unit
capturedUnit.civInfo.addNotification("An enemy [" + attacker.getName() + "] has captured our [" + defender.getName() + "]",
defender.getTile().position, NotificationType.War)
defender.getTile().position, NotificationIcon.War)
// Apparently in Civ V, captured settlers are converted to workers.
if (capturedUnit.name == Constants.settler) {
@ -433,17 +433,17 @@ object Battle {
if (attacker.isDefeated()) {
attacker.getCivInfo()
.addNotification("Our [$attackerName] was destroyed by an intercepting [$interceptorName]",
NotificationType.War)
NotificationIcon.War)
defender.getCivInfo()
.addNotification("Our [$interceptorName] intercepted and destroyed an enemy [$attackerName]",
interceptor.currentTile.position, NotificationType.War)
interceptor.currentTile.position, NotificationIcon.War)
} else {
attacker.getCivInfo()
.addNotification("Our [$attackerName] was attacked by an intercepting [$interceptorName]",
NotificationType.War)
NotificationIcon.War)
defender.getCivInfo()
.addNotification("Our [$interceptorName] intercepted and attacked an enemy [$attackerName]",
interceptor.currentTile.position, NotificationType.War)
interceptor.currentTile.position, NotificationIcon.War)
}
return
}
@ -498,8 +498,8 @@ object Battle {
// and count 1 attack for attacker but leave it in place
reduceAttackerMovementPointsAndAttacks(attacker, defender)
val notificationString = "[" + defendBaseUnit.name + "] withdrew from a [" + attackBaseUnit.name + "]"
defender.getCivInfo().addNotification(notificationString, toTile.position, NotificationType.War)
attacker.getCivInfo().addNotification(notificationString, toTile.position, NotificationType.War)
defender.getCivInfo().addNotification(notificationString, toTile.position, NotificationIcon.War)
attacker.getCivInfo().addNotification(notificationString, toTile.position, NotificationIcon.War)
return true
}

View File

@ -3,7 +3,7 @@ package com.unciv.logic.city
import com.badlogic.gdx.graphics.Color
import com.unciv.logic.automation.ConstructionAutomation
import com.unciv.logic.civilization.AlertType
import com.unciv.logic.civilization.NotificationType
import com.unciv.logic.civilization.NotificationIcon
import com.unciv.logic.civilization.PopupAlert
import com.unciv.models.ruleset.Building
import com.unciv.models.ruleset.UniqueMap
@ -310,10 +310,10 @@ class CityConstructions {
if (civ.exploredTiles.contains(cityInfo.location))
civ.addNotification("[${construction.name}] has been built in [${cityInfo.name}]", cityInfo.location, Color.BROWN)
else
civ.addNotification("[${construction.name}] has been built in a faraway land", null, Color.BROWN)
civ.addNotification("[${construction.name}] has been built in a faraway land", "BuildingIcons/${construction.name}")
}
} else
cityInfo.civInfo.addNotification("[${construction.name}] has been built in [" + cityInfo.name + "]", cityInfo.location, NotificationType.Construction)
cityInfo.civInfo.addNotification("[${construction.name}] has been built in [" + cityInfo.name + "]", cityInfo.location, NotificationIcon.Construction)
}
fun addBuilding(buildingName: String) {

View File

@ -1,8 +1,7 @@
package com.unciv.logic.city
import com.badlogic.gdx.graphics.Color
import com.unciv.logic.automation.Automation
import com.unciv.logic.civilization.NotificationType
import com.unciv.logic.civilization.NotificationIcon
import com.unciv.logic.map.TileInfo
import com.unciv.ui.utils.withItem
import com.unciv.ui.utils.withoutItem
@ -144,7 +143,7 @@ class CityExpansionManager {
fun nextTurn(culture: Float) {
cultureStored += culture.toInt()
if (cultureStored >= getCultureToNextTile() && addNewTileWithCulture())
cityInfo.civInfo.addNotification("[" + cityInfo.name + "] has expanded its borders!", cityInfo.location, NotificationType.Culture)
cityInfo.civInfo.addNotification("[" + cityInfo.name + "] has expanded its borders!", cityInfo.location, NotificationIcon.Culture)
}
fun setTransients() {

View File

@ -2,7 +2,7 @@ package com.unciv.logic.city
import com.badlogic.gdx.graphics.Color
import com.unciv.logic.automation.Automation
import com.unciv.logic.civilization.NotificationType
import com.unciv.logic.civilization.NotificationIcon
import com.unciv.logic.map.TileInfo
import com.unciv.models.Counter
import com.unciv.ui.utils.withItem
@ -65,7 +65,7 @@ class PopulationManager {
foodStored += (getFoodToNextPopulation() * percentOfFoodCarriedOver / 100f).toInt()
population++
autoAssignPopulation()
cityInfo.civInfo.addNotification("[${cityInfo.name}] has grown!", cityInfo.location, NotificationType.Growth)
cityInfo.civInfo.addNotification("[${cityInfo.name}] has grown!", cityInfo.location, NotificationIcon.Growth)
}
}

View File

@ -553,9 +553,9 @@ class CivilizationInfo {
addNotification(text, color, LocationAction(locations))
}
fun addNotification(text: String, location: Vector2?, notificationType: NotificationType) {
fun addNotification(text: String, location: Vector2?, notificationIcon: String) {
val locations = if (location != null) listOf(location) else emptyList()
addNotification(text, notificationType, LocationAction(locations))
addNotification(text, LocationAction(locations), notificationIcon)
}
@ -564,9 +564,12 @@ class CivilizationInfo {
notifications.add(Notification(text, color, action))
}
fun addNotification(text: String, notificationType: NotificationType, action: NotificationAction? = null) {
fun addNotification(text: String, vararg notificationIcons: String) = addNotification(text, null, *notificationIcons)
fun addNotification(text: String, action:NotificationAction?, vararg notificationIcons: String) {
if (playerType == PlayerType.AI) return // no point in lengthening the saved game info if no one will read it
notifications.add(Notification(text, notificationType, action))
val arrayList = ArrayList<String>().apply { addAll(notificationIcons) }
notifications.add(Notification(text, arrayList, action))
}
fun addUnit(unitName: String, city: CityInfo? = null) {

View File

@ -7,13 +7,13 @@ import com.unciv.ui.pickerscreens.TechPickerScreen
import com.unciv.ui.trade.DiplomacyScreen
import com.unciv.ui.worldscreen.WorldScreen
enum class NotificationType {
Culture,
Construction,
Growth,
War,
Trade,
Science
object NotificationIcon {
val Culture = "StatIcons/Culture"
val Construction = "StatIcons/Production"
val Growth = "StatIcons/Population"
val War = "OtherIcons/Pillage"
val Trade = "StatIcons/Acquire"
val Science = "StatIcons/Science"
}
/**
@ -24,7 +24,7 @@ open class Notification() {
var text: String=""
var color: Color?=null
var notificationType:NotificationType?=null
var icons: ArrayList<String> = ArrayList<String>() // Must be ArrayList and not List so it can be deserialized
var action: NotificationAction? = null
// default parameters necessary for json deserialization
@ -34,9 +34,9 @@ open class Notification() {
this.action = action
}
constructor(text: String, notificationType: NotificationType, action: NotificationAction? = null) : this() {
constructor(text: String, notificationIcons: ArrayList<String>, action: NotificationAction? = null) : this() {
this.text = text
this.notificationType = notificationType
this.icons = notificationIcons
this.action = action
}

View File

@ -257,7 +257,7 @@ class TechManager {
}
}
for (it in getRuleset().policyBranches.values.filter { it.era == currentEra }) {
civInfo.addNotification("[" + it.name + "] policy branch unlocked!", NotificationType.Culture)
civInfo.addNotification("[" + it.name + "] policy branch unlocked!", NotificationIcon.Culture)
}
}

View File

@ -307,8 +307,8 @@ class DiplomacyManager() {
trades.remove(trade)
val otherCivTrades = otherCiv().getDiplomacyManager(civInfo).trades
otherCivTrades.removeAll { it.equals(trade.reverse()) }
civInfo.addNotification("One of our trades with [$otherCivName] has been cut short", NotificationType.Trade)
otherCiv().addNotification("One of our trades with [${civInfo.civName}] has been cut short", NotificationType.Trade)
civInfo.addNotification("One of our trades with [$otherCivName] has been cut short", NotificationIcon.Trade)
otherCiv().addNotification("One of our trades with [${civInfo.civName}] has been cut short", NotificationIcon.Trade)
civInfo.updateDetailedCivResources()
}
}
@ -417,8 +417,8 @@ class DiplomacyManager() {
trades.remove(trade)
for (offer in trade.ourOffers.union(trade.theirOffers).filter { it.duration == 0 }) { // this was a timed trade
if (offer in trade.theirOffers)
civInfo.addNotification("[${offer.name}] from [$otherCivName] has ended", NotificationType.Trade)
else civInfo.addNotification("[${offer.name}] to [$otherCivName] has ended", NotificationType.Trade)
civInfo.addNotification("[${offer.name}] from [$otherCivName] has ended", NotificationIcon.Trade)
else civInfo.addNotification("[${offer.name}] to [$otherCivName] has ended", NotificationIcon.Trade)
civInfo.updateStatsForNextTurn() // if they were bringing us gold per turn
civInfo.updateDetailedCivResources() // if they were giving us resources
@ -471,7 +471,7 @@ class DiplomacyManager() {
// Cancel all trades.
for (trade in trades)
for (offer in trade.theirOffers.filter { it.duration > 0 })
civInfo.addNotification("[" + offer.name + "] from [$otherCivName] has ended", NotificationType.Trade)
civInfo.addNotification("[" + offer.name + "] from [$otherCivName] has ended", NotificationIcon.Trade)
trades.clear()
updateHasOpenBorders()
@ -487,11 +487,11 @@ class DiplomacyManager() {
onWarDeclared()
otherCivDiplomacy.onWarDeclared()
otherCiv.addNotification("[${civInfo.civName}] has declared war on us!", NotificationType.War)
otherCiv.addNotification("[${civInfo.civName}] has declared war on us!", NotificationIcon.War)
otherCiv.popupAlerts.add(PopupAlert(AlertType.WarDeclaration, civInfo.civName))
getCommonKnownCivs().forEach {
it.addNotification("[${civInfo.civName}] has declared war on [${otherCiv().civName}]!", NotificationType.War)
it.addNotification("[${civInfo.civName}] has declared war on [${otherCiv().civName}]!", NotificationIcon.War)
}
otherCivDiplomacy.setModifier(DiplomaticModifiers.DeclaredWarOnUs, -20f)

View File

@ -7,7 +7,7 @@ import com.unciv.UncivGame
import com.unciv.logic.automation.UnitAutomation
import com.unciv.logic.automation.WorkerAutomation
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.civilization.NotificationType
import com.unciv.logic.civilization.NotificationIcon
import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.Unique
import com.unciv.models.ruleset.unit.BaseUnit
@ -616,7 +616,7 @@ class MapUnit {
val city = civInfo.cities.random(tileBasedRandom)
city.population.population++
city.population.autoAssignPopulation()
civInfo.addNotification("We have found survivors in the ruins - population added to [" + city.name + "]", tile.position, NotificationType.Growth)
civInfo.addNotification("We have found survivors in the ruins - population added to [" + city.name + "]", tile.position, NotificationIcon.Growth)
}
val researchableAncientEraTechs = tile.tileMap.gameInfo.ruleSet.technologies.values
.filter {
@ -628,7 +628,7 @@ class MapUnit {
actions.add {
val tech = researchableAncientEraTechs.random(tileBasedRandom).name
civInfo.tech.addTechnology(tech)
civInfo.addNotification("We have discovered the lost technology of [$tech] in the ruins!", tile.position, NotificationType.Science)
civInfo.addNotification("We have discovered the lost technology of [$tech] in the ruins!", tile.position, NotificationIcon.Science)
}
@ -657,7 +657,7 @@ class MapUnit {
actions.add {
civInfo.policies.addCulture(20)
civInfo.addNotification("We have discovered cultural artifacts in the ruins! (+20 Culture)", tile.position, NotificationType.Culture)
civInfo.addNotification("We have discovered cultural artifacts in the ruins! (+20 Culture)", tile.position, NotificationIcon.Culture)
}
// Map of the surrounding area

View File

@ -33,9 +33,10 @@ class NotificationsScroll(internal val worldScreen: WorldScreen) : ScrollPane(nu
val label = notification.text.toLabel(Color.BLACK, 30)
val listItem = Table()
if (notification.notificationType != null)
listItem.add(ImageGetter.getImage("NotificationIcons/" + notification.notificationType!!.name)).size(20f).padRight(5f)
else listItem.add(ImageGetter.getCircle()
if (notification.icons.isNotEmpty())
for(icon in notification.icons)
listItem.add(ImageGetter.getImage(icon)).size(20f).padRight(5f)
else if(notification.color!=null) listItem.add(ImageGetter.getCircle()
.apply { color = notification.color }).size(20f).padRight(5f)
listItem.background = ImageGetter.getRoundedEdgeTableBackground().apply { setScale(0.5f) }
listItem.add(label)