This commit is contained in:
2025-12-07 13:44:51 +09:00
parent 30c84a48ac
commit d3fca333cb
29 changed files with 1437 additions and 137 deletions
+123 -20
View File
@@ -15,6 +15,8 @@ import '../game/enums.dart';
import '../game/model/damage_event.dart'; // DamageEvent import
import '../game/model/effect_event.dart'; // EffectEvent import
import '../game/save_manager.dart';
class EnemyIntent {
final EnemyActionType type;
final int value;
@@ -47,8 +49,10 @@ class BattleProvider with ChangeNotifier {
int turnCount = 1;
List<Item> rewardOptions = [];
bool showRewardPopup = false;
int _lastGoldReward = 0; // New: Stores gold gained from last victory
List<String> get logs => battleLogs;
int get lastGoldReward => _lastGoldReward;
// Damage Event Stream
final _damageEventController = StreamController<DamageEvent>.broadcast();
@@ -69,6 +73,18 @@ class BattleProvider with ChangeNotifier {
super.dispose();
}
void loadFromSave(Map<String, dynamic> data) {
stage = data['stage'];
turnCount = data['turnCount'];
player = Character.fromJson(data['player']);
battleLogs.clear();
_addLog("Game Loaded! Resuming Stage $stage");
_prepareNextStage();
notifyListeners();
}
void initializeBattle() {
stage = 1;
turnCount = 1;
@@ -87,6 +103,9 @@ class BattleProvider with ChangeNotifier {
);
}
// Give test gold
player.gold = 50;
// Provide starter equipment
final starterSword = Item(
id: "starter_sword",
@@ -147,6 +166,9 @@ class BattleProvider with ChangeNotifier {
}
void _prepareNextStage() {
// Save Game at the start of each stage
SaveManager.saveGame(this);
StageType type;
// Stage Type Logic
@@ -209,15 +231,7 @@ class BattleProvider with ChangeNotifier {
_addLog("Stage $stage ($type) started! A wild ${enemy.name} appeared.");
} else if (type == StageType.shop) {
// Generate random items for shop
final random = Random();
List<ItemTemplate> allTemplates = List.from(ItemTable.allItems);
allTemplates.shuffle(random);
int count = min(4, allTemplates.length);
shopItems = allTemplates
.sublist(0, count)
.map((t) => t.createItem(stage: stage))
.toList();
shopItems = _generateShopItems();
// Dummy enemy to prevent null errors in existing UI (until UI is fully updated)
enemy = Character(name: "Merchant", maxHp: 9999, armor: 0, atk: 0);
@@ -238,6 +252,55 @@ class BattleProvider with ChangeNotifier {
notifyListeners();
}
/// Generate 4 random items for the shop based on current stage tier
List<Item> _generateShopItems() {
ItemTier currentTier = ItemTier.tier1;
if (stage > 24)
currentTier = ItemTier.tier3;
else if (stage > 12)
currentTier = ItemTier.tier2;
List<Item> items = [];
for (int i = 0; i < 4; i++) {
ItemTemplate? template = ItemTable.getRandomItem(tier: currentTier);
if (template != null) {
items.add(template.createItem(stage: stage));
}
}
return items;
}
void rerollShopItems() {
const int rerollCost = 50;
if (player.gold >= rerollCost) {
player.gold -= rerollCost;
// Modify the existing list because shopItems is final
currentStage.shopItems.clear();
currentStage.shopItems.addAll(_generateShopItems());
_addLog("Shop items rerolled for $rerollCost G.");
notifyListeners();
} else {
_addLog("Not enough gold to reroll!");
}
}
void buyItem(Item item) {
if (player.gold >= item.price) {
bool added = player.addToInventory(item);
if (added) {
player.gold -= item.price;
currentStage.shopItems.remove(item); // Remove from shop
_addLog("Bought ${item.name} for ${item.price} G.");
} else {
_addLog("Inventory is full!");
}
notifyListeners();
} else {
_addLog("Not enough gold!");
}
}
// Replaces _spawnEnemy
// void _spawnEnemy() { ... } - Removed
@@ -621,28 +684,68 @@ class BattleProvider with ChangeNotifier {
}
void _onVictory() {
_addLog("Enemy defeated! Choose a reward.");
// Calculate Gold Reward
// Base 10 + (Stage * 5) + Random variance
final random = Random();
int goldReward = 10 + (stage * 5) + random.nextInt(10);
player.gold += goldReward;
_lastGoldReward = goldReward; // Store for UI display
_addLog("Enemy defeated! Gained $goldReward Gold.");
_addLog("Choose a reward.");
List<ItemTemplate> allTemplates = List.from(ItemTable.allItems);
allTemplates.shuffle(random); // Shuffle to randomize selection
// Take first 3 items (ensure distinct templates if possible, though list is small now)
int count = min(3, allTemplates.length);
rewardOptions = allTemplates.sublist(0, count).map((template) {
return template.createItem(stage: stage);
}).toList();
// Item Rewards
// Logic: Get random items based on current round tier? For now just random.
// Ideally should use ItemTable.getRandomItem() with Tier logic.
// Let's use our new weighted random logic if available, or fallback to simple shuffle for now to keep it simple.
// Since we just refactored ItemTable, let's use getRandomItem!
ItemTier currentTier = ItemTier.tier1;
if (stage > 24)
currentTier = ItemTier.tier3;
else if (stage > 12)
currentTier = ItemTier.tier2;
rewardOptions = [];
// Get 3 distinct items if possible
for (int i = 0; i < 3; i++) {
ItemTemplate? item = ItemTable.getRandomItem(tier: currentTier);
if (item != null) {
rewardOptions.add(item.createItem(stage: stage));
}
}
// Add "None" (Skip) Option
// We can represent "None" as a null or a special Item.
// Using a special Item with ID "reward_skip" is safer for List<Item>.
rewardOptions.add(
Item(
id: "reward_skip",
name: "Skip Reward",
description: "Take nothing and move on.",
atkBonus: 0,
hpBonus: 0,
slot: EquipmentSlot.accessory,
),
);
showRewardPopup = true;
notifyListeners();
}
void selectReward(Item item) {
bool added = player.addToInventory(item);
if (added) {
_addLog("Added ${item.name} to inventory.");
if (item.id == "reward_skip") {
_addLog("Skipped reward.");
} else {
_addLog("Inventory is full! ${item.name} discarded.");
bool added = player.addToInventory(item);
if (added) {
_addLog("Added ${item.name} to inventory.");
} else {
_addLog("Inventory is full! ${item.name} discarded.");
}
}
// Heal player after selecting reward