Add Notifications Log (#7122)

This commit is contained in:
alexban011 2022-06-25 14:40:42 +03:00 committed by GitHub
parent 50a8ff3ce0
commit 8047278d80
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 150 additions and 15 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

View File

@ -704,6 +704,7 @@ Continuous rendering =
When disabled, saves battery life but certain animations will be suspended =
Order trade offers by amount =
Ask for confirmation when pressing next turn =
Notifications log max turns =
Check extension mods based on: =
-none- =
Reload mods =
@ -1124,6 +1125,7 @@ City-State Luxuries =
Occupied City =
Buildings =
Wonders =
Notifications =
Base values =
Bonuses =
Final =
@ -1166,6 +1168,8 @@ Near [city] =
Somewhere around [city] =
Far away =
Status =
Current turn =
Turn [turnNumber] =
Location =
Unimproved =
Number of tiles with this resource\nin your territory, without an\nappropriate improvement to use it =

View File

@ -158,11 +158,17 @@ class CivilizationInfo {
var ruinsManager = RuinsManager()
var diplomacy = HashMap<String, DiplomacyManager>()
var proximity = HashMap<String, Proximity>()
var notifications = ArrayList<Notification>()
val popupAlerts = ArrayList<PopupAlert>()
private var allyCivName: String? = null
var naturalWonders = ArrayList<String>()
var notifications = ArrayList<Notification>()
var notificationsLog = ArrayList<NotificationsLog>()
class NotificationsLog(val turn: Int = 0) {
var notifications = ArrayList<Notification>()
}
/** for trades here, ourOffers is the current civ's offers, and theirOffers is what the requesting civ offers */
val tradeRequests = ArrayList<TradeRequest>()
@ -267,6 +273,7 @@ class CivilizationInfo {
toReturn.exploredTiles.addAll(gameInfo.tileMap.values.asSequence().map { it.position }.filter { it in exploredTiles })
toReturn.lastSeenImprovement.putAll(lastSeenImprovement)
toReturn.notifications.addAll(notifications)
toReturn.notificationsLog.addAll(notificationsLog)
toReturn.citiesCreated = citiesCreated
toReturn.popupAlerts.addAll(popupAlerts)
toReturn.tradeRequests.addAll(tradeRequests)
@ -912,6 +919,16 @@ class CivilizationInfo {
}
fun endTurn() {
val notificationsThisTurn = NotificationsLog(gameInfo.turns)
notificationsThisTurn.notifications.addAll(notifications)
while (notificationsLog.size >= UncivGame.Current.settings.notificationsLogMaxTurns) {
notificationsLog.removeFirst()
}
if (notificationsThisTurn.notifications.isNotEmpty())
notificationsLog.add(notificationsThisTurn)
notifications.clear()
updateStatsForNextTurn()
val nextTurnStats = statsForNextTurn

View File

@ -1,7 +1,11 @@
package com.unciv.logic.civilization
import com.badlogic.gdx.math.Vector2
import com.badlogic.gdx.scenes.scene2d.Actor
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.unciv.models.ruleset.Ruleset
import com.unciv.ui.cityscreen.CityScreen
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.pickerscreens.TechPickerScreen
import com.unciv.ui.trade.DiplomacyScreen
import com.unciv.ui.utils.MayaCalendar
@ -48,6 +52,22 @@ open class Notification() {
this.icons = notificationIcons
this.action = action
}
fun addNotificationIcons(ruleset: Ruleset, iconSize: Float, table: Table) {
if (icons.isEmpty()) return
for (icon in icons.reversed()) {
val image: Actor = when {
ruleset.technologies.containsKey(icon) -> ImageGetter.getTechIcon(icon)
ruleset.nations.containsKey(icon) -> ImageGetter.getNationIndicator(
ruleset.nations[icon]!!,
iconSize
)
ruleset.units.containsKey(icon) -> ImageGetter.getUnitIcon(icon)
else -> ImageGetter.getImage(icon)
}
table.add(image).size(iconSize).padRight(5f)
}
}
}
/** defines what to do if the user clicks on a notification */

View File

@ -56,6 +56,8 @@ class GameSettings {
var useDemographics: Boolean = false
var showZoomButtons: Boolean = false
var notificationsLogMaxTurns = 5
var androidCutout: Boolean = false
var multiplayer = GameSettingsMultiplayer()

View File

@ -3,7 +3,10 @@ package com.unciv.ui.options
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.unciv.UncivGame
import com.unciv.logic.civilization.PlayerType
import com.unciv.models.metadata.GameSettings
import com.unciv.ui.utils.BaseScreen
import com.unciv.ui.utils.UncivSlider
import com.unciv.ui.utils.extensions.toLabel
import com.unciv.ui.worldscreen.WorldScreen
fun gameplayTab(
@ -35,4 +38,20 @@ fun gameplayTab(
) { settings.automatedWorkersReplaceImprovements = it }
optionsPopup.addCheckbox(this, "Order trade offers by amount", settings.orderTradeOffersByAmount) { settings.orderTradeOffersByAmount = it }
optionsPopup.addCheckbox(this, "Ask for confirmation when pressing next turn", settings.confirmNextTurn) { settings.confirmNextTurn = it }
addNotificationLogMaxTurnsSlider(this, settings, UncivGame.Current.worldScreen, optionsPopup.selectBoxMinWidth)
}
private fun addNotificationLogMaxTurnsSlider(table: Table, settings: GameSettings, screen: BaseScreen?, selectBoxMinWidth: Float) {
table.add("Notifications log max turns".toLabel()).left().fillX()
val minimapSlider = UncivSlider(
3f, 15f, 1f,
initial = settings.notificationsLogMaxTurns.toFloat()
) {
val turns = it.toInt()
settings.notificationsLogMaxTurns = turns
settings.save()
}
table.add(minimapSlider).minWidth(selectBoxMinWidth).pad(10f).row()
}

View File

@ -1,6 +1,7 @@
package com.unciv.ui.overviewscreen
import com.badlogic.gdx.utils.Align
import com.unciv.UncivGame
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.ui.utils.KeyCharAndCode
import com.unciv.ui.overviewscreen.EmpireOverviewTab.EmpireOverviewTabPersistableData
@ -14,7 +15,7 @@ private fun Boolean.toState(): EmpireOverviewTabState = if (this) EmpireOverview
/** This controls which Tabs for the [EmpireOverviewScreen] exist and their order.
*
* To add a Tab, build a new [EmpireOverviewTab] subclass and fill out a new entry here, that's all.
* Note the enum value's name is used as Tab caption, so if you ever need a non-alphanumeric caption please redesign to include a property for the caption.
* Note the enum value's name is used as Tab caption, so if you ever need a non-alphanumeric caption please redesign to include a property for the caption.
*/
enum class EmpireOverviewCategories(
val iconName: String,
@ -59,7 +60,10 @@ enum class EmpireOverviewCategories(
fun (viewingPlayer: CivilizationInfo, overviewScreen: EmpireOverviewScreen, _: EmpireOverviewTabPersistableData?)
= WonderOverviewTab(viewingPlayer, overviewScreen),
fun (viewingPlayer: CivilizationInfo) = (viewingPlayer.naturalWonders.isEmpty() && viewingPlayer.cities.isEmpty()).toState()),
;
Notifications("OtherIcons/Notifications", 'N', Align.top,
fun (viewingPlayer: CivilizationInfo, overviewScreen: EmpireOverviewScreen, _: EmpireOverviewTabPersistableData?)
= NotificationsOverviewTable(worldScreen = UncivGame.Current.worldScreen!!, viewingPlayer, overviewScreen),
fun (_: CivilizationInfo) = EmpireOverviewTabState.Normal);
constructor(iconName: String, shortcutChar: Char, scrollAlign: Int, factory: FactoryType, stateTester: StateTesterType = { _ -> EmpireOverviewTabState.Normal })
: this(iconName, KeyCharAndCode(shortcutChar), scrollAlign, factory, stateTester)

View File

@ -0,0 +1,80 @@
package com.unciv.ui.overviewscreen
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.scenes.scene2d.Touchable
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.unciv.UncivGame
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.civilization.Notification
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.utils.BaseScreen
import com.unciv.ui.utils.WrappableLabel
import com.unciv.ui.utils.extensions.onClick
import com.unciv.ui.worldscreen.WorldScreen
class NotificationsOverviewTable(
val worldScreen: WorldScreen,
viewingPlayer: CivilizationInfo,
overviewScreen: EmpireOverviewScreen
) : EmpireOverviewTab(viewingPlayer, overviewScreen) {
val notificationLog = viewingPlayer.notificationsLog
private val notificationTable = Table(BaseScreen.skin)
val scaleFactor = 0.3f
val inverseScaleFactor = 1f / scaleFactor
private val maxWidthOfStage = 0.333f
private val maxEntryWidth = worldScreen.stage.width * maxWidthOfStage * inverseScaleFactor
val iconSize = 20f
init {
val tablePadding = 30f
defaults().pad(tablePadding).top()
generateNotificationTable()
add(notificationTable)
}
private fun generateNotificationTable() {
if (viewingPlayer.notifications.isNotEmpty())
notificationTable.add(notificationsArrayTable("Current", viewingPlayer.notifications)).row()
for (notification in notificationLog.asReversed()) {
notificationTable.add(notificationsArrayTable(notification.turn.toString(), notification.notifications))
notificationTable.padTop(20f).row()
}
}
private fun notificationsArrayTable(index: String, notifications: ArrayList<Notification>): Table {
val turnTable = Table(BaseScreen.skin)
if (index != "Current")
turnTable.add("Turn [$index]").row()
else
turnTable.add("Current turn").row()
for (notification in notifications) {
val notificationTable = Table(BaseScreen.skin)
val labelWidth = maxEntryWidth * notification.icons.size - 10f
val label = WrappableLabel(notification.text, labelWidth, Color.BLACK, 20)
notificationTable.add(label)
notificationTable.background = ImageGetter.getRoundedEdgeRectangle()
notificationTable.touchable = Touchable.enabled
notificationTable.onClick {
UncivGame.Current.resetToWorldScreen()
notification.action?.execute(worldScreen)
}
notification.addNotificationIcons(worldScreen.gameInfo.ruleSet, iconSize, notificationTable)
turnTable.add(notificationTable).padTop(5f)
turnTable.padTop(20f).row()
}
turnTable.padTop(20f).row()
return turnTable
}
}

View File

@ -78,18 +78,7 @@ class NotificationsScroll(
listItem.add(label).padRight(10f)
}
if (notification.icons.isNotEmpty()) {
val ruleset = worldScreen.gameInfo.ruleSet
for (icon in notification.icons.reversed()) {
val image: Actor = when {
ruleset.technologies.containsKey(icon) -> ImageGetter.getTechIcon(icon)
ruleset.nations.containsKey(icon) -> ImageGetter.getNationIndicator(ruleset.nations[icon]!!, iconSize)
ruleset.units.containsKey(icon) -> ImageGetter.getUnitIcon(icon)
else -> ImageGetter.getImage(icon)
}
listItem.add(image).size(iconSize).padRight(5f)
}
}
notification.addNotificationIcons(worldScreen.gameInfo.ruleSet, iconSize, listItem)
// using a large click area with no gap in between each message item.
// this avoids accidentally clicking in between the messages, resulting in a map click