diff --git a/android/assets/jsons/Civ V - Gods & Kings/Nations.json b/android/assets/jsons/Civ V - Gods & Kings/Nations.json index 230f6e5fa5..afd7727ab3 100644 --- a/android/assets/jsons/Civ V - Gods & Kings/Nations.json +++ b/android/assets/jsons/Civ V - Gods & Kings/Nations.json @@ -301,7 +301,7 @@ "innerColor": [185,0,0], "favoredReligion": "Shinto", "uniqueName": "Bushido", - "uniques": ["Units fight as though they were at full strength even when damaged"], + "uniques": ["Damage is ignored when determining unit Strength "], "cities": ["Kyoto","Osaka","Tokyo","Satsuma","Kagoshima","Nara","Nagoya","Izumo","Nagasaki","Yokohama", "Shimonoseki","Matsuyama","Sapporo","Hakodate","Ise","Toyama","Fukushima","Suo","Bizen","Echizen", "Izumi","Omi","Echigo","Kozuke","Sado","Kobe","Nagano","Hiroshima","Takayama","Akita","Fukuoka","Aomori", @@ -351,7 +351,7 @@ "innerColor": [60,60,60], "favoredReligion": "Christianity", "uniqueName": "Furor Teutonicus", - "uniques": ["67% chance to earn 25 Gold and recruit a Barbarian unit from a conquered encampment", + "uniques": ["When conquering an encampment, earn [25] Gold and recruit a Barbarian unit ", "[-25]% maintenance costs "], "cities": ["Berlin","Hamburg","Munich","Cologne","Frankfurt","Essen","Dortmund","Stuttgart","Düsseldorf","Bremen", "Hannover","Duisburg","Leipzig","Dresden","Bonn","Bochum","Bielefeld","Karlsruhe","Gelsenkirchen","Wiesbaden", @@ -382,7 +382,7 @@ "favoredReligion": "Islam", "uniqueName": "Barbary Corsairs", "uniques": ["[-66]% maintenance costs ", - "50% chance of capturing defeated Barbarian naval units and earning 25 Gold"], + "When defeating a [{Barbarian} {Water}] unit, earn [25] Gold and recruit it "], "cities": ["Istanbul","Edirne","Ankara","Bursa","Konya","Samsun","Gaziantep","Diyarbakır","Izmir","Kayseri","Malatya", "Mersin","Antalya","Zonguldak","Denizli","Ordu","Muğla","Eskişehir","Inebolu","Sinop","Adana","Artvin", "Bodrum","Eregli","Silifke","Sivas","Amasya","Marmaris","Trabzon","Erzurum","Urfa","Izmit","Afyonkarahisar", @@ -489,7 +489,7 @@ "innerColor": [255,255,78], "favoredReligion": "Christianity", "uniqueName": "Wayfinding", - "uniques": ["Enables embarkation for land units ", "Enables [All] units to enter ocean tiles ", "Normal vision when embarked ", "+[10]% Strength if within [2] tiles of a [Moai]"], + "uniques": ["Enables embarkation for land units ", "Enables [All] units to enter ocean tiles ", "Normal vision when embarked ", "[+10]% Strength "], "cities": ["Honolulu","Samoa","Tonga","Nuku Hiva","Raiatea","Aotearoa","Tahiti","Hilo","Te Wai Pounamu","Rapa Nui", "Tuamotu","Rarotonga","Tuvalu","Tubuai","Mangareva","Oahu","Kiritimati","Ontong Java","Niue","Rekohu", "Rakahanga","Bora Bora","Kailua","Uvea","Futuna","Rotuma","Tokelau","Lahaina","Bellona","Mungava","Tikopia", diff --git a/android/assets/jsons/Civ V - Vanilla/Nations.json b/android/assets/jsons/Civ V - Vanilla/Nations.json index a3ed09d4cc..d5e813a6d8 100644 --- a/android/assets/jsons/Civ V - Vanilla/Nations.json +++ b/android/assets/jsons/Civ V - Vanilla/Nations.json @@ -290,7 +290,7 @@ "outerColor": [215,225,225], "innerColor": [185,0,0], "uniqueName": "Bushido", - "uniques": ["Units fight as though they were at full strength even when damaged"], + "uniques": ["Damage is ignored when determining unit Strength "], "cities": ["Kyoto","Osaka","Tokyo","Satsuma","Kagoshima","Nara","Nagoya","Izumo","Nagasaki","Yokohama", "Shimonoseki","Matsuyama","Sapporo","Hakodate","Ise","Toyama","Fukushima","Suo","Bizen","Echizen", "Izumi","Omi","Echigo","Kozuke","Sado","Kobe","Nagano","Hiroshima","Takayama","Akita","Fukuoka","Aomori", @@ -336,7 +336,7 @@ "outerColor": [150,150,150], "innerColor": [60,60,60], "uniqueName": "Furor Teutonicus", - "uniques": ["67% chance to earn 25 Gold and recruit a Barbarian unit from a conquered encampment", + "uniques": ["When conquering an encampment, earn [25] Gold and recruit a Barbarian unit ", "[-25]% maintenance costs "], "cities": ["Berlin","Hamburg","Munich","Cologne","Frankfurt","Essen","Dortmund","Stuttgart","Düsseldorf","Bremen", "Hannover","Duisburg","Leipzig","Dresden","Bonn","Bochum","Bielefeld","Karlsruhe","Gelsenkirchen","Wiesbaden", @@ -366,7 +366,7 @@ "innerColor": [18,84,30], "uniqueName": "Barbary Corsairs", "uniques": ["[-66]% maintenance costs ", - "50% chance of capturing defeated Barbarian naval units and earning 25 Gold"], + "When defeating a [{Barbarian} {Water}] unit, earn [25] Gold and recruit it "], "cities": ["Istanbul","Edirne","Ankara","Bursa","Konya","Samsun","Gaziantep","Diyarbakır","Izmir","Kayseri","Malatya", "Mersin","Antalya","Zonguldak","Denizli","Ordu","Muğla","Eskişehir","Inebolu","Sinop","Adana","Artvin", "Bodrum","Eregli","Silifke","Sivas","Amasya","Marmaris","Trabzon","Erzurum","Urfa","Izmit","Afyonkarahisar", @@ -469,7 +469,7 @@ "outerColor": [225,105,0], "innerColor": [255,255,78], "uniqueName": "Wayfinding", - "uniques": ["Enables embarkation for land units ", "Enables [All] units to enter ocean tiles ", "Normal vision when embarked ", "+[10]% Strength if within [2] tiles of a [Moai]"], + "uniques": ["Enables embarkation for land units ", "Enables [All] units to enter ocean tiles ", "Normal vision when embarked ", "[+10]% Strength "], "cities": ["Honolulu","Samoa","Tonga","Nuku Hiva","Raiatea","Aotearoa","Tahiti","Hilo","Te Wai Pounamu","Rapa Nui", "Tuamotu","Rarotonga","Tuvalu","Tubuai","Mangareva","Oahu","Kiritimati","Ontong Java","Niue","Rekohu", "Rakahanga","Bora Bora","Kailua","Uvea","Futuna","Rotuma","Tokelau","Lahaina","Bellona","Mungava","Tikopia", diff --git a/android/assets/jsons/translations/template.properties b/android/assets/jsons/translations/template.properties index ef0c75173b..2684bf206f 100644 --- a/android/assets/jsons/translations/template.properties +++ b/android/assets/jsons/translations/template.properties @@ -633,6 +633,7 @@ Your [ourUnit] captured an enemy [theirUnit]! = Your [ourUnit] plundered [amount] [Stat] from [theirUnit] = We have captured a barbarian encampment and recovered [goldAmount] gold! = A barbarian [unitType] has joined us! = +We have captured an enemy [unitType]! = We have found survivors in the ruins - population added to [cityName] = We have discovered cultural artifacts in the ruins! (+20 Culture) = We have discovered the lost technology of [techName] in the ruins! = diff --git a/core/src/com/unciv/logic/battle/Battle.kt b/core/src/com/unciv/logic/battle/Battle.kt index 251a2ab438..11f12fee6c 100644 --- a/core/src/com/unciv/logic/battle/Battle.kt +++ b/core/src/com/unciv/logic/battle/Battle.kt @@ -94,8 +94,11 @@ object Battle { if (!captureMilitaryUnitSuccess) // capture creates a new unit, but `defender` still is the original, so this function would still show a kill message postBattleNotifications(attacker, defender, attackedTile, attacker.getTile()) + if (defender.getCivInfo().isBarbarian() && attackedTile.improvement == Constants.barbarianEncampment) + defender.getCivInfo().gameInfo.barbarians.campAttacked(attackedTile.position) + postBattleNationUniques(defender, attackedTile, attacker) - + // This needs to come BEFORE the move-to-tile, because if we haven't conquered it we can't move there =) if (defender.isDefeated() && defender is CityCombatant && attacker is MapUnitCombatant && attacker.isMelee() && !attacker.unit.hasUnique(UniqueType.CannotCaptureCities)) { @@ -206,21 +209,7 @@ object Battle { // This is called after takeDamage and so the defeated defender is already destroyed and // thus removed from the tile - but MapUnit.destroy() will not clear the unit's currentTile. // Therefore placeUnitNearTile _will_ place the new unit exactly where the defender was - val defenderName = defender.getName() - val newUnit = attacker.getCivInfo().placeUnitNearTile(defender.getTile().position, defenderName) - ?: return false // silently fail - - attacker.getCivInfo().addNotification( - "Your [${attacker.getName()}] captured an enemy [$defenderName]", - newUnit.getTile().position, attacker.getName(), NotificationIcon.War, defenderName ) - - // Also capture any civilians on the same tile - if (newUnit.currentTile.civilianUnit != null) - captureCivilianUnit(attacker, MapUnitCombatant(newUnit.currentTile.civilianUnit!!)) - - newUnit.currentMovement = 0f - newUnit.health = 50 - return true + return spawnCapturedUnit(defender.getName(), attacker, defender.getTile(), "Your [${attacker.getName()}] captured an enemy [${defender.getName()}]!") } private fun takeDamage(attacker: ICombatant, defender: ICombatant) { @@ -325,38 +314,71 @@ object Battle { attacker.unit.healBy(amountToHeal) } } + + /** Places a [unitName] unit near [tile] after being attacked by [attacker]. + * Adds a notification to [attacker]'s civInfo and returns whether the captured unit could be placed */ + private fun spawnCapturedUnit(unitName: String, attacker: ICombatant, tile: TileInfo, notification: String): Boolean { + val addedUnit = attacker.getCivInfo().placeUnitNearTile(tile.position, unitName) ?: return false + addedUnit.currentMovement = 0f + addedUnit.health = 50 + attacker.getCivInfo().addNotification(notification, addedUnit.getTile().position, attacker.getName(), unitName) + // Also capture any civilians on the same tile + if (tile.civilianUnit != null) + captureCivilianUnit(attacker, MapUnitCombatant(tile.civilianUnit!!)) + return true + } private fun postBattleNationUniques(defender: ICombatant, attackedTile: TileInfo, attacker: ICombatant) { - + if (!defender.isDefeated()) return + // Barbarians reduce spawn countdown after their camp was attacked "kicking the hornet's nest" if (defender.getCivInfo().isBarbarian() && attackedTile.improvement == Constants.barbarianEncampment) { - defender.getCivInfo().gameInfo.barbarians.campAttacked(attackedTile.position) - + var unitPlaced = false // German unique - needs to be checked before we try to move to the enemy tile, since the encampment disappears after we move in - if (defender.isDefeated() - && attacker.getCivInfo().hasUnique(UniqueType.ChanceToRecruitBarbarianFromEncampment) - && Random().nextDouble() < 0.67) { - attacker.getCivInfo().placeUnitNearTile(attackedTile.position, defender.getName()) - attacker.getCivInfo().addGold(25) - attacker.getCivInfo().addNotification("A barbarian [${defender.getName()}] has joined us!", attackedTile.position, defender.getName()) - // Also capture any civilians on the same tile - if (attackedTile.civilianUnit != null) - captureCivilianUnit(attacker, MapUnitCombatant(attackedTile.civilianUnit!!)) + // Deprecated as of 4.0.3 + if (attacker.getCivInfo().hasUnique(UniqueType.ChanceToRecruitBarbarianFromEncampment) + && Random().nextDouble() < 0.67 + ) { + attacker.getCivInfo().addGold(25) + unitPlaced = spawnCapturedUnit(defender.getName(), attacker, attackedTile,"A barbarian [${defender.getName()}] has joined us!") + } + + // New version of unique + // + for (unique in attacker.getCivInfo().getMatchingUniques(UniqueType.GainFromEncampment)) { + attacker.getCivInfo().addGold(unique.params[0].toInt()) + if (unitPlaced) continue + unitPlaced = spawnCapturedUnit(defender.getName(), attacker, attackedTile,"A barbarian [${defender.getName()}] has joined us!") } } - + // Similarly, Ottoman unique - if (attacker.getCivInfo().hasUnique(UniqueType.ChanceToRecruitNavalBarbarian) - && defender.isDefeated() - && defender is MapUnitCombatant - && defender.unit.baseUnit.isWaterUnit() - && defender.getCivInfo().isBarbarian() - && attacker.isMelee() - && attacker is MapUnitCombatant - && attacker.unit.baseUnit.isWaterUnit() - && Random().nextDouble() > 0.5) { - attacker.getCivInfo().placeUnitNearTile(attackedTile.position, defender.getName()) - attacker.getCivInfo().addGold(25) + // Deprecated as of 4.0.3 + if (attacker.getCivInfo().hasUnique(UniqueType.ChanceToRecruitNavalBarbarian) + && defender.isDefeated() + && defender is MapUnitCombatant + && defender.unit.baseUnit.isWaterUnit() + && defender.getCivInfo().isBarbarian() + && attacker.isMelee() + && attacker is MapUnitCombatant + && attacker.unit.baseUnit.isWaterUnit() + && Random().nextDouble() < 0.5) { + attacker.getCivInfo().addGold(25) + spawnCapturedUnit(defender.getName(), attacker, attackedTile, "We have captured an enemy [${defender.getName()}]!") + } + // + if (defender.isDefeated() && defender is MapUnitCombatant) { + var unitPlaced = false + for (unique in attacker.getCivInfo().getMatchingUniques(UniqueType.GainFromDefeatingUnit)) { + if (defender.unit.matchesFilter(unique.params[0]) + && attacker.isMelee() + ) { + attacker.getCivInfo().addGold(unique.params[1].toInt()) + if (unitPlaced) continue + unitPlaced = spawnCapturedUnit(defender.getName(), attacker, attackedTile, "We have captured an enemy [${defender.getName()}]!") + + } + } } } diff --git a/core/src/com/unciv/logic/battle/BattleDamage.kt b/core/src/com/unciv/logic/battle/BattleDamage.kt index 508687b4ee..0aa2ac6b55 100644 --- a/core/src/com/unciv/logic/battle/BattleDamage.kt +++ b/core/src/com/unciv/logic/battle/BattleDamage.kt @@ -206,6 +206,7 @@ object BattleDamage { return modifiers } + @Deprecated("As of 4.0.3", level=DeprecationLevel.WARNING) private fun getTileSpecificModifiers(unit: MapUnitCombatant, tile: TileInfo): Counter { val modifiers = Counter() @@ -226,14 +227,14 @@ object BattleDamage { } private fun getHealthDependantDamageRatio(combatant: ICombatant): Float { - return if (combatant !is MapUnitCombatant // is city - || (combatant.getCivInfo().hasUnique(UniqueType.UnitsFightFullStrengthWhenDamaged) - && !combatant.unit.baseUnit.movesLikeAirUnits() - ) + return if (combatant !is MapUnitCombatant + || combatant.unit.hasUnique(UniqueType.NoDamagePenalty, checkCivInfoUniques = true) + || combatant.getCivInfo().hasUnique(UniqueType.UnitsFightFullStrengthWhenDamaged) ) { 1f } - else 1 - (100 - combatant.getHealth()) / 300f// Each 3 points of health reduces damage dealt by 1% like original game + // Each 3 points of health reduces damage dealt by 1% + else 1 - (100 - combatant.getHealth()) / 300f } diff --git a/core/src/com/unciv/logic/civilization/ReligionManager.kt b/core/src/com/unciv/logic/civilization/ReligionManager.kt index 05d08d7be9..a72ccdbc54 100644 --- a/core/src/com/unciv/logic/civilization/ReligionManager.kt +++ b/core/src/com/unciv/logic/civilization/ReligionManager.kt @@ -119,7 +119,7 @@ class ReligionManager { if (getGreatProphetEquivalent() == null) return false if (storedFaith < faithForNextGreatProphet()) return false if (!civInfo.isMajorCiv()) return false - if (civInfo.hasUnique(UniqueType.MAyNotGenerateGreatProphet)) return false + if (civInfo.hasUnique(UniqueType.MayNotGenerateGreatProphet)) return false return true } diff --git a/core/src/com/unciv/logic/map/TileInfo.kt b/core/src/com/unciv/logic/map/TileInfo.kt index 37b8a15571..fd6a9205a2 100644 --- a/core/src/com/unciv/logic/map/TileInfo.kt +++ b/core/src/com/unciv/logic/map/TileInfo.kt @@ -466,13 +466,12 @@ open class TileInfo { improvement.techRequired != null && !civInfo.tech.isResearched(improvement.techRequired!!) -> false getOwner() != civInfo && !( improvement.hasUnique(UniqueType.CanBuildOutsideBorders) - || ( // citadel can be built only next to or within own borders - improvement.hasUnique(UniqueType.CanBuildJustOutsideBorders) - && neighbors.any { it.getOwner() == civInfo } && civInfo.cities.isNotEmpty() - ) + || ( // citadel can be built only next to or within own borders + improvement.hasUnique(UniqueType.CanBuildJustOutsideBorders) + && neighbors.any { it.getOwner() == civInfo } + ) ) -> false - improvement.uniqueObjects.filter { it.type == UniqueType.OnlyAvailableWhen } - .any { !it.conditionalsApply(StateForConditionals(civInfo)) } -> false + improvement.hasUnique(UniqueType.OnlyAvailableWhen, StateForConditionals(civInfo=civInfo, tile=this)) -> false improvement.getMatchingUniques(UniqueType.ObsoleteWith).any { civInfo.tech.isResearched(it.params[0]) } -> return false diff --git a/core/src/com/unciv/models/ruleset/unique/Unique.kt b/core/src/com/unciv/models/ruleset/unique/Unique.kt index cd798c78e3..e356de2107 100644 --- a/core/src/com/unciv/models/ruleset/unique/Unique.kt +++ b/core/src/com/unciv/models/ruleset/unique/Unique.kt @@ -11,6 +11,7 @@ import com.unciv.models.ruleset.Ruleset import java.util.* import kotlin.collections.ArrayList import kotlin.collections.HashMap +import kotlin.random.Random class Unique(val text: String, val sourceObjectType: UniqueTarget? = null, val sourceObjectName: String? = null) { @@ -131,12 +132,16 @@ class Unique(val text: String, val sourceObjectType: UniqueTarget? = null, val s if (state.ourCombatant != null && state.ourCombatant is MapUnitCombatant) state.ourCombatant.unit else state.unit } + + val stateBasedRandom by lazy { Random(state.hashCode()) } return when (condition.type) { // These are 'what to do' and not 'when to do' conditionals UniqueType.ConditionalTimedUnique -> true UniqueType.ConditionalConsumeUnit -> true + UniqueType.ConditionalChance -> stateBasedRandom.nextFloat() < condition.params[0].toFloat() / 100f + UniqueType.ConditionalWar -> state.civInfo?.isAtWar() == true UniqueType.ConditionalNotWar -> state.civInfo?.isAtWar() == false UniqueType.ConditionalWithResource -> state.civInfo?.hasResource(condition.params[0]) == true @@ -200,8 +205,13 @@ class Unique(val text: String, val sourceObjectType: UniqueTarget? = null, val s UniqueType.ConditionalFightingInTiles -> state.attackedTile?.matchesFilter(condition.params[0], state.civInfo) == true UniqueType.ConditionalInTilesAnd -> - relevantTile!=null && relevantTile!!.matchesFilter(condition.params[0], state.civInfo) + relevantTile != null && relevantTile!!.matchesFilter(condition.params[0], state.civInfo) && relevantTile!!.matchesFilter(condition.params[1], state.civInfo) + UniqueType.ConditionalNearTiles -> + relevantTile != null && relevantTile!!.getTilesInDistance(condition.params[0].toInt()).any { + it.matchesFilter(condition.params[1]) + } + UniqueType.ConditionalVsLargerCiv -> { val yourCities = state.civInfo?.cities?.size ?: 1 val theirCities = state.theirCombatant?.getCivInfo()?.cities?.size ?: 0 diff --git a/core/src/com/unciv/models/ruleset/unique/UniqueType.kt b/core/src/com/unciv/models/ruleset/unique/UniqueType.kt index 9c93ad4f8d..406506bc98 100644 --- a/core/src/com/unciv/models/ruleset/unique/UniqueType.kt +++ b/core/src/com/unciv/models/ruleset/unique/UniqueType.kt @@ -223,14 +223,19 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: // Misc national uniques NotifiedOfBarbarianEncampments("Notified of new Barbarian encampments", UniqueTarget.Global), BorrowsCityNames("\"Borrows\" city names from other civilizations in the game", UniqueTarget.Global), + @Deprecated("as of 4.0.3", ReplaceWith("Damage is ignored when determining unit Strength ")) UnitsFightFullStrengthWhenDamaged("Units fight as though they were at full strength even when damaged", UniqueTarget.Global), GoldWhenDiscoveringNaturalWonder("100 Gold for discovering a Natural Wonder (bonus enhanced to 500 Gold if first to discover it)", UniqueTarget.Global), UnhappinessFromCitiesDoubled("Unhappiness from number of Cities doubled", UniqueTarget.Global), GreatGeneralProvidesDoubleCombatBonus("Great General provides double combat bonus", UniqueTarget.Global), TechBoostWhenScientificBuildingsBuiltInCapital("Receive a tech boost when scientific buildings/wonders are built in capital", UniqueTarget.Global), - MAyNotGenerateGreatProphet("May not generate great prophet equivalents naturally", UniqueTarget.Global), + MayNotGenerateGreatProphet("May not generate great prophet equivalents naturally", UniqueTarget.Global), + @Deprecated("as of 4.0.3", ReplaceWith("When conquering an encampment, earn [25] Gold and recruit a Barbarian unit ")) ChanceToRecruitBarbarianFromEncampment("67% chance to earn 25 Gold and recruit a Barbarian unit from a conquered encampment", UniqueTarget.Global), + GainFromEncampment("When conquering an encampment, earn [amount] Gold and recruit a Barbarian unit", UniqueTarget.Global), + @Deprecated("as of 4.0.3", ReplaceWith("When defeating a [{Barbarian} {Water}] unit, earn [25] Gold and recruit it ")) ChanceToRecruitNavalBarbarian("50% chance of capturing defeated Barbarian naval units and earning 25 Gold", UniqueTarget.Global), + GainFromDefeatingUnit("When defeating a [mapUnitFilter] unit, earn [amount] Gold and recruit it", UniqueTarget.Global), TripleGoldFromEncampmentsAndCities("Receive triple Gold from Barbarian encampments and pillaging Cities", UniqueTarget.Global), CitiesAreRazedXTimesFaster("Cities are razed [amount] times as fast", UniqueTarget.Global), GreatPersonBoostWithFriendship("When declaring friendship, both parties gain a [amount]% boost to great person generation", UniqueTarget.Global), @@ -240,8 +245,8 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: GainInfluenceWithUnitGiftToCityState("Gain [amount] Influence with a [baseUnitFilter] gift to a City-State", UniqueTarget.Global), FaithCostOfGreatProphetChange("[amount]% Faith cost of generating Great Prophet equivalents", UniqueTarget.Global), RestingPointOfCityStatesFollowingReligionChange("Resting point for Influence with City-States following this religion [amount]", UniqueTarget.Global), - // Todo can be replaced with a conditional - StrengthWithinTilesOfTile("+[amount]% Strength if within [amount] tiles of a [tileFilter]", UniqueTarget.Global), + @Deprecated("as of 4.0.3", ReplaceWith("[+amount]% Strength ")) + StrengthWithinTilesOfTile("+[amount]% Strength if within [amount2] tiles of a [tileFilter]", UniqueTarget.Global), StatBonusPercentFromCityStates("[amount]% [stat] from City-States", UniqueTarget.Global), ProvidesGoldWheneverGreatPersonExpended("Provides a sum of gold each time you spend a Great Person", UniqueTarget.Global), @@ -420,6 +425,7 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: NoDefensiveTerrainBonus("No defensive terrain bonus", UniqueTarget.Unit, UniqueTarget.Global), NoDefensiveTerrainPenalty("No defensive terrain penalty", UniqueTarget.Unit, UniqueTarget.Global), + NoDamagePenalty("Damage is ignored when determining unit Strength", UniqueTarget.Unit, UniqueTarget.Global), Uncapturable("Uncapturable", UniqueTarget.Unit), MayWithdraw("May withdraw before melee ([amount]%)", UniqueTarget.Unit), CannotCaptureCities("Unable to capture cities", UniqueTarget.Unit), @@ -437,6 +443,7 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: NormalVisionWhenEmbarked("Normal vision when embarked", UniqueTarget.Unit, UniqueTarget.Global), DefenceBonusWhenEmbarked("Defense bonus when embarked", UniqueTarget.Unit, UniqueTarget.Global), + @Deprecated("as of 4.0.3", ReplaceWith("Defense bonus when embarked ")) DefenceBonusWhenEmbarkedCivwide("Embarked units can defend themselves", UniqueTarget.Global), @Deprecated("as of 3.19.8", ReplaceWith("Eliminates combat penalty for attacking across a coast")) AttackFromSea("Eliminates combat penalty for attacking from the sea", UniqueTarget.Unit), @@ -586,6 +593,11 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: ///////////////////////////////////////// region CONDITIONALS ///////////////////////////////////////// + /////// general conditionals + ConditionalTimedUnique("for [amount] turns", UniqueTarget.Conditional), + ConditionalConsumeUnit("by consuming this unit", UniqueTarget.Conditional), + ConditionalChance("with [amount]% chance", UniqueTarget.Conditional), + /////// civ conditionals ConditionalWar("when at war", UniqueTarget.Conditional), ConditionalNotWar("when not at war", UniqueTarget.Conditional), @@ -608,9 +620,6 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: ConditionalNoPolicy("before adopting [policy]", UniqueTarget.Conditional), ConditionalBuildingBuilt("if [buildingName] is constructed", UniqueTarget.Conditional), - ConditionalTimedUnique("for [amount] turns", UniqueTarget.Conditional), - ConditionalConsumeUnit("by consuming this unit", UniqueTarget.Conditional), - /////// city conditionals ConditionalCityWithBuilding("in cities with a [buildingFilter]", UniqueTarget.Conditional), ConditionalCityWithoutBuilding("in cities without a [buildingFilter]", UniqueTarget.Conditional), @@ -642,6 +651,7 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: ConditionalInTiles("in [tileFilter] tiles", UniqueTarget.Conditional), ConditionalInTilesAnd("in [tileFilter] [tileFilter] tiles", UniqueTarget.Conditional), ConditionalInTilesNot("in tiles without [tileFilter]", UniqueTarget.Conditional), + ConditionalNearTiles("within [amount] tiles of a [tileFilter]", UniqueTarget.Conditional), /////// area conditionals ConditionalOnWaterMaps("on water maps", UniqueTarget.Conditional), @@ -682,7 +692,6 @@ enum class UniqueType(val text: String, vararg targets: UniqueTarget, val flags: OneTimeUnitGainPromotion("This Unit gains the [promotion] promotion", UniqueTarget.Triggerable), // Not used in Vanilla UnitsGainPromotion("[mapUnitFilter] units gain the [promotion] promotion", UniqueTarget.Triggerable), // Not used in Vanilla - // todo: remove forced sign @Deprecated("as of 3.19.8", ReplaceWith("[+amount]% Strength ")) TimedAttackStrength("+[amount]% attack strength to all [mapUnitFilter] units for [amount2] turns", UniqueTarget.Global), // used in Policy FreeStatBuildings("Provides the cheapest [stat] building in your first [amount] cities for free", UniqueTarget.Triggerable), // used in Policy diff --git a/docs/Modders/uniques.md b/docs/Modders/uniques.md index 596df05c8a..7889466c52 100644 --- a/docs/Modders/uniques.md +++ b/docs/Modders/uniques.md @@ -441,9 +441,6 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl ??? example ""Borrows" city names from other civilizations in the game" Applicable to: Global -??? example "Units fight as though they were at full strength even when damaged" - Applicable to: Global - ??? example "100 Gold for discovering a Natural Wonder (bonus enhanced to 500 Gold if first to discover it)" Applicable to: Global @@ -459,10 +456,14 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl ??? example "May not generate great prophet equivalents naturally" Applicable to: Global -??? example "67% chance to earn 25 Gold and recruit a Barbarian unit from a conquered encampment" +??? example "When conquering an encampment, earn [amount] Gold and recruit a Barbarian unit" + Example: "When conquering an encampment, earn [20] Gold and recruit a Barbarian unit" + Applicable to: Global -??? example "50% chance of capturing defeated Barbarian naval units and earning 25 Gold" +??? example "When defeating a [mapUnitFilter] unit, earn [amount] Gold and recruit it" + Example: "When defeating a [Wounded] unit, earn [20] Gold and recruit it" + Applicable to: Global ??? example "Receive triple Gold from Barbarian encampments and pillaging Cities" @@ -508,11 +509,6 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl Applicable to: Global -??? example "+[amount]% Strength if within [amount] tiles of a [tileFilter]" - Example: "+[20]% Strength if within [20] tiles of a [Farm]" - - Applicable to: Global - ??? example "[amount]% [stat] from City-States" Example: "[20]% [Culture] from City-States" @@ -689,6 +685,9 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl ??? example "No defensive terrain penalty" Applicable to: Global, Unit +??? example "Damage is ignored when determining unit Strength" + Applicable to: Global, Unit + ??? example "No movement cost to pillage" Applicable to: Global, Unit @@ -712,9 +711,6 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl ??? example "Defense bonus when embarked" Applicable to: Global, Unit -??? example "Embarked units can defend themselves" - Applicable to: Global - ??? example "[amount]% maintenance costs" Example: "[20]% maintenance costs" @@ -1448,6 +1444,19 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl Applicable to: CityState ## Conditional uniques +??? example "<for [amount] turns>" + Example: "<for [20] turns>" + + Applicable to: Conditional + +??? example "<by consuming this unit>" + Applicable to: Conditional + +??? example "<with [amount]% chance>" + Example: "<with [20]% chance>" + + Applicable to: Conditional + ??? example "<when at war>" Applicable to: Conditional @@ -1523,14 +1532,6 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl Applicable to: Conditional -??? example "<for [amount] turns>" - Example: "<for [20] turns>" - - Applicable to: Conditional - -??? example "<by consuming this unit>" - Applicable to: Conditional - ??? example "<in cities with a [buildingFilter]>" Example: "<in cities with a [Culture]>" @@ -1629,6 +1630,11 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl Applicable to: Conditional +??? example "<within [amount] tiles of a [tileFilter]>" + Example: "<within [20] tiles of a [Farm]>" + + Applicable to: Conditional + ??? example "<on water maps>" Applicable to: Conditional diff --git a/gradlew.bat b/gradlew.bat index 107acd32c4..5eb53f8d77 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -33,7 +33,7 @@ set APP_HOME=%DIRNAME% for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" +set DEFAULT_JVM_OPTS="-Xmx4G" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome