Merge pull request #334 from ninjatao/add_battleship

Add Battleship. Enabled Electronics for battleship.
This commit is contained in:
yairm210 2018-12-13 12:21:45 +02:00 committed by GitHub
commit ac241d2744
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 426 additions and 325 deletions

View File

@ -62,6 +62,8 @@ All the following are from [the Noun Project](https://thenounproject.com) licenc
* [Helmet](https://thenounproject.com/term/helmet/25216/) By Daniel Turner for Great War Infantry * [Helmet](https://thenounproject.com/term/helmet/25216/) By Daniel Turner for Great War Infantry
* [Tank](https://thenounproject.com/term/tank/1287510/) By corpus delicti for Landship * [Tank](https://thenounproject.com/term/tank/1287510/) By corpus delicti for Landship
* [Warship](https://thenounproject.com/term/warship/1597474/) By zidney for Destroyer * [Warship](https://thenounproject.com/term/warship/1597474/) By zidney for Destroyer
* [Battleship](https://thenounproject.com/search/?q=battleship&i=1986807) By Vitaliy Gorbachev, KZ for Battleship
* [Submarine](https://thenounproject.com/search/?q=submarine&i=589519) By Hea Poh Lin, MY
### Great People ### Great People
@ -345,6 +347,7 @@ All the following are from [the Noun Project](https://thenounproject.com) licenc
* [Plastic](https://thenounproject.com/term/plastic/478826/) By Yu luck * [Plastic](https://thenounproject.com/term/plastic/478826/) By Yu luck
* [Microphone](https://thenounproject.com/term/microphone/470266/) By Viktor Vorobyev for Mass Media * [Microphone](https://thenounproject.com/term/microphone/470266/) By Viktor Vorobyev for Mass Media
* [Flight](https://thenounproject.com/term/flight/1014306/) By Genius Icons * [Flight](https://thenounproject.com/term/flight/1014306/) By Genius Icons
* [Refridgerator](https://thenounproject.com/search/?q=refridgerator&i=1188873) By b farias, CL
### Information ### Information
* [Pill](https://thenounproject.com/term/pill/780458/) By Alex Arseneau for Pharmaceuticals * [Pill](https://thenounproject.com/term/pill/780458/) By Alex Arseneau for Pharmaceuticals
@ -357,6 +360,7 @@ All the following are from [the Noun Project](https://thenounproject.com) licenc
### Future ### Future
* [Nanoparticles](https://thenounproject.com/term/nanoparticles/822286/) By Gyan Lakhwani for Nanotechnology * [Nanoparticles](https://thenounproject.com/term/nanoparticles/822286/) By Gyan Lakhwani for Nanotechnology
* [Satellite](https://thenounproject.com/term/satellite/1466641/) By Ben Davis for Satellites * [Satellite](https://thenounproject.com/term/satellite/1466641/) By Ben Davis for Satellites
* [Electronics](https://thenounproject.com/search/?q=Electronics&i=1565843) By Cuby Design
* [Atom](https://thenounproject.com/term/atom/1586852/) By Kelsey Armstrong for Particle Physics * [Atom](https://thenounproject.com/term/atom/1586852/) By Kelsey Armstrong for Particle Physics
* [Information Technology](https://thenounproject.com/term/information-technology/1927668/) By Vectors Markeet for Future Tech * [Information Technology](https://thenounproject.com/term/information-technology/1927668/) By Vectors Markeet for Future Tech

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 968 B

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 818 KiB

After

Width:  |  Height:  |  Size: 825 KiB

View File

@ -356,13 +356,12 @@
techCost: 4505, techCost: 4505,
buildingCost:500, buildingCost:500,
wonderCost:1250, wonderCost:1250,
techs:[/* techs:[
{ {
name:"Refrigeration", name:"Refrigeration",
row:4, row:3,
prerequisites:["Electricity"], prerequisites:["Biology", "Electricity"], //to do: offshore platform should need this
baseDescription:"Does nothing since we have no sea tiles - In theory, allows construction of offshore platforms and submarines" },
},*/
{ {
name:"Replacable Parts", name:"Replacable Parts",
row:4, row:4,
@ -391,13 +390,12 @@
name:"Plastics", name:"Plastics",
row:3, row:3,
prerequisites:["Biology","Replacable Parts"] prerequisites:["Biology","Replacable Parts"]
},/* },
{ {
name:"Electronics", name:"Electronics",
row:5, row:5,
prerequisites:["Radio"], prerequisites:["Replacable Parts", "Flight"],
baseDescription:"Contributes only war-relatied things - on hold until AI is introduced - todo" },
},*/
{ {
name:"Mass Media", name:"Mass Media",
row:6, row:6,

View File

@ -368,6 +368,8 @@
cost: 185, cost: 185,
requiredResource:"Iron", requiredResource:"Iron",
requiredTech:"Navigation", requiredTech:"Navigation",
obsoleteTech:"Electronics",
upgradesTo:"Battleship",
hurryCostModifier:20 hurryCostModifier:20
}, },
{ {
@ -465,7 +467,31 @@
strength:55, strength:55,
cost: 375, cost: 375,
requiredTech:"Combustion", requiredTech:"Combustion",
uniques:[], // todo: add interception and bonus vs submarines once we have air and submarine units uniques:["Can attack submarines"], // todo: add interception and bonus vs submarines once we have air and submarine units
hurryCostModifier:20
},
{
name: "Battleship",
unitType: "WaterRanged",
movement: 5,
strength: 55,
rangedStrength: 55,
range: 3,
cost: 375,
requiredResource:"Oil",
requiredTech:"Electronics",
uniques:["Indirect Fire", "Bonus vs City 30%"],
hurryCostModifier:20
},
{
name: "Submarine",
unitType: "WaterRanged",
movement: 5,
strength: 35,
rangedStrength: 60,
cost: 325,
requiredTech:"Refrigeration",
uniques:["Bonus as Attacker 75%", "Invisible to others", "Can Only Attack Water", "Can attack submarines"], //to do: 3 uniques
hurryCostModifier:20 hurryCostModifier:20
}, },
{ {

View File

@ -118,6 +118,12 @@ class UnitAutomation{
if(tileCombatant==null) return false if(tileCombatant==null) return false
if(tileCombatant.getCivilization()==unit.civInfo ) return false if(tileCombatant.getCivilization()==unit.civInfo ) return false
if(!unit.civInfo.isAtWarWith(tileCombatant.getCivilization())) return false if(!unit.civInfo.isAtWarWith(tileCombatant.getCivilization())) return false
//only submarine and destroyer can attack submarine
if (tileCombatant.isInvisible()
&& (!unit.hasUnique("Can attack submarines") || !unit.civInfo.viewableInvisibleUnitsTiles.map { it.position }.contains(tile.position))){
return false
}
return true return true
} }

View File

@ -88,6 +88,12 @@ class BattleDamage{
else modifiers[text] = BDM.modificationAmount else modifiers[text] = BDM.modificationAmount
} }
} }
for (ability in attacker.unit.getUniques()) {
val regexResult = Regex("""Bonus as Attacker (\d*)%""").matchEntire(ability) //to do: extend to defender, and penalyy
if (regexResult == null) continue
modifiers["Attacker Bonus"] = regexResult.groups[1]!!.value.toFloat() / 100
}
} }
if (attacker.isMelee()) { if (attacker.isMelee()) {

View File

@ -12,6 +12,7 @@ class CityCombatant(val city: CityInfo) : ICombatant {
override fun getTile(): TileInfo = city.getCenterTile() override fun getTile(): TileInfo = city.getCenterTile()
override fun getName(): String = city.name override fun getName(): String = city.name
override fun isDefeated(): Boolean = city.health==1 override fun isDefeated(): Boolean = city.health==1
override fun isInvisible(): Boolean = false
override fun takeDamage(damage: Int) { override fun takeDamage(damage: Int) {
city.health -= damage city.health -= damage

View File

@ -1,6 +1,7 @@
package com.unciv.logic.battle package com.unciv.logic.battle
import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.map.MapUnit
import com.unciv.logic.map.TileInfo import com.unciv.logic.map.TileInfo
import com.unciv.models.gamebasics.unit.UnitType import com.unciv.models.gamebasics.unit.UnitType
@ -14,6 +15,7 @@ interface ICombatant{
fun isDefeated():Boolean fun isDefeated():Boolean
fun getCivilization(): CivilizationInfo fun getCivilization(): CivilizationInfo
fun getTile(): TileInfo fun getTile(): TileInfo
fun isInvisible(): Boolean
fun isMelee(): Boolean { fun isMelee(): Boolean {
return this.getUnitType().isMelee() return this.getUnitType().isMelee()

View File

@ -11,6 +11,7 @@ class MapUnitCombatant(val unit: MapUnit) : ICombatant {
override fun getTile(): TileInfo = unit.getTile() override fun getTile(): TileInfo = unit.getTile()
override fun getName(): String = unit.name override fun getName(): String = unit.name
override fun isDefeated(): Boolean = unit.health <= 0 override fun isDefeated(): Boolean = unit.health <= 0
override fun isInvisible(): Boolean = unit.isInvisible()
override fun takeDamage(damage: Int) { override fun takeDamage(damage: Int) {
unit.health -= damage unit.health -= damage

View File

@ -33,6 +33,7 @@ class CivilizationInfo {
*/ */
@Transient private var units=ArrayList<MapUnit>() @Transient private var units=ArrayList<MapUnit>()
@Transient var viewableTiles = HashSet<TileInfo>() @Transient var viewableTiles = HashSet<TileInfo>()
@Transient var viewableInvisibleUnitsTiles = HashSet<TileInfo>()
var gold = 0 var gold = 0
var happiness = 15 var happiness = 15
@ -228,6 +229,9 @@ class CivilizationInfo {
newViewableTiles.addAll(getCivUnits().flatMap { it.getViewableTiles()}) newViewableTiles.addAll(getCivUnits().flatMap { it.getViewableTiles()})
viewableTiles = newViewableTiles // to avoid concurrent modification problems viewableTiles = newViewableTiles // to avoid concurrent modification problems
val newViewableInvisibleTiles = HashSet<TileInfo>()
newViewableInvisibleTiles.addAll(getCivUnits().filter {it.hasUnique("Can attack submarines")}.flatMap {it.getViewableTiles()})
viewableInvisibleUnitsTiles = newViewableInvisibleTiles
// updating the viewable tiles also affects the explored tiles, obvs // updating the viewable tiles also affects the explored tiles, obvs
val newExploredTiles = HashSet<Vector2>(exploredTiles) val newExploredTiles = HashSet<Vector2>(exploredTiles)

View File

@ -178,6 +178,12 @@ class MapUnit {
return currentTile.baseTerrain=="Ocean"||currentTile.baseTerrain=="Coast" return currentTile.baseTerrain=="Ocean"||currentTile.baseTerrain=="Coast"
} }
fun isInvisible(): Boolean {
if(hasUnique("Invisible to others"))
return true
return false
}
fun getEmbarkedMovement(): Int { fun getEmbarkedMovement(): Int {
var movement=2 var movement=2
movement += civInfo.tech.getUniques().count { it == "Increases embarked movement +1" } movement += civInfo.tech.getUniques().count { it == "Increases embarked movement +1" }

View File

@ -281,5 +281,14 @@ open class TileInfo {
turnsToImprovement = improvement.getTurnsToBuild(civInfo) turnsToImprovement = improvement.getTurnsToBuild(civInfo)
} }
fun hasEnemySubmarine(): Boolean {
val unitsInTile = getUnits()
if (unitsInTile.isEmpty()) return false
if (!unitsInTile.first().civInfo.isPlayerCivilization() &&
unitsInTile.firstOrNull {it.isInvisible() == true} != null) {
return true
}
return false
}
//endregion //endregion
} }

View File

@ -23,8 +23,10 @@ class CityTileGroup(private val city: CityInfo, tileInfo: TileInfo) : TileGroup(
fun update() { fun update() {
val canSeeTile = UnCivGame.Current.viewEntireMapForDebug val canSeeTile = UnCivGame.Current.viewEntireMapForDebug
|| city.civInfo.viewableTiles.contains(tileInfo) || city.civInfo.viewableTiles.contains(tileInfo)
val showSubmarine = UnCivGame.Current.viewEntireMapForDebug
super.update(canSeeTile,true) || city.civInfo.viewableInvisibleUnitsTiles.contains(tileInfo)
|| (!tileInfo.hasEnemySubmarine())
super.update(canSeeTile,true, showSubmarine)
updatePopulationImage() updatePopulationImage()
if (improvementImage != null) improvementImage!!.setColor(1f, 1f, 1f, 0.5f) if (improvementImage != null) improvementImage!!.setColor(1f, 1f, 1f, 0.5f)

View File

@ -133,7 +133,7 @@ open class TileGroup(var tileInfo: TileInfo) : Group() {
} }
open fun update(isViewable: Boolean, showResourcesAndImprovements:Boolean) { open fun update(isViewable: Boolean, showResourcesAndImprovements:Boolean, showSubmarine: Boolean) {
hideCircle() hideCircle()
if (!UnCivGame.Current.viewEntireMapForDebug if (!UnCivGame.Current.viewEntireMapForDebug
&& !tileInfo.tileMap.gameInfo.getPlayerCivilization().exploredTiles.contains(tileInfo.position)) { && !tileInfo.tileMap.gameInfo.getPlayerCivilization().exploredTiles.contains(tileInfo.position)) {
@ -150,7 +150,7 @@ open class TileGroup(var tileInfo: TileInfo) : Group() {
civilianUnitImage = newUnitImage(tileInfo.civilianUnit, civilianUnitImage, isViewable, -20f) civilianUnitImage = newUnitImage(tileInfo.civilianUnit, civilianUnitImage, isViewable, -20f)
militaryUnitImage = newUnitImage(tileInfo.militaryUnit, militaryUnitImage, isViewable, 20f) militaryUnitImage = newUnitImage(tileInfo.militaryUnit, militaryUnitImage, isViewable && showSubmarine, 20f)
updateRoadImages() updateRoadImages()
updateBorderImages() updateBorderImages()

View File

@ -23,7 +23,7 @@ class WorldTileGroup(tileInfo: TileInfo) : TileGroup(tileInfo) {
} }
fun update(isViewable: Boolean) { fun update(isViewable: Boolean, showSubmarine: Boolean) {
val city = tileInfo.getCity() val city = tileInfo.getCity()
removePopulationIcon() removePopulationIcon()
@ -36,7 +36,7 @@ class WorldTileGroup(tileInfo: TileInfo) : TileGroup(tileInfo) {
updateCityButton(city, isViewable || UnCivGame.Current.viewEntireMapForDebug) // needs to be before the update so the units will be above the city button updateCityButton(city, isViewable || UnCivGame.Current.viewEntireMapForDebug) // needs to be before the update so the units will be above the city button
super.update(isViewable || UnCivGame.Current.viewEntireMapForDebug, super.update(isViewable || UnCivGame.Current.viewEntireMapForDebug,
UnCivGame.Current.settings.showResourcesAndImprovements) UnCivGame.Current.settings.showResourcesAndImprovements, showSubmarine)
yieldGroup.isVisible = !UnCivGame.Current.settings.showResourcesAndImprovements yieldGroup.isVisible = !UnCivGame.Current.settings.showResourcesAndImprovements
if (yieldGroup.isVisible) if (yieldGroup.isVisible)

View File

@ -180,6 +180,7 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap:
internal fun updateTiles(civInfo: CivilizationInfo) { internal fun updateTiles(civInfo: CivilizationInfo) {
val playerViewableTilePositions = civInfo.viewableTiles.map { it.position }.toHashSet() val playerViewableTilePositions = civInfo.viewableTiles.map { it.position }.toHashSet()
val playerViewableInvisibleUnitsTilePositions = civInfo.viewableInvisibleUnitsTiles.map { it.position }.toHashSet()
cityButtonOverlays.forEach{it.remove()} cityButtonOverlays.forEach{it.remove()}
cityButtonOverlays.clear() cityButtonOverlays.clear()
@ -187,9 +188,16 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap:
for (tileGroup in tileGroups.values){ for (tileGroup in tileGroups.values){
val canSeeTile = UnCivGame.Current.viewEntireMapForDebug val canSeeTile = UnCivGame.Current.viewEntireMapForDebug
|| playerViewableTilePositions.contains(tileGroup.tileInfo.position) || playerViewableTilePositions.contains(tileGroup.tileInfo.position)
tileGroup.update(canSeeTile)
val showSubmarine = UnCivGame.Current.viewEntireMapForDebug
|| playerViewableInvisibleUnitsTilePositions.contains(tileGroup.tileInfo.position)
|| (!tileGroup.tileInfo.hasEnemySubmarine())
tileGroup.update(canSeeTile, showSubmarine)
val unitsInTile = tileGroup.tileInfo.getUnits() val unitsInTile = tileGroup.tileInfo.getUnits()
if(canSeeTile && unitsInTile.isNotEmpty() && !unitsInTile.first().civInfo.isPlayerCivilization()) val canSeeEnemy = unitsInTile.isNotEmpty() && !unitsInTile.first().civInfo.isPlayerCivilization()
&& (showSubmarine || unitsInTile.firstOrNull {!it.isInvisible()}!=null)
if(canSeeTile && canSeeEnemy)
tileGroup.showCircle(Color.RED) // Display ALL viewable enemies with a red circle so that users don't need to go "hunting" for enemy units tileGroup.showCircle(Color.RED) // Display ALL viewable enemies with a red circle so that users don't need to go "hunting" for enemy units
} }