diff --git a/README.md b/README.md index 7032eca2a4..603c70a9f9 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ [![Google Play](https://img.shields.io/static/v1?label=Google&message=Play&color=607D8B&logo=google-play)](https://play.google.com/store/apps/details?id=com.unciv.app) [![F-Droid](https://img.shields.io/f-droid/v/com.unciv.app)](https://f-droid.org/en/packages/com.unciv.app/) [![itch.io](https://img.shields.io/static/v1?label=itch.io&message=Unciv&color=607D8B&logo=itch.io)](https://yairm210.itch.io/unciv) +[![Flathub](https://img.shields.io/flathub/v/io.github.yairm210.unciv)](https://flathub.org/apps/details/io.github.yairm210.unciv) [![Travis CI w/ Logo](https://img.shields.io/travis/yairm210/Unciv/master.svg?logo=travis)](https://travis-ci.com/yairm210/Unciv) ![Build and deploy](https://github.com/yairm210/Unciv/workflows/Build%20and%20deploy/badge.svg) @@ -79,6 +80,8 @@ Yes! Windows and Linux versions are available at [itch.io](https://yairm210.itch If you have Java 8, and are familiar with the command line, there are (considerably smaller) JARs in [Releases](https://github.com/yairm210/UnCiv/releases) which you can run with `java -jar Unciv.jar`. This is also (currently) the only way to run the game on MacOS. +If you use Flatpaks, there's a Flatpak by [MayeulC](https://github.com/MayeulC) and you can know more about it [here](https://github.com/flathub/io.github.yairm210.unciv). Flathub link is available in the [Downloads](#downloads) section. + If you want to build it from sratch for some reason, [we have instructions for that as well](https://github.com/yairm210/Unciv/wiki/Building-locally-without-Android-Studio) ## How about IOS? @@ -124,4 +127,9 @@ Multiplayer takes advantage of Dropbox, which is *non-free software*, for syncin Single player does not use this feature. +## Downloads + +| [![](https://static.itch.io/images/badge.svg)](https://yairm210.itch.io/unciv) | [![](https://play.google.com/intl/en_us/badges/images/generic/en-play-badge.png)](https://play.google.com/store/apps/details?id=com.unciv.app) | [![](https://fdroid.gitlab.io/artwork/badge/get-it-on.png)](https://f-droid.org/en/packages/com.unciv.app/) | [![](https://flathub.org/assets/badges/flathub-badge-en.svg)](https://flathub.org/apps/details/io.github.yairm210.unciv) +|--- |--- |--- |--- | + # [Credits and 3rd parties](docs/Credits.md) diff --git a/android/ImagesToPackSeparately/UnitIcons/Paratrooper.png b/android/ImagesToPackSeparately/UnitIcons/Paratrooper.png new file mode 100644 index 0000000000..1a1b78d1a2 Binary files /dev/null and b/android/ImagesToPackSeparately/UnitIcons/Paratrooper.png differ diff --git a/android/assets/UnitIcons.atlas b/android/assets/UnitIcons.atlas index 9136cc5b86..9553d0a871 100644 --- a/android/assets/UnitIcons.atlas +++ b/android/assets/UnitIcons.atlas @@ -487,132 +487,139 @@ Panzer orig: 100, 100 offset: 0, 0 index: -1 -Persian Immortal +Paratrooper rotate: false xy: 1430, 308 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 -Pikeman +Persian Immortal rotate: false xy: 1532, 410 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 -Rifleman +Pikeman rotate: false xy: 1328, 105 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 -Rocket Artillery +Rifleman rotate: false xy: 1430, 206 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 -Samurai +Rocket Artillery rotate: false xy: 1532, 308 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 -Scout +Samurai rotate: false xy: 1634, 410 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 -Settler +Scout rotate: false xy: 1328, 3 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 -Ship of the Line +Settler rotate: false xy: 1430, 104 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 -Sipahi +Ship of the Line rotate: false xy: 1430, 2 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 -Slinger +Sipahi rotate: false xy: 1532, 206 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 -Spearman +Slinger rotate: false xy: 1634, 308 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 -Stealth Bomber +Spearman rotate: false xy: 1736, 410 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 -Submarine +Stealth Bomber rotate: false xy: 1532, 104 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 -Swordsman +Submarine rotate: false xy: 1532, 2 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 -Tank +Swordsman rotate: false xy: 1634, 206 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 -Tercio +Tank rotate: false xy: 1736, 308 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 -Trebuchet +Tercio rotate: false xy: 1838, 410 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 -Triplane +Trebuchet rotate: false xy: 1634, 104 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 +Triplane + rotate: false + xy: 1634, 2 + size: 100, 100 + orig: 100, 100 + offset: 0, 0 + index: -1 Trireme rotate: false xy: 1736, 205 @@ -622,49 +629,49 @@ Trireme index: -1 Turtle Ship rotate: false - xy: 1634, 2 + xy: 1838, 308 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 War Chariot rotate: false - xy: 1838, 308 + xy: 1940, 410 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 War Elephant rotate: false - xy: 1940, 410 + xy: 1736, 103 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 Warrior rotate: false - xy: 1736, 103 + xy: 1838, 206 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 Work Boats rotate: false - xy: 1838, 206 + xy: 1940, 308 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 Worker rotate: false - xy: 1940, 308 + xy: 1838, 104 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 Zero rotate: false - xy: 1838, 104 + xy: 1838, 2 size: 100, 100 orig: 100, 100 offset: 0, 0 diff --git a/android/assets/UnitIcons.png b/android/assets/UnitIcons.png index ba9e72ac87..e0bf572db7 100644 Binary files a/android/assets/UnitIcons.png and b/android/assets/UnitIcons.png differ diff --git a/android/assets/jsons/Civ V - Vanilla/Buildings.json b/android/assets/jsons/Civ V - Vanilla/Buildings.json index 0cdf2a1c0f..0fff03ded6 100644 --- a/android/assets/jsons/Civ V - Vanilla/Buildings.json +++ b/android/assets/jsons/Civ V - Vanilla/Buildings.json @@ -110,7 +110,7 @@ "isWonder": true, "cost": 185, "greatPersonPoints": {"production": 1}, - "uniques": ["+[10]% growth in all cities", "+[15]% Production when constructing [Ranged] units [in all cities]"], + "uniques": ["+[10]% [Food] [in all cities]", "+[15]% Production when constructing [Ranged] units [in all cities]"], "requiredTech": "Archery", "quote": "'It is not so much for its beauty that the forest makes a claim upon men's hearts, as for that subtle something, that quality of air, that emanation from old trees, that so wonderfully changes and renews a weary spirit.' - Robert Louis Stevenson" }, @@ -937,7 +937,7 @@ { "name": "Manhattan Project", "isNationalWonder": true, - "uniques": ["Enables nuclear weapon"], + "uniques": ["Enables nuclear weapon", "Triggers a global alert upon completion"], "requiredTech": "Nuclear Fission" }, { @@ -1014,13 +1014,13 @@ "name": "SS Booster", "requiredResource": "Aluminum", "requiredTech": "Robotics", - "uniques": ["Spaceship part", "Cannot be purchased"] + "uniques": ["Spaceship part", "Triggers a global alert upon completion", "Cannot be purchased"] }, { "name": "Apollo Program", "cost": 1500, "isNationalWonder": true, - "uniques": ["Enables construction of Spaceship parts"], + "uniques": ["Enables construction of Spaceship parts", "Triggers a global alert upon completion"], "requiredTech": "Rocketry" }, @@ -1044,18 +1044,18 @@ "name": "SS Cockpit", "requiredResource": "Aluminum", "requiredTech": "Satellites", - "uniques": ["Spaceship part", "Cannot be purchased"] + "uniques": ["Spaceship part", "Triggers a global alert upon completion", "Cannot be purchased"] }, { "name": "SS Engine", "requiredResource": "Aluminum", "requiredTech": "Particle Physics", - "uniques": ["Spaceship part", "Cannot be purchased"] + "uniques": ["Spaceship part", "Triggers a global alert upon completion", "Cannot be purchased"] }, { "name": "SS Stasis Chamber", "requiredResource": "Aluminum", "requiredTech": "Nanotechnology", - "uniques": ["Spaceship part", "Cannot be purchased"] + "uniques": ["Spaceship part", "Triggers a global alert upon completion", "Cannot be purchased"] } ] diff --git a/android/assets/jsons/Civ V - Vanilla/Units.json b/android/assets/jsons/Civ V - Vanilla/Units.json index d781a5f6de..73b2927fd6 100644 --- a/android/assets/jsons/Civ V - Vanilla/Units.json +++ b/android/assets/jsons/Civ V - Vanilla/Units.json @@ -1152,7 +1152,6 @@ "uniques": ["+[20]% Strength in [Foreign Land]"], "attackSound": "shot" }, - /* { "name": "Paratrooper", "unitType": "Melee", @@ -1160,11 +1159,10 @@ "strength": 40, "cost": 375, "requiredTech": "Radar", - "uniques": ["May Paradrop"], + "uniques": ["May Paradrop up to [5] tiles from inside friendly territory"], "attackSound": "shot" // 65 strength in expansions, upgradesTo "XCOM Squad", "No Movement Cost to Pillage" in BNW }, - */ { "name": "Infantry", "unitType": "Melee", diff --git a/android/assets/jsons/translations/Dutch.properties b/android/assets/jsons/translations/Dutch.properties index 04c21ae922..7d97c9d7a4 100644 --- a/android/assets/jsons/translations/Dutch.properties +++ b/android/assets/jsons/translations/Dutch.properties @@ -515,6 +515,7 @@ Sleep = Slaap Sleep until healed = Slaap tot geheeld Moving = Bewegen Set up = Opstellen +Paradrop = Parachutelanding Upgrade to [unitType] ([goldCost] gold) = Waardeer [unitType] op ([goldCost] goud) Found city = Stad stichten Promote = Promoveren @@ -522,7 +523,7 @@ Health = Gezondheid Disband unit = Eenheid opheffen Explore = Ontdekken Stop exploration = Stop ontdekken -Pillage = Plundering +Pillage = Plunderen Do you really want to disband this unit? = Wil je echt deze eenheid opheffen Disband this unit for [goldAmount] gold? = Deze eenheid ontbinden voor [goldAmount] goud? Create [improvement] = Maak [improvement] @@ -919,7 +920,7 @@ Land = Land Wounded = Gewond Marine = Marine Mobile SAM = Mobiele grond-lucht raket -Paratrooper = Paracommando +Paratrooper = Parachutist Helicopter Gunship = Helicopter Wapenschip Atomic Bomb = Atoombom Unbuildable = Onbouwbaar diff --git a/android/assets/jsons/translations/template.properties b/android/assets/jsons/translations/template.properties index 0be55ba60c..c345f78fe5 100644 --- a/android/assets/jsons/translations/template.properties +++ b/android/assets/jsons/translations/template.properties @@ -395,6 +395,8 @@ Cannot provide unit upkeep for [unitName] - unit has been disbanded! = [cityName] is starving! = [construction] has been built in [cityName] = [wonder] has been built in a faraway land = +[civName] has completed [construction]! = +An unknown civilization has completed [construction]! = Work has started on [construction] = [cityName] cannot continue work on [construction] = [cityName] has expanded its borders! = @@ -502,6 +504,7 @@ Sleep = Sleep until healed = Moving = Set up = +Paradrop = Upgrade to [unitType] ([goldCost] gold) = Found city = Promote = diff --git a/core/src/com/unciv/Constants.kt b/core/src/com/unciv/Constants.kt index 63e733ffe8..769b3e8e5a 100644 --- a/core/src/com/unciv/Constants.kt +++ b/core/src/com/unciv/Constants.kt @@ -57,6 +57,8 @@ object Constants { const val unitActionSleepUntilHealed = "Sleep until healed" const val unitActionAutomation = "Automate" const val unitActionExplore = "Explore" + const val unitActionParadrop = "Paradrop" + const val futureTech = "Future Tech" const val cancelImprovementOrder = "Cancel improvement order" diff --git a/core/src/com/unciv/UncivGame.kt b/core/src/com/unciv/UncivGame.kt index bf24edc579..e75bc09f75 100644 --- a/core/src/com/unciv/UncivGame.kt +++ b/core/src/com/unciv/UncivGame.kt @@ -62,7 +62,6 @@ class UncivGame(parameters: UncivGameParameters) : Game() { var music: Music? = null val musicLocation = "music/thatched-villagers.mp3" - private var isSizeRestored = false var isInitialized = false @@ -118,7 +117,6 @@ class UncivGame(parameters: UncivGameParameters) : Game() { thread(name="Music") { startMusic() } - restoreSize() if (settings.isFreshlyCreated) { setScreen(LanguagePickerScreen()) @@ -129,14 +127,6 @@ class UncivGame(parameters: UncivGameParameters) : Game() { crashController = CrashController.Impl(crashReportSender) } - fun restoreSize() { - if (!isSizeRestored && Gdx.app.type == Application.ApplicationType.Desktop && settings.windowState.height>39 && settings.windowState.width>39) { - isSizeRestored = true - Gdx.graphics.setWindowedMode(settings.windowState.width, settings.windowState.height) - } - } - - fun loadGame(gameInfo: GameInfo) { this.gameInfo = gameInfo ImageGetter.setNewRuleset(gameInfo.ruleSet) diff --git a/core/src/com/unciv/logic/city/CityConstructions.kt b/core/src/com/unciv/logic/city/CityConstructions.kt index e493fc9eb9..1d0c09d28c 100644 --- a/core/src/com/unciv/logic/city/CityConstructions.kt +++ b/core/src/com/unciv/logic/city/CityConstructions.kt @@ -347,7 +347,16 @@ class CityConstructions { cityInfo.civInfo.addNotification("[${construction.name}] has been built in [" + cityInfo.name + "]", cityInfo.location, NotificationIcon.Construction, icon) } - + if (construction is Building && "Triggers a global alert upon completion" in construction.uniques) { + for (otherCiv in cityInfo.civInfo.gameInfo.civilizations) { + // No need to notify ourself, since we already got the building notification anyway + if (otherCiv == cityInfo.civInfo) continue + val completingCivDescription = + if (otherCiv.knows(cityInfo.civInfo)) "[${cityInfo.civInfo.civName}]" else "An unknown civilization" + otherCiv.addNotification("$completingCivDescription has completed [${construction.name}]!", + NotificationIcon.Construction, buildingIcon) + } + } } fun addBuilding(buildingName: String) { diff --git a/core/src/com/unciv/logic/map/MapUnit.kt b/core/src/com/unciv/logic/map/MapUnit.kt index e0f2e8ca32..a65249dc19 100644 --- a/core/src/com/unciv/logic/map/MapUnit.kt +++ b/core/src/com/unciv/logic/map/MapUnit.kt @@ -71,6 +71,9 @@ class MapUnit { @Transient var cannotEnterOceanTilesUntilAstronomy = false + @Transient + var paradropRange = 0 + lateinit var owner: String /** @@ -547,6 +550,9 @@ class MapUnit { action = null // wake up when healed } + if (action == Constants.unitActionParadrop) + action = null + getCitadelDamage() getTerrainDamage() } diff --git a/core/src/com/unciv/logic/map/UnitMovementAlgorithms.kt b/core/src/com/unciv/logic/map/UnitMovementAlgorithms.kt index 7fea549464..7677abc642 100644 --- a/core/src/com/unciv/logic/map/UnitMovementAlgorithms.kt +++ b/core/src/com/unciv/logic/map/UnitMovementAlgorithms.kt @@ -2,6 +2,7 @@ package com.unciv.logic.map import com.badlogic.gdx.math.Vector2 import com.unciv.Constants +import com.unciv.logic.HexMath.getDistance import com.unciv.logic.civilization.CivilizationInfo class UnitMovementAlgorithms(val unit:MapUnit) { @@ -169,8 +170,8 @@ class UnitMovementAlgorithms(val unit:MapUnit) { val currentTile = unit.getTile() if (currentTile == finalDestination) return currentTile - // head there directly - if (unit.type.isAirUnit()) return finalDestination + // If we can fly, head there directly + if (unit.type.isAirUnit() || unit.action == Constants.unitActionParadrop) return finalDestination val distanceToTiles = getDistanceToTiles() @@ -209,6 +210,8 @@ class UnitMovementAlgorithms(val unit:MapUnit) { fun canReach(destination: TileInfo): Boolean { if (unit.type.isAirUnit()) return unit.currentTile.aerialDistanceTo(destination) <= unit.getRange()*2 + if (unit.action == Constants.unitActionParadrop) + return getDistance(unit.currentTile.position, destination.position) <= unit.paradropRange && canParadropOn(destination) return getShortestPath(destination).any() } @@ -239,13 +242,27 @@ class UnitMovementAlgorithms(val unit:MapUnit) { fun moveToTile(destination: TileInfo) { if (destination == unit.getTile()) return // already here! - if (unit.type.isAirUnit()) { // they move differently from all other units + if (unit.type.isAirUnit()) { // air units move differently from all other units unit.action = null unit.removeFromTile() unit.isTransported = false // it has left the carrier by own means unit.putInTile(destination) unit.currentMovement = 0f return + } else if (unit.action == Constants.unitActionParadrop) { // paratrooping move differently + unit.action = null + unit.removeFromTile() + unit.putInTile(destination) + unit.currentMovement -= 1f + // Check if unit maintenance changed + // Is also done for other units, but because we skip everything else, we have to manually check it + // The reasong we skip everything, is that otherwise `getPathToTile()` throws an exception + // As we can not reach our destination in a single turn + if (unit.canGarrison() + && (unit.getTile().isCityCenter() || destination.isCityCenter()) + && unit.civInfo.hasUnique("Units in cities cost no Maintenance") + ) unit.civInfo.updateStatsForNextTurn() + return } val distanceToTiles = getDistanceToTiles() @@ -326,7 +343,14 @@ class UnitMovementAlgorithms(val unit:MapUnit) { } return false } - + + // Can a paratrooper land at this tile? + fun canParadropOn(destination: TileInfo): Boolean { + // Can only move to land tiles within range that are visible and not impassible + // Based on some testing done in the base game + if (!destination.isLand || destination.isImpassible() || !unit.civInfo.viewableTiles.contains(destination)) return false + return true + } // This is the most called function in the entire game, // so multiple callees of this function have been optimized, diff --git a/core/src/com/unciv/models/UnitAction.kt b/core/src/com/unciv/models/UnitAction.kt index c4429c5693..b5103576c8 100644 --- a/core/src/com/unciv/models/UnitAction.kt +++ b/core/src/com/unciv/models/UnitAction.kt @@ -10,17 +10,18 @@ data class UnitAction( enum class UnitActionType(val value: String) { Automate("Automate"), - StopMovement("Stop movement"), StopAutomation("Stop automation"), - StopExploration("Stop exploration"), + StopMovement("Stop movement"), Sleep("Sleep"), SleepUntilHealed("Sleep until healed"), Fortify("Fortify"), FortifyUntilHealed("Fortify until healed"), Explore("Explore"), + StopExploration("Stop exploration"), Promote("Promote"), Upgrade("Upgrade"), Pillage("Pillage"), + Paradrop("Paradrop"), SetUp("Set up"), FoundCity("Found city"), ConstructImprovement("Construct improvement"), diff --git a/core/src/com/unciv/models/metadata/GameSettings.kt b/core/src/com/unciv/models/metadata/GameSettings.kt index b8b058d5a4..3bb07b65f1 100644 --- a/core/src/com/unciv/models/metadata/GameSettings.kt +++ b/core/src/com/unciv/models/metadata/GameSettings.kt @@ -4,7 +4,7 @@ import com.badlogic.gdx.Application import com.badlogic.gdx.Gdx import com.unciv.logic.GameSaver -data class WindowState (val width:Int=0, val height:Int=0) +data class WindowState (val width: Int = 900, val height: Int = 600) class GameSettings { var showWorkedTiles: Boolean = false diff --git a/core/src/com/unciv/models/ruleset/Building.kt b/core/src/com/unciv/models/ruleset/Building.kt index 6331e14713..9f1854483e 100644 --- a/core/src/com/unciv/models/ruleset/Building.kt +++ b/core/src/com/unciv/models/ruleset/Building.kt @@ -413,8 +413,8 @@ class Building : NamedStats(), IConstruction { civInfo.victoryManager.currentsSpaceshipParts.add(name, 1) return true } - cityConstructions.addBuilding(name) + cityConstructions.addBuilding(name) val improvement = getImprovement(civInfo.gameInfo.ruleSet) if (improvement != null) { diff --git a/core/src/com/unciv/ui/worldscreen/WorldMapHolder.kt b/core/src/com/unciv/ui/worldscreen/WorldMapHolder.kt index d5a9367c9b..f4dc3a05e8 100644 --- a/core/src/com/unciv/ui/worldscreen/WorldMapHolder.kt +++ b/core/src/com/unciv/ui/worldscreen/WorldMapHolder.kt @@ -218,7 +218,11 @@ class WorldMapHolder(internal val worldScreen: WorldScreen, internal val tileMap val turnsToGetThere = if (unit.type.isAirUnit()) { if (unit.movement.canReach(tileInfo)) 1 else 0 - } else unit.movement.getShortestPath(tileInfo).size // this is what takes the most time, tbh + } else if (unit.action == Constants.unitActionParadrop) { + if (unit.movement.canReach(tileInfo)) 1 + else 0 + } else + unit.movement.getShortestPath(tileInfo).size // this is what takes the most time, tbh unitToTurnsToTile[unit] = turnsToGetThere } @@ -393,11 +397,15 @@ class WorldMapHolder(internal val worldScreen: WorldScreen, internal val tileMap } val isAirUnit = unit.type.isAirUnit() - val tilesInMoveRange = - if (isAirUnit) - unit.getTile().getTilesInDistanceRange(IntRange(1, unit.getRange() * 2)) - else - unit.movement.getDistanceToTiles().keys.asSequence() + val moveTileOverlayColor = if (unit.action == Constants.unitActionParadrop) Color.BLUE else Color.WHITE + val tilesInMoveRange = + if (isAirUnit) + unit.getTile().getTilesInDistanceRange(IntRange(1, unit.getRange() * 2)) + else if (unit.action == Constants.unitActionParadrop) + unit.getTile().getTilesInDistance(unit.paradropRange) + .filter { unit.movement.canParadropOn(it) } + else + unit.movement.getDistanceToTiles().keys.asSequence() for (tile in tilesInMoveRange) { for (tileToColor in tileGroups[tile]!!) { @@ -411,7 +419,7 @@ class WorldMapHolder(internal val worldScreen: WorldScreen, internal val tileMap } if (unit.movement.canMoveTo(tile) || unit.movement.isUnknownTileWeShouldAssumeToBePassable(tile) && !unit.type.isAirUnit()) - tileToColor.showCircle(Color.WHITE, + tileToColor.showCircle(moveTileOverlayColor, if (UncivGame.Current.settings.singleTapMove || isAirUnit) 0.7f else 0.3f) } } diff --git a/core/src/com/unciv/ui/worldscreen/unit/UnitActions.kt b/core/src/com/unciv/ui/worldscreen/unit/UnitActions.kt index 691f27761e..8db5880b23 100644 --- a/core/src/com/unciv/ui/worldscreen/unit/UnitActions.kt +++ b/core/src/com/unciv/ui/worldscreen/unit/UnitActions.kt @@ -51,6 +51,7 @@ object UnitActions { addPromoteAction(unit, actionList) addUnitUpgradeAction(unit, actionList) addPillageAction(unit, actionList, worldScreen) + addParadropAction(unit, actionList, worldScreen) addSetupAction(unit, actionList) addFoundCityAction(unit, actionList, tile) addWorkerActions(unit, actionList, tile, worldScreen, unitTable) @@ -152,6 +153,26 @@ object UnitActions { }.takeIf { unit.currentMovement > 0 && !isSetUp }) } + private fun addParadropAction(unit: MapUnit, actionList: ArrayList, worldScreen: WorldScreen) { + val paradropUniques = unit.getMatchingUniques("May Paradrop up to [] tiles from inside friendly territory") + if (!paradropUniques.any() || unit.isEmbarked()) return + unit.paradropRange = paradropUniques.maxOfOrNull { it.params[0] }!!.toInt() + actionList += UnitAction(UnitActionType.Paradrop, + isCurrentAction = unit.action == Constants.unitActionParadrop, + action = { + if (unit.action != Constants.unitActionParadrop) { + unit.action = Constants.unitActionParadrop + } else { + unit.action = null + } + }.takeIf { + unit.currentMovement == unit.getMaxMovement().toFloat() && + unit.currentTile.isFriendlyTerritory(unit.civInfo) && + !unit.isEmbarked() + }) + + } + private fun addPillageAction(unit: MapUnit, actionList: ArrayList, worldScreen: WorldScreen) { val pillageAction = getPillageAction(unit) if (pillageAction == null) return diff --git a/core/src/com/unciv/ui/worldscreen/unit/UnitActionsTable.kt b/core/src/com/unciv/ui/worldscreen/unit/UnitActionsTable.kt index 99599cd13b..ac9b87906e 100644 --- a/core/src/com/unciv/ui/worldscreen/unit/UnitActionsTable.kt +++ b/core/src/com/unciv/ui/worldscreen/unit/UnitActionsTable.kt @@ -49,12 +49,13 @@ class UnitActionsTable(val worldScreen: WorldScreen) : Table() { "Start Golden Age" -> return UnitIconAndKey(ImageGetter.getUnitIcon("Great Artist"), 'g') "Hurry Wonder" -> return UnitIconAndKey(ImageGetter.getUnitIcon("Great Engineer"), 'g') "Conduct Trade Mission" -> return UnitIconAndKey(ImageGetter.getUnitIcon("Great Merchant"), 'g') + "Construct road" -> return UnitIconAndKey(ImageGetter.getImprovementIcon("Road"), 'r') + "Paradrop" -> return UnitIconAndKey(ImageGetter.getUnitIcon("Paratrooper"), 'p') "Set up" -> return UnitIconAndKey(ImageGetter.getUnitIcon("Catapult"), 't') - "Disband unit" -> return UnitIconAndKey(ImageGetter.getImage("OtherIcons/DisbandUnit")) "Explore" -> return UnitIconAndKey(ImageGetter.getUnitIcon("Scout"), 'x') "Stop exploration" -> return UnitIconAndKey(ImageGetter.getImage("OtherIcons/Stop"), 'x') "Pillage" -> return UnitIconAndKey(ImageGetter.getImage("OtherIcons/Pillage"), 'p') - "Construct road" -> return UnitIconAndKey(ImageGetter.getImprovementIcon("Road"), 'r') + "Disband unit" -> return UnitIconAndKey(ImageGetter.getImage("OtherIcons/DisbandUnit")) else -> return UnitIconAndKey(ImageGetter.getImage("OtherIcons/Star")) } } diff --git a/desktop/src/com/unciv/app/desktop/DesktopLauncher.kt b/desktop/src/com/unciv/app/desktop/DesktopLauncher.kt index 2a4f46b9e6..0534d6c1c1 100644 --- a/desktop/src/com/unciv/app/desktop/DesktopLauncher.kt +++ b/desktop/src/com/unciv/app/desktop/DesktopLauncher.kt @@ -6,10 +6,14 @@ import club.minnced.discord.rpc.DiscordRichPresence import com.badlogic.gdx.Files import com.badlogic.gdx.backends.lwjgl.LwjglApplication import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration +import com.badlogic.gdx.files.FileHandle import com.badlogic.gdx.graphics.Texture import com.badlogic.gdx.tools.texturepacker.TexturePacker +import com.unciv.JsonParser import com.unciv.UncivGame import com.unciv.UncivGameParameters +import com.unciv.logic.GameSaver +import com.unciv.models.metadata.GameSettings import com.unciv.models.translations.tr import com.unciv.ui.utils.Fonts import io.ktor.application.* @@ -39,6 +43,11 @@ internal object DesktopLauncher { config.addIcon("ExtraImages/Icon.png", Files.FileType.Internal) config.title = "Unciv" config.useHDPI = true + if (FileHandle(GameSaver.settingsFileName).exists()) { + val settings = JsonParser().getFromJson(GameSettings::class.java, FileHandle(GameSaver.settingsFileName)) + config.width = settings.windowState.width + config.height = settings.windowState.height + } val versionFromJar = DesktopLauncher.javaClass.`package`.specificationVersion ?: "Desktop" diff --git a/docs/Credits.md b/docs/Credits.md index 6e325784bb..7e8c9f5683 100644 --- a/docs/Credits.md +++ b/docs/Credits.md @@ -104,6 +104,7 @@ Unless otherwise specified, all the following are from [the Noun Project](https: * [Nuclear Missile](https://thenounproject.com/marialuisa.iborra/collection/missiles-bombs/?i=1022574) By Lluisa Iborra, ES * Icon for Carrier made by [JackRainy](https://github.com/JackRainy), based on [Aircraft Carrier](https://thenounproject.com/icolabs/collection/flat-icons-transport/?i=2332914) By IcoLabs, BR * [Water Gun](https://thenounproject.com/term/water-gun/2121571) by ProSymbols for Marine +* [Parachute](https://thenounproject.com/term/parachute/2025018) by Nociconist for Paratrooper* ### Great People