Removed debugging logging.

This commit is contained in:
lightheel 2025-11-17 17:22:25 -05:00
parent d1908d629a
commit c4450296db
11 changed files with 4 additions and 106 deletions

View File

@ -63,14 +63,11 @@ fun AnimatedSpriteImage(
// Update sprite when animation state changes
LaunchedEffect(animationStateMachine.currentFrameNumber) {
val frameNumber = animationStateMachine.getCurrentFrame()
println("Loading animated sprite frame: $frameNumber for character: $characterId")
bitmap = spriteManager.loadSpriteFrame(characterId, frameNumber)
if (bitmap == null) {
println("Failed to load animated sprite frame: $frameNumber for character: $characterId")
} else {
println("Successfully loaded animated sprite frame: $frameNumber for character: $characterId")
}
}

View File

@ -112,7 +112,6 @@ class ArenaBattleSystem {
val opponentAttackIsHit: Boolean get() = _opponentAttackIsHit
fun startPlayerAttack() {
Log.d(TAG, "Starting player attack")
_attackPhase = 1
_attackProgress = 0f
_isPlayerAttacking = true
@ -121,7 +120,6 @@ class ArenaBattleSystem {
}
fun startOpponentAttack() {
Log.d(TAG, "Starting opponent attack")
_attackPhase = 3
_attackProgress = 0f
_isPlayerAttacking = false
@ -131,7 +129,6 @@ class ArenaBattleSystem {
fun advanceAttackPhase() {
_attackPhase++
_attackProgress = 0f
Log.d(TAG, "Advanced to attack phase: $_attackPhase")
}
fun setAttackProgress(progress: Float) {
@ -144,12 +141,10 @@ class ArenaBattleSystem {
fun switchToView(view: Int) {
_currentView = view
Log.d(TAG, "Switched to view: $view")
}
fun enableAttackButton() {
_isAttackButtonEnabled = true
Log.d(TAG, "Attack button enabled")
}
fun applyDamage(isPlayer: Boolean, damage: Float) {
@ -158,19 +153,16 @@ class ArenaBattleSystem {
} else {
_opponentHP = (_opponentHP - damage).coerceAtLeast(0f)
}
Log.d(TAG, "Applied damage: ${if (isPlayer) "player" else "opponent"} -$damage")
}
fun updateHPFromAPI(playerHP: Float, opponentHP: Float) {
_playerHP = playerHP
_opponentHP = opponentHP
Log.d(TAG, "Updated HP from API: Player=$playerHP, Opponent=$opponentHP")
}
fun initializeHP(playerMaxHP: Float, opponentMaxHP: Float) {
_playerHP = playerMaxHP
_opponentHP = opponentMaxHP
Log.d(TAG, "Initialized HP: Player=$playerMaxHP, Opponent=$opponentMaxHP")
}
fun completeAttackAnimation(playerDamage: Float = 0f, opponentDamage: Float = 0f) {
@ -180,7 +172,6 @@ class ArenaBattleSystem {
if (opponentDamage > 0f) {
applyDamage(false, opponentDamage)
}
Log.d(TAG, "Completed attack animation with damage: Player=$playerDamage, Opponent=$opponentDamage")
}
fun resetAttackState() {
@ -209,7 +200,6 @@ class ArenaBattleSystem {
_shouldCounterAttack = false
_counterAttackIsHit = false
_opponentAttackIsHit = false
Log.d(TAG, "Reset attack state")
}
fun checkBattleOver(): Boolean {
@ -218,7 +208,6 @@ class ArenaBattleSystem {
fun endBattle() {
_isBattleOver = true
Log.d(TAG, "Battle ended")
}
fun updateCritBarProgress(progress: Int) {
@ -231,7 +220,6 @@ class ArenaBattleSystem {
_isDodging = true
_dodgeProgress = 0f
_dodgeDirection = 1f // Start moving up
Log.d(TAG, "Started dodge animation")
}
fun setDodgeProgress(progress: Float) {
@ -245,14 +233,12 @@ class ArenaBattleSystem {
fun endDodge() {
_isDodging = false
_dodgeProgress = 0f
Log.d(TAG, "Ended dodge animation")
}
// Hit animation methods
fun startHit() {
_isHit = true
_hitProgress = 0f
Log.d(TAG, "Started hit animation")
}
fun setHitProgress(progress: Float) {
@ -262,7 +248,6 @@ class ArenaBattleSystem {
fun endHit() {
_isHit = false
_hitProgress = 0f
Log.d(TAG, "Ended hit animation")
}
// Player-specific dodge methods
@ -270,13 +255,11 @@ class ArenaBattleSystem {
_isPlayerDodging = true
_playerDodgeProgress = 0f
_playerDodgeDirection = 1f
Log.d(TAG, "Started player dodge animation")
}
fun endPlayerDodge() {
_isPlayerDodging = false
_playerDodgeProgress = 0f
Log.d(TAG, "Ended player dodge animation")
}
fun setPlayerDodgeProgress(progress: Float) {
@ -292,13 +275,11 @@ class ArenaBattleSystem {
_isOpponentDodging = true
_opponentDodgeProgress = 0f
_opponentDodgeDirection = 1f
Log.d(TAG, "Started opponent dodge animation")
}
fun endOpponentDodge() {
_isOpponentDodging = false
_opponentDodgeProgress = 0f
Log.d(TAG, "Ended opponent dodge animation")
}
fun setOpponentDodgeProgress(progress: Float) {
@ -313,67 +294,55 @@ class ArenaBattleSystem {
fun startPlayerHit() {
_isPlayerHit = true
_hitProgress = 0f
Log.d(TAG, "Started player hit animation")
}
fun startPlayerHitDelayed() {
_isPlayerHitDelayed = true
Log.d(TAG, "Started delayed player hit animation")
}
fun endPlayerHit() {
_isPlayerHit = false
_hitProgress = 0f
Log.d(TAG, "Ended player hit animation")
}
fun endPlayerHitDelayed() {
_isPlayerHitDelayed = false
Log.d(TAG, "Ended delayed player hit animation")
}
// Opponent-specific hit methods
fun startOpponentHit() {
_isOpponentHit = true
_hitProgress = 0f
Log.d(TAG, "Started opponent hit animation")
}
fun startOpponentHitDelayed() {
_isOpponentHitDelayed = true
Log.d(TAG, "Started delayed opponent hit animation")
}
fun endOpponentHit() {
_isOpponentHit = false
_hitProgress = 0f
Log.d(TAG, "Ended opponent hit animation")
}
fun endOpponentHitDelayed() {
_isOpponentHitDelayed = false
Log.d(TAG, "Ended delayed opponent hit animation")
}
// Delayed shake methods
fun startPlayerShakeDelayed() {
_isPlayerShakeDelayed = true
Log.d(TAG, "Started delayed player shake animation")
}
fun endPlayerShakeDelayed() {
_isPlayerShakeDelayed = false
Log.d(TAG, "Ended delayed player shake animation")
}
fun startOpponentShakeDelayed() {
_isOpponentShakeDelayed = true
Log.d(TAG, "Started delayed opponent shake animation")
}
fun endOpponentShakeDelayed() {
_isOpponentShakeDelayed = false
Log.d(TAG, "Ended delayed opponent shake animation")
}
// Combined method to handle attack result
@ -386,7 +355,6 @@ class ArenaBattleSystem {
// Player attack missed - opponent dodges
startOpponentDodge()
}
Log.d(TAG, "Handled player attack result: ${if (isHit) "HIT" else "DODGE"}")
}
// Method to handle opponent attack result
@ -399,14 +367,12 @@ class ArenaBattleSystem {
// Opponent attack missed - player dodges
startPlayerDodge()
}
Log.d(TAG, "Handled opponent attack result: ${if (isHit) "HIT" else "DODGE"}")
}
// Counter-attack methods
fun setupCounterAttack(isHit: Boolean) {
_shouldCounterAttack = true
_counterAttackIsHit = isHit
Log.d(TAG, "Setup counter-attack: ${if (isHit) "HIT" else "DODGE"}, isHit=$isHit")
}
fun startCounterAttack() {
@ -415,6 +381,5 @@ class ArenaBattleSystem {
_isPlayerAttacking = false
_currentView = 1
_opponentAttackIsHit = _counterAttackIsHit
Log.d(TAG, "Started counter-attack with opponentAttackIsHit=$_opponentAttackIsHit, counterAttackIsHit=$_counterAttackIsHit")
}
}

View File

@ -43,15 +43,12 @@ class AttackSpriteManager(private val context: Context) {
try {
// Get character data
val characterData = getCharacterData(characterId) ?: return null
println("AttackSpriteManager: Got character data: $characterData")
// Determine which attack file to use
val attackFileName = if (isLarge) {
characterData.laugeFileName
} else {
characterData.smalefilename
}
println("AttackSpriteManager: Attack filename = $attackFileName")
// Skip if no attack file
if (attackFileName == "0") {
@ -61,12 +58,9 @@ class AttackSpriteManager(private val context: Context) {
// Load the attack sprite from external storage
val attackFile = File(getAttackTexturesBaseDir(), "$attackFileName.png")
println("AttackSpriteManager: Attack file path = ${attackFile.absolutePath}")
println("AttackSpriteManager: Attack file exists = ${attackFile.exists()}")
return if (attackFile.exists()) {
val bitmap = BitmapFactory.decodeFile(attackFile.absolutePath)
println("AttackSpriteManager: Successfully loaded bitmap = ${bitmap != null}")
bitmap
} else {
println("AttackSpriteManager: Attack file does not exist")
@ -80,10 +74,8 @@ class AttackSpriteManager(private val context: Context) {
}
private fun getCharacterData(characterId: String): CharacterData? {
println("AttackSpriteManager: Getting character data for characterId=$characterId")
// Check cache first
if (characterDataCache.containsKey(characterId)) {
println("AttackSpriteManager: Found character data in cache")
return characterDataCache[characterId]
}
@ -91,8 +83,6 @@ class AttackSpriteManager(private val context: Context) {
// Load character data from JSON file in external storage
val externalDir = android.os.Environment.getExternalStorageDirectory()
val characterDataFile = File(externalDir, "VBHelper/battle_sprites/extracted_digimon_stats/character_data/CharacterData.json")
println("AttackSpriteManager: Character data file path = ${characterDataFile.absolutePath}")
println("AttackSpriteManager: Character data file exists = ${characterDataFile.exists()}")
if (!characterDataFile.exists()) {
println("AttackSpriteManager: Character data file does not exist, using default data")
@ -109,7 +99,6 @@ class AttackSpriteManager(private val context: Context) {
}
val jsonContent = characterDataFile.readText()
println("AttackSpriteManager: JSON content length = ${jsonContent.length}")
// Parse the JSON response
val response = gson.fromJson(jsonContent, CharacterDataResponse::class.java)
@ -136,7 +125,6 @@ class AttackSpriteManager(private val context: Context) {
)
characterDataCache[characterId] = characterData
println("AttackSpriteManager: Found character data: $characterData")
return characterData
}
}
@ -152,7 +140,6 @@ class AttackSpriteManager(private val context: Context) {
)
characterDataCache[characterId] = characterData
println("AttackSpriteManager: Created default character data: $characterData")
return characterData
} catch (e: Exception) {

View File

@ -79,11 +79,13 @@ class DigimonAnimationStateMachine(
DigimonAnimationType.ATTACK to 650L,
DigimonAnimationType.FLEE to 150L
)
/*
init {
println("Initialized DigimonAnimationStateMachine for character: $characterId with frame offset: $initialFrameOffset, timing offset: $timingOffset")
println("Available animation types: ${animationTypeToFrames.keys}")
}
*/
suspend fun playAnimation(animationType: DigimonAnimationType) {
if (currentAnimation == animationType && isPlaying) {
@ -96,8 +98,6 @@ class DigimonAnimationStateMachine(
val frameNumbers = animationTypeToFrames[animationType] ?: listOf(1)
val duration = animationDurations[animationType] ?: 100L
println("Playing animation: $animationType with frames: $frameNumbers")
// For non-looping animations like ATTACK, play once and return to IDLE
if (animationType == DigimonAnimationType.ATTACK) {
currentFrameNumber = frameNumbers.firstOrNull() ?: 1
@ -130,8 +130,6 @@ class DigimonAnimationStateMachine(
// Combine frames for cycling idle animation
val combinedFrames = (idleFrames + idle2Frames).distinct()
println("Playing idle animation with frames: $combinedFrames, starting at offset: $initialFrameOffset, timing offset: $timingOffset")
val duration = animationDurations[DigimonAnimationType.IDLE] ?: 500L
// Apply initial timing offset

View File

@ -39,7 +39,6 @@ fun HitEffectOverlay(
LaunchedEffect(isVisible) {
if (isVisible) {
println("DEBUG: Starting hit effect animation")
// Add delay before starting hit effect animation
delay(400) // Increased from 200ms to 400ms delay before hit effect appears

View File

@ -44,8 +44,6 @@ class HitEffectSpriteManager(private val context: Context) {
return null
}
println("Successfully loaded hit sprite: $spriteName.png (${bitmap.width}x${bitmap.height})")
// Cache the result
spriteCache[cacheKey] = bitmap

View File

@ -53,8 +53,6 @@ class IndividualSpriteManager(private val context: Context) {
return null
}
println("Successfully loaded sprite frame: $spriteFileName (${bitmap.width}x${bitmap.height})")
// Cache the result
spriteCache[cacheKey] = bitmap

View File

@ -205,9 +205,6 @@ class RetrofitHelper {
val service: AuthService = retrofit.create<AuthService>(AuthService::class.java)
val request = AuthenticateRequest(userToken = token)
println("RetrofitHelper: Sending request to api/auth/validate with userToken: $token")
//println("RetrofitHelper: Request object: $request")
//println("RetrofitHelper: Request JSON will be: {\"userToken\": \"$token\"}")
val call: Call<AuthenticateResponse> = service.validate(request)
call.enqueue(object : Callback<AuthenticateResponse> {
@ -218,13 +215,10 @@ class RetrofitHelper {
}
override fun onResponse(call: Call<AuthenticateResponse>, response: Response<AuthenticateResponse>) {
println("RetrofitHelper: Validate API response received - Code: ${response.code()}")
println("RetrofitHelper: Response body: ${response.body()}")
if (response.isSuccessful) {
val authResponse: AuthenticateResponse? = response.body()
if (authResponse != null) {
println("RetrofitHelper: Validation successful: ${authResponse.success}, message: ${authResponse.message}")
callback(authResponse)
} else {
println("RetrofitHelper: Validation failed: Invalid response body")

View File

@ -24,8 +24,6 @@ fun SpriteImage(
bitmap = spriteManager.loadSpriteFrame(characterId, frameNumber)
if (bitmap == null) {
println("Failed to load sprite frame: $frameNumber for character: $characterId")
} else {
println("Successfully loaded sprite frame: $frameNumber for character: $characterId")
}
}

View File

@ -30,7 +30,6 @@ fun AttackSpriteImage(
val loadedBitmap = withContext(Dispatchers.IO) {
attackSpriteManager.getAttackSprite(characterId, isLarge)
}
println("AttackSpriteImage: Loaded bitmap = ${loadedBitmap != null}")
bitmap = loadedBitmap
}
}

View File

@ -1051,39 +1051,28 @@ fun MiddleBattleView(
when (apiResult.state) {
1 -> {
// Match is still ongoing - update HP and continue
println("Round ${apiResult.currentRound}: Player HP=${apiResult.playerHP}, Opponent HP=${apiResult.opponentHP}")
// Set pending damage based on API result
if (apiResult.playerAttackDamage > 0) {
// Player attack hit - enemy takes damage at end of player animation
println("Player attack hit! Enemy will take ${apiResult.playerAttackDamage} damage")
onSetPendingDamage(0f, apiResult.playerAttackDamage.toFloat()) // Opponent takes damage
battleSystem.setAttackHitState(true)
// Also check if enemy counter-attacks and hits
if (apiResult.opponentAttackDamage > 0) {
println("Enemy counter-attack hits! Player takes ${apiResult.opponentAttackDamage} damage")
onSetPendingDamage(apiResult.opponentAttackDamage.toFloat(), apiResult.playerAttackDamage.toFloat()) // Both take damage
}
} else {
// Player attack missed - enemy counter-attacks
println("Player attack missed! Enemy counter-attacks")
battleSystem.setAttackHitState(false)
// Set up counter-attack - determine if it hits based on API result
val counterAttackHits = apiResult.opponentAttackDamage > 0
println("Setting up counter-attack: counterAttackHits=$counterAttackHits, opponentAttackDamage=${apiResult.opponentAttackDamage}")
println("Full API response: status=${apiResult.status}, state=${apiResult.state}, playerAttackHit=${apiResult.playerAttackHit}, playerAttackDamage=${apiResult.playerAttackDamage}, opponentAttackDamage=${apiResult.opponentAttackDamage}, playerHP=${apiResult.playerHP}, opponentHP=${apiResult.opponentHP}")
println("DEBUG: Using playerAttackDamage > 0 instead of playerAttackHit for hit detection")
// Use opponentAttackDamage to determine counter-attack hit
val finalCounterAttackHits = counterAttackHits
println("Using opponentAttackDamage > 0 for counter-attack: $finalCounterAttackHits")
if (finalCounterAttackHits) {
println("Counter-attack hits! Player takes ${apiResult.opponentAttackDamage} damage")
onSetPendingDamage(apiResult.opponentAttackDamage.toFloat(), 0f) // Player takes damage
} else {
println("Counter-attack misses! Player dodges")
onSetPendingDamage(0f, 0f) // No damage
}
battleSystem.setupCounterAttack(finalCounterAttackHits)
@ -1671,13 +1660,11 @@ fun BattlesScreen() {
val currentCharacter = activeUserCharacter
if (currentCharacter != null && canBattle && playerBattleType != null) {
println("BATTLESCREEN: Loading opponents for stage ${currentCharacter.stage}, battle type: $playerBattleType")
try {
RetrofitHelper().getOpponents(context, playerBattleType!!) { opponents ->
try {
// Create a new list to trigger UI recomposition
opponentsList = ArrayList(opponents.opponentsList)
println("BATTLESCREEN: Loaded ${opponents.opponentsList.size} opponents from API")
} catch (e: Exception) {
Log.d(TAG, "Error processing opponents data: ${e.message}")
e.printStackTrace()
@ -1714,7 +1701,6 @@ fun BattlesScreen() {
if (!processedTokens.contains(token)) {
// Mark token as being processed IMMEDIATELY to prevent duplicate API calls
processedTokens = processedTokens + token
println("BATTLESCREEN: Received token from URI: $token (URI: $uri) - marking as processing")
// Exchange token with battle server
RetrofitHelper().authenticate(context, token) { response ->
@ -1770,8 +1756,6 @@ fun BattlesScreen() {
}
}
}
} else {
println("BATTLESCREEN: Token already processed (or currently processing), skipping: $token")
}
} else {
println("BATTLESCREEN: No token found in URI: $uri (checked 'c' and 'token' parameters)")
@ -1785,7 +1769,6 @@ fun BattlesScreen() {
val localAuthState = authRepository.isAuthenticated.first()
val storedToken = authRepository.authToken.first()
val storedUserId = authRepository.userId.first()
println("BATTLESCREEN: Local authentication status - isAuthenticated: $localAuthState, hasToken: ${storedToken != null}, userId: $storedUserId")
// Load stored userId if available
if (storedUserId != null) {
@ -1799,7 +1782,6 @@ fun BattlesScreen() {
isAuthenticated = true
isCheckingAuth = false
userId = storedUserId
println("BATTLESCREEN: Restored authentication state from storage (userId: $storedUserId) - isCheckingAuth set to false")
}
// Only check for token in intent if it's a fresh deep link (ACTION_VIEW intent)
@ -1808,9 +1790,7 @@ fun BattlesScreen() {
val intent = activity?.intent
if (intent?.action == Intent.ACTION_VIEW) {
intent.data?.let { uri ->
println("BATTLESCREEN: Found ACTION_VIEW intent with URI: $uri")
if (uri.getQueryParameter("c") != null || uri.getQueryParameter("token") != null) {
println("BATTLESCREEN: Token found in fresh deep link, processing...")
handleTokenFromUri(uri)
return@LaunchedEffect // Don't open auth URL if we're processing a token
}
@ -1820,7 +1800,6 @@ fun BattlesScreen() {
// If we have a stored token, validate it with the server in the background
if (localAuthState && storedToken != null && storedToken.isNotEmpty()) {
// State already set above, now validate in background
println("BATTLESCREEN: Validating stored token with server in background...")
RetrofitHelper().authenticate(context, storedToken) { response ->
// Update UI on main thread
kotlinx.coroutines.CoroutineScope(Dispatchers.Main).launch {
@ -1832,7 +1811,6 @@ fun BattlesScreen() {
authRepository.setAuthenticated(true, storedToken, extractedUserId)
}
}
println("BATTLESCREEN: Token validation successful, userId: $extractedUserId")
isAuthenticated = true
isCheckingAuth = false
userId = extractedUserId
@ -1897,23 +1875,18 @@ fun BattlesScreen() {
if (intent?.action == Intent.ACTION_VIEW) {
val uri = intent.data
if (uri != null) {
println("BATTLESCREEN: Checking ACTION_VIEW intent data - URI: $uri, scheme: ${uri.scheme}, host: ${uri.host}, path: ${uri.path}")
println("BATTLESCREEN: All query parameters: ${uri.queryParameterNames}")
// Handle vbhelper://auth?token= or vbhelper://auth?c= deep link
if (uri.scheme == "vbhelper" && uri.host == "auth") {
println("BATTLESCREEN: Detected vbhelper://auth deep link")
handleTokenFromUri(uri)
}
// Handle http://localhost:8080/authenticate?c= redirect
else if ((uri.scheme == "http" || uri.scheme == "https") &&
(uri.host == "localhost" || uri.host == "127.0.0.1" || uri.host?.contains("8080") == true)) {
println("BATTLESCREEN: Detected localhost redirect, checking for token")
handleTokenFromUri(uri)
}
// Also check if there's a 'c' or 'token' parameter in any URL
else if (uri.getQueryParameter("c") != null || uri.getQueryParameter("token") != null) {
println("BATTLESCREEN: Found token parameter (c or token) in URI, attempting to authenticate")
handleTokenFromUri(uri)
} else {
println("BATTLESCREEN: URI found but no token parameter detected")
@ -1938,9 +1911,7 @@ fun BattlesScreen() {
val intent = activity?.intent
if (intent?.action == Intent.ACTION_VIEW) {
intent.data?.let { uri ->
println("BATTLESCREEN: Activity resumed with ACTION_VIEW intent, checking for token - URI: $uri")
if (uri.getQueryParameter("c") != null || uri.getQueryParameter("token") != null) {
println("BATTLESCREEN: Found token in fresh deep link on resume")
handleTokenFromUri(uri)
}
}
@ -2204,7 +2175,6 @@ fun BattlesScreen() {
}
}
} else {
println("BATTLESCREEN: UI - No opponents in list, showing message")
Text("No opponents available for your stage",
fontSize = 16.sp,
color = Color(0xFFFFA500), // Orange color
@ -2288,7 +2258,6 @@ fun BattlesScreen() {
selectedOpponent?.name ?: "Opponent",
opponentStage
) { cleanupResult ->
println("Cleanup call completed")
}
}
}
@ -2460,7 +2429,6 @@ fun MultiLayerAnimatedBattleBackground(
LaunchedEffect(Unit) {
screenWidth = with(density) { configuration.screenWidthDp.dp }
screenHeight = with(density) { configuration.screenHeightDp.dp }
println("DEBUG: Multi-layer screen dimensions = ${screenWidth.value}x${screenHeight.value}dp")
}
// Load all three background layers from external storage
@ -2473,7 +2441,6 @@ fun MultiLayerAnimatedBattleBackground(
val backLayerFile = File(externalDir, "VBHelper/battle_sprites/extracted_battlebgs/${selectedSet.backLayer}")
if (backLayerFile.exists()) {
backLayerBitmap = BitmapFactory.decodeFile(backLayerFile.absolutePath)
println("Successfully loaded back layer background (Set ${backgroundSetIndex + 1}): ${backLayerFile.absolutePath}")
} else {
println("Back layer background file not found: ${backLayerFile.absolutePath}")
}
@ -2482,7 +2449,6 @@ fun MultiLayerAnimatedBattleBackground(
val middleLayerFile = File(externalDir, "VBHelper/battle_sprites/extracted_battlebgs/${selectedSet.middleLayer}")
if (middleLayerFile.exists()) {
middleLayerBitmap = BitmapFactory.decodeFile(middleLayerFile.absolutePath)
println("Successfully loaded middle layer background (Set ${backgroundSetIndex + 1}): ${middleLayerFile.absolutePath}")
} else {
println("Middle layer background file not found: ${middleLayerFile.absolutePath}")
}
@ -2491,7 +2457,6 @@ fun MultiLayerAnimatedBattleBackground(
val frontLayerFile = File(externalDir, "VBHelper/battle_sprites/extracted_battlebgs/${selectedSet.frontLayer}")
if (frontLayerFile.exists()) {
frontLayerBitmap = BitmapFactory.decodeFile(frontLayerFile.absolutePath)
println("Successfully loaded front layer background (Set ${backgroundSetIndex + 1}): ${frontLayerFile.absolutePath}")
} else {
println("Front layer background file not found: ${frontLayerFile.absolutePath}")
}