Added promotions mechanism!
This commit is contained in:
parent
92abe0cf73
commit
c6caf0cecd
16 changed files with 203 additions and 151 deletions
|
@ -71,18 +71,18 @@
|
|||
{
|
||||
name:"Scouting I",
|
||||
effect:"+1 Visibility Range",
|
||||
unitTypes:["Melee","Mounted"]
|
||||
unitTypes:["Scout"]
|
||||
}
|
||||
{
|
||||
name:"Scouting II",
|
||||
prerequisites:["Scouting I"],
|
||||
effect:"+1 Visibility Range",
|
||||
unitTypes:["Melee","Mounted"]
|
||||
unitTypes:["Scout"]
|
||||
}
|
||||
{
|
||||
name:"Scouting III",
|
||||
prerequisites:["Scouting II"],
|
||||
effect:"+1 Visibility Range",
|
||||
unitTypes:["Melee","Mounted"]
|
||||
unitTypes:["Scout"]
|
||||
}
|
||||
]
|
|
@ -2,6 +2,7 @@ package com.unciv.logic.automation
|
|||
|
||||
import com.unciv.UnCivGame
|
||||
import com.unciv.logic.battle.Battle
|
||||
import com.unciv.logic.battle.BattleDamage
|
||||
import com.unciv.logic.battle.MapUnitCombatant
|
||||
import com.unciv.logic.civilization.CivilizationInfo
|
||||
import com.unciv.logic.map.MapUnit
|
||||
|
@ -90,7 +91,7 @@ class UnitAutomation{
|
|||
if(setupAction!=null) setupAction.action()
|
||||
|
||||
val enemy = Battle().getMapCombatantOfTile(enemyTileToAttack)!!
|
||||
val damageToAttacker = Battle(unit.civInfo.gameInfo).calculateDamageToAttacker(MapUnitCombatant(unit), enemy)
|
||||
val damageToAttacker = BattleDamage().calculateDamageToAttacker(MapUnitCombatant(unit), enemy)
|
||||
|
||||
if (damageToAttacker < unit.health) { // don't attack if we'll die from the attack
|
||||
if(MapUnitCombatant(unit).isMelee())
|
||||
|
|
|
@ -8,116 +8,17 @@ import com.unciv.logic.map.TileInfo
|
|||
import com.unciv.models.gamebasics.unit.UnitType
|
||||
import com.unciv.ui.utils.tr
|
||||
import java.util.*
|
||||
import kotlin.collections.HashMap
|
||||
import kotlin.math.max
|
||||
|
||||
/**
|
||||
* Damage calculations according to civ v wiki and https://steamcommunity.com/sharedfiles/filedetails/?id=170194443
|
||||
*/
|
||||
class Battle(val gameInfo:GameInfo=UnCivGame.Current.gameInfo) {
|
||||
|
||||
private fun getGeneralModifiers(combatant: ICombatant, enemy: ICombatant): HashMap<String, Float> {
|
||||
val modifiers = HashMap<String, Float>()
|
||||
if (combatant is MapUnitCombatant) {
|
||||
val uniques = combatant.unit.getBaseUnit().uniques
|
||||
if (uniques != null) {
|
||||
// This beut allows us to have generic unit uniques: "Bonus vs City 75%", "Penatly vs Mounted 25%" etc.
|
||||
for (unique in uniques) {
|
||||
val regexResult = Regex("""(Bonus|Penalty) vs (\S*) (\d*)%""").matchEntire(unique)
|
||||
if (regexResult == null) continue
|
||||
val vsType = UnitType.valueOf(regexResult.groups[2]!!.value)
|
||||
val modificationAmount = regexResult.groups[3]!!.value.toFloat() / 100 // if it says 15%, that's 0.15f in modification
|
||||
if (enemy.getUnitType() == vsType) {
|
||||
if (regexResult.groups[1]!!.value == "Bonus")
|
||||
modifiers["Bonus vs $vsType"] = modificationAmount
|
||||
else modifiers["Penalty vs $vsType"] = -modificationAmount
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(enemy.getCivilization().isBarbarianCivilization())
|
||||
modifiers["vs Barbarians"] = 0.33f
|
||||
|
||||
if(combatant.getCivilization().happiness<0)
|
||||
modifiers["Unhappiness"] = 0.02f * combatant.getCivilization().happiness //https://www.carlsguides.com/strategy/civilization5/war/combatbonuses.php
|
||||
}
|
||||
|
||||
return modifiers
|
||||
}
|
||||
|
||||
fun getAttackModifiers(attacker: ICombatant, defender: ICombatant): HashMap<String, Float> {
|
||||
val modifiers = getGeneralModifiers(attacker, defender)
|
||||
if (attacker.isMelee()) {
|
||||
val numberOfAttackersSurroundingDefender = defender.getTile().neighbors.count {
|
||||
it.militaryUnit != null
|
||||
&& it.militaryUnit!!.owner == attacker.getCivilization().civName
|
||||
&& MapUnitCombatant(it.militaryUnit!!).isMelee()
|
||||
}
|
||||
if (numberOfAttackersSurroundingDefender > 1)
|
||||
modifiers["Flanking"] = 0.1f * (numberOfAttackersSurroundingDefender-1) //https://www.carlsguides.com/strategy/civilization5/war/combatbonuses.php
|
||||
}
|
||||
|
||||
return modifiers
|
||||
}
|
||||
|
||||
fun getDefenceModifiers(attacker: ICombatant, defender: ICombatant): HashMap<String, Float> {
|
||||
val modifiers = getGeneralModifiers(defender, attacker)
|
||||
if (!(defender is MapUnitCombatant && defender.unit.hasUnique("No defensive terrain bonus"))) {
|
||||
val tileDefenceBonus = defender.getTile().getDefensiveBonus()
|
||||
if (tileDefenceBonus > 0) modifiers["Terrain"] = tileDefenceBonus
|
||||
}
|
||||
if(defender is MapUnitCombatant && defender.unit.isFortified())
|
||||
modifiers["Fortification"]=0.2f*defender.unit.getFortificationTurns()
|
||||
return modifiers
|
||||
}
|
||||
|
||||
private fun modifiersToMultiplicationBonus(modifiers: HashMap<String, Float>): Float {
|
||||
// modifiers are like 0.1 for a 10% bonus, -0.1 for a 10% loss
|
||||
var modifier = 1f
|
||||
for (m in modifiers.values) modifier *= (1 + m)
|
||||
return modifier
|
||||
}
|
||||
|
||||
private fun getHealthDependantDamageRatio(combatant: ICombatant): Float {
|
||||
if (combatant.getUnitType() == UnitType.City) return 1f
|
||||
return 1/2f + combatant.getHealth()/200f // Each point of health reduces damage dealt by 0.5%
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Includes attack modifiers
|
||||
*/
|
||||
fun getAttackingStrength(attacker: ICombatant, defender: ICombatant): Float {
|
||||
val attackModifier = modifiersToMultiplicationBonus(getAttackModifiers(attacker,defender))
|
||||
return attacker.getAttackingStrength(defender) * attackModifier
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Includes defence modifiers
|
||||
*/
|
||||
fun getDefendingStrength(attacker: ICombatant, defender: ICombatant): Float {
|
||||
val defenceModifier = modifiersToMultiplicationBonus(getDefenceModifiers(attacker,defender))
|
||||
return defender.getDefendingStrength(attacker) * defenceModifier
|
||||
}
|
||||
|
||||
fun calculateDamageToAttacker(attacker: ICombatant, defender: ICombatant): Int {
|
||||
if(attacker.isRanged()) return 0
|
||||
if(defender.getUnitType()== UnitType.Civilian) return 0
|
||||
val ratio = getDefendingStrength(attacker,defender) / getAttackingStrength(attacker,defender)
|
||||
return (ratio * 30 * getHealthDependantDamageRatio(defender)).toInt()
|
||||
}
|
||||
|
||||
fun calculateDamageToDefender(attacker: ICombatant, defender: ICombatant): Int {
|
||||
val ratio = getAttackingStrength(attacker,defender) / getDefendingStrength(attacker,defender)
|
||||
return (ratio * 30 * getHealthDependantDamageRatio(attacker)).toInt()
|
||||
}
|
||||
|
||||
fun attack(attacker: ICombatant, defender: ICombatant) {
|
||||
val attackedTile = defender.getTile()
|
||||
|
||||
var damageToDefender = calculateDamageToDefender(attacker,defender)
|
||||
var damageToAttacker = calculateDamageToAttacker(attacker,defender)
|
||||
var damageToDefender = BattleDamage().calculateDamageToDefender(attacker,defender)
|
||||
var damageToAttacker = BattleDamage().calculateDamageToAttacker(attacker,defender)
|
||||
|
||||
if(defender.getUnitType() == UnitType.Civilian && attacker.isMelee()){
|
||||
captureCivilianUnit(attacker,defender)
|
||||
|
@ -182,6 +83,19 @@ class Battle(val gameInfo:GameInfo=UnCivGame.Current.gameInfo) {
|
|||
unit.attacksThisTurn+=1
|
||||
if(unit.isFortified()) attacker.unit.action=null // but not, for instance, if it's Set Up - then it should definitely keep the action!
|
||||
}
|
||||
|
||||
// XP!
|
||||
if(attacker.isMelee()){
|
||||
if(defender.getCivilization() != attacker.getCivilization()) // unit was not captured but actually attacked
|
||||
{
|
||||
if (attacker is MapUnitCombatant) attacker.unit.promotions.XP += 5
|
||||
if (defender is MapUnitCombatant) defender.unit.promotions.XP += 4
|
||||
}
|
||||
}
|
||||
else{ // ranged attack
|
||||
if(attacker is MapUnitCombatant) attacker.unit.promotions.XP += 2
|
||||
if(defender is MapUnitCombatant) defender.unit.promotions.XP += 2
|
||||
}
|
||||
}
|
||||
|
||||
private fun conquerCity(city: CityInfo, attacker: ICombatant) {
|
||||
|
@ -235,4 +149,5 @@ class Battle(val gameInfo:GameInfo=UnCivGame.Current.gameInfo) {
|
|||
capturedUnit.civInfo = attacker.getCivilization()
|
||||
capturedUnit.owner = capturedUnit.civInfo.civName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
104
core/src/com/unciv/logic/battle/BattleDamage.kt
Normal file
104
core/src/com/unciv/logic/battle/BattleDamage.kt
Normal file
|
@ -0,0 +1,104 @@
|
|||
package com.unciv.logic.battle
|
||||
|
||||
import com.unciv.models.gamebasics.unit.UnitType
|
||||
|
||||
|
||||
class BattleDamage{
|
||||
|
||||
private fun getGeneralModifiers(combatant: ICombatant, enemy: ICombatant): HashMap<String, Float> {
|
||||
val modifiers = HashMap<String, Float>()
|
||||
if (combatant is MapUnitCombatant) {
|
||||
val uniques = combatant.unit.getBaseUnit().uniques
|
||||
if (uniques != null) {
|
||||
// This beut allows us to have generic unit uniques: "Bonus vs City 75%", "Penatly vs Mounted 25%" etc.
|
||||
for (unique in uniques) {
|
||||
val regexResult = Regex("""(Bonus|Penalty) vs (\S*) (\d*)%""").matchEntire(unique)
|
||||
if (regexResult == null) continue
|
||||
val vsType = UnitType.valueOf(regexResult.groups[2]!!.value)
|
||||
val modificationAmount = regexResult.groups[3]!!.value.toFloat() / 100 // if it says 15%, that's 0.15f in modification
|
||||
if (enemy.getUnitType() == vsType) {
|
||||
if (regexResult.groups[1]!!.value == "Bonus")
|
||||
modifiers["Bonus vs $vsType"] = modificationAmount
|
||||
else modifiers["Penalty vs $vsType"] = -modificationAmount
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(enemy.getCivilization().isBarbarianCivilization())
|
||||
modifiers["vs Barbarians"] = 0.33f
|
||||
|
||||
if(combatant.getCivilization().happiness<0)
|
||||
modifiers["Unhappiness"] = 0.02f * combatant.getCivilization().happiness //https://www.carlsguides.com/strategy/civilization5/war/combatbonuses.php
|
||||
}
|
||||
|
||||
return modifiers
|
||||
}
|
||||
|
||||
fun getAttackModifiers(attacker: ICombatant, defender: ICombatant): HashMap<String, Float> {
|
||||
val modifiers = getGeneralModifiers(attacker, defender)
|
||||
if (attacker.isMelee()) {
|
||||
val numberOfAttackersSurroundingDefender = defender.getTile().neighbors.count {
|
||||
it.militaryUnit != null
|
||||
&& it.militaryUnit!!.owner == attacker.getCivilization().civName
|
||||
&& MapUnitCombatant(it.militaryUnit!!).isMelee()
|
||||
}
|
||||
if (numberOfAttackersSurroundingDefender > 1)
|
||||
modifiers["Flanking"] = 0.1f * (numberOfAttackersSurroundingDefender-1) //https://www.carlsguides.com/strategy/civilization5/war/combatbonuses.php
|
||||
}
|
||||
|
||||
return modifiers
|
||||
}
|
||||
|
||||
fun getDefenceModifiers(attacker: ICombatant, defender: ICombatant): HashMap<String, Float> {
|
||||
val modifiers = getGeneralModifiers(defender, attacker)
|
||||
if (!(defender is MapUnitCombatant && defender.unit.hasUnique("No defensive terrain bonus"))) {
|
||||
val tileDefenceBonus = defender.getTile().getDefensiveBonus()
|
||||
if (tileDefenceBonus > 0) modifiers["Terrain"] = tileDefenceBonus
|
||||
}
|
||||
if(defender is MapUnitCombatant && defender.unit.isFortified())
|
||||
modifiers["Fortification"]=0.2f*defender.unit.getFortificationTurns()
|
||||
return modifiers
|
||||
}
|
||||
|
||||
private fun modifiersToMultiplicationBonus(modifiers: HashMap<String, Float>): Float {
|
||||
// modifiers are like 0.1 for a 10% bonus, -0.1 for a 10% loss
|
||||
var modifier = 1f
|
||||
for (m in modifiers.values) modifier *= (1 + m)
|
||||
return modifier
|
||||
}
|
||||
|
||||
private fun getHealthDependantDamageRatio(combatant: ICombatant): Float {
|
||||
if (combatant.getUnitType() == UnitType.City) return 1f
|
||||
return 1/2f + combatant.getHealth()/200f // Each point of health reduces damage dealt by 0.5%
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Includes attack modifiers
|
||||
*/
|
||||
fun getAttackingStrength(attacker: ICombatant, defender: ICombatant): Float {
|
||||
val attackModifier = modifiersToMultiplicationBonus(getAttackModifiers(attacker,defender))
|
||||
return attacker.getAttackingStrength(defender) * attackModifier
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Includes defence modifiers
|
||||
*/
|
||||
fun getDefendingStrength(attacker: ICombatant, defender: ICombatant): Float {
|
||||
val defenceModifier = modifiersToMultiplicationBonus(getDefenceModifiers(attacker,defender))
|
||||
return defender.getDefendingStrength(attacker) * defenceModifier
|
||||
}
|
||||
|
||||
fun calculateDamageToAttacker(attacker: ICombatant, defender: ICombatant): Int {
|
||||
if(attacker.isRanged()) return 0
|
||||
if(defender.getUnitType()== UnitType.Civilian) return 0
|
||||
val ratio = getDefendingStrength(attacker,defender) / getAttackingStrength(attacker,defender)
|
||||
return (ratio * 30 * getHealthDependantDamageRatio(defender)).toInt()
|
||||
}
|
||||
|
||||
fun calculateDamageToDefender(attacker: ICombatant, defender: ICombatant): Int {
|
||||
val ratio = getAttackingStrength(attacker,defender) / getDefendingStrength(attacker,defender)
|
||||
return (ratio * 30 * getHealthDependantDamageRatio(attacker)).toInt()
|
||||
}
|
||||
}
|
|
@ -17,12 +17,12 @@ class MapUnitCombatant(val unit: MapUnit) : ICombatant {
|
|||
if(isDefeated()) unit.removeFromTile()
|
||||
}
|
||||
|
||||
override fun getAttackingStrength(defender: ICombatant): Int {
|
||||
override fun getAttackingStrength(defender: ICombatant): Int { // todo remove defender
|
||||
if (isRanged()) return unit.getBaseUnit().rangedStrength
|
||||
else return unit.getBaseUnit().strength
|
||||
}
|
||||
|
||||
override fun getDefendingStrength(attacker: ICombatant): Int {
|
||||
override fun getDefendingStrength(attacker: ICombatant): Int { // todo remove attacker
|
||||
return unit.getBaseUnit().strength
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ class MapUnit {
|
|||
var health:Int = 100
|
||||
var action: String? = null // work, automation, fortifying, I dunno what.
|
||||
var attacksThisTurn = 0
|
||||
var promotions = UnitPromotions()
|
||||
|
||||
fun getBaseUnit(): Unit = GameBasics.Units[name]!!
|
||||
fun getMovementString(): String = DecimalFormat("0.#").format(currentMovement.toDouble()) + "/" + maxMovement
|
||||
|
|
16
core/src/com/unciv/logic/map/UnitPromotions.kt
Normal file
16
core/src/com/unciv/logic/map/UnitPromotions.kt
Normal file
|
@ -0,0 +1,16 @@
|
|||
package com.unciv.logic.map
|
||||
|
||||
class UnitPromotions{
|
||||
var XP=0
|
||||
var promotions = HashSet<String>()
|
||||
var numberOfPromotions = 0 // The number of times this unit has been promoted - some promotions don't come from being promoted but from other things!
|
||||
|
||||
fun xpForNextPromotion() = (numberOfPromotions+1)*10
|
||||
fun canBePromoted() = XP >= xpForNextPromotion()
|
||||
|
||||
fun addPromotion(promotionName:String){
|
||||
XP -= xpForNextPromotion()
|
||||
promotions.add(promotionName)
|
||||
numberOfPromotions++
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@ import com.unciv.models.gamebasics.tile.Terrain
|
|||
import com.unciv.models.gamebasics.tile.TileImprovement
|
||||
import com.unciv.models.gamebasics.tile.TileResource
|
||||
import com.unciv.models.gamebasics.unit.Unit
|
||||
import com.unciv.models.gamebasics.unit.UnitPromotion
|
||||
import com.unciv.models.gamebasics.unit.Promotion
|
||||
import com.unciv.models.stats.INamed
|
||||
import kotlin.collections.set
|
||||
|
||||
|
@ -18,7 +18,7 @@ object GameBasics {
|
|||
val Technologies = LinkedHashMap<String, Technology>()
|
||||
val Helps = LinkedHashMap<String, BasicHelp>()
|
||||
val Units = LinkedHashMap<String, Unit>()
|
||||
val UnitPromotions = LinkedHashMap<String, UnitPromotion>()
|
||||
val UnitPromotions = LinkedHashMap<String, Promotion>()
|
||||
val Civilizations = LinkedHashMap<String, Civilization>()
|
||||
val PolicyBranches = LinkedHashMap<String, PolicyBranch>()
|
||||
val Tutorials = LinkedHashMap<String, List<String>>()
|
||||
|
@ -43,7 +43,7 @@ object GameBasics {
|
|||
TileImprovements += createHashmap(getFromJson(Array<TileImprovement>::class.java, "TileImprovements"))
|
||||
Helps += createHashmap(getFromJson(Array<BasicHelp>::class.java, "BasicHelp"))
|
||||
Units += createHashmap(getFromJson(Array<Unit>::class.java, "Units"))
|
||||
UnitPromotions += createHashmap(getFromJson(Array<UnitPromotion>::class.java, "UnitPromotions"))
|
||||
UnitPromotions += createHashmap(getFromJson(Array<Promotion>::class.java, "UnitPromotions"))
|
||||
PolicyBranches += createHashmap(getFromJson(Array<PolicyBranch>::class.java, "Policies"))
|
||||
Civilizations += createHashmap(getFromJson(Array<Civilization>::class.java, "Civilizations"))
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ package com.unciv.models.gamebasics.unit
|
|||
import com.unciv.models.gamebasics.ICivilopedia
|
||||
import com.unciv.models.stats.INamed
|
||||
|
||||
class UnitPromotion : ICivilopedia, INamed{
|
||||
class Promotion : ICivilopedia, INamed{
|
||||
override lateinit var name: String
|
||||
override val description: String
|
||||
get(){
|
||||
|
@ -11,5 +11,5 @@ class UnitPromotion : ICivilopedia, INamed{
|
|||
}
|
||||
var prerequisites = listOf<String>()
|
||||
lateinit var effect:String;
|
||||
var unitTypes = listOf<UnitType>()
|
||||
var unitTypes = listOf<String>() // The json parser woulddn't agree to deserialize this as a list of UnitTypes. =(
|
||||
}
|
|
@ -61,7 +61,7 @@ class CityStatsTable(val cityScreen: CityScreen) : Table(){
|
|||
!(construction is Building && construction.isWonder)) {
|
||||
row()
|
||||
val buildingGoldCost = construction.getGoldCost(city.civInfo.policies.getAdoptedPolicies())
|
||||
val buildingBuyButton = TextButton("Buy for".tr()+"\r\n$buildingGoldCost gold", CameraStageBaseScreen.skin)
|
||||
val buildingBuyButton = TextButton("Buy for".tr()+"\r\n$buildingGoldCost "+"Gold".tr(), CameraStageBaseScreen.skin)
|
||||
buildingBuyButton.addClickListener {
|
||||
city.cityConstructions.purchaseBuilding(city.cityConstructions.currentConstruction)
|
||||
update()
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
package com.unciv.ui.pickerscreens
|
||||
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.scenes.scene2d.Touchable
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.*
|
||||
import com.badlogic.gdx.utils.Align
|
||||
import com.unciv.ui.utils.CameraStageBaseScreen
|
||||
import com.unciv.ui.utils.addClickListener
|
||||
import com.unciv.ui.utils.disable
|
||||
import com.unciv.ui.utils.tr
|
||||
import com.unciv.ui.utils.*
|
||||
|
||||
open class PickerScreen : CameraStageBaseScreen() {
|
||||
|
||||
|
@ -53,9 +48,7 @@ open class PickerScreen : CameraStageBaseScreen() {
|
|||
}
|
||||
|
||||
protected fun pick(rightButtonText: String) {
|
||||
rightSideButton.touchable = Touchable.enabled
|
||||
rightSideButton.color = Color.WHITE
|
||||
rightSideButton.enable()
|
||||
rightSideButton.setText(rightButtonText)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -6,37 +6,44 @@ import com.badlogic.gdx.scenes.scene2d.ui.Label
|
|||
import com.badlogic.gdx.scenes.scene2d.ui.VerticalGroup
|
||||
import com.unciv.logic.map.MapUnit
|
||||
import com.unciv.models.gamebasics.GameBasics
|
||||
import com.unciv.models.gamebasics.unit.UnitPromotion
|
||||
import com.unciv.ui.utils.ImageGetter
|
||||
import com.unciv.ui.utils.addClickListener
|
||||
import com.unciv.ui.utils.setFontColor
|
||||
import com.unciv.models.gamebasics.unit.Promotion
|
||||
import com.unciv.ui.utils.*
|
||||
|
||||
class PromotionPickerScreen(mapUnit: MapUnit) : PickerScreen() {
|
||||
private var selectedPromotion: UnitPromotion? = null
|
||||
private var selectedPromotion: Promotion? = null
|
||||
|
||||
|
||||
init {
|
||||
rightSideButton.setText("Pick promotion")
|
||||
rightSideButton.addClickListener {
|
||||
// todo add promotion to unit and decrease XP
|
||||
mapUnit.promotions.addPromotion(selectedPromotion!!.name)
|
||||
game.setWorldScreen()
|
||||
dispose()
|
||||
}
|
||||
|
||||
val availablePromotions = VerticalGroup()
|
||||
availablePromotions.space(10f)
|
||||
val unitType = mapUnit.getBaseUnit().unitType
|
||||
for (promotion in GameBasics.UnitPromotions.values) {
|
||||
if (!promotion.unitTypes.contains(mapUnit.getBaseUnit().unitType)) continue
|
||||
if (!promotion.unitTypes.contains(unitType.toString())) continue
|
||||
val isPromotionAvailable = promotion.prerequisites.all { mapUnit.promotions.promotions.contains(it) }
|
||||
val unitHasPromotion = mapUnit.promotions.promotions.contains(promotion.name)
|
||||
val promotionButton = Button(skin)
|
||||
|
||||
if(!isPromotionAvailable) promotionButton.color = Color.GRAY
|
||||
promotionButton.add(ImageGetter.getPromotionIcon(promotion.name)).size(30f).pad(10f)
|
||||
|
||||
promotionButton.add(Label(promotion.name, skin)
|
||||
.setFontColor(Color.WHITE)).pad(10f)
|
||||
if(unitHasPromotion) promotionButton.color = Color.GREEN
|
||||
|
||||
promotionButton.addClickListener {
|
||||
selectedPromotion = promotion
|
||||
pick(promotion.name)
|
||||
descriptionLabel.setText(promotion.effect)
|
||||
rightSideButton.setText(promotion.name)
|
||||
if(isPromotionAvailable && !unitHasPromotion) rightSideButton.enable()
|
||||
else rightSideButton.disable()
|
||||
var descriptionText = promotion.effect
|
||||
if(promotion.prerequisites.isNotEmpty()) descriptionText +="\nRequires: "+promotion.prerequisites.joinToString()
|
||||
descriptionLabel.setText(descriptionText)
|
||||
}
|
||||
availablePromotions.addActor(promotionButton)
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table
|
|||
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
|
||||
import com.unciv.logic.automation.UnitAutomation
|
||||
import com.unciv.logic.battle.Battle
|
||||
import com.unciv.logic.battle.BattleDamage
|
||||
import com.unciv.logic.battle.ICombatant
|
||||
import com.unciv.logic.battle.MapUnitCombatant
|
||||
import com.unciv.models.gamebasics.unit.UnitType
|
||||
|
@ -19,7 +20,7 @@ class BattleTable(val worldScreen: WorldScreen): Table() {
|
|||
skin = CameraStageBaseScreen.skin
|
||||
background = ImageGetter.getDrawable(ImageGetter.WhiteDot)
|
||||
.tint(ImageGetter.getBlue())
|
||||
pad(10f)
|
||||
pad(5f)
|
||||
}
|
||||
|
||||
fun hide(){
|
||||
|
@ -66,17 +67,17 @@ class BattleTable(val worldScreen: WorldScreen): Table() {
|
|||
add("Strength: "+defender.getDefendingStrength(attacker))
|
||||
row().pad(5f)
|
||||
|
||||
val attackerModifiers = battle.getAttackModifiers(attacker,defender) .map { it.key+": "+(if(it.value>0)"+" else "")+(it.value*100).toInt()+"%" }
|
||||
val defenderModifiers = battle.getDefenceModifiers(attacker, defender).map { it.key+": "+(if(it.value>0)"+" else "")+(it.value*100).toInt()+"%" }
|
||||
val attackerModifiers = BattleDamage().getAttackModifiers(attacker,defender) .map { it.key+": "+(if(it.value>0)"+" else "")+(it.value*100).toInt()+"%" }
|
||||
val defenderModifiers = BattleDamage().getDefenceModifiers(attacker, defender).map { it.key+": "+(if(it.value>0)"+" else "")+(it.value*100).toInt()+"%" }
|
||||
|
||||
for(i in 0..max(attackerModifiers.size,defenderModifiers.size)){
|
||||
if (attackerModifiers.size > i) add(attackerModifiers[i]) else add()
|
||||
if (defenderModifiers.size > i) add(defenderModifiers[i]) else add()
|
||||
row().pad(5f)
|
||||
row().pad(2f)
|
||||
}
|
||||
|
||||
var damageToDefender = battle.calculateDamageToDefender(attacker,defender)
|
||||
var damageToAttacker = battle.calculateDamageToAttacker(attacker,defender)
|
||||
var damageToDefender = BattleDamage().calculateDamageToDefender(attacker,defender)
|
||||
var damageToAttacker = BattleDamage().calculateDamageToAttacker(attacker,defender)
|
||||
|
||||
|
||||
if (damageToAttacker>attacker.getHealth() && damageToDefender>defender.getHealth()) // when damage exceeds health, we don't want to show negative health numbers
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
package com.unciv.ui.worldscreen.unit
|
||||
|
||||
import com.unciv.UnCivGame
|
||||
import com.unciv.logic.automation.WorkerAutomation
|
||||
import com.unciv.logic.map.MapUnit
|
||||
import com.unciv.models.gamebasics.Building
|
||||
import com.unciv.models.gamebasics.GameBasics
|
||||
import com.unciv.models.gamebasics.unit.UnitType
|
||||
import com.unciv.ui.pickerscreens.ImprovementPickerScreen
|
||||
import com.unciv.ui.pickerscreens.PromotionPickerScreen
|
||||
import com.unciv.ui.pickerscreens.TechPickerScreen
|
||||
import com.unciv.ui.worldscreen.WorldScreen
|
||||
import java.util.*
|
||||
|
@ -34,7 +36,6 @@ class UnitActions {
|
|||
unitTable.currentlyExecutingAction = "moveTo"
|
||||
}, unit.currentMovement != 0f )
|
||||
}
|
||||
|
||||
else {
|
||||
actionList +=
|
||||
UnitAction("Stop movement", {
|
||||
|
@ -43,9 +44,15 @@ class UnitActions {
|
|||
},true)
|
||||
}
|
||||
|
||||
if(unit.getBaseUnit().unitType!= UnitType.Civilian && !unit.hasUnique("No defensive terrain bonus")){
|
||||
if(!unit.isFortified())
|
||||
actionList += UnitAction("Fortify",{unit.action="Fortify 0"}, unit.currentMovement != 0f)
|
||||
if(unit.getBaseUnit().unitType!= UnitType.Civilian
|
||||
&& !unit.hasUnique("No defensive terrain bonus") && !unit.isFortified()) {
|
||||
actionList += UnitAction("Fortify", { unit.action = "Fortify 0" }, unit.currentMovement != 0f)
|
||||
}
|
||||
|
||||
if(unit.promotions.canBePromoted()){
|
||||
actionList += UnitAction("Promote",
|
||||
{UnCivGame.Current.screen = PromotionPickerScreen(unit)},
|
||||
unit.currentMovement != 0f)
|
||||
}
|
||||
|
||||
if(unit.getBaseUnit().upgradesTo!=null) {
|
||||
|
@ -158,5 +165,4 @@ class UnitActions {
|
|||
return actionList
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -21,6 +21,7 @@ class UnitActionsTable(val worldScreen: WorldScreen) : Table(){
|
|||
"Move unit" -> return ImageGetter.getStatIcon("Movement")
|
||||
"Stop movement"-> return ImageGetter.getStatIcon("Movement").apply { color= Color.RED }
|
||||
"Fortify" -> return ImageGetter.getImage("OtherIcons/Shield.png").apply { color= Color.BLACK }
|
||||
"Promote" -> return ImageGetter.getImage("OtherIcons/Star.png").apply { color= Color.GOLD }
|
||||
"Construct improvement" -> return ImageGetter.getUnitIcon("Worker")
|
||||
"Automate" -> return ImageGetter.getUnitIcon("Great Engineer")
|
||||
"Stop automation" -> return ImageGetter.getImage("OtherIcons/Stop.png")
|
||||
|
|
|
@ -6,6 +6,7 @@ import com.unciv.logic.map.MapUnit
|
|||
import com.unciv.logic.map.TileInfo
|
||||
import com.unciv.models.gamebasics.unit.UnitType
|
||||
import com.unciv.ui.utils.CameraStageBaseScreen
|
||||
import com.unciv.ui.utils.ImageGetter
|
||||
import com.unciv.ui.utils.addClickListener
|
||||
import com.unciv.ui.utils.tr
|
||||
import com.unciv.ui.worldscreen.WorldScreen
|
||||
|
@ -14,26 +15,27 @@ class UnitTable(val worldScreen: WorldScreen) : Table(){
|
|||
private val prevIdleUnitButton = IdleUnitButton(this,worldScreen.tileMapHolder,true)
|
||||
private val nextIdleUnitButton = IdleUnitButton(this,worldScreen.tileMapHolder,false)
|
||||
private val unitNameLabel = Label("",CameraStageBaseScreen.skin)
|
||||
private val promotionsTable = Table()
|
||||
private val unitDescriptionLabel = Label("",CameraStageBaseScreen.skin)
|
||||
var selectedUnit : MapUnit? = null
|
||||
var currentlyExecutingAction : String? = null
|
||||
|
||||
init {
|
||||
|
||||
pad(20f)
|
||||
pad(5f)
|
||||
|
||||
add(Table().apply {
|
||||
add(prevIdleUnitButton)
|
||||
add(unitNameLabel).pad(10f)
|
||||
add(unitNameLabel).pad(5f)
|
||||
add(nextIdleUnitButton)
|
||||
}).colspan(2)
|
||||
row()
|
||||
}).colspan(2).row()
|
||||
add(promotionsTable).row()
|
||||
add(unitDescriptionLabel)
|
||||
}
|
||||
|
||||
fun update() {
|
||||
prevIdleUnitButton.update()
|
||||
nextIdleUnitButton.update()
|
||||
promotionsTable.clear()
|
||||
unitDescriptionLabel.clearListeners()
|
||||
|
||||
if(selectedUnit!=null)
|
||||
|
@ -58,6 +60,9 @@ class UnitTable(val worldScreen: WorldScreen) : Table(){
|
|||
if(unit.health<100) nameLabelText+=" ("+unit.health+")"
|
||||
unitNameLabel.setText(nameLabelText)
|
||||
|
||||
for(promotion in unit.promotions.promotions)
|
||||
promotionsTable.add(ImageGetter.getPromotionIcon(promotion)).size(20f)
|
||||
|
||||
var unitLabelText = "Movement".tr()+": " + unit.getMovementString()
|
||||
if (unit.getBaseUnit().unitType != UnitType.Civilian) {
|
||||
unitLabelText += "\n"+"Strength".tr()+": " + unit.getBaseUnit().strength
|
||||
|
@ -65,6 +70,8 @@ class UnitTable(val worldScreen: WorldScreen) : Table(){
|
|||
if (unit.getBaseUnit().rangedStrength!=0)
|
||||
unitLabelText += "\n"+"Ranged strength".tr()+": "+unit.getBaseUnit().rangedStrength
|
||||
|
||||
unitLabelText += "\n"+"XP".tr()+": "+unit.promotions.XP
|
||||
|
||||
if(unit.isFortified() && unit.getFortificationTurns()>0)
|
||||
unitLabelText+="\n+"+unit.getFortificationTurns()*20+"% fortification"
|
||||
|
||||
|
|
Loading…
Reference in a new issue