Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add "Wait" to Next unit button, Next unit cycles #12799

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified android/Images.ConstructionIcons/UnitActionIcons/Wait.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified android/Images.Icons/OtherIcons/Wait.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified android/assets/ConstructionIcons.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified android/assets/Icons.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 8 additions & 8 deletions android/assets/jsons/Tutorials.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
{"text": "Cities will house Citizens, which can work tiles up to 3 tiles away from the city. This means you don’t have to settle cities right on or next to good tiles. Let’s say, for example, that you want access to some Iron – but the resource is in a desert area. You don’t have to settle your city in the desert. You can settle a few tiles away in more prosperous lands. Your city will grow and eventually gain access to the resource. You only need to settle right on top of resources if you need them immediately."},
{},
{"text": "The first thing coming out of your city depends on the strategy you want to follow, but the 'classic' build order is to build first two Scouts, then a Shrine, and three Settlers, and adopt Tradition, to explore the map quickly (Scouts ignore terrain cost), and to get an early Pantheon (if you're playing with religion enabled)."},
{"text": "But feel free to experiment with your own build orders!", "color": "#fa0"},
{"text": "But feel free to experiment with your own build orders!", "color": "#fa0"}
]
},
{
Expand Down Expand Up @@ -129,7 +129,7 @@
{"text":"This greatly improves the speed you can get Units around the map."},
{"text":"Until you research the technology that removes it, Roads do not cross Rivers"},
{"text":"Connecting your cities to the capital by Roads and/or Railroads will generate Gold via the Trade Route.","link":"Tutorials/Trade Route"},
{"text":"However, since each Road and Railroad have a Maintenance Cost, it may be more economical to wait until the cities grow and only place where needed."},
{"text":"However, since each Road and Railroad have a Maintenance Cost, it may be more economical to wait until the cities grow and only place where needed."}
]
},
{
Expand Down Expand Up @@ -233,7 +233,7 @@
{
"name": "Idle Units",
"steps": [
"If you don't want to move a unit this turn, you can skip it by clicking 'Next unit' again, or command the unit to 'Wait'.\nIf you won't be moving it for a while, you can have the unit enter Fortify or Sleep mode - \n units in Fortify or Sleep are not considered idle units.\nIf you want to disable the 'Next unit' feature entirely, you can toggle it in Menu -> Check for idle units."
"Clicking 'Next unit' again will skip this unit for now and cycle back to it later this turn.\nIf you don't want to move a unit, you can command it to 'Wait' this turn.\nIf you won't be moving it for a while, you can have the unit enter Fortify or Sleep mode - \n units in Fortify or Sleep are not considered idle units.\nIf you want to disable the 'Next unit' feature entirely, you can toggle it in Menu -> Check for idle units."
]
},
{
Expand Down Expand Up @@ -348,7 +348,7 @@
"⑥: Unit Action Buttons - while a unit is selected its possible actions appear here.",
"⑦: The unit/city info pane - shows information about a selected unit or city.",
"⑧: The name (and unit icon) of the selected unit or city, with current health if wounded. Clicking a unit name or icon will open its civilopedia entry.",
"⑨: The arrow buttons allow jumping to the next/previous unit.",
"⑨: The arrow buttons allow jumping to the next/previous idle unit.",
"⑩: For a selected unit, its promotions appear here, and clicking leads to the promotions screen for that unit.",
"⑪: Remaining/per turn movement points, strength and experience / XP needed for promotion. For cities, you get its combat strength.",
"⑫: This button closes the selected unit/city info pane.",
Expand Down Expand Up @@ -494,7 +494,7 @@
{"text":"The Intercepting Unit rolls to see if it hits. Whether it hits or not costs an Attack, and most units (without Promotions) can only Attack Once per Nation's Turn. It does NOT cost Movement Points, but Air Units that have used their Movement cannot Intercept between turns."},
{"text":"If the Intercepting Unit Hits, it deals damage according to the Combat Strength calculation to the Attacking Air Unit, potentially with any Strength Bonuses that apply to Interception. It does not receive damage from the Attacking Air Unit."},
{"text":"After Interception resolves, the Attacking Air Unit and the Defending Unit in the targeted tile do Combat as normal, with damage dealt to both sides."},
{"text":"To help deal with Interceptions, see Air Sweeps.","link": "Tutorials/Air Sweeps"},
{"text":"To help deal with Interceptions, see Air Sweeps.","link": "Tutorials/Air Sweeps"}
]
},
{
Expand Down Expand Up @@ -545,7 +545,7 @@
{"text":"Spies at a higher rank have a higher chance of success. The max rank a spy can reach is rank 3. After a spy is killed it will revive after a certain amount of turns back at rank 1."},
{"text":"Building buildings like the constabulary and police station will reduce the technology steal rate of spies in that city."},
{},
{"text":"Espionage is available using the Gods and Kings ruleset. To enable it in a new game click advanced settings, then click on the Enable Espionage option."},
{"text":"Espionage is available using the Gods and Kings ruleset. To enable it in a new game click advanced settings, then click on the Enable Espionage option."}
]
},
{
Expand Down Expand Up @@ -671,15 +671,15 @@
{},
{"text":"Tile improvements\nIn Civilzation V, workers start working on an improvement-under-construction at the beginning of movement. Unciv changes this, to allow players to assign workers to tiles, and then reconsider and change improvement or move them elsewhere."},
{},
{"text":"Forest and Jungle Visibility\nIn Unciv, forests and jungles are visible 1 tile outside visibility range. In Civilization V, this is the behaviour of hills and mountains, but not of forests and jungles, yet jungle and forest can block hills, and hill + forest can block mountain, indicating they're on the same elevation. This is considered to be a bug in the otherwise well-structured visibility logic in Civilization V."},
{"text":"Forest and Jungle Visibility\nIn Unciv, forests and jungles are visible 1 tile outside visibility range. In Civilization V, this is the behaviour of hills and mountains, but not of forests and jungles, yet jungle and forest can block hills, and hill + forest can block mountain, indicating they're on the same elevation. This is considered to be a bug in the otherwise well-structured visibility logic in Civilization V."}
]
},
{
"name": "Settler",
"civilopediaText": [
{"text": "Founding Cities\nThe Settler is a unit that can found a new city. You can build a Settler unit in a city with at least 2 population, and then move them to a good location to found a new city. This will usually be your main way of acquiring more cities."},
{},
{"text": "Food conversion to Production\nDuring the construction of a Settler, the city will not grow. Instead, the 1st, 2nd, 4th, and from there on every 4th, excess Food (Growth) is converted into Production, with the rest of the excess Food being lost."},
{"text": "Food conversion to Production\nDuring the construction of a Settler, the city will not grow. Instead, the 1st, 2nd, 4th, and from there on every 4th, excess Food (Growth) is converted into Production, with the rest of the excess Food being lost."}
]
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ class NotificationsScroll(
* The 'covered' parameters are used to make sure we can scroll up or down far enough so the bottom or top entry is visible.
*
* @param notifications Data to display
* @param coveredNotificationsTop Height of the portion that may be covered on the bottom w/o any padding
* @param coveredNotificationsTop Height of the portion that may be covered on the top w/o any padding
* @param coveredNotificationsBottom Height of the portion that may be covered on the bottom w/o any padding
*/
internal fun update(
Expand All @@ -170,11 +170,8 @@ class NotificationsScroll(

restoreButton.block() // For the update, since ScrollPane may layout and change scrollX
val contentChanged = updateContent(notifications, coveredNotificationsTop, coveredNotificationsBottom)
if (contentChanged) {
updateLayout()
} else {
updateSpacers(coveredNotificationsTop, coveredNotificationsBottom)
}
updateSpacers(coveredNotificationsTop, coveredNotificationsBottom)
updateLayout()

scrollX = maxX - previousScrollXinv
scrollY = if (selectedCell == null) {
Expand Down
6 changes: 4 additions & 2 deletions core/src/com/unciv/ui/screens/worldscreen/WorldScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ import com.unciv.ui.screens.worldscreen.status.MultiplayerStatusButton
import com.unciv.ui.screens.worldscreen.status.NextTurnButton
import com.unciv.ui.screens.worldscreen.status.NextTurnProgress
import com.unciv.ui.screens.worldscreen.status.StatusButtons
import com.unciv.ui.screens.worldscreen.status.UnitWaitButton
import com.unciv.ui.screens.worldscreen.topbar.WorldScreenTopBar
import com.unciv.ui.screens.worldscreen.unit.AutoPlay
import com.unciv.ui.screens.worldscreen.unit.UnitTable
Expand Down Expand Up @@ -121,6 +122,7 @@ class WorldScreen(
internal val notificationsScroll = NotificationsScroll(this)
internal val nextTurnButton = NextTurnButton(this)
private val statusButtons = StatusButtons(nextTurnButton)
internal val unitWaitButton = UnitWaitButton(this, statusButtons)
private val tutorialTaskTable = Table().apply {
background = skinStrings.getUiBackground("WorldScreen/TutorialTaskTable", tintColor = skinStrings.skinConfig.baseColor.darken(0.5f))
}
Expand Down Expand Up @@ -638,9 +640,9 @@ class WorldScreen(
}
}

fun switchToNextUnit() {
fun switchToNextUnit(resetDue: Boolean = true) {
// Try to select something new if we already have the next pending unit selected.
if (bottomUnitTable.selectedUnit != null)
if (bottomUnitTable.selectedUnit != null && resetDue)
bottomUnitTable.selectedUnit!!.due = false
val nextDueUnit = viewingCiv.units.cycleThroughDueUnits(bottomUnitTable.selectedUnit)
if (nextDueUnit != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ enum class NextTurnAction(protected val text: String, val color: Color) {
override fun isChoice(worldScreen: WorldScreen) =
worldScreen.viewingCiv.units.shouldGoToDueUnit()
override fun action(worldScreen: WorldScreen) =
worldScreen.switchToNextUnit()
worldScreen.switchToNextUnit(resetDue = false)
},
MoveAutomatedUnits("Move automated units", Color.LIGHT_GRAY) {
override fun isChoice(worldScreen: WorldScreen) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ class NextTurnButton(
onRightClick { NextTurnMenu(stage, this, this, worldScreen) }
keyShortcuts.add(KeyboardBinding.NextTurn)
keyShortcuts.add(KeyboardBinding.NextTurnAlternate)
// Let unit actions override this for command "Wait".
keyShortcuts.add(KeyboardBinding.Wait, -99)
}

fun update() {
Expand All @@ -46,6 +44,8 @@ class NextTurnButton(
|| (!worldScreen.hasOpenPopups() && worldScreen.isPlayersTurn
&& !worldScreen.waitingForAutosave && !worldScreen.isNextTurnUpdateRunning())
if (isEnabled) addTooltip(KeyboardBinding.NextTurn) else addTooltip("")

worldScreen.unitWaitButton.update()
}

internal fun updateButton(nextTurnAction: NextTurnAction) {
Expand All @@ -61,4 +61,7 @@ class NextTurnButton(
private fun getNextTurnAction(worldScreen: WorldScreen) =
// Guaranteed to return a non-null NextTurnAction because the last isChoice always returns true
NextTurnAction.entries.first { it.isChoice(worldScreen) }

fun isNextUnitAction(): Boolean = nextTurnAction == NextTurnAction.NextUnit

}
29 changes: 17 additions & 12 deletions core/src/com/unciv/ui/screens/worldscreen/status/StatusButtons.kt
Original file line number Diff line number Diff line change
@@ -1,43 +1,48 @@
package com.unciv.ui.screens.worldscreen.status

import com.badlogic.gdx.scenes.scene2d.ui.Container
import com.badlogic.gdx.scenes.scene2d.ui.HorizontalGroup
import com.badlogic.gdx.utils.Disposable

class StatusButtons(
nextTurnButton: NextTurnButton,
autoPlayStatusButton: AutoPlayStatusButton? = null,
multiplayerStatusButton: MultiplayerStatusButton? = null
val nextTurnButton: NextTurnButton
) : HorizontalGroup(), Disposable {
var autoPlayStatusButton: AutoPlayStatusButton? = autoPlayStatusButton
var autoPlayStatusButton: AutoPlayStatusButton? = null
set(button) {
autoPlayStatusButton?.remove()
field = button
if (button != null) {
addActorAt(0, button)
}
}
var multiplayerStatusButton: MultiplayerStatusButton? = multiplayerStatusButton
var multiplayerStatusButton: MultiplayerStatusButton? = null
set(button) {
multiplayerStatusButton?.remove()
field = button
if (button != null) {
addActorAt(0, button)
}
}
var unitWaitButton: UnitWaitButton? = null
set(button) {
// wait button is wrapped in container, remove that container
unitWaitButton?.parent?.remove()
field = button
if (button != null) {
// fix uneven spacing applied by HorizontalGroup.wrap()
val container = Container(button)
container.padBottom(nextTurnButton.height - button.height)
// insert next to next-turn-button
addActorAt(children.indexOf(nextTurnButton, true), container)
}
}


init {
space(10f)
right()
wrapReverse()
wrapSpace(10f)
rowRight()
if (autoPlayStatusButton != null) {
addActor(autoPlayStatusButton)
}
if (multiplayerStatusButton != null) {
addActor(multiplayerStatusButton)
}
sulai marked this conversation as resolved.
Show resolved Hide resolved
addActor(nextTurnButton)
}

Expand Down
36 changes: 36 additions & 0 deletions core/src/com/unciv/ui/screens/worldscreen/status/UnitWaitButton.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.unciv.ui.screens.worldscreen.status

import com.unciv.ui.components.UncivTooltip.Companion.addTooltip
import com.unciv.ui.components.extensions.isEnabled
import com.unciv.ui.components.input.KeyboardBinding
import com.unciv.ui.components.input.keyShortcuts
import com.unciv.ui.components.input.onActivation
import com.unciv.ui.images.IconTextButton
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.screens.worldscreen.WorldScreen

class UnitWaitButton(
private val worldScreen: WorldScreen,
private val statusButtons: StatusButtons
) : IconTextButton("Wait", ImageGetter.getUnitActionPortrait("Wait")) {

init {
onActivation {
worldScreen.switchToNextUnit(resetDue = true)
}
// Let unit actions override this for command "Wait".
keyShortcuts.add(KeyboardBinding.Wait, -99)
}

fun update() {
val nextTurnButton = statusButtons.nextTurnButton
val visible = nextTurnButton.isVisible
&& nextTurnButton.isNextUnitAction()
statusButtons.unitWaitButton = if (visible) this else null
isEnabled = nextTurnButton.isEnabled
&& worldScreen.bottomUnitTable.selectedUnit?.run { due && isIdle() } == true
if (isEnabled) addTooltip(KeyboardBinding.Wait) else addTooltip("")
pack()
}

}
Loading