Fixed battle animation crash (#12585)

This commit is contained in:
Yair Morgenstern 2024-12-06 12:18:09 +02:00 committed by GitHub
parent d745b10a1b
commit 67ce623f05
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 24 additions and 15 deletions

View File

@ -29,7 +29,7 @@ import com.unciv.ui.images.ImageGetter
import com.unciv.ui.screens.basescreen.BaseScreen
import com.unciv.ui.screens.worldscreen.UndoHandler.Companion.clearUndoCheckpoints
import com.unciv.ui.screens.worldscreen.WorldScreen
import com.unciv.ui.screens.worldscreen.bottombar.BattleTableHelpers.battleAnimation
import com.unciv.ui.screens.worldscreen.bottombar.BattleTableHelpers.battleAnimationDeferred
import com.unciv.ui.screens.worldscreen.bottombar.BattleTableHelpers.getHealthBar
import com.unciv.utils.DebugUtils
import kotlin.math.max
@ -305,7 +305,7 @@ class BattleTable(val worldScreen: WorldScreen) : Table() {
SoundPlayer.play(attacker.getAttackSound())
val (damageToDefender, damageToAttacker) = Battle.attackOrNuke(attacker, attackableTile)
worldScreen.battleAnimation(attacker, damageToAttacker, defender, damageToDefender)
worldScreen.battleAnimationDeferred(attacker, damageToAttacker, defender, damageToDefender)
if (!attacker.canAttack()) hide()
}

View File

@ -4,7 +4,6 @@ import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.math.Interpolation
import com.badlogic.gdx.math.Vector2
import com.badlogic.gdx.scenes.scene2d.Actor
import com.badlogic.gdx.scenes.scene2d.Group
import com.badlogic.gdx.scenes.scene2d.actions.Actions
import com.badlogic.gdx.scenes.scene2d.actions.FloatAction
import com.badlogic.gdx.scenes.scene2d.actions.RelativeTemporalAction
@ -23,6 +22,7 @@ import com.unciv.ui.components.tilegroups.TileSetStrings
import com.unciv.ui.components.widgets.ShadowedLabel
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.screens.worldscreen.WorldScreen
import com.unciv.utils.Concurrency
object BattleTableHelpers {
@ -144,22 +144,31 @@ object BattleTableHelpers {
}
}
fun WorldScreen.battleAnimationDeferred(
attacker: ICombatant, damageToAttacker: Int,
defender: ICombatant, damageToDefender: Int
){
// This ensures that we schedule the animation to happen AFTER the worldscreen.update(),
// where the spriteGroup of the attacker is created on the tile it moves to
Concurrency.runOnGLThread { battleAnimation(attacker, damageToAttacker, defender, damageToDefender) }
}
fun WorldScreen.battleAnimation(
private fun WorldScreen.battleAnimation(
attacker: ICombatant, damageToAttacker: Int,
defender: ICombatant, damageToDefender: Int
) {
fun getMapActorsForCombatant(combatant: ICombatant): Sequence<Actor> =
sequence {
val tileGroup = mapHolder.tileGroups[combatant.getTile()]!!
if (combatant.isCity()) {
val icon = tileGroup.layerMisc.improvementIcon
if (icon != null) yield (icon)
} else if (!combatant.isAirUnit()) {
val slot = if (combatant.isCivilian()) 0 else 1
yieldAll((tileGroup.layerUnitArt.getChild(slot) as Group).children)
}
sequence {
val tileGroup = mapHolder.tileGroups[combatant.getTile()]!!
if (combatant.isCity()) {
val icon = tileGroup.layerMisc.improvementIcon
if (icon != null) yield (icon)
} else if (!combatant.isAirUnit()) {
val slot = tileGroup.layerUnitArt.getSpriteSlot((combatant as MapUnitCombatant).unit)
if (slot != null) yieldAll(slot.spriteGroup.children)
}
}
val actorsToFlashRed =
sequence {

View File

@ -44,7 +44,7 @@ import com.unciv.ui.components.widgets.ZoomableScrollPane
import com.unciv.ui.screens.basescreen.UncivStage
import com.unciv.ui.screens.worldscreen.UndoHandler.Companion.recordUndoCheckpoint
import com.unciv.ui.screens.worldscreen.WorldScreen
import com.unciv.ui.screens.worldscreen.bottombar.BattleTableHelpers.battleAnimation
import com.unciv.ui.screens.worldscreen.bottombar.BattleTableHelpers.battleAnimationDeferred
import com.unciv.utils.Concurrency
import com.unciv.utils.Log
import com.unciv.utils.launchOnGLThread
@ -236,7 +236,7 @@ class WorldMapHolder(
SoundPlayer.play(attacker.getAttackSound())
val (damageToDefender, damageToAttacker) = Battle.attackOrNuke(attacker, attackableTile)
if (attackableTile.combatant != null)
worldScreen.battleAnimation(attacker, damageToAttacker, attackableTile.combatant, damageToDefender)
worldScreen.battleAnimationDeferred(attacker, damageToAttacker, attackableTile.combatant, damageToDefender)
localShouldUpdate = true
} else if (unit.movement.canReach(tile)) {
/** ****** Right-click Move ****** */