diff --git a/core/src/com/unciv/logic/city/CityConstructions.kt b/core/src/com/unciv/logic/city/CityConstructions.kt index 6faa62ca80..df4b778728 100644 --- a/core/src/com/unciv/logic/city/CityConstructions.kt +++ b/core/src/com/unciv/logic/city/CityConstructions.kt @@ -33,6 +33,7 @@ import com.unciv.models.translations.tr import com.unciv.ui.components.fonts.Fonts import com.unciv.ui.screens.civilopediascreen.CivilopediaCategories import com.unciv.ui.screens.civilopediascreen.FormattedLine +import com.unciv.ui.screens.pickerscreens.PromotionTree import com.unciv.utils.withItem import com.unciv.utils.withoutItem import kotlin.math.ceil @@ -465,20 +466,36 @@ class CityConstructions : IsPartOfGameInfoSerialization { 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. + /* check if it's true that we should load saved promotion for the unitType, + Then check if the player want to rebuild the unit the saved promotion, + and do a null check. + and finally check if the current unit has enough XP. */ + val possiblePromotions = hashSetOf() + + // to get promotion in order from nodes + val prmotionTreeOrder = mutableSetOf() + + /* Added all the possible Prmotion that the unit can be promoted, + to avoid edge case where upgrading a scout to spearman + whould give the rest of the spearman the "ignore terrain cost" promotion + when built with auto promotion. */ + for (promotion in PromotionTree(unit).possiblePromotions) possiblePromotions.add(promotion.name) + for (roots in PromotionTree(unit).allNodes()) prmotionTreeOrder.add(roots.promotion.name) + val savedPromotion = city.unitToPromotions[unit.baseUnit.name] + if (city.unitShouldUseSavedPromotion[unit.baseUnit.name] == true && savedPromotion != null && unit.promotions.XP >= savedPromotion.XP) { - // sorting it to avoid getting Accuracy III before Accuracy I - for (promotions in savedPromotion.promotions.sorted()) { - if (unit.promotions.XP >= savedPromotion.XP) { - unit.promotions.addPromotion(promotions) - } else { - break - } + // this variable is the filted promotion from savedPrmotion to only get promotion that are possible for this unit. + val possiblePromotionFilted = savedPromotion.promotions.filter { it in possiblePromotions } + // sort in order to avoid getting Accuracy III before Accuracy I + for (promotions in prmotionTreeOrder) { + // check if here is enough XP for the next promotion + if (unit.promotions.XP-unit.promotions.xpForNextPromotion() >= 0) { + if (promotions in possiblePromotionFilted) unit.promotions.addPromotion(promotions) + } else { + break + } } } } diff --git a/core/src/com/unciv/logic/city/managers/CityConquestFunctions.kt b/core/src/com/unciv/logic/city/managers/CityConquestFunctions.kt index 5dc4f90275..95be16308f 100644 --- a/core/src/com/unciv/logic/city/managers/CityConquestFunctions.kt +++ b/core/src/com/unciv/logic/city/managers/CityConquestFunctions.kt @@ -11,6 +11,7 @@ import com.unciv.logic.civilization.NotificationCategory import com.unciv.logic.civilization.NotificationIcon import com.unciv.logic.civilization.diplomacy.DiplomaticModifiers import com.unciv.logic.civilization.diplomacy.DiplomaticStatus +import com.unciv.logic.map.mapunit.UnitPromotions import com.unciv.logic.trade.TradeLogic import com.unciv.logic.trade.TradeOffer import com.unciv.logic.trade.TradeOfferType @@ -48,6 +49,11 @@ class CityConquestFunctions(val city: City) { } } } + + private fun removeAutoPromotion() { + city.unitShouldUseSavedPromotion = HashMap() + city.unitToPromotions = HashMap() + } private fun removeBuildingsOnMoveToCiv() { // Remove all buildings provided for free to this city @@ -275,6 +281,9 @@ class CityConquestFunctions(val city: City) { // Remove their free buildings from this city and remove free buildings provided by the city from their cities removeBuildingsOnMoveToCiv() + + // Remove auto promotion from city that is being moved + removeAutoPromotion() // catch-all - should ideally not happen as we catch the individual cases with an appropriate notification city.espionage.removeAllPresentSpies(SpyFleeReason.Other) diff --git a/core/src/com/unciv/ui/screens/pickerscreens/PromotionPickerScreen.kt b/core/src/com/unciv/ui/screens/pickerscreens/PromotionPickerScreen.kt index 55e9042211..8da42b4f64 100644 --- a/core/src/com/unciv/ui/screens/pickerscreens/PromotionPickerScreen.kt +++ b/core/src/com/unciv/ui/screens/pickerscreens/PromotionPickerScreen.kt @@ -200,7 +200,11 @@ class PromotionPickerScreen private constructor( // adds the checkBoxs to choice to save unit promotion. private fun saveUnitTypePromotionForCity() { // if you are not in a city tile then don't show up - if (unit.currentTile.getCity() == null) return + // then player should not be able to save promotion in enermy tiles/puppet citys + // even their own because you can't build any unit there. + val currentCity = unit.currentTile.getCity() ?: return + if (currentCity.civ.civName != unit.civ.civName) return + if (currentCity.isPuppet) return val checkBoxSaveUnitPromotion = "Default promotions for [${unit.baseUnit.name}]".toCheckBox(saveUnitTypePromotion) {saveUnitTypePromotion = it} promotionsTable.add(checkBoxSaveUnitPromotion) } @@ -208,7 +212,6 @@ class PromotionPickerScreen private constructor( // going to reuse this bit of code 2 time so turn it into a funtion private fun checkSaveUnitTypePrormotion() { if (!saveUnitTypePromotion) return - val unitCurrentCity = unit.currentTile.getCity() if (unitCurrentCity != null) { // If you are clicked the save baseUnit promotion, you want the next baseUnit to have the same promotion.