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

Implement a waiting command (#6884) #6896

Merged
merged 4 commits into from
May 25, 2022
Merged
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
54 changes: 44 additions & 10 deletions core/src/com/unciv/logic/civilization/CivilizationInfo.kt
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ class CivilizationInfo {
@Transient
private var units = listOf<MapUnit>()

/**
* Index in the unit list above of the unit that is potentially due and is next up for button "Next unit".
*/
@Transient
private var nextPotentiallyDueAt = 0

@Transient
var viewableTiles = setOf<TileInfo>()

Expand Down Expand Up @@ -448,10 +454,19 @@ class CivilizationInfo {
fun getCivUnits(): Sequence<MapUnit> = units.asSequence()
fun getCivGreatPeople(): Sequence<MapUnit> = getCivUnits().filter { mapUnit -> mapUnit.isGreatPerson() }

// Similar to getCivUnits(), but the returned list is rotated so that the
// 'nextPotentiallyDueAt' unit is first here.
private fun getCivUnitsStartingAtNextDue(): Sequence<MapUnit> = sequenceOf(units.subList(nextPotentiallyDueAt, units.size) + units.subList(0, nextPotentiallyDueAt)).flatten()

fun addUnit(mapUnit: MapUnit, updateCivInfo: Boolean = true) {
val newList = ArrayList(units)
// Since we create a new list anyway (otherwise some concurrent modification
// exception will happen), also rearrange existing units so that
// 'nextPotentiallyDueAt' becomes 0. This way new units are always last to be due
// (can be changed as wanted, just have a predictable place).
var newList = getCivUnitsStartingAtNextDue().toMutableList()
newList.add(mapUnit)
units = newList
nextPotentiallyDueAt = 0

if (updateCivInfo) {
// Not relevant when updating TileInfo transients, since some info of the civ itself isn't yet available,
Expand All @@ -462,27 +477,46 @@ class CivilizationInfo {
}

fun removeUnit(mapUnit: MapUnit) {
val newList = ArrayList(units)
// See comment in addUnit().
var newList = getCivUnitsStartingAtNextDue().toMutableList()
newList.remove(mapUnit)
units = newList
nextPotentiallyDueAt = 0

updateStatsForNextTurn() // unit upkeep
updateDetailedCivResources()
}

fun getIdleUnits() = getCivUnits().filter { it.isIdle() }

private fun getDueUnits() = getCivUnits().filter { it.due && it.isIdle() }
fun getDueUnits(): Sequence<MapUnit> = getCivUnitsStartingAtNextDue().filter { it.due && it.isIdle() }

fun shouldGoToDueUnit() = UncivGame.Current.settings.checkForDueUnits && getDueUnits().any()

fun getNextDueUnit(): MapUnit? {
val dueUnits = getDueUnits()
if (dueUnits.any()) {
val unit = dueUnits.first()
unit.due = false
return unit
// Return the next due unit, but preferably not 'unitToSkip': this is returned only if it is the only remaining due unit.
fun cycleThroughDueUnits(unitToSkip: MapUnit? = null): MapUnit? {
if (units.none()) return null

var returnAt = nextPotentiallyDueAt
var fallbackAt = -1

do {
if (units[returnAt].due && units[returnAt].isIdle()) {
if (units[returnAt] != unitToSkip) {
nextPotentiallyDueAt = (returnAt + 1) % units.size
return units[returnAt]
}
else fallbackAt = returnAt
}

returnAt = (returnAt + 1) % units.size
} while (returnAt != nextPotentiallyDueAt)

if (fallbackAt >= 0) {
nextPotentiallyDueAt = (fallbackAt + 1) % units.size
return units[fallbackAt]
}
return null
else return null
}
//endregion

Expand Down
2 changes: 2 additions & 0 deletions core/src/com/unciv/models/UnitAction.kt
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ enum class UnitActionType(
{ ImageGetter.getImage("OtherIcons/DisbandUnit") }, KeyCharAndCode.DEL),
GiftUnit("Gift unit",
{ ImageGetter.getImage("OtherIcons/Present") }, UncivSound.Silent),
Wait("Wait",
null, 'z', UncivSound.Silent),
ShowAdditionalActions("Show more",
{ imageGetShowMore() }, KeyCharAndCode(Input.Keys.PAGE_DOWN)),
HideAdditionalActions("Back",
Expand Down
30 changes: 17 additions & 13 deletions core/src/com/unciv/ui/worldscreen/WorldScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,6 @@ class WorldScreen(val gameInfo: GameInfo, val viewingCiv:CivilizationInfo) : Bas
else
mapHolder.setCenterPosition(tileToCenterOn, immediately = true, selectUnit = true)


tutorialController.allTutorialsShowedCallback = { shouldUpdate = true }

onBackButtonClicked { backButtonAndESCHandler() }
Expand Down Expand Up @@ -727,6 +726,22 @@ class WorldScreen(val gameInfo: GameInfo, val viewingCiv:CivilizationInfo) : Bas
}
}

fun switchToNextUnit() {
// Try to select something new if we already have the next pending unit selected.
val nextDueUnit = viewingCiv.cycleThroughDueUnits(bottomUnitTable.selectedUnit)
if (nextDueUnit != null) {
mapHolder.setCenterPosition(
nextDueUnit.currentTile.position,
immediately = false,
selectUnit = false
)
bottomUnitTable.selectUnit(nextDueUnit)
shouldUpdate = true
// Unless 'wait' action is chosen, the unit will not be considered due anymore.
nextDueUnit.due = false
}
}

private fun updateNextTurnButton(isSomethingOpen: Boolean) {
nextTurnButton.update(isSomethingOpen, isPlayersTurn, waitingForAutosave, getNextTurnAction())
nextTurnButton.setPosition(stage.width - nextTurnButton.width - 10f, topBar.y - nextTurnButton.height - 10f)
Expand All @@ -741,18 +756,7 @@ class WorldScreen(val gameInfo: GameInfo, val viewingCiv:CivilizationInfo) : Bas
NextTurnAction("Waiting for other players...",Color.GRAY) {}

viewingCiv.shouldGoToDueUnit() ->
NextTurnAction("Next unit", Color.LIGHT_GRAY) {
val nextDueUnit = viewingCiv.getNextDueUnit()
if (nextDueUnit != null) {
mapHolder.setCenterPosition(
nextDueUnit.currentTile.position,
immediately = false,
selectUnit = false
)
bottomUnitTable.selectUnit(nextDueUnit)
shouldUpdate = true
}
}
NextTurnAction("Next unit", Color.LIGHT_GRAY) { switchToNextUnit() }

viewingCiv.cities.any { it.cityConstructions.currentConstructionFromQueue == "" } ->
NextTurnAction("Pick construction", Color.CORAL) {
Expand Down
16 changes: 14 additions & 2 deletions core/src/com/unciv/ui/worldscreen/unit/UnitActions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ object UnitActions {
addTriggerUniqueActions(unit, actionList)
addAddInCapitalAction(unit, actionList, tile)

addWaitAction(unit, actionList, worldScreen);

addToggleActionsAction(unit, actionList, unitTable)

Expand Down Expand Up @@ -821,6 +822,18 @@ object UnitActions {
}
}

private fun addWaitAction(unit: MapUnit, actionList: ArrayList<UnitAction>, worldScreen: WorldScreen) {
if (!unit.isIdle()) return
if (worldScreen.viewingCiv.getDueUnits().filter { it != unit }.none()) return
actionList += UnitAction(
type = UnitActionType.Wait,
action = {
unit.due = true
worldScreen.switchToNextUnit()
}
)
}

private fun addToggleActionsAction(unit: MapUnit, actionList: ArrayList<UnitAction>, unitTable: UnitTable) {
actionList += UnitAction(
type = if (unit.showAdditionalActions) UnitActionType.HideAdditionalActions
Expand All @@ -831,5 +844,4 @@ object UnitActions {
}
)
}

}
}