diff --git a/android/Images.Icons/OtherIcons/Scenarios.png b/android/Images.Icons/OtherIcons/Scenarios.png new file mode 100644 index 0000000000..89611a878a Binary files /dev/null and b/android/Images.Icons/OtherIcons/Scenarios.png differ diff --git a/android/assets/Icons.atlas b/android/assets/Icons.atlas index 50b0e8e26b..cb87404677 100644 --- a/android/assets/Icons.atlas +++ b/android/assets/Icons.atlas @@ -41,105 +41,105 @@ CityStateIcons/Religious index: -1 EmojiIcons/Automate rotate: false - xy: 1123, 1622 + xy: 1347, 1753 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 EmojiIcons/Culture rotate: false - xy: 1388, 1753 + xy: 1521, 1753 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 EmojiIcons/Death rotate: false - xy: 1446, 1753 + xy: 1579, 1753 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 EmojiIcons/Faith rotate: false - xy: 1504, 1753 + xy: 1637, 1753 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 EmojiIcons/Food rotate: false - xy: 1562, 1753 + xy: 1695, 1753 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 EmojiIcons/Gold rotate: false - xy: 1678, 1753 + xy: 1811, 1753 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 EmojiIcons/Great Artist rotate: false - xy: 1736, 1753 + xy: 1869, 1753 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 EmojiIcons/Great Engineer rotate: false - xy: 1794, 1753 + xy: 1231, 1695 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 EmojiIcons/Great General rotate: false - xy: 1852, 1753 + xy: 1289, 1695 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 EmojiIcons/Great Merchant rotate: false - xy: 1910, 1753 + xy: 1347, 1695 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 EmojiIcons/Great Scientist rotate: false - xy: 946, 1536 + xy: 1405, 1695 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 EmojiIcons/Happiness rotate: false - xy: 946, 1478 + xy: 1463, 1695 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 EmojiIcons/Production rotate: false - xy: 1297, 1637 + xy: 946, 1536 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 EmojiIcons/Science rotate: false - xy: 1413, 1695 + xy: 1214, 1637 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 EmojiIcons/Turn rotate: false - xy: 1471, 1695 + xy: 1330, 1637 size: 50, 50 orig: 50, 50 offset: 0, 0 @@ -384,14 +384,14 @@ ImprovementIcons/Road index: -1 ImprovementIcons/Terrace farm rotate: false - xy: 1108, 1811 + xy: 1216, 1811 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ImprovementIcons/Trading post rotate: false - xy: 1324, 1811 + xy: 1432, 1811 size: 100, 100 orig: 100, 100 offset: 0, 0 @@ -431,27 +431,6 @@ StatIcons/Faith orig: 100, 100 offset: 0, 0 index: -1 -NotificationIcons/Loading - rotate: false - xy: 220, 451 - size: 100, 100 - orig: 100, 100 - offset: 0, 0 - index: -1 -NotificationIcons/Working - rotate: false - xy: 220, 451 - size: 100, 100 - orig: 100, 100 - offset: 0, 0 - index: -1 -OtherIcons/Loading - rotate: false - xy: 220, 451 - size: 100, 100 - orig: 100, 100 - offset: 0, 0 - index: -1 NotificationIcons/PickConstruction rotate: false xy: 436, 683 @@ -468,7 +447,7 @@ StatIcons/Production index: -1 NotificationIcons/PickPolicy rotate: false - xy: 298, 1320 + xy: 2009, 1986 size: 33, 33 orig: 33, 33 offset: 0, 0 @@ -496,42 +475,42 @@ OtherIcons/AirSweep index: -1 OtherIcons/Aircraft rotate: false - xy: 1123, 1680 + xy: 1231, 1753 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 OtherIcons/ArrowRight rotate: false - xy: 1214, 1753 + xy: 1289, 1753 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 NotificationIcons/MoveAutomatedUnits rotate: false - xy: 1214, 1753 + xy: 1289, 1753 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 NotificationIcons/NextUnit rotate: false - xy: 1214, 1753 + xy: 1289, 1753 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 StatIcons/Movement rotate: false - xy: 1214, 1753 + xy: 1289, 1753 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 OtherIcons/BackArrow rotate: false - xy: 1272, 1753 + xy: 1405, 1753 size: 50, 50 orig: 50, 50 offset: 0, 0 @@ -559,7 +538,7 @@ OtherIcons/Blockade index: -1 OtherIcons/Camera rotate: false - xy: 946, 1387 + xy: 298, 1328 size: 25, 25 orig: 25, 25 offset: 0, 0 @@ -601,7 +580,7 @@ OtherIcons/Cities index: -1 OtherIcons/CityState rotate: false - xy: 1330, 1753 + xy: 1463, 1753 size: 50, 50 orig: 50, 50 offset: 0, 0 @@ -664,7 +643,7 @@ OtherIcons/Fire index: -1 OtherIcons/ForwardArrow rotate: false - xy: 1620, 1753 + xy: 1753, 1753 size: 50, 50 orig: 50, 50 offset: 0, 0 @@ -685,7 +664,7 @@ OtherIcons/HexagonOutline index: -1 OtherIcons/Improvements rotate: false - xy: 946, 1420 + xy: 1521, 1695 size: 50, 50 orig: 50, 50 offset: 0, 0 @@ -711,9 +690,30 @@ OtherIcons/Load orig: 100, 100 offset: 0, 0 index: -1 +OtherIcons/Loading + rotate: false + xy: 220, 451 + size: 100, 100 + orig: 100, 100 + offset: 0, 0 + index: -1 +NotificationIcons/Loading + rotate: false + xy: 220, 451 + size: 100, 100 + orig: 100, 100 + offset: 0, 0 + index: -1 +NotificationIcons/Working + rotate: false + xy: 220, 451 + size: 100, 100 + orig: 100, 100 + offset: 0, 0 + index: -1 OtherIcons/LockSmall rotate: false - xy: 1972, 1803 + xy: 1637, 1695 size: 50, 50 orig: 50, 50 offset: 0, 0 @@ -755,7 +755,7 @@ OtherIcons/NationSwap index: -1 OtherIcons/Nations rotate: false - xy: 1239, 1637 + xy: 1927, 1753 size: 50, 50 orig: 50, 50 offset: 0, 0 @@ -783,7 +783,7 @@ OtherIcons/Options index: -1 OtherIcons/Pause rotate: false - xy: 1297, 1695 + xy: 1927, 1695 size: 50, 50 orig: 50, 50 offset: 0, 0 @@ -886,79 +886,86 @@ OtherIcons/Resume orig: 100, 100 offset: 0, 0 index: -1 -OtherIcons/Search +OtherIcons/Scenarios rotate: false xy: 760, 794 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 -OtherIcons/SecretOptions +OtherIcons/Search rotate: false xy: 760, 686 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 -OtherIcons/Settings +OtherIcons/SecretOptions rotate: false xy: 760, 578 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 +OtherIcons/Settings + rotate: false + xy: 760, 470 + size: 100, 100 + orig: 100, 100 + offset: 0, 0 + index: -1 OtherIcons/Shield rotate: false - xy: 760, 362 + xy: 760, 254 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Sleep rotate: false - xy: 760, 38 + xy: 784, 1796 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Speaker rotate: false - xy: 784, 1796 + xy: 799, 1688 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Spy rotate: false - xy: 838, 1472 + xy: 838, 1364 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Spy_White rotate: false - xy: 838, 1364 + xy: 898, 1256 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Star rotate: false - xy: 898, 1262 + xy: 898, 1154 size: 100, 94 orig: 100, 94 offset: 0, 0 index: -1 OtherIcons/Swap rotate: false - xy: 1000, 1811 + xy: 1108, 1811 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Timer rotate: false - xy: 1216, 1811 + xy: 1324, 1811 size: 100, 100 orig: 100, 100 offset: 0, 0 @@ -972,35 +979,35 @@ OtherIcons/Triangle index: -1 OtherIcons/Turn right rotate: false - xy: 1540, 1811 + xy: 1648, 1811 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Tyrannosaurus rotate: false - xy: 1648, 1811 + xy: 1756, 1811 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/WLTKD rotate: false - xy: 1123, 1738 + xy: 1123, 1630 size: 83, 65 orig: 83, 65 offset: 0, 0 index: -1 OtherIcons/Wait rotate: false - xy: 1864, 1811 + xy: 907, 1702 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 OtherIcons/Wonders rotate: false - xy: 1015, 1595 + xy: 1123, 1703 size: 100, 100 orig: 100, 100 offset: 0, 0 @@ -1182,77 +1189,77 @@ ResourceIcons/Salt index: -1 ResourceIcons/Sheep rotate: false - xy: 760, 470 + xy: 760, 362 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Silk rotate: false - xy: 760, 254 + xy: 760, 146 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Silver rotate: false - xy: 760, 146 + xy: 760, 38 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Spices rotate: false - xy: 799, 1580 + xy: 838, 1472 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Stone rotate: false - xy: 898, 1154 + xy: 892, 1810 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Sugar rotate: false - xy: 892, 1810 + xy: 1000, 1811 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Truffles rotate: false - xy: 1432, 1811 + xy: 1540, 1811 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Uranium rotate: false - xy: 1756, 1811 + xy: 1864, 1811 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Whales rotate: false - xy: 907, 1702 + xy: 907, 1594 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Wheat rotate: false - xy: 907, 1594 + xy: 1015, 1703 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 ResourceIcons/Wine rotate: false - xy: 1015, 1703 + xy: 1015, 1595 size: 100, 100 orig: 100, 100 offset: 0, 0 @@ -1301,7 +1308,7 @@ StatIcons/Happiness index: -1 StatIcons/InterceptRange rotate: false - xy: 1972, 1861 + xy: 1579, 1695 size: 50, 50 orig: 50, 50 offset: 0, 0 @@ -1329,14 +1336,14 @@ TileIcons/Worked index: -1 StatIcons/Range rotate: false - xy: 1355, 1695 + xy: 946, 1478 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 StatIcons/RangedStrength rotate: false - xy: 1355, 1637 + xy: 946, 1420 size: 50, 50 orig: 50, 50 offset: 0, 0 @@ -1357,14 +1364,14 @@ StatIcons/Resistance index: -1 StatIcons/Specialist rotate: false - xy: 799, 1688 + xy: 799, 1580 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 StatIcons/Strength rotate: false - xy: 1413, 1637 + xy: 1272, 1637 size: 50, 50 orig: 50, 50 offset: 0, 0 @@ -1399,28 +1406,28 @@ TileIcons/Locked index: -1 TileIcons/MapOverlayToggleMovement rotate: false - xy: 1968, 1745 + xy: 1695, 1695 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 TileIcons/MapOverlayToggleResources rotate: false - xy: 1181, 1680 + xy: 1753, 1695 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 TileIcons/MapOverlayToggleWorkedTiles rotate: false - xy: 1181, 1622 + xy: 1811, 1695 size: 50, 50 orig: 50, 50 offset: 0, 0 index: -1 TileIcons/MapOverlayToggleYields rotate: false - xy: 1239, 1695 + xy: 1869, 1695 size: 50, 50 orig: 50, 50 offset: 0, 0 diff --git a/android/assets/Icons.png b/android/assets/Icons.png index 0b0db06ac3..b22ec06eec 100644 Binary files a/android/assets/Icons.png and b/android/assets/Icons.png differ diff --git a/android/assets/jsons/translations/template.properties b/android/assets/jsons/translations/template.properties index f81c2ff357..6a9dd51ef5 100644 --- a/android/assets/jsons/translations/template.properties +++ b/android/assets/jsons/translations/template.properties @@ -1869,6 +1869,8 @@ Stars ↓ = Status ↓ = Scenarios = +Error loading scenario: = +Choose scenario = # Uniques that are relevant to more than one type of game object diff --git a/core/src/com/unciv/ui/screens/mainmenuscreen/MainMenuScreen.kt b/core/src/com/unciv/ui/screens/mainmenuscreen/MainMenuScreen.kt index 376a23d3d4..0a50e1a183 100644 --- a/core/src/com/unciv/ui/screens/mainmenuscreen/MainMenuScreen.kt +++ b/core/src/com/unciv/ui/screens/mainmenuscreen/MainMenuScreen.kt @@ -167,7 +167,7 @@ class MainMenuScreen: BaseScreen(), RecreateOnResize { column2.add(modsTable).row() if (game.files.getScenarioFiles().any()){ - val scenarioTable = getMenuButton("Scenarios", "OtherIcons/Mods", KeyboardBinding.Scenarios) + val scenarioTable = getMenuButton("Scenarios", "OtherIcons/Scenarios", KeyboardBinding.Scenarios) { game.pushScreen(ScenarioScreen()) } column2.add(scenarioTable).row() } diff --git a/core/src/com/unciv/ui/screens/mainmenuscreen/ScenarioScreen.kt b/core/src/com/unciv/ui/screens/mainmenuscreen/ScenarioScreen.kt index b19c3542f5..113f0cbd5f 100644 --- a/core/src/com/unciv/ui/screens/mainmenuscreen/ScenarioScreen.kt +++ b/core/src/com/unciv/ui/screens/mainmenuscreen/ScenarioScreen.kt @@ -1,45 +1,65 @@ package com.unciv.ui.screens.mainmenuscreen import com.badlogic.gdx.files.FileHandle +import com.unciv.logic.UncivShowableException import com.unciv.models.translations.tr import com.unciv.ui.components.extensions.enable -import com.unciv.ui.components.extensions.toTextButton -import com.unciv.ui.components.input.onClick +import com.unciv.ui.components.input.KeyCharAndCode +import com.unciv.ui.components.input.keyShortcuts +import com.unciv.ui.components.input.onActivation +import com.unciv.ui.components.input.onDoubleClick +import com.unciv.ui.popups.ToastPopup import com.unciv.ui.screens.pickerscreens.PickerScreen +import com.unciv.ui.screens.savescreens.VerticalFileListScrollPane import com.unciv.utils.Concurrency +import com.unciv.utils.launchOnGLThread -class ScenarioScreen: PickerScreen() { +class ScenarioScreen: PickerScreen(disableScroll = true) { + private val scenarioScrollPane = VerticalFileListScrollPane() private var scenarioToLoad: FileHandle? = null - init { - val scenarioFiles = game.files.getScenarioFiles() - rightSideButton.setText("Choose scenario") - topTable.defaults().pad(5f) - Concurrency.run { - for ((file, mod) in scenarioFiles) { - try { - val scenarioPreview = game.files.loadGamePreviewFromFile(file) - Concurrency.runOnGLThread { - topTable.add(file.name().toTextButton().onClick { - descriptionLabel.setText("Mod: [${mod.name}]".tr()) - scenarioToLoad = file - rightSideButton.setText(file.name()) - rightSideButton.enable() - }).row() - } - } catch (ex: Exception) { } // invalid, couldn't even load preview, probably invalid json - } - } + /** Caches the mod names while the getScenarioFiles Sequence is iterated */ + private val sourceMods = mutableMapOf() - rightSideButton.onClick { - if (scenarioToLoad != null) - Concurrency.run { - val scenario = game.files.loadScenario(scenarioToLoad!!) - game.loadGame(scenario) - } - } + init { + scenarioScrollPane.onChange(::selectScenario) + scenarioScrollPane.onDoubleClick(action = ::loadSelectedScenario) + topTable.defaults().pad(5f) + topTable.add(scenarioScrollPane).grow().row() + + rightSideButton.setText("Choose scenario") + rightSideButton.onActivation(::loadSelectedScenario) + rightSideButton.keyShortcuts.add(KeyCharAndCode.RETURN) setDefaultCloseAction() + + scenarioScrollPane.update( + game.files.getScenarioFiles().map { + sourceMods[it.first] = it.second.name + it.first + } + ) + } + + private fun selectScenario(file: FileHandle) { + descriptionLabel.setText(sourceMods[file]?.let { "Mod: [$it]".tr() }) + scenarioToLoad = file + rightSideButton.setText(file.name()) + rightSideButton.enable() + } + + private fun loadSelectedScenario() { + val file = scenarioToLoad ?: return + Concurrency.run("LoadScenario") { + try { + val scenario = game.files.loadScenario(file) + game.loadGame(scenario) + } catch (ex: UncivShowableException) { + launchOnGLThread { + ToastPopup("{Error loading scenario:}\n{${ex.message}}", this@ScenarioScreen) + } + } + } } } diff --git a/core/src/com/unciv/ui/screens/savescreens/VerticalFileListScrollPane.kt b/core/src/com/unciv/ui/screens/savescreens/VerticalFileListScrollPane.kt index a747087213..8fc986c4b1 100644 --- a/core/src/com/unciv/ui/screens/savescreens/VerticalFileListScrollPane.kt +++ b/core/src/com/unciv/ui/screens/savescreens/VerticalFileListScrollPane.kt @@ -21,7 +21,6 @@ import com.unciv.utils.launchOnGLThread /** A widget holding TextButtons vertically in a Table contained in a ScrollPane, with methods to * hold file names and FileHandle's in those buttons. Used to display existing saves in the Load and Save game dialogs. * - * @param shorcutScreen optionally pass in a [BaseScreen] where global keyboard shorcuts should be installed. * @param existingSavesTable exists here for coder convenience. No need to touch. */ class VerticalFileListScrollPane( diff --git a/docs/Credits.md b/docs/Credits.md index a49376c725..38b2dd35e3 100644 --- a/docs/Credits.md +++ b/docs/Credits.md @@ -748,7 +748,8 @@ Unless otherwise specified, all the following are from [the Noun Project](https: - [Go back](https://thenounproject.com/icon/go%20back-1901947) by Salvia Santos for Resume - [Multiplayer](https://thenounproject.com/icon/multiplayer-1215652) by Roy Charles - [Options](https://thenounproject.com/icon/options-866090) By Thengakola -- [Package](https://thenounproject.com/icon/package-1886048) by shashank singh +- [Package](https://thenounproject.com/icon/package-1886048) by shashank singh for Mods +- [scenario planning](https://thenounproject.com/icon/scenario-6569968) by nicolas for Scenarios ## Sound credits diff --git a/docs/Modders/Scenarios.md b/docs/Modders/Scenarios.md index a9cd459e40..d6dbb4dc32 100644 --- a/docs/Modders/Scenarios.md +++ b/docs/Modders/Scenarios.md @@ -17,5 +17,15 @@ To create a scenario: To open the console, click the `` button on your keyboard. -To see available commands, click enter. This works for subcommands as well (e.g. when you entered `tile`) +To see available commands, click enter. This works for subcommands as well (e.g. when you entered `tile`). +The console has autocompletion: +* Enter a partial command, subcommand or argument and hit Tab... +* When the entered part, compared from the start, matches exactly one of the possible options, that option is completed and a space added for the next subcommand or parameter. +* When no option matches, nothing happens. +* When two or more options match, the possibilities are displayed, and the longest common substring is entered for you (e.g. you enter 'c', Tab: commands 'city' or 'civ' match, the console partially completes 'ci' for you). +* When you haven't yet entered a partial text (console input is empty or ends in a space), autocompletion will display all options. + +Some commands operate on a tile or unit you need to select on the map before opening the console. + +The console does intentionally not follow all rules defined by the ruleset - e.g. it allows Farms on hills without fresh water or the Mobility promotion on a Worker. Any unexpected consequences are your responsibility.