update
This commit is contained in:
@@ -7,12 +7,14 @@ class EnemyTemplate {
|
||||
final int baseHp;
|
||||
final int baseAtk;
|
||||
final int baseDefense;
|
||||
final String? image;
|
||||
|
||||
const EnemyTemplate({
|
||||
required this.name,
|
||||
required this.baseHp,
|
||||
required this.baseAtk,
|
||||
required this.baseDefense,
|
||||
this.image,
|
||||
});
|
||||
|
||||
factory EnemyTemplate.fromJson(Map<String, dynamic> json) {
|
||||
@@ -21,6 +23,7 @@ class EnemyTemplate {
|
||||
baseHp: json['baseHp'] ?? 10,
|
||||
baseAtk: json['baseAtk'] ?? 1,
|
||||
baseDefense: json['baseDefense'] ?? 0,
|
||||
image: json['image'],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -36,6 +39,7 @@ class EnemyTemplate {
|
||||
atk: scaledAtk,
|
||||
baseDefense: scaledDefense,
|
||||
armor: 0,
|
||||
image: image,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ class ItemTemplate {
|
||||
final int baseArmor;
|
||||
final EquipmentSlot slot;
|
||||
final List<ItemEffect> effects;
|
||||
final int price;
|
||||
final String? image;
|
||||
|
||||
const ItemTemplate({
|
||||
required this.name,
|
||||
@@ -20,6 +22,8 @@ class ItemTemplate {
|
||||
this.baseArmor = 0,
|
||||
required this.slot,
|
||||
this.effects = const [],
|
||||
this.price = 0,
|
||||
this.image,
|
||||
});
|
||||
|
||||
factory ItemTemplate.fromJson(Map<String, dynamic> json) {
|
||||
@@ -30,10 +34,13 @@ class ItemTemplate {
|
||||
baseHp: json['baseHp'] ?? 0,
|
||||
baseArmor: json['baseArmor'] ?? 0,
|
||||
slot: EquipmentSlot.values.firstWhere((e) => e.name == json['slot']),
|
||||
effects: (json['effects'] as List<dynamic>?)
|
||||
effects:
|
||||
(json['effects'] as List<dynamic>?)
|
||||
?.map((e) => ItemEffect.fromJson(e))
|
||||
.toList() ??
|
||||
[],
|
||||
price: json['price'] ?? 0,
|
||||
image: json['image'],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -45,12 +52,12 @@ class ItemTemplate {
|
||||
int scaledHp = baseHp > 0 ? baseHp + (stage - 1) * 5 : 0;
|
||||
int scaledArmor = baseArmor > 0 ? baseArmor + (stage - 1) : 0;
|
||||
|
||||
// Calculate price based on stats
|
||||
int calculatedPrice = (scaledAtk * 10) + (scaledHp * 2) + (scaledArmor * 5);
|
||||
if (effects.isNotEmpty) {
|
||||
calculatedPrice += effects.length * 50; // Bonus value for special effects
|
||||
// Use fixed price from template
|
||||
int finalPrice = price;
|
||||
// Optional: Increase price if stage > 1 (e.g. +10% per stage)
|
||||
if (stage > 1) {
|
||||
finalPrice = (price * (1 + (stage - 1) * 0.1)).toInt();
|
||||
}
|
||||
if (calculatedPrice < 10) calculatedPrice = 10; // Minimum price
|
||||
|
||||
return Item(
|
||||
name: "$name${stage > 1 ? ' +${stage - 1}' : ''}", // Append +1, +2 etc.
|
||||
@@ -60,7 +67,8 @@ class ItemTemplate {
|
||||
armorBonus: scaledArmor,
|
||||
slot: slot,
|
||||
effects: effects, // Pass the effects to the Item
|
||||
price: calculatedPrice,
|
||||
price: finalPrice,
|
||||
image: image,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -72,13 +80,23 @@ class ItemTable {
|
||||
static List<ItemTemplate> accessories = [];
|
||||
|
||||
static Future<void> load() async {
|
||||
final String jsonString = await rootBundle.loadString('assets/data/items.json');
|
||||
final String jsonString = await rootBundle.loadString(
|
||||
'assets/data/items.json',
|
||||
);
|
||||
final Map<String, dynamic> data = jsonDecode(jsonString);
|
||||
|
||||
weapons = (data['weapons'] as List).map((e) => ItemTemplate.fromJson(e)).toList();
|
||||
armors = (data['armors'] as List).map((e) => ItemTemplate.fromJson(e)).toList();
|
||||
shields = (data['shields'] as List).map((e) => ItemTemplate.fromJson(e)).toList();
|
||||
accessories = (data['accessories'] as List).map((e) => ItemTemplate.fromJson(e)).toList();
|
||||
weapons = (data['weapons'] as List)
|
||||
.map((e) => ItemTemplate.fromJson(e))
|
||||
.toList();
|
||||
armors = (data['armors'] as List)
|
||||
.map((e) => ItemTemplate.fromJson(e))
|
||||
.toList();
|
||||
shields = (data['shields'] as List)
|
||||
.map((e) => ItemTemplate.fromJson(e))
|
||||
.toList();
|
||||
accessories = (data['accessories'] as List)
|
||||
.map((e) => ItemTemplate.fromJson(e))
|
||||
.toList();
|
||||
}
|
||||
|
||||
static List<ItemTemplate> get allItems => [
|
||||
|
||||
@@ -8,7 +8,9 @@ class Character {
|
||||
int armor; // Current temporary shield/armor points in battle
|
||||
int baseAtk;
|
||||
int baseDefense; // Base defense stat
|
||||
|
||||
int gold; // New: Currency
|
||||
String? image; // New: Image path
|
||||
Map<EquipmentSlot, Item> equipment = {};
|
||||
List<Item> inventory = [];
|
||||
final int maxInventorySize = 16;
|
||||
@@ -24,9 +26,10 @@ class Character {
|
||||
required int atk,
|
||||
this.baseDefense = 0,
|
||||
this.gold = 0,
|
||||
}) : baseMaxHp = maxHp,
|
||||
baseAtk = atk,
|
||||
hp = hp ?? maxHp;
|
||||
this.image,
|
||||
}) : baseMaxHp = maxHp,
|
||||
baseAtk = atk,
|
||||
hp = hp ?? maxHp;
|
||||
|
||||
/// Adds a status effect. If it already exists, it refreshes duration or stacks based on logic.
|
||||
/// For now, we'll implement a simple refresh/overwrite logic.
|
||||
@@ -99,7 +102,9 @@ class Character {
|
||||
if (!inventory.contains(newItem)) return false;
|
||||
|
||||
// 1. Calculate current HP ratio before any changes
|
||||
double hpRatio = totalMaxHp > 0 ? hp / totalMaxHp : 0.0; // Avoid division by zero
|
||||
double hpRatio = totalMaxHp > 0
|
||||
? hp / totalMaxHp
|
||||
: 0.0; // Avoid division by zero
|
||||
|
||||
// 2. Handle Swap: If slot is occupied, unequip the old item first
|
||||
if (equipment.containsKey(newItem.slot)) {
|
||||
@@ -116,9 +121,10 @@ class Character {
|
||||
hp = (totalMaxHp * hpRatio).toInt();
|
||||
if (hp < 0) hp = 0; // Ensure HP does not go below zero
|
||||
if (hp > totalMaxHp) {
|
||||
hp = totalMaxHp; // Final Safety Clamp, though hpRatio <= 1.0 should prevent this
|
||||
hp =
|
||||
totalMaxHp; // Final Safety Clamp, though hpRatio <= 1.0 should prevent this
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -128,7 +134,9 @@ class Character {
|
||||
if (!equipment.containsValue(item)) return false;
|
||||
|
||||
// 1. Calculate current HP ratio before any changes
|
||||
double hpRatio = totalMaxHp > 0 ? hp / totalMaxHp : 0.0; // Avoid division by zero
|
||||
double hpRatio = totalMaxHp > 0
|
||||
? hp / totalMaxHp
|
||||
: 0.0; // Avoid division by zero
|
||||
|
||||
if (inventory.length < maxInventorySize) {
|
||||
equipment.remove(item.slot);
|
||||
@@ -138,11 +146,12 @@ class Character {
|
||||
hp = (totalMaxHp * hpRatio).toInt();
|
||||
if (hp < 0) hp = 0; // Ensure HP does not go below zero
|
||||
if (hp > totalMaxHp) {
|
||||
hp = totalMaxHp; // Final Safety Clamp, though hpRatio <= 1.0 should prevent this
|
||||
hp =
|
||||
totalMaxHp; // Final Safety Clamp, though hpRatio <= 1.0 should prevent this
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ class Item {
|
||||
final EquipmentSlot slot;
|
||||
final List<ItemEffect> effects; // Status effects this item can inflict
|
||||
final int price; // New: Sell/Buy value
|
||||
final String? image; // New: Image path
|
||||
|
||||
Item({
|
||||
required this.name,
|
||||
@@ -56,6 +57,7 @@ class Item {
|
||||
required this.slot,
|
||||
this.effects = const [], // Default to no effects
|
||||
this.price = 0,
|
||||
this.image,
|
||||
});
|
||||
|
||||
String get typeName {
|
||||
@@ -70,4 +72,4 @@ class Item {
|
||||
return "Accessory";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -515,8 +515,9 @@ class BattleProvider with ChangeNotifier {
|
||||
|
||||
void sellItem(Item item) {
|
||||
if (player.inventory.remove(item)) {
|
||||
player.gold += item.price;
|
||||
_addLog("Sold ${item.name} for ${item.price} G.");
|
||||
int sellPrice = GameMath.floor(item.price * 0.6);
|
||||
player.gold += sellPrice;
|
||||
_addLog("Sold ${item.name} for $sellPrice G.");
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user