Added Replacable Parts tech and Great War Infantry
Musketman now upgrades to Rifleman Solved more rare concurrency problems
This commit is contained in:
parent
28ae533acc
commit
24b27a791f
22 changed files with 427 additions and 387 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -127,3 +127,5 @@ gradle.properties
|
||||||
SaveFiles/
|
SaveFiles/
|
||||||
android/android-release.apk
|
android/android-release.apk
|
||||||
android/assets/GameSettings.json
|
android/assets/GameSettings.json
|
||||||
|
android/release/output.json
|
||||||
|
android/release/android-release.apk
|
||||||
|
|
|
@ -57,6 +57,7 @@ All the following are from [the Noun Project](https://thenounproject.com) licenc
|
||||||
|
|
||||||
### Modern
|
### Modern
|
||||||
|
|
||||||
|
* [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
|
||||||
|
|
||||||
### Great People
|
### Great People
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
![](https://travis-ci.org/yairm210/UnCiv.svg?branch=master)
|
![](https://travis-ci.org/yairm210/UnCiv.svg?branch=master)
|
||||||
|
|
||||||
[![LibGDX](https://img.shields.io/badge/libgdx-1.9.6-red.svg)](https://libgdx.badlogicgames.com/)
|
[![LibGDX](https://img.shields.io/badge/libgdx-1.9.9-red.svg)](https://libgdx.badlogicgames.com/)
|
||||||
[![Kotlin](https://img.shields.io/badge/kotlin-1.2.41-orange.svg)](http://kotlinlang.org/)
|
[![Kotlin](https://img.shields.io/badge/kotlin-1.3.10-orange.svg)](http://kotlinlang.org/)
|
||||||
|
|
||||||
## What is this?
|
## What is this?
|
||||||
|
|
||||||
|
|
BIN
android/Images/TechIcons/Replacable Parts.png
Normal file
BIN
android/Images/TechIcons/Replacable Parts.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
BIN
android/Images/UnitIcons/Great War Infantry.png
Normal file
BIN
android/Images/UnitIcons/Great War Infantry.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1 KiB |
File diff suppressed because it is too large
Load diff
Binary file not shown.
Before Width: | Height: | Size: 768 KiB After Width: | Height: | Size: 780 KiB |
|
@ -363,6 +363,11 @@
|
||||||
prerequisites:["Electricity"],
|
prerequisites:["Electricity"],
|
||||||
baseDescription:"Does nothing since we have no sea tiles - In theory, allows construction of offshore platforms and submarines"
|
baseDescription:"Does nothing since we have no sea tiles - In theory, allows construction of offshore platforms and submarines"
|
||||||
},*/
|
},*/
|
||||||
|
{
|
||||||
|
name:"Replacable Parts",
|
||||||
|
row:4,
|
||||||
|
prerequisites:["Electricity","Steam Power"]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name:"Radio",
|
name:"Radio",
|
||||||
row:5,
|
row:5,
|
||||||
|
@ -385,7 +390,7 @@
|
||||||
{
|
{
|
||||||
name:"Plastics",
|
name:"Plastics",
|
||||||
row:3,
|
row:3,
|
||||||
prerequisites:["Biology"]
|
prerequisites:["Biology","Replacable Parts"]
|
||||||
},/*
|
},/*
|
||||||
{
|
{
|
||||||
name:"Electronics",
|
name:"Electronics",
|
||||||
|
|
|
@ -292,6 +292,8 @@
|
||||||
strength:24,
|
strength:24,
|
||||||
cost: 150,
|
cost: 150,
|
||||||
requiredTech:"Gunpowder",
|
requiredTech:"Gunpowder",
|
||||||
|
upgradesTo:"Rifleman,"
|
||||||
|
obsoleteTech:"Rifling",
|
||||||
hurryCostModifier:20
|
hurryCostModifier:20
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -303,6 +305,8 @@
|
||||||
strength:28,
|
strength:28,
|
||||||
cost: 150,
|
cost: 150,
|
||||||
requiredTech:"Gunpowder",
|
requiredTech:"Gunpowder",
|
||||||
|
upgradesTo:"Rifleman,"
|
||||||
|
obsoleteTech:"Rifling",
|
||||||
hurryCostModifier:20
|
hurryCostModifier:20
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -337,6 +341,8 @@
|
||||||
strength:34,
|
strength:34,
|
||||||
cost: 225,
|
cost: 225,
|
||||||
requiredTech:"Rifling",
|
requiredTech:"Rifling",
|
||||||
|
obsoleteTech:"Replacable Parts",
|
||||||
|
upgradesTo:"Great War Infantry",
|
||||||
hurryCostModifier:20
|
hurryCostModifier:20
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -347,6 +353,7 @@
|
||||||
cost: 225,
|
cost: 225,
|
||||||
requiredTech:"Military Science",
|
requiredTech:"Military Science",
|
||||||
requiredResource:"Horses",
|
requiredResource:"Horses",
|
||||||
|
upgradesTo:"Landship",
|
||||||
uniques:["Can move after attacking","No defensive terrain bonus","Penalty vs City 33%" ],
|
uniques:["Can move after attacking","No defensive terrain bonus","Penalty vs City 33%" ],
|
||||||
hurryCostModifier:20
|
hurryCostModifier:20
|
||||||
},
|
},
|
||||||
|
@ -359,7 +366,8 @@
|
||||||
range:3,
|
range:3,
|
||||||
cost: 320,
|
cost: 320,
|
||||||
requiredTech:"Dynamite",
|
requiredTech:"Dynamite",
|
||||||
uniques:["Bonus vs City 200%","No defensive terrain bonus","Must set up to ranged attack","Limited Visibility","Indirect Fire"],
|
uniques:["Bonus vs City 200%","No defensive terrain bonus",
|
||||||
|
"Must set up to ranged attack","Limited Visibility","Indirect Fire"],
|
||||||
hurryCostModifier:20
|
hurryCostModifier:20
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -387,6 +395,15 @@
|
||||||
uniques:["Can move after attacking","No defensive terrain bonus"],
|
uniques:["Can move after attacking","No defensive terrain bonus"],
|
||||||
hurryCostModifier:20
|
hurryCostModifier:20
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name:"Great War Infantry",
|
||||||
|
unitType:"Melee",
|
||||||
|
movement:2,
|
||||||
|
strength:50,
|
||||||
|
cost: 320,
|
||||||
|
requiredTech:"Replacable Parts",
|
||||||
|
hurryCostModifier:20
|
||||||
|
},
|
||||||
|
|
||||||
/* Great people */
|
/* Great people */
|
||||||
|
|
||||||
|
|
|
@ -21,8 +21,8 @@ android {
|
||||||
applicationId "com.unciv.game"
|
applicationId "com.unciv.game"
|
||||||
minSdkVersion 14
|
minSdkVersion 14
|
||||||
targetSdkVersion 26
|
targetSdkVersion 26
|
||||||
versionCode 169
|
versionCode 170
|
||||||
versionName "2.10.8"
|
versionName "2.10.9"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Had to add this crap for Travis to build, it wanted to sign the app
|
// Had to add this crap for Travis to build, it wanted to sign the app
|
||||||
|
|
|
@ -62,7 +62,7 @@ class UnCivGame : Game() {
|
||||||
fun setWorldScreen() {
|
fun setWorldScreen() {
|
||||||
setScreen(worldScreen)
|
setScreen(worldScreen)
|
||||||
Gdx.input.inputProcessor = worldScreen.stage
|
Gdx.input.inputProcessor = worldScreen.stage
|
||||||
worldScreen.update() // This can set the screen to the policy picker or tech picker screen, so the input processor must come before
|
worldScreen.shouldUpdate=true // This can set the screen to the policy picker or tech picker screen, so the input processor must come before
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun resume() {
|
override fun resume() {
|
||||||
|
|
|
@ -34,7 +34,8 @@ class UnitAutomation{
|
||||||
return SpecificUnitAutomation().automateWorkBoats(unit)
|
return SpecificUnitAutomation().automateWorkBoats(unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(unit.name.startsWith("Great")){
|
if(unit.name.startsWith("Great")
|
||||||
|
&& unit.name in GreatPersonManager().statToGreatPersonMapping.values){ // So "Great War Infantry" isn't caught here
|
||||||
return SpecificUnitAutomation().automateGreatPerson(unit)// I don't know what to do with you yet.
|
return SpecificUnitAutomation().automateGreatPerson(unit)// I don't know what to do with you yet.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -357,10 +358,8 @@ class SpecificUnitAutomation{
|
||||||
if (unit.currentMovement > 0 && unit.currentTile == closestReachableResource) {
|
if (unit.currentMovement > 0 && unit.currentTile == closestReachableResource) {
|
||||||
val createImprovementAction = UnitActions().getUnitActions(unit, UnCivGame.Current.worldScreen)
|
val createImprovementAction = UnitActions().getUnitActions(unit, UnCivGame.Current.worldScreen)
|
||||||
.firstOrNull { it.name.startsWith("Create") } // could be either fishing boats or oil well
|
.firstOrNull { it.name.startsWith("Create") } // could be either fishing boats or oil well
|
||||||
if (createImprovementAction != null) {
|
if (createImprovementAction != null)
|
||||||
createImprovementAction.action()
|
return createImprovementAction.action() // unit is already gone, can't "explore"
|
||||||
return // unit is already gone, can't "explore"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else UnitAutomation().explore(unit, unit.getDistanceToTiles())
|
else UnitAutomation().explore(unit, unit.getDistanceToTiles())
|
||||||
|
@ -402,10 +401,7 @@ class SpecificUnitAutomation{
|
||||||
.firstOrNull { unit.movementAlgs().canReach(it) }
|
.firstOrNull { unit.movementAlgs().canReach(it) }
|
||||||
|
|
||||||
if(bestCityLocation==null) // We got a badass over here, all tiles within 5 are taken? Screw it, random walk.
|
if(bestCityLocation==null) // We got a badass over here, all tiles within 5 are taken? Screw it, random walk.
|
||||||
{
|
return UnitAutomation().explore(unit, unit.getDistanceToTiles())
|
||||||
UnitAutomation().explore(unit, unit.getDistanceToTiles())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if(bestCityLocation.getTilesInDistance(3).any { it.isCityCenter() })
|
if(bestCityLocation.getTilesInDistance(3).any { it.isCityCenter() })
|
||||||
throw Exception("City within distance")
|
throw Exception("City within distance")
|
||||||
|
@ -430,7 +426,7 @@ class SpecificUnitAutomation{
|
||||||
for(city in citiesByStatBoost){
|
for(city in citiesByStatBoost){
|
||||||
val pathToCity =unit.movementAlgs().getShortestPath(city.getCenterTile())
|
val pathToCity =unit.movementAlgs().getShortestPath(city.getCenterTile())
|
||||||
if(pathToCity.isEmpty()) continue
|
if(pathToCity.isEmpty()) continue
|
||||||
if(pathToCity.size>2) {
|
if(pathToCity.size>2){
|
||||||
unit.movementAlgs().headTowards(city.getCenterTile())
|
unit.movementAlgs().headTowards(city.getCenterTile())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,7 +84,7 @@ class TechPickerScreen(internal val civInfo: CivilizationInfo) : PickerScreen()
|
||||||
} else
|
} else
|
||||||
civTech.techsToResearch = techsToResearch
|
civTech.techsToResearch = techsToResearch
|
||||||
game.setWorldScreen()
|
game.setWorldScreen()
|
||||||
game.worldScreen.update()
|
game.worldScreen.shouldUpdate=true
|
||||||
dispose()
|
dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -118,7 +118,7 @@ class MinimapHolder(val tileMapHolder: TileMapHolder): Table(){
|
||||||
populationImage.onClick {
|
populationImage.onClick {
|
||||||
settings.showWorkedTiles = !settings.showWorkedTiles
|
settings.showWorkedTiles = !settings.showWorkedTiles
|
||||||
populationImage.image.color.a = if(settings.showWorkedTiles) 1f else 0.5f
|
populationImage.image.color.a = if(settings.showWorkedTiles) 1f else 0.5f
|
||||||
worldScreen.update()
|
worldScreen.shouldUpdate=true
|
||||||
}
|
}
|
||||||
toggleIconTable.add(populationImage).row()
|
toggleIconTable.add(populationImage).row()
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ class MinimapHolder(val tileMapHolder: TileMapHolder): Table(){
|
||||||
resourceImage.onClick {
|
resourceImage.onClick {
|
||||||
settings.showResourcesAndImprovements = !settings.showResourcesAndImprovements
|
settings.showResourcesAndImprovements = !settings.showResourcesAndImprovements
|
||||||
resourceImage.image.color.a = if(settings.showResourcesAndImprovements) 1f else 0.5f
|
resourceImage.image.color.a = if(settings.showResourcesAndImprovements) 1f else 0.5f
|
||||||
worldScreen.update()
|
worldScreen.shouldUpdate=true
|
||||||
}
|
}
|
||||||
toggleIconTable.add(resourceImage)
|
toggleIconTable.add(resourceImage)
|
||||||
toggleIconTable.pack()
|
toggleIconTable.pack()
|
||||||
|
|
|
@ -102,7 +102,7 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap:
|
||||||
}
|
}
|
||||||
|
|
||||||
worldScreen.bottomBar.unitTable.tileSelected(tileInfo)
|
worldScreen.bottomBar.unitTable.tileSelected(tileInfo)
|
||||||
worldScreen.update()
|
worldScreen.shouldUpdate=true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addMoveHereButtonToTile(selectedUnit: MapUnit, tileInfo: TileInfo, tileGroup: WorldTileGroup) {
|
private fun addMoveHereButtonToTile(selectedUnit: MapUnit, tileInfo: TileInfo, tileGroup: WorldTileGroup) {
|
||||||
|
@ -114,7 +114,8 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap:
|
||||||
val turnsToGetThere = selectedUnit.movementAlgs().getShortestPath(tileInfo).size
|
val turnsToGetThere = selectedUnit.movementAlgs().getShortestPath(tileInfo).size
|
||||||
val numberCircle = ImageGetter.getImage("OtherIcons/Circle").apply { width = size / 2; height = size / 2;color = Color.BLUE }
|
val numberCircle = ImageGetter.getImage("OtherIcons/Circle").apply { width = size / 2; height = size / 2;color = Color.BLUE }
|
||||||
moveHereButton.addActor(numberCircle)
|
moveHereButton.addActor(numberCircle)
|
||||||
moveHereButton.addActor(Label(turnsToGetThere.toString(), CameraStageBaseScreen.skin).apply { center(numberCircle); setFontColor(Color.WHITE) })
|
moveHereButton.addActor(Label(turnsToGetThere.toString(), CameraStageBaseScreen.skin)
|
||||||
|
.apply { center(numberCircle); setFontColor(Color.WHITE) })
|
||||||
|
|
||||||
val unitIcon = ImageGetter.getUnitImage(selectedUnit, size / 2)
|
val unitIcon = ImageGetter.getUnitImage(selectedUnit, size / 2)
|
||||||
unitIcon.y = size - unitIcon.height
|
unitIcon.y = size - unitIcon.height
|
||||||
|
@ -132,7 +133,7 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap:
|
||||||
|
|
||||||
// we don't update it directly because we're on a different thread; instead, we tell it to update itself
|
// we don't update it directly because we're on a different thread; instead, we tell it to update itself
|
||||||
worldScreen.shouldUpdate = true
|
worldScreen.shouldUpdate = true
|
||||||
moveToOverlay!!.remove()
|
moveToOverlay?.remove()
|
||||||
moveToOverlay = null
|
moveToOverlay = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -220,7 +221,7 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap:
|
||||||
// Here it's the same, only the Y axis is inverted - when at 0 we're at the top, not bottom - so we invert it back.
|
// Here it's the same, only the Y axis is inverted - when at 0 we're at the top, not bottom - so we invert it back.
|
||||||
scrollY = maxY - (tileGroup.y + tileGroup.width / 2 - worldScreen.stage.height / 2)
|
scrollY = maxY - (tileGroup.y + tileGroup.width / 2 - worldScreen.stage.height / 2)
|
||||||
updateVisualScroll()
|
updateVisualScroll()
|
||||||
worldScreen.update()
|
worldScreen.shouldUpdate=true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -86,8 +86,10 @@ class WorldScreen : CameraStageBaseScreen() {
|
||||||
createNextTurnButton() // needs civ table to be positioned
|
createNextTurnButton() // needs civ table to be positioned
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is private so that we will set the shouldUpdate to true instead.
|
||||||
fun update() {
|
// That way, not only do we save a lot of unneccesary updates, we also ensure that all updates are called from the main GL thread
|
||||||
|
// and we don't get any silly concurrency problems!
|
||||||
|
private fun update() {
|
||||||
// many of the display functions will be called with the game clone and not the actual game,
|
// many of the display functions will be called with the game clone and not the actual game,
|
||||||
// because that's guaranteed to stay the exact same and so we won't get any concurrent modification exceptions
|
// because that's guaranteed to stay the exact same and so we won't get any concurrent modification exceptions
|
||||||
|
|
||||||
|
|
|
@ -137,7 +137,7 @@ class BattleTable(val worldScreen: WorldScreen): Table() {
|
||||||
attackButton.onClick {
|
attackButton.onClick {
|
||||||
attacker.unit.moveToTile(attackableEnemy.tileToAttackFrom)
|
attacker.unit.moveToTile(attackableEnemy.tileToAttackFrom)
|
||||||
battle.attack(attacker, defender)
|
battle.attack(attacker, defender)
|
||||||
worldScreen.update()
|
worldScreen.shouldUpdate=true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,6 +89,6 @@ class WorldScreenDisplayOptionsTable() : PopupTable(){
|
||||||
|
|
||||||
pack() // Needed to show the background.
|
pack() // Needed to show the background.
|
||||||
center(UnCivGame.Current.worldScreen.stage)
|
center(UnCivGame.Current.worldScreen.stage)
|
||||||
UnCivGame.Current.worldScreen.update()
|
UnCivGame.Current.worldScreen.shouldUpdate=true
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -41,7 +41,7 @@ class IdleUnitButton (internal val unitTable: UnitTable,
|
||||||
tileToSelect = tilesWithIdleUnits[index]
|
tileToSelect = tilesWithIdleUnits[index]
|
||||||
}
|
}
|
||||||
tileMapHolder.setCenterPosition(tileToSelect.position)
|
tileMapHolder.setCenterPosition(tileToSelect.position)
|
||||||
unitTable.worldScreen.update()
|
unitTable.worldScreen.shouldUpdate=true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -185,7 +185,7 @@ class UnitActions {
|
||||||
actionList += UnitAction("Disband unit",unit.currentMovement != 0f
|
actionList += UnitAction("Disband unit",unit.currentMovement != 0f
|
||||||
) {
|
) {
|
||||||
YesNoPopupTable("Do you really want to disband this unit?".tr(),
|
YesNoPopupTable("Do you really want to disband this unit?".tr(),
|
||||||
{unit.destroy(); worldScreen.update()} )
|
{unit.destroy(); worldScreen.shouldUpdate=true} )
|
||||||
}
|
}
|
||||||
|
|
||||||
return actionList
|
return actionList
|
||||||
|
|
|
@ -14,7 +14,9 @@ class UnitActionsTable(val worldScreen: WorldScreen) : Table(){
|
||||||
|
|
||||||
fun getIconForUnitAction(unitAction:String): Actor {
|
fun getIconForUnitAction(unitAction:String): Actor {
|
||||||
if(unitAction.startsWith("Upgrade to")){
|
if(unitAction.startsWith("Upgrade to")){
|
||||||
val unitToUpgradeTo = Regex("""Upgrade to \[(\S*)\]""").find(unitAction)!!.groups[1]!!.value
|
// Regexplaination: start with a [, take as many non-] chars as you can, until you reach a ].
|
||||||
|
// What you find between the first [ and the first ] that comes after it, will be group no. 1
|
||||||
|
val unitToUpgradeTo = Regex("""Upgrade to \[([^\]]*)\]""").find(unitAction)!!.groups[1]!!.value
|
||||||
return ImageGetter.getUnitIcon(unitToUpgradeTo)
|
return ImageGetter.getUnitIcon(unitToUpgradeTo)
|
||||||
}
|
}
|
||||||
when(unitAction){
|
when(unitAction){
|
||||||
|
@ -60,7 +62,7 @@ class UnitActionsTable(val worldScreen: WorldScreen) : Table(){
|
||||||
actionButton.add(Label(unitAction.name.tr(),CameraStageBaseScreen.skin)
|
actionButton.add(Label(unitAction.name.tr(),CameraStageBaseScreen.skin)
|
||||||
.setFontColor(Color.WHITE)).pad(5f)
|
.setFontColor(Color.WHITE)).pad(5f)
|
||||||
actionButton.pack()
|
actionButton.pack()
|
||||||
actionButton.onClick({ unitAction.action(); UnCivGame.Current.worldScreen.update() })
|
actionButton.onClick { unitAction.action(); UnCivGame.Current.worldScreen.shouldUpdate=true }
|
||||||
if (!unitAction.canAct) actionButton.disable()
|
if (!unitAction.canAct) actionButton.disable()
|
||||||
return actionButton
|
return actionButton
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue