import 'package:flutter/material.dart'; import 'package:game_test/game/model/item.dart'; import 'package:game_test/game/model/stage.dart'; // Import StageModel import 'package:provider/provider.dart'; import '../providers/battle_provider.dart'; import '../game/model/entity.dart'; class BattleScreen extends StatefulWidget { const BattleScreen({super.key}); @override State createState() => _BattleScreenState(); } class _BattleScreenState extends State { final ScrollController _scrollController = ScrollController(); @override void initState() { super.initState(); // Scroll to the bottom of the log when new messages are added WidgetsBinding.instance.addPostFrameCallback((_) { if (_scrollController.hasClients) { _scrollController.jumpTo(_scrollController.position.maxScrollExtent); } }); } @override void dispose() { _scrollController.dispose(); super.dispose(); } void _showRiskLevelSelection(BuildContext context, ActionType actionType) { final player = context.read().player; final baseValue = actionType == ActionType.attack ? player.totalAtk : player.totalDefense; showDialog( context: context, builder: (BuildContext context) { return SimpleDialog( title: Text("Select Risk Level for ${actionType.name}"), children: RiskLevel.values.map((risk) { String infoText = ""; Color infoColor = Colors.black; double efficiency = 0.0; int expectedValue = 0; switch (risk) { case RiskLevel.safe: efficiency = 0.5; infoColor = Colors.green; break; case RiskLevel.normal: efficiency = 1.0; infoColor = Colors.blue; break; case RiskLevel.risky: efficiency = 2.0; infoColor = Colors.red; break; } expectedValue = (baseValue * efficiency).toInt(); String valueUnit = actionType == ActionType.attack ? "Dmg" : "Armor"; String successRate = ""; switch (risk) { case RiskLevel.safe: successRate = "100%"; break; case RiskLevel.normal: successRate = "80%"; break; case RiskLevel.risky: successRate = "40%"; break; } infoText = "Success: $successRate, Eff: ${(efficiency * 100).toInt()}% ($expectedValue $valueUnit)"; return SimpleDialogOption( onPressed: () { context.read().playerAction(actionType, risk); Navigator.pop(context); // Ensure the log scrolls to the bottom after action WidgetsBinding.instance.addPostFrameCallback((_) { _scrollController.animateTo( _scrollController.position.maxScrollExtent, duration: const Duration(milliseconds: 300), curve: Curves.easeOut, ); }); }, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( risk.name, style: const TextStyle(fontWeight: FontWeight.bold), ), Text( infoText, style: TextStyle(fontSize: 12, color: infoColor), ), ], ), ); }).toList(), ); }, ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Consumer( builder: (context, provider, child) => Text( "Colosseum - Stage ${provider.stage} (${provider.currentStage.type.name.toUpperCase()})", ), ), actions: [ IconButton( icon: const Icon(Icons.refresh), onPressed: () => context.read().initializeBattle(), ), ], ), body: Consumer( builder: (context, battleProvider, child) { // UI Switching based on Stage Type if (battleProvider.currentStage.type == StageType.shop) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.store, size: 64, color: Colors.amber), const SizedBox(height: 16), const Text("Merchant Shop", style: TextStyle(fontSize: 24)), const SizedBox(height: 8), const Text("Buying/Selling feature coming soon!"), const SizedBox(height: 32), ElevatedButton( onPressed: () => battleProvider.proceedToNextStage(), child: const Text("Leave Shop"), ), ], ), ); } else if (battleProvider.currentStage.type == StageType.rest) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.local_hotel, size: 64, color: Colors.blue), const SizedBox(height: 16), const Text("Rest Area", style: TextStyle(fontSize: 24)), const SizedBox(height: 8), const Text("Take a breath and heal."), const SizedBox(height: 32), ElevatedButton( onPressed: () { battleProvider.player.heal(20); // Simple heal battleProvider.proceedToNextStage(); }, child: const Text("Rest & Leave (+20 HP)"), ), ], ), ); } // Default: Battle UI (for Battle and Elite) return Stack( children: [ Column( children: [ // Top (Status Area) Padding( padding: const EdgeInsets.all(8.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ _buildCharacterStatus( battleProvider.enemy, isEnemy: true, ), _buildCharacterStatus( battleProvider.player, isEnemy: false, ), ], ), ), // Middle (Log Area) Expanded( child: Container( color: Colors.black87, padding: const EdgeInsets.all(8.0), child: ListView.builder( controller: _scrollController, itemCount: battleProvider.battleLogs.length, itemBuilder: (context, index) { return Text( battleProvider.battleLogs[index], style: const TextStyle( color: Colors.white, fontFamily: 'Monospace', fontSize: 12, ), ); }, ), ), ), // Bottom (Control Area) Padding( padding: const EdgeInsets.all(8.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ _buildActionButton( context, "ATTACK", ActionType.attack, battleProvider.isPlayerTurn && !battleProvider.player.isDead && !battleProvider.enemy.isDead && !battleProvider.showRewardPopup, ), _buildActionButton( context, "DEFEND", ActionType.defend, battleProvider.isPlayerTurn && !battleProvider.player.isDead && !battleProvider.enemy.isDead && !battleProvider.showRewardPopup, ), ], ), ), ], ), if (battleProvider.showRewardPopup) Container( color: Colors.black54, child: Center( child: SimpleDialog( title: const Text("Victory! Choose a Reward"), children: battleProvider.rewardOptions.map((item) { return SimpleDialogOption( onPressed: () { battleProvider.selectReward(item); }, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( item.name, style: const TextStyle( fontWeight: FontWeight.bold, ), ), _buildItemStatText(item), // Display stats here Text( item.description, style: const TextStyle( fontSize: 12, color: Colors.grey, ), ), ], ), ); }).toList(), ), ), ), ], ); }, ), ); } Widget _buildItemStatText(Item item) { List stats = []; if (item.atkBonus > 0) stats.add("+${item.atkBonus} ATK"); if (item.hpBonus > 0) stats.add("+${item.hpBonus} HP"); if (item.armorBonus > 0) stats.add("+${item.armorBonus} DEF"); List effectTexts = item.effects.map((e) => e.description).toList(); if (stats.isEmpty && effectTexts.isEmpty) return const SizedBox.shrink(); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ if (stats.isNotEmpty) Padding( padding: const EdgeInsets.only(top: 4.0, bottom: 4.0), child: Text( stats.join(", "), style: const TextStyle(fontSize: 12, color: Colors.blueAccent), ), ), if (effectTexts.isNotEmpty) Padding( padding: const EdgeInsets.only(bottom: 4.0), child: Text( effectTexts.join(", "), style: const TextStyle(fontSize: 11, color: Colors.orangeAccent), ), ), ], ); } Widget _buildCharacterStatus(Character character, {bool isEnemy = false}) { return Column( children: [ Text( "${character.name}: HP ${character.hp}/${character.totalMaxHp}", style: TextStyle( color: character.isDead ? Colors.red : Colors.white, fontWeight: FontWeight.bold, ), ), SizedBox( width: 100, child: LinearProgressIndicator( value: character.totalMaxHp > 0 ? character.hp / character.totalMaxHp : 0, color: isEnemy ? Colors.red : Colors.green, backgroundColor: Colors.grey, ), ), // Display Active Status Effects if (character.statusEffects.isNotEmpty) Padding( padding: const EdgeInsets.only(top: 4.0), child: Wrap( spacing: 4.0, children: character.statusEffects.map((effect) { return Container( padding: const EdgeInsets.symmetric( horizontal: 6, vertical: 2, ), decoration: BoxDecoration( color: Colors.deepOrange, borderRadius: BorderRadius.circular(4), ), child: Text( "${effect.type.name.toUpperCase()} (${effect.duration})", style: const TextStyle( color: Colors.white, fontSize: 10, fontWeight: FontWeight.bold, ), ), ); }).toList(), ), ), if (!isEnemy) ...[ Text("Armor: ${character.armor}"), Text("ATK: ${character.totalAtk}"), Text("DEF: ${character.totalDefense}"), ], ], ); } Widget _buildActionButton( BuildContext context, String text, ActionType actionType, bool isEnabled, ) { return ElevatedButton( onPressed: isEnabled ? () => _showRiskLevelSelection(context, actionType) : null, style: ElevatedButton.styleFrom( padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 15), backgroundColor: Colors.blueGrey, foregroundColor: Colors.white, textStyle: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), child: Text(text), ); } }