"Sleep until healed" functionality (#1821)

* "Sleep until healed" functionality

* Unit test for actions translations is added

* "Fortify until healed" functionality

* Refactoring
This commit is contained in:
JackRainy 2020-02-02 09:55:10 +02:00 committed by GitHub
parent 0914750489
commit db5cc82ec7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 142 additions and 62 deletions

View File

@ -1380,10 +1380,12 @@ Stop automation =
Construct road =
# Requires translation!
Fortify =
Fortify until healed = Fortify until healed
# Requires translation!
Fortification =
# Requires translation!
Sleep =
Sleep until healed = Sleep until healed
# Requires translation!
Moving =
# Requires translation!

View File

@ -760,8 +760,10 @@ Automate = Автоматизировать
Stop automation = Остановить автоматизацию
Construct road = Построить дорогу
Fortify = Укрепить
Fortify until healed = Укрепить до выздоровления
Fortification = к защите
Sleep = Спать
Sleep until healed = Спать до выздоровления
Moving = В движении
Set up = Подготовиться
Upgrade to [unitType] ([goldCost] gold) = Улучшить до [unitType] ([goldCost] золота)

View File

@ -762,8 +762,10 @@ Automate = Автоматизувати
Stop automation = Зупинити автоматизацію
Construct road = Будувати дорогу
Fortify = Укріпити
Fortify until healed = Укріпити до одужання
Fortification = Фортифікація
Sleep = Спати
Sleep until healed = Спати до одужання
Moving = У русі
Set up = Підготуватися
Upgrade to [unitType] ([goldCost] gold) = Удосконалити до [unitType] ([goldCost] золота)

View File

@ -760,8 +760,10 @@ Automate =
Stop automation =
Construct road =
Fortify =
Fortify until healed =
Fortification =
Sleep =
Sleep until healed =
Moving =
Set up =
Upgrade to [unitType] ([goldCost] gold) =

View File

@ -41,6 +41,7 @@ class Constants{
val unitActionSetUp = "Set Up"
val unitActionSleep = "Sleep"
val unitActionSleepUntilHealed = "Sleep until healed"
val unitActionAutomation = "Automate"
val unitActionExplore = "Explore"
val futureTech = "Future Tech"

View File

@ -201,7 +201,7 @@ object Battle {
unit.useMovementPoints(1f)
} else unit.currentMovement = 0f
unit.attacksThisTurn += 1
if (unit.isFortified() || unit.action == Constants.unitActionSleep)
if (unit.isFortified() || unit.isSleeping())
attacker.unit.action = null // but not, for instance, if it's Set Up - then it should definitely keep the action!
} else if (attacker is CityCombatant) {
attacker.city.attackedThisTurn = true

View File

@ -166,6 +166,10 @@ class MapUnit {
return action?.startsWith("Fortify") == true
}
fun isSleeping(): Boolean {
return action?.startsWith("Sleep") == true
}
fun getFortificationTurns(): Int {
if(!isFortified()) return 0
return action!!.split(" ")[1].toInt()
@ -181,7 +185,7 @@ class MapUnit {
if (name == Constants.worker && getTile().improvementInProgress != null) return false
if (hasUnique("Can construct roads") && currentTile.improvementInProgress=="Road") return false
if (isFortified()) return false
if (action==Constants.unitActionExplore || action==Constants.unitActionSleep
if (action==Constants.unitActionExplore || isSleeping()
|| action == Constants.unitActionAutomation) return false
return true
}
@ -268,13 +272,17 @@ class MapUnit {
action = "Fortify 0"
}
fun fortifyUntilHealed() {
action = "Fortify 0 until healed"
}
fun fortifyIfCan() {
if (canFortify()) {
fortify()
}
}
fun adjacentHealingBonus():Int{
private fun adjacentHealingBonus():Int{
var healingBonus = 0
if(hasUnique("This unit and all others in adjacent tiles heal 5 additional HP per turn")) healingBonus +=5
if(hasUnique("This unit and all others in adjacent tiles heal 5 additional HP. This unit heals 5 additional HP outside of friendly territory.")) healingBonus +=5
@ -334,10 +342,11 @@ class MapUnit {
private fun doPostTurnAction() {
if (name == Constants.worker && getTile().improvementInProgress != null) workOnImprovement()
if(hasUnique("Can construct roads") && currentTile.improvementInProgress=="Road") workOnImprovement()
if(currentMovement== getMaxMovement().toFloat()
if(currentMovement == getMaxMovement().toFloat()
&& isFortified()){
val currentTurnsFortified = getFortificationTurns()
if(currentTurnsFortified<2) action = "Fortify ${currentTurnsFortified+1}"
if(currentTurnsFortified<2)
action = action!!.replace(currentTurnsFortified.toString(),(currentTurnsFortified+1).toString(), true)
}
}
@ -418,6 +427,10 @@ class MapUnit {
|| getUniques().contains("Unit will heal every turn, even if it performs an action")){
heal()
}
if(action != null && health > 99)
if (action!!.endsWith(" until healed")) {
action = null // wake up when healed
}
}
fun startTurn(){
@ -426,7 +439,7 @@ class MapUnit {
due = true
// Wake sleeping units if there's an enemy nearby
if(action==Constants.unitActionSleep && currentTile.getTilesInDistance(2).any {
if(isSleeping() && currentTile.getTilesInDistance(2).any {
it.militaryUnit!=null && it.militaryUnit!!.civInfo.isAtWarWith(civInfo)
})
action=null

View File

@ -235,7 +235,7 @@ class UnitMovementAlgorithms(val unit:MapUnit) {
unit.currentMovement -= distanceToTiles[destination]!!.totalDistance
if (unit.currentMovement < 0.1) unit.currentMovement = 0f // silly floats which are "almost zero"
if(unit.isFortified() || unit.action==Constants.unitActionSetUp || unit.action==Constants.unitActionSleep)
if(unit.isFortified() || unit.action==Constants.unitActionSetUp || unit.isSleeping())
unit.action=null // unfortify/setup after moving
// If this unit is a carrier, keep record of its air payload whereabouts.

View File

@ -15,7 +15,9 @@ enum class UnitActionType(val value: String) {
StopAutomation("Stop automation"),
StopExploration("Stop exploration"),
Sleep("Sleep"),
SleepUntilHealed("Sleep until healed"),
Fortify("Fortify"),
FortifyUntilHealed("Fortify until healed"),
Explore("Explore"),
Promote("Promote"),
Upgrade("Upgrade"),

View File

@ -16,7 +16,7 @@ class Translations : LinkedHashMap<String, TranslationEntry>(){
return get(text)!![language]!!
}
fun hasTranslation(text:String,language:String): Boolean {
private fun hasTranslation(text:String,language:String): Boolean {
return containsKey(text) && get(text)!!.containsKey(language)
}

View File

@ -35,31 +35,18 @@ class UnitActions {
val workingOnImprovement = unit.hasUnique("Can build improvements on tiles")
&& unit.currentTile.hasImprovementInProgress()
if (!unit.isFortified() && (!unit.canFortify() || unit.health < 100) && unit.currentMovement > 0
&& !workingOnImprovement) {
val isSleeping = unit.action == Constants.unitActionSleep
actionList += UnitAction(
type = UnitActionType.Sleep,
canAct = !isSleeping,
isCurrentAction = isSleeping,
action = {
unit.action = Constants.unitActionSleep
unitTable.selectedUnit = null
})
if (!unit.isFortified() && !unit.canFortify()
&& unit.currentMovement > 0 && !workingOnImprovement) {
addSleepActions(actionList, unit, unitTable)
}
if (unit.canFortify()) {
actionList += UnitAction(
type = UnitActionType.Fortify,
canAct = unit.currentMovement > 0,
uncivSound = UncivSound.Fortify,
action = {
unit.fortify()
unitTable.selectedUnit = null
})
addFortifyActions(actionList, unit, unitTable)
} else if (unit.isFortified()) {
actionList += UnitAction(
type = UnitActionType.Fortify,
type = if (unit.action!!.endsWith(" until healed"))
UnitActionType.FortifyUntilHealed else
UnitActionType.Fortify,
canAct = false,
isCurrentAction = true,
title = "${"Fortification".tr()} ${unit.getFortificationTurns() * 20}%"
@ -320,6 +307,58 @@ class UnitActions {
return actionList
}
private fun addFortifyActions(actionList: ArrayList<UnitAction>, unit: MapUnit, unitTable: UnitTable) {
val action = UnitAction(
type = UnitActionType.Fortify,
canAct = unit.currentMovement > 0,
uncivSound = UncivSound.Fortify,
action = {
unit.fortify()
unitTable.selectedUnit = null
})
if (unit.health < 100) {
val actionForWounded = action.copy(
type = UnitActionType.FortifyUntilHealed,
title = UnitActionType.FortifyUntilHealed.value,
action = {
unit.fortifyUntilHealed()
unitTable.selectedUnit = null
})
actionList += actionForWounded
}
actionList += action
}
private fun addSleepActions(actionList: ArrayList<UnitAction>, unit: MapUnit, unitTable: UnitTable) {
val isSleeping = unit.isSleeping()
val action = UnitAction(
type = UnitActionType.Sleep,
canAct = !isSleeping,
isCurrentAction = isSleeping,
action = {
unit.action = Constants.unitActionSleep
unitTable.selectedUnit = null
})
if (unit.health < 100 && !isSleeping) {
val actionForWounded = action.copy(
type = UnitActionType.SleepUntilHealed,
title = UnitActionType.SleepUntilHealed.value,
action = {
unit.action = Constants.unitActionSleepUntilHealed
unitTable.selectedUnit = null
})
actionList += actionForWounded
}
actionList += action
}
fun canPillage(unit: MapUnit, tile: TileInfo): Boolean {
if (tile.improvement == null || tile.improvement == Constants.barbarianEncampment
|| tile.improvement == Constants.ancientRuins

View File

@ -18,40 +18,42 @@ class UnitActionsTable(val worldScreen: WorldScreen) : Table(){
touchable = Touchable.enabled
}
fun getIconForUnitAction(unitAction:String): Actor {
if(unitAction.startsWith("Upgrade to")){
// 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)
}
when(unitAction){
"Move unit" -> return ImageGetter.getStatIcon("Movement")
"Stop movement"-> return ImageGetter.getStatIcon("Movement").apply { color= Color.RED }
"Fortify" -> return ImageGetter.getImage("OtherIcons/Shield").apply { color= Color.BLACK }
"Promote" -> return ImageGetter.getImage("OtherIcons/Star").apply { color= Color.GOLD }
"Construct improvement" -> return ImageGetter.getUnitIcon(Constants.worker)
"Automate" -> return ImageGetter.getUnitIcon("Great Engineer")
"Stop automation" -> return ImageGetter.getImage("OtherIcons/Stop")
"Found city" -> return ImageGetter.getUnitIcon(Constants.settler)
"Hurry Research" -> return ImageGetter.getUnitIcon("Great Scientist")
"Construct Academy" -> return ImageGetter.getImprovementIcon("Academy")
"Start Golden Age" -> return ImageGetter.getUnitIcon("Great Artist")
"Construct Landmark" -> return ImageGetter.getImprovementIcon("Landmark")
"Hurry Wonder" -> return ImageGetter.getUnitIcon("Great Engineer")
"Construct Manufactory" -> return ImageGetter.getImprovementIcon("Manufactory")
"Conduct Trade Mission" -> return ImageGetter.getUnitIcon("Great Merchant")
"Construct Customs House" -> return ImageGetter.getImprovementIcon("Customs house")
"Set up" -> return ImageGetter.getUnitIcon("Catapult")
"Disband unit" -> return ImageGetter.getImage("OtherIcons/DisbandUnit")
"Sleep" -> return ImageGetter.getImage("OtherIcons/Sleep")
"Explore" -> return ImageGetter.getUnitIcon("Scout")
"Stop exploration" -> return ImageGetter.getImage("OtherIcons/Stop")
"Create Fishing Boats" -> return ImageGetter.getImprovementIcon("Fishing Boats")
"Create Oil well" -> return ImageGetter.getImprovementIcon("Oil well")
"Pillage" -> return ImageGetter.getImage("OtherIcons/Pillage")
"Construct road" -> return ImageGetter.getImprovementIcon("Road")
else -> return ImageGetter.getImage("OtherIcons/Star")
private fun getIconForUnitAction(unitAction:String): Actor {
when {
unitAction.startsWith("Upgrade to") -> {
// 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)
}
unitAction.startsWith("Sleep") -> return ImageGetter.getImage("OtherIcons/Sleep")
unitAction.startsWith("Fortify") -> return ImageGetter.getImage("OtherIcons/Shield").apply { color= Color.BLACK }
else -> when(unitAction){
"Move unit" -> return ImageGetter.getStatIcon("Movement")
"Stop movement"-> return ImageGetter.getStatIcon("Movement").apply { color= Color.RED }
"Promote" -> return ImageGetter.getImage("OtherIcons/Star").apply { color= Color.GOLD }
"Construct improvement" -> return ImageGetter.getUnitIcon(Constants.worker)
"Automate" -> return ImageGetter.getUnitIcon("Great Engineer")
"Stop automation" -> return ImageGetter.getImage("OtherIcons/Stop")
"Found city" -> return ImageGetter.getUnitIcon(Constants.settler)
"Hurry Research" -> return ImageGetter.getUnitIcon("Great Scientist")
"Construct Academy" -> return ImageGetter.getImprovementIcon("Academy")
"Start Golden Age" -> return ImageGetter.getUnitIcon("Great Artist")
"Construct Landmark" -> return ImageGetter.getImprovementIcon("Landmark")
"Hurry Wonder" -> return ImageGetter.getUnitIcon("Great Engineer")
"Construct Manufactory" -> return ImageGetter.getImprovementIcon("Manufactory")
"Conduct Trade Mission" -> return ImageGetter.getUnitIcon("Great Merchant")
"Construct Customs House" -> return ImageGetter.getImprovementIcon("Customs house")
"Set up" -> return ImageGetter.getUnitIcon("Catapult")
"Disband unit" -> return ImageGetter.getImage("OtherIcons/DisbandUnit")
"Explore" -> return ImageGetter.getUnitIcon("Scout")
"Stop exploration" -> return ImageGetter.getImage("OtherIcons/Stop")
"Create Fishing Boats" -> return ImageGetter.getImprovementIcon("Fishing Boats")
"Create Oil well" -> return ImageGetter.getImprovementIcon("Oil well")
"Pillage" -> return ImageGetter.getImage("OtherIcons/Pillage")
"Construct road" -> return ImageGetter.getImprovementIcon("Road")
else -> return ImageGetter.getImage("OtherIcons/Star")
}
}
}

View File

@ -4,6 +4,7 @@ package com.unciv.testing
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.utils.Array
import com.unciv.JsonParser
import com.unciv.models.UnitActionType
import com.unciv.models.ruleset.Nation
import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.RulesetCache
@ -52,6 +53,20 @@ class TranslationTests {
allStringsHaveTranslation)
}
@Test
fun allUnitActionsHaveTranslation() {
val actions: MutableSet<String> = HashSet()
for (action in UnitActionType.values()) {
if (action == UnitActionType.Upgrade)
actions.add("Upgrade to [unitType] ([goldCost] gold)")
else
actions.add(action.value)
}
val allUnitActionsHaveTranslation = allStringAreTranslated(actions)
Assert.assertTrue("This test will only pass when there is a translation for all unit actions",
allUnitActionsHaveTranslation)
}
@Test
fun allBuildingsHaveTranslation() {
val allBuildingsHaveTranslation = allStringAreTranslated(ruleset.buildings.keys)