From 2a8edb3af05f43eafbb7ac685f0d92a058736fa1 Mon Sep 17 00:00:00 2001 From: General_E <121508218+Emandac@users.noreply.github.com> Date: Thu, 13 Feb 2025 19:34:58 +0100 Subject: [PATCH] Added feature to save unitType promotion. (#12894) * Settler settle best tile when not escort and dangerous Tiles instead of running away Settler unit will now settle on best tile in dangerous Tiles without escort instead of running away. * Update WorkerAutomation.kt * Update SpecificUnitAutomation.kt * Update WorkerAutomation.kt * Update SpecificUnitAutomation.kt * Now city states get mad when you steal their Lands * new version * change to getDiplomacyManagerOrMeet * added text to template.properties and changed AlertPopup.kt * Update template.properties * with period at the end :b * add flag now * Made Option to declare war when a city state is bullied unavailable * added option to change the Maximum Autosave turns stored * remove print * change letter * should fix issue with building test * update with changes * Added UniqueType.FoundPuppetCity with "Founds a new puppet city" in "uniques" of an unit in Units.json. Making it so you can now settle a puppet city. * Added save promotion * Updated for PR * Updated with requested changes * Removed unnecessary check * updated PR * Update PromotionPickerScreen.kt to save promotion cells too * change name and added ! * updated name of variable --- android/assets/Icons.atlas | 98 +++++++++---------- .../jsons/translations/template.properties | 2 + core/src/com/unciv/logic/city/City.kt | 9 +- .../com/unciv/logic/city/CityConstructions.kt | 13 +++ .../ui/popups/CityScreenConstructionMenu.kt | 1 + .../cityscreen/ConstructionInfoTable.kt | 15 ++- .../pickerscreens/PromotionPickerScreen.kt | 27 ++++- 7 files changed, 112 insertions(+), 53 deletions(-) diff --git a/android/assets/Icons.atlas b/android/assets/Icons.atlas index 76b259eb39..57f33fe7d9 100644 --- a/android/assets/Icons.atlas +++ b/android/assets/Icons.atlas @@ -200,6 +200,34 @@ OtherIcons/Stop orig: 100, 100 offset: 0, 0 index: -1 +ImprovementIcons/Circle + rotate: false + xy: 289, 1590 + size: 178, 178 + orig: 178, 178 + offset: 0, 0 + index: -1 +OtherIcons/Circle + rotate: false + xy: 289, 1590 + size: 178, 178 + orig: 178, 178 + offset: 0, 0 + index: -1 +ResourceIcons/Circle + rotate: false + xy: 289, 1590 + size: 178, 178 + orig: 178, 178 + offset: 0, 0 + index: -1 +StatIcons/Circle + rotate: false + xy: 289, 1590 + size: 178, 178 + orig: 178, 178 + offset: 0, 0 + index: -1 ImprovementIcons/Citadel rotate: false xy: 4, 62 @@ -459,6 +487,27 @@ StatIcons/Faith orig: 100, 100 offset: 0, 0 index: -1 +NotificationIcons/Loading + rotate: false + xy: 907, 1686 + size: 100, 100 + orig: 100, 100 + offset: 0, 0 + index: -1 +NotificationIcons/Working + rotate: false + xy: 907, 1686 + size: 100, 100 + orig: 100, 100 + offset: 0, 0 + index: -1 +OtherIcons/Loading + rotate: false + xy: 907, 1686 + size: 100, 100 + orig: 100, 100 + offset: 0, 0 + index: -1 NotificationIcons/PickConstruction rotate: false xy: 1771, 1500 @@ -620,34 +669,6 @@ NotificationIcons/NextTurn orig: 100, 100 offset: 0, 0 index: -1 -OtherIcons/Circle - rotate: false - xy: 289, 1590 - size: 178, 178 - orig: 178, 178 - offset: 0, 0 - index: -1 -ImprovementIcons/Circle - rotate: false - xy: 289, 1590 - size: 178, 178 - orig: 178, 178 - offset: 0, 0 - index: -1 -ResourceIcons/Circle - rotate: false - xy: 289, 1590 - size: 178, 178 - orig: 178, 178 - offset: 0, 0 - index: -1 -StatIcons/Circle - rotate: false - xy: 289, 1590 - size: 178, 178 - orig: 178, 178 - offset: 0, 0 - index: -1 OtherIcons/Cities rotate: false xy: 208, 1436 @@ -823,27 +844,6 @@ OtherIcons/Load orig: 100, 100 offset: 0, 0 index: -1 -OtherIcons/Loading - rotate: false - xy: 907, 1686 - size: 100, 100 - orig: 100, 100 - offset: 0, 0 - index: -1 -NotificationIcons/Loading - rotate: false - xy: 907, 1686 - size: 100, 100 - orig: 100, 100 - offset: 0, 0 - index: -1 -NotificationIcons/Working - rotate: false - xy: 907, 1686 - size: 100, 100 - orig: 100, 100 - offset: 0, 0 - index: -1 OtherIcons/LockSmall rotate: false xy: 1398, 1168 diff --git a/android/assets/jsons/translations/template.properties b/android/assets/jsons/translations/template.properties index bbc4eb1f0b..c7ba0463fd 100644 --- a/android/assets/jsons/translations/template.properties +++ b/android/assets/jsons/translations/template.properties @@ -113,6 +113,8 @@ Requires [PolicyOrNationalWonder] = Cannot be purchased = Can only be purchased = See also = +Use default promotions = +Default promotions for [unitType] = Requires at least one of the following: = Requires all of the following: = diff --git a/core/src/com/unciv/logic/city/City.kt b/core/src/com/unciv/logic/city/City.kt index ea2d3655ea..1dfab78de5 100644 --- a/core/src/com/unciv/logic/city/City.kt +++ b/core/src/com/unciv/logic/city/City.kt @@ -14,6 +14,7 @@ import com.unciv.logic.city.managers.SpyFleeReason import com.unciv.logic.civilization.Civilization import com.unciv.logic.map.TileMap import com.unciv.logic.map.mapunit.MapUnit +import com.unciv.logic.map.mapunit.UnitPromotions import com.unciv.logic.map.tile.RoadStatus import com.unciv.logic.map.tile.Tile import com.unciv.models.Counter @@ -91,7 +92,11 @@ class City : IsPartOfGameInfoSerialization, INamed { var hasSoldBuildingThisTurn = false var isPuppet = false var shouldReassignPopulation = false // flag so that on startTurn() we reassign population - + + var unitTypeShouldUseSavedPromotion = HashMap() + + var cityUnitTypePromotions = HashMap() + @delegate:Transient val neighboringCities: List by lazy { civ.gameInfo.getCities().filter { it != this && it.getCenterTile().isExplored(civ) && it.getCenterTile().aerialDistanceTo(getCenterTile()) <= 12 }.toList() @@ -153,6 +158,8 @@ class City : IsPartOfGameInfoSerialization, INamed { toReturn.avoidGrowth = avoidGrowth toReturn.manualSpecialists = manualSpecialists toReturn.connectedToCapitalStatus = connectedToCapitalStatus + toReturn.unitTypeShouldUseSavedPromotion = unitTypeShouldUseSavedPromotion + toReturn.cityUnitTypePromotions = cityUnitTypePromotions return toReturn } diff --git a/core/src/com/unciv/logic/city/CityConstructions.kt b/core/src/com/unciv/logic/city/CityConstructions.kt index e8ad366c90..7d97a02fb1 100644 --- a/core/src/com/unciv/logic/city/CityConstructions.kt +++ b/core/src/com/unciv/logic/city/CityConstructions.kt @@ -464,6 +464,19 @@ class CityConstructions : IsPartOfGameInfoSerialization { else if (construction is BaseUnit) { unit = construction.construct(this, null) ?: return false // unable to place unit + + // checking if it's true that we should load saved promotion for the unitType + // Check if the player want to rebuild the unit the saved promotion + // and null check. + // and finally check if the current unit has enough XP. + val savedPromotion = city.cityUnitTypePromotions[unit.baseUnit.unitType] + if (city.unitTypeShouldUseSavedPromotion[unit.baseUnit.unitType] == true && + savedPromotion != null && unit.promotions.XP >= savedPromotion.XP) { + + for (promotions in savedPromotion.promotions) { + unit.promotions.addPromotion(promotions) + } + } } if (construction.name in inProgressConstructions) diff --git a/core/src/com/unciv/ui/popups/CityScreenConstructionMenu.kt b/core/src/com/unciv/ui/popups/CityScreenConstructionMenu.kt index 2d246c2926..b282139316 100644 --- a/core/src/com/unciv/ui/popups/CityScreenConstructionMenu.kt +++ b/core/src/com/unciv/ui/popups/CityScreenConstructionMenu.kt @@ -9,6 +9,7 @@ import com.unciv.logic.city.CityConstructions import com.unciv.models.ruleset.Building import com.unciv.models.ruleset.IConstruction import com.unciv.models.ruleset.PerpetualConstruction +import com.unciv.models.ruleset.unit.BaseUnit import com.unciv.ui.components.input.KeyboardBinding //todo Check move/top/end for "place one improvement" buildings diff --git a/core/src/com/unciv/ui/screens/cityscreen/ConstructionInfoTable.kt b/core/src/com/unciv/ui/screens/cityscreen/ConstructionInfoTable.kt index bce95f5c23..35cf12005c 100644 --- a/core/src/com/unciv/ui/screens/cityscreen/ConstructionInfoTable.kt +++ b/core/src/com/unciv/ui/screens/cityscreen/ConstructionInfoTable.kt @@ -15,6 +15,7 @@ import com.unciv.models.translations.tr import com.unciv.ui.components.extensions.darken import com.unciv.ui.components.extensions.disable import com.unciv.ui.components.extensions.isEnabled +import com.unciv.ui.components.extensions.toCheckBox import com.unciv.ui.components.extensions.toTextButton import com.unciv.ui.components.fonts.Fonts import com.unciv.ui.components.input.onClick @@ -90,7 +91,7 @@ class ConstructionInfoTable(val cityScreen: CityScreen) : Table() { val descriptionLabel = Label(description, BaseScreen.skin) // already translated descriptionLabel.wrap = true add(descriptionLabel).colspan(2).width(stage.width / if(cityScreen.isCrampedPortrait()) 3 else 4) - + if (cityConstructions.isBuilt(construction.name)) { showSellButton(construction) } else if (buyButtonFactory.hasBuyButtons(construction)) { @@ -99,6 +100,16 @@ class ConstructionInfoTable(val cityScreen: CityScreen) : Table() { selectedConstructionTable.add(button).padTop(5f).colspan(2).center().row() } } + if (construction is BaseUnit) { + val unitType = construction.unitType + + val buildUnitWithPromotions = city.unitTypeShouldUseSavedPromotion[unitType] + + if (buildUnitWithPromotions != null) { + row() + add("Use default promotions".toCheckBox(buildUnitWithPromotions) {city.unitTypeShouldUseSavedPromotion[unitType] = it}).colspan(2).center() + } + } } } @@ -133,7 +144,7 @@ class ConstructionInfoTable(val cityScreen: CityScreen) : Table() { } } } - + private fun sellBuildingClicked(construction: Building, sellText: String) { cityScreen.closeAllPopups() diff --git a/core/src/com/unciv/ui/screens/pickerscreens/PromotionPickerScreen.kt b/core/src/com/unciv/ui/screens/pickerscreens/PromotionPickerScreen.kt index 54964fd94c..d186832624 100644 --- a/core/src/com/unciv/ui/screens/pickerscreens/PromotionPickerScreen.kt +++ b/core/src/com/unciv/ui/screens/pickerscreens/PromotionPickerScreen.kt @@ -15,6 +15,7 @@ import com.unciv.models.ruleset.unit.Promotion import com.unciv.models.translations.tr import com.unciv.ui.audio.SoundPlayer import com.unciv.ui.components.extensions.isEnabled +import com.unciv.ui.components.extensions.toCheckBox import com.unciv.ui.components.extensions.toTextButton import com.unciv.ui.components.input.KeyCharAndCode import com.unciv.ui.components.input.KeyboardBinding @@ -64,6 +65,8 @@ class PromotionPickerScreen private constructor( // Logic private val tree = PromotionTree(unit) + // This if we should save the unit promotion or not. + private var saveUnitTypePromotion = false init { closeButton.onActivation { @@ -77,6 +80,8 @@ class PromotionPickerScreen private constructor( rightSideButton.setText("Pick promotion".tr()) rightSideButton.onClick(UncivSound.Silent) { acceptPromotion(selectedPromotion) + + checkSaveUnitTypePrormotion() } } else { rightSideButton.isVisible = false @@ -191,9 +196,29 @@ class PromotionPickerScreen private constructor( } topTable.add(promotionsTable) + saveUnitTypePromotionForCity() addConnectingLines(emptySet()) } + + // adds the checkBoxs to choice to save unit promotion. + private fun saveUnitTypePromotionForCity() { + val checkBoxSaveUnitPromotion = "Default promotions for [${unit.baseUnit.unitType}]".toCheckBox(saveUnitTypePromotion) {saveUnitTypePromotion = it} + promotionsTable.add(checkBoxSaveUnitPromotion) + } + + // going to reuse this bit of code 2 time so turn it into a funtion + private fun checkSaveUnitTypePrormotion() { + if (!saveUnitTypePromotion) { + val unitCurrentCity = unit.currentTile.getCity() + if (unitCurrentCity != null) { + // If you are clicked the save unitType promotion, you want the next unitType to have the same promotion. + unitCurrentCity.unitTypeShouldUseSavedPromotion.put(unit.baseUnit.unitType,true) + unitCurrentCity.cityUnitTypePromotions.put(unit.baseUnit.unitType,unit.promotions) + } + } + } + private fun getButton(tree: PromotionTree, node: PromotionTree.PromotionNode) : PromotionButton { val isPickable = canPromoteNow && (!node.pathIsAmbiguous || node.distanceToAdopted == 1) && @@ -221,6 +246,7 @@ class PromotionPickerScreen private constructor( if (isPickable) button.onDoubleClick(UncivSound.Silent) { acceptPromotion(button) + checkSaveUnitTypePrormotion() } return button @@ -352,7 +378,6 @@ class PromotionPickerScreen private constructor( } override fun recreate() = recreate(closeOnPick) - fun recreate(closeOnPick: Boolean): BaseScreen { val newScreen = PromotionPickerScreen(unit, closeOnPick, originalName, onChange) newScreen.setScrollY(scrollPane.scrollY)