Nuke your enemy! (#1318)
* Nuke your enemy! * Fantasy tiles. Worker automaticly clears fallout. * Some AI improvement for choosing wonder and military unit. * Add nuclear weapon option.
BIN
android/Images/BuildingIcons/Manhattan Project.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
android/Images/TileSets/Default/FalloutOverlay.png
Normal file
After Width: | Height: | Size: 9.1 KiB |
BIN
android/Images/TileSets/FantasyHex/Tiles/Desert+Fallout.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
android/Images/TileSets/FantasyHex/Tiles/Grassland+Fallout.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
android/Images/TileSets/FantasyHex/Tiles/Hill+Fallout.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
android/Images/TileSets/FantasyHex/Tiles/Plains+Fallout.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
android/Images/TileSets/FantasyHex/Tiles/Tundra+Fallout.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
android/Images/UnitIcons/Nuclear Missile.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 857 KiB After Width: | Height: | Size: 872 KiB |
Before Width: | Height: | Size: 247 KiB After Width: | Height: | Size: 274 KiB |
@ -359,6 +359,12 @@
|
||||
requiredBuildingInAllCities:"Library",
|
||||
requiredTech:"Civil Service"
|
||||
},
|
||||
{
|
||||
name:"Manhattan Project",
|
||||
isNationalWonder:true,
|
||||
uniques:["Enables nuclear weapon"],
|
||||
requiredTech:"Nuclear Fission"
|
||||
},
|
||||
{
|
||||
name:"Chichen Itza",
|
||||
culture:1,
|
||||
|
@ -111,6 +111,16 @@
|
||||
defenceBonus: -0.1,
|
||||
occursOn:["Grassland"]
|
||||
},
|
||||
{
|
||||
name:"Fallout",
|
||||
type:"TerrainFeature",
|
||||
food:-3,
|
||||
production:-3,
|
||||
gold:-3,
|
||||
movementCost:2,
|
||||
unbuildable:true,
|
||||
defenceBonus: -0.15,
|
||||
},
|
||||
{
|
||||
name:"Oasis",
|
||||
type:"TerrainFeature",
|
||||
|
@ -104,13 +104,19 @@
|
||||
terrainsCanBeBuiltOn:["Jungle"],
|
||||
techRequired:"Bronze Working"
|
||||
},
|
||||
{
|
||||
name:"Remove Fallout",
|
||||
turnsToBuild:8,
|
||||
terrainsCanBeBuiltOn:["Fallout"],
|
||||
techRequired:"Agriculture"
|
||||
},
|
||||
{
|
||||
name:"Remove Marsh",
|
||||
turnsToBuild:6,
|
||||
terrainsCanBeBuiltOn:["Marsh"],
|
||||
techRequired:"Bronze Working"
|
||||
},
|
||||
|
||||
|
||||
// These are unique and have unique in-game checks related to them
|
||||
{
|
||||
name:"Remove Road",
|
||||
|
@ -457,6 +457,8 @@
|
||||
Polish:"Akademia Narodowa"
|
||||
Czech:"Národní Akademie"
|
||||
}
|
||||
"Manhattan Project":{
|
||||
}
|
||||
|
||||
"Chichen Itza":{
|
||||
Italian:"Chichen Itza"
|
||||
@ -496,6 +498,9 @@
|
||||
Czech:"Délka Zlatého věku se prodloužila o 50%"
|
||||
}
|
||||
|
||||
"Enables nuclear weapon":{
|
||||
}
|
||||
|
||||
"Lighthouse":{
|
||||
Spanish:"faro"
|
||||
Italian:"Faro"
|
||||
|
@ -1690,6 +1690,9 @@
|
||||
Ukrainian:"Обстрілювати"
|
||||
}
|
||||
|
||||
"NUKE":{
|
||||
}
|
||||
|
||||
"Captured!":{// Shown in the battle table when attacking a civilian unit
|
||||
Italian:"Cattura!"
|
||||
Russian:"Захвачен!"
|
||||
|
@ -160,6 +160,9 @@
|
||||
Czech:"Bažina"
|
||||
}
|
||||
|
||||
"Fallout":{
|
||||
}
|
||||
|
||||
"Oasis":{
|
||||
Italian:"Oasi"
|
||||
Russian:"Оазис"
|
||||
@ -1040,6 +1043,9 @@
|
||||
Ukrainian:"Висушити болото"
|
||||
}
|
||||
|
||||
"Remove Fallout":{
|
||||
},
|
||||
|
||||
"Ancient ruins":{
|
||||
Italian:"Antiche rovine"
|
||||
Romanian:"Ruine străvechi"
|
||||
|
@ -1291,6 +1291,9 @@
|
||||
Czech:"[percent]% šance zabránit leteckým útokům"
|
||||
}
|
||||
|
||||
"Requires Manhattan Project":{
|
||||
},
|
||||
|
||||
"6 tiles in every direction always visible":{
|
||||
Italian:"6 caselle in ogni direzione sempre visibili"
|
||||
Simplified_Chinese:"全方向6格视野范围"
|
||||
@ -1502,14 +1505,12 @@
|
||||
Italian:"Missile guidato"
|
||||
Czech:"Naváděná střela"
|
||||
}
|
||||
|
||||
*/
|
||||
"Nuclear Missile":{
|
||||
Italian:"Missile nucleare"
|
||||
Czech:"Jaderná raketa"
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
////// Great units
|
||||
|
||||
"Great Artist":{
|
||||
|
@ -1003,6 +1003,19 @@
|
||||
hurryCostModifier:20,
|
||||
attackSound:"shot"
|
||||
},
|
||||
{
|
||||
name:"Nuclear Missile",
|
||||
unitType:"Missile",
|
||||
movement:1,
|
||||
strength:300,
|
||||
rangedStrength:300,
|
||||
range:12,
|
||||
cost: 1000,
|
||||
requiredTech:"Rocketry",
|
||||
requiredResource:"Uranium",
|
||||
uniques:["Requires Manhattan Project"],
|
||||
hurryCostModifier:20,
|
||||
},
|
||||
{
|
||||
name:"Landship",
|
||||
unitType:"Armor",
|
||||
|
@ -93,7 +93,7 @@ class Automation {
|
||||
(it.isCityCenter() && it.getOwner() != city.civInfo)
|
||||
|| (it.militaryUnit != null && it.militaryUnit!!.civInfo != city.civInfo)
|
||||
}) // there is absolutely no reason for you to make water units on this body of water.
|
||||
militaryUnits = militaryUnits.filter { it.unitType.isLandUnit() }
|
||||
militaryUnits = militaryUnits.filter { it.unitType.isLandUnit() || it.unitType.isAirUnit() }
|
||||
|
||||
val chosenUnit: BaseUnit
|
||||
if(!city.civInfo.isAtWar() && city.civInfo.cities.any { it.getCenterTile().militaryUnit==null}
|
||||
|
@ -146,6 +146,10 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
|
||||
if (preferredVictoryType == VictoryType.Scientific) return 1.5f
|
||||
else return 1.3f
|
||||
}
|
||||
if (wonder.name == "Manhattan Project") {
|
||||
if (preferredVictoryType == VictoryType.Domination) return 2f
|
||||
else return 1.3f
|
||||
}
|
||||
if (wonder.isStatRelated(Stat.Happiness)) return 1.2f
|
||||
if (wonder.isStatRelated(Stat.Production)) return 1.1f
|
||||
return 1f
|
||||
|
@ -176,6 +176,7 @@ class WorkerAutomation(val unit: MapUnit) {
|
||||
val improvementStringForResource : String ?= when {
|
||||
tile.resource == null || !tile.hasViewableResource(civInfo) -> null
|
||||
tile.terrainFeature == "Marsh" -> "Remove Marsh"
|
||||
tile.terrainFeature == "Fallout" -> "Remove Fallout"
|
||||
tile.terrainFeature == Constants.jungle -> "Remove Jungle"
|
||||
tile.terrainFeature == Constants.forest && tile.getTileResource().improvement!="Camp" -> "Remove Forest"
|
||||
else -> tile.getTileResource().improvement
|
||||
@ -188,6 +189,7 @@ class WorkerAutomation(val unit: MapUnit) {
|
||||
tile.containsUnfinishedGreatImprovement() -> null
|
||||
tile.terrainFeature == Constants.jungle -> "Trading post"
|
||||
tile.terrainFeature == "Marsh" -> "Remove Marsh"
|
||||
tile.terrainFeature == "Fallout" -> "Remove Fallout"
|
||||
tile.terrainFeature == "Oasis" -> null
|
||||
tile.terrainFeature == Constants.forest -> "Lumber mill"
|
||||
tile.baseTerrain == Constants.hill -> "Mine"
|
||||
|
@ -7,6 +7,7 @@ import com.unciv.logic.automation.UnitAutomation
|
||||
import com.unciv.logic.city.CityInfo
|
||||
import com.unciv.logic.civilization.AlertType
|
||||
import com.unciv.logic.civilization.PopupAlert
|
||||
import com.unciv.logic.map.RoadStatus
|
||||
import com.unciv.logic.map.TileInfo
|
||||
import com.unciv.models.gamebasics.unit.UnitType
|
||||
import java.util.*
|
||||
@ -40,7 +41,10 @@ class Battle(val gameInfo:GameInfo) {
|
||||
var damageToDefender = BattleDamage().calculateDamageToDefender(attacker,defender)
|
||||
var damageToAttacker = BattleDamage().calculateDamageToAttacker(attacker,defender)
|
||||
|
||||
if(defender.getUnitType().isCivilian() && attacker.isMelee()){
|
||||
if (attacker.getUnitType().isMissileUnit()) {
|
||||
nuclearBlast(attacker, defender)
|
||||
}
|
||||
else if(defender.getUnitType().isCivilian() && attacker.isMelee()){
|
||||
captureCivilianUnit(attacker,defender)
|
||||
}
|
||||
else if (attacker.isRanged()) {
|
||||
@ -95,6 +99,15 @@ class Battle(val gameInfo:GameInfo) {
|
||||
if (attacker is MapUnitCombatant && attacker.unit.action != null
|
||||
&& attacker.unit.action!!.startsWith("moveTo"))
|
||||
attacker.unit.action = null
|
||||
|
||||
if (attacker is MapUnitCombatant) {
|
||||
if (attacker.getUnitType().isMissileUnit()) {
|
||||
attacker.unit.destroy()
|
||||
} else if (attacker.unit.action != null
|
||||
&& attacker.unit.action!!.startsWith("moveTo")) {
|
||||
attacker.unit.action = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun postBattleNotifications(attacker: ICombatant, defender: ICombatant, attackedTile: TileInfo) {
|
||||
@ -282,6 +295,30 @@ class Battle(val gameInfo:GameInfo) {
|
||||
capturedUnit.updateVisibleTiles()
|
||||
}
|
||||
|
||||
private fun nuclearBlast(attacker: ICombatant, defender: ICombatant) {
|
||||
for (tile in defender.getTile().getTilesInDistance(2)) {
|
||||
if (tile.isCityCenter()) { //duantao: To Do
|
||||
val city = tile.getCity()!!
|
||||
city.health = 1
|
||||
if (city.population.population <= 5) {
|
||||
city.destroyCity()
|
||||
} else {
|
||||
city.population.population -= 5
|
||||
city.population.unassignExtraPopulation()
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if (tile.militaryUnit != null) tile.militaryUnit!!.destroy()
|
||||
if (tile.civilianUnit != null) tile.civilianUnit!!.destroy()
|
||||
tile.improvement = null
|
||||
tile.improvementInProgress = null
|
||||
tile.turnsToImprovement = 0
|
||||
tile.roadStatus = RoadStatus.None
|
||||
if (tile.isLand) tile.terrainFeature = "Fallout"
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryInterceptAirAttack(attacker:MapUnitCombatant, defender: ICombatant) {
|
||||
val attackedTile = defender.getTile()
|
||||
for (interceptor in defender.getCivInfo().getCivUnits().filter { it.canIntercept(attackedTile) }) {
|
||||
|
@ -189,7 +189,7 @@ class MapGenerator {
|
||||
fun addRandomTerrainFeature(tileInfo: TileInfo) {
|
||||
if (tileInfo.getBaseTerrain().canHaveOverlay && Math.random() > 0.7f) {
|
||||
val secondaryTerrains = GameBasics.Terrains.values
|
||||
.filter { it.type === TerrainType.TerrainFeature && it.occursOn!!.contains(tileInfo.baseTerrain) }
|
||||
.filter { it.type === TerrainType.TerrainFeature && it.occursOn != null && it.occursOn!!.contains(tileInfo.baseTerrain) }
|
||||
if (secondaryTerrains.any()) tileInfo.terrainFeature = secondaryTerrains.random().name
|
||||
}
|
||||
}
|
||||
|
@ -131,6 +131,10 @@ class BaseUnit : INamed, IConstruction {
|
||||
if (obsoleteTech!=null && civInfo.tech.isResearched(obsoleteTech!!)) return "Obsolete by $obsoleteTech"
|
||||
if (uniqueTo!=null && uniqueTo!=civInfo.civName) return "Unique to $uniqueTo"
|
||||
if (GameBasics.Units.values.any { it.uniqueTo==civInfo.civName && it.replaces==name }) return "Our unique unit replaces this"
|
||||
if (!civInfo.gameInfo.gameParameters.nuclearWeaponEnabled
|
||||
&& (name == "Manhattan Project" || uniques.contains("Requires Manhattan Project"))) return "Disabled by setting"
|
||||
if (uniques.contains("Requires Manhattan Project") && !civInfo.containsBuildingUnique("Enables nuclear weapon"))
|
||||
return "Requires Manhattan Project"
|
||||
if (requiredResource!=null && !civInfo.hasResource(requiredResource!!)) return "Requires [$requiredResource]"
|
||||
if (name == Constants.settler && civInfo.isCityState()) return "No settler for city-states"
|
||||
if (name == Constants.settler && civInfo.isOneCityChallenger()) return "No settler for players in One City Challenge"
|
||||
|
@ -16,7 +16,8 @@ enum class UnitType{
|
||||
WaterSubmarine,
|
||||
|
||||
Fighter,
|
||||
Bomber;
|
||||
Bomber,
|
||||
Missile;
|
||||
|
||||
fun isMelee(): Boolean {
|
||||
return this == Melee
|
||||
@ -59,5 +60,10 @@ enum class UnitType{
|
||||
fun isAirUnit():Boolean{
|
||||
return this==Bomber
|
||||
|| this==Fighter
|
||||
|| this==Missile
|
||||
}
|
||||
|
||||
fun isMissileUnit():Boolean{
|
||||
return this == Missile
|
||||
}
|
||||
}
|
@ -17,7 +17,8 @@ class GameParameters { // Default values are the default new game
|
||||
var mapType = MapType.pangaea
|
||||
var noBarbarians = false
|
||||
var oneCityChallenge = false
|
||||
var noRuins = false
|
||||
var nuclearWeaponEnabled = false
|
||||
var noRuins = false;
|
||||
var mapFileName: String? = null
|
||||
var victoryTypes: ArrayList<VictoryType> = VictoryType.values().toCollection(ArrayList()) // By default, all victory types
|
||||
var startingEra = TechEra.Ancient
|
||||
|
@ -160,7 +160,10 @@ class TileEditorOptionsTable(val mapEditorScreen: MapEditorScreen): Table(Camera
|
||||
val terrain = resource.terrainsCanBeFoundOn.first()
|
||||
val terrainObject = GameBasics.Terrains[terrain]!!
|
||||
if (terrainObject.type == TerrainType.TerrainFeature) {
|
||||
tileInfo.baseTerrain = terrainObject.occursOn!!.first()
|
||||
tileInfo.baseTerrain = when {
|
||||
terrainObject.occursOn == null -> terrainObject.occursOn!!.first()
|
||||
else -> "Grassland"
|
||||
}
|
||||
tileInfo.terrainFeature = terrain
|
||||
} else tileInfo.baseTerrain = terrain
|
||||
|
||||
@ -177,7 +180,10 @@ class TileEditorOptionsTable(val mapEditorScreen: MapEditorScreen): Table(Camera
|
||||
for (terrain in GameBasics.Terrains.values) {
|
||||
val tileInfo = TileInfo()
|
||||
if (terrain.type == TerrainType.TerrainFeature) {
|
||||
tileInfo.baseTerrain = terrain.occursOn!!.first()
|
||||
tileInfo.baseTerrain = when {
|
||||
terrain.occursOn == null -> terrain.occursOn!!.first()
|
||||
else -> "Grassland"
|
||||
}
|
||||
tileInfo.terrainFeature = terrain.name
|
||||
} else tileInfo.baseTerrain = terrain.name
|
||||
|
||||
|
@ -28,6 +28,7 @@ class NewGameScreenOptionsTable(val newGameParameters: GameParameters, val onMul
|
||||
addVictoryTypeCheckboxes()
|
||||
addBarbariansCheckbox()
|
||||
addOneCityChallengeCheckbox()
|
||||
addNuclearWeaponCheckbox()
|
||||
addNoRuinsCheckbox()
|
||||
|
||||
addIsOnlineMultiplayerCheckbox()
|
||||
@ -56,6 +57,18 @@ class NewGameScreenOptionsTable(val newGameParameters: GameParameters, val onMul
|
||||
})
|
||||
add(oneCityChallengeCheckbox).colspan(2).row()
|
||||
}
|
||||
|
||||
private fun addNuclearWeaponCheckbox() {
|
||||
val nuclearWeaponCheckbox = CheckBox("Enable nuclear weapon".tr(), CameraStageBaseScreen.skin)
|
||||
nuclearWeaponCheckbox.isChecked = newGameParameters.nuclearWeaponEnabled
|
||||
nuclearWeaponCheckbox.addListener(object : ChangeListener() {
|
||||
override fun changed(event: ChangeEvent?, actor: Actor?) {
|
||||
newGameParameters.nuclearWeaponEnabled = nuclearWeaponCheckbox.isChecked
|
||||
}
|
||||
})
|
||||
add(nuclearWeaponCheckbox).colspan(2).row()
|
||||
}
|
||||
|
||||
private fun addNoRuinsCheckbox() {
|
||||
val noRuinsCheckbox = CheckBox("No ancient ruins".tr(), CameraStageBaseScreen.skin)
|
||||
noRuinsCheckbox.isChecked = newGameParameters.noRuins
|
||||
|
@ -151,7 +151,11 @@ class BattleTable(val worldScreen: WorldScreen): Table() {
|
||||
}
|
||||
|
||||
row().pad(5f)
|
||||
val attackText : String = if (attacker is MapUnitCombatant) "Attack" else "Bombard"
|
||||
val attackText : String = when {
|
||||
attacker is MapUnitCombatant && attacker.getUnitType().isMissileUnit() -> "NUKE"
|
||||
attacker is MapUnitCombatant -> "Attack"
|
||||
else -> "Bombard"
|
||||
}
|
||||
val attackButton = TextButton(attackText.tr(), skin).apply { color= Color.RED }
|
||||
|
||||
var attackableEnemy : UnitAutomation.AttackableTile? = null
|
||||
|
@ -97,6 +97,8 @@ Unless otherwise specified, all the following are from [the Noun Project](https:
|
||||
* [APC](https://thenounproject.com/search/?q=apc&i=9965) By Luke Anthony Firth for Mechanized Infantry
|
||||
* [Military vehicle](https://thenounproject.com/search/?q=Army%20rocket&i=23115) By Luke Anthony Firth For Rocket Artillery
|
||||
* [Modern Armor](https://thenounproject.com/search/?q=tank&i=218) By Public Domain Nouns for Modern Armor
|
||||
* [Manhattan Project](https://thenounproject.com/search/?q=Nuclear%20Bomb&i=2041074) By corpus delicti, GR
|
||||
* [Nuclear Missile](https://thenounproject.com/marialuisa.iborra/collection/missiles-bombs/?i=1022574) By Lluisa Iborra, ES
|
||||
|
||||
### Great People
|
||||
|
||||
|