update
This commit is contained in:
@@ -7,74 +7,70 @@ class ItemTemplate {
|
||||
final String id;
|
||||
final String name;
|
||||
final String description;
|
||||
final int baseAtk;
|
||||
final int baseHp;
|
||||
final int baseArmor;
|
||||
final int atkBonus;
|
||||
final int hpBonus;
|
||||
final int armorBonus;
|
||||
final EquipmentSlot slot;
|
||||
final List<ItemEffect> effects;
|
||||
final int price;
|
||||
final String? image;
|
||||
final int luck;
|
||||
|
||||
const ItemTemplate({
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.description,
|
||||
this.baseAtk = 0,
|
||||
this.baseHp = 0,
|
||||
this.baseArmor = 0,
|
||||
required this.atkBonus,
|
||||
required this.hpBonus,
|
||||
required this.armorBonus,
|
||||
required this.slot,
|
||||
this.effects = const [],
|
||||
this.price = 0,
|
||||
required this.effects,
|
||||
required this.price,
|
||||
this.image,
|
||||
this.luck = 0,
|
||||
});
|
||||
|
||||
factory ItemTemplate.fromJson(Map<String, dynamic> json) {
|
||||
var effectsList = <ItemEffect>[];
|
||||
if (json['effects'] != null) {
|
||||
effectsList = (json['effects'] as List)
|
||||
.map((e) => ItemEffect.fromJson(e))
|
||||
.toList();
|
||||
}
|
||||
|
||||
return ItemTemplate(
|
||||
id:
|
||||
json['id'] ??
|
||||
json['name'], // Fallback to name if id is missing (for backward compatibility during dev)
|
||||
id: json['id'],
|
||||
name: json['name'],
|
||||
description: json['description'],
|
||||
baseAtk: json['baseAtk'] ?? 0,
|
||||
baseHp: json['baseHp'] ?? 0,
|
||||
baseArmor: json['baseArmor'] ?? 0,
|
||||
atkBonus: json['atkBonus'] ?? 0,
|
||||
hpBonus: json['hpBonus'] ?? 0,
|
||||
armorBonus: json['armorBonus'] ?? 0,
|
||||
slot: EquipmentSlot.values.firstWhere((e) => e.name == json['slot']),
|
||||
effects:
|
||||
(json['effects'] as List<dynamic>?)
|
||||
?.map((e) => ItemEffect.fromJson(e))
|
||||
.toList() ??
|
||||
[],
|
||||
price: json['price'] ?? 0,
|
||||
effects: effectsList,
|
||||
price: json['price'] ?? 10,
|
||||
image: json['image'],
|
||||
luck: json['luck'] ?? 0,
|
||||
);
|
||||
}
|
||||
|
||||
// Create an instance of Item based on this template, optionally scaling with stage
|
||||
Item createItem({int stage = 1}) {
|
||||
// Simple scaling logic: add stage-1 to relevant stats
|
||||
// You can make this more complex (multiplier, tiering, etc.)
|
||||
int scaledAtk = baseAtk > 0 ? baseAtk + (stage - 1) : 0;
|
||||
int scaledHp = baseHp > 0 ? baseHp + (stage - 1) * 5 : 0;
|
||||
int scaledArmor = baseArmor > 0 ? baseArmor + (stage - 1) : 0;
|
||||
|
||||
// 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();
|
||||
}
|
||||
// Scale stats based on stage
|
||||
int scaledAtk = (atkBonus * (1 + (stage - 1) * 0.1)).toInt();
|
||||
int scaledHp = (hpBonus * (1 + (stage - 1) * 0.1)).toInt();
|
||||
int scaledArmor = (armorBonus * (1 + (stage - 1) * 0.1)).toInt();
|
||||
|
||||
return Item(
|
||||
id: id,
|
||||
name: "$name${stage > 1 ? ' +${stage - 1}' : ''}", // Append +1, +2 etc.
|
||||
name: "$name${stage > 1 ? ' +${stage - 1}' : ''}",
|
||||
description: description,
|
||||
atkBonus: scaledAtk,
|
||||
hpBonus: scaledHp,
|
||||
armorBonus: scaledArmor,
|
||||
slot: slot,
|
||||
effects: effects, // Pass the effects to the Item
|
||||
price: finalPrice,
|
||||
effects: effects,
|
||||
price: price,
|
||||
image: image,
|
||||
luck: luck,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,3 +33,4 @@ enum EquipmentSlot { weapon, armor, shield, accessory }
|
||||
|
||||
enum DamageType { normal, bleed, vulnerable }
|
||||
|
||||
enum StatType { maxHp, atk, defense }
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'item.dart';
|
||||
import 'status_effect.dart';
|
||||
import 'stat_modifier.dart';
|
||||
import '../enums.dart';
|
||||
|
||||
class Character {
|
||||
@@ -19,6 +20,9 @@ class Character {
|
||||
// Active status effects
|
||||
List<StatusEffect> statusEffects = [];
|
||||
|
||||
// Permanent stat modifiers (e.g. Ascension, Potions)
|
||||
List<PermanentStatModifier> permanentModifiers = [];
|
||||
|
||||
Character({
|
||||
required this.name,
|
||||
int? hp,
|
||||
@@ -66,6 +70,14 @@ class Character {
|
||||
statusEffects.removeWhere((e) => e.duration <= 0);
|
||||
}
|
||||
|
||||
void addPermanentModifier(PermanentStatModifier modifier) {
|
||||
permanentModifiers.add(modifier);
|
||||
}
|
||||
|
||||
void removePermanentModifier(String id) {
|
||||
permanentModifiers.removeWhere((m) => m.id == id);
|
||||
}
|
||||
|
||||
/// Helper to check if character has a specific status
|
||||
bool hasStatus(StatusEffectType type) {
|
||||
return statusEffects.any((e) => e.type == type);
|
||||
@@ -86,6 +98,10 @@ class Character {
|
||||
return baseDefense + bonus;
|
||||
}
|
||||
|
||||
int get totalLuck {
|
||||
return equipment.values.fold(0, (sum, item) => sum + item.luck);
|
||||
}
|
||||
|
||||
bool get isDead => hp <= 0;
|
||||
|
||||
// Adds an item to inventory, returns true if successful, false if inventory is full
|
||||
|
||||
@@ -46,8 +46,9 @@ class Item {
|
||||
final List<ItemEffect> effects; // Status effects this item can inflict
|
||||
final int price; // New: Sell/Buy value
|
||||
final String? image; // New: Image path
|
||||
final int luck; // Success rate bonus (e.g. 5 = 5%)
|
||||
|
||||
Item({
|
||||
const Item({
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.description,
|
||||
@@ -58,6 +59,7 @@ class Item {
|
||||
this.effects = const [], // Default to no effects
|
||||
this.price = 0,
|
||||
this.image,
|
||||
this.luck = 0,
|
||||
});
|
||||
|
||||
String get typeName {
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import '../enums.dart';
|
||||
|
||||
class PermanentStatModifier {
|
||||
final String id;
|
||||
final String name;
|
||||
final String description;
|
||||
final StatType statType;
|
||||
final ModifierType type;
|
||||
final double value;
|
||||
|
||||
const PermanentStatModifier({
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.description,
|
||||
required this.statType,
|
||||
required this.type,
|
||||
required this.value,
|
||||
});
|
||||
|
||||
factory PermanentStatModifier.fromJson(Map<String, dynamic> json) {
|
||||
return PermanentStatModifier(
|
||||
id: json['id'],
|
||||
name: json['name'],
|
||||
description: json['description'],
|
||||
statType: StatType.values.firstWhere((e) => e.name == json['statType']),
|
||||
type: ModifierType.values.firstWhere((e) => e.name == json['type']),
|
||||
value: json['value'].toDouble(),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'name': name,
|
||||
'description': description,
|
||||
'statType': statType.name,
|
||||
'type': type.name,
|
||||
'value': value,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -277,15 +277,24 @@ class BattleProvider with ChangeNotifier {
|
||||
|
||||
switch (risk) {
|
||||
case RiskLevel.safe:
|
||||
success = random.nextDouble() < 1.0; // 100%
|
||||
// Safe: 100% base chance + luck
|
||||
double chance = 1.0 + (player.totalLuck / 100.0);
|
||||
if (chance > 1.0) chance = 1.0;
|
||||
success = random.nextDouble() < chance;
|
||||
efficiency = 0.5; // 50%
|
||||
break;
|
||||
case RiskLevel.normal:
|
||||
success = random.nextDouble() < 0.8; // 80%
|
||||
// Normal: 80% base chance + luck
|
||||
double chance = 0.8 + (player.totalLuck / 100.0);
|
||||
if (chance > 1.0) chance = 1.0;
|
||||
success = random.nextDouble() < chance;
|
||||
efficiency = 1.0; // 100%
|
||||
break;
|
||||
case RiskLevel.risky:
|
||||
success = random.nextDouble() < 0.4; // 40%
|
||||
// Risky: 40% base chance + luck
|
||||
double chance = 0.4 + (player.totalLuck / 100.0);
|
||||
if (chance > 1.0) chance = 1.0;
|
||||
success = random.nextDouble() < chance;
|
||||
efficiency = 2.0; // 200%
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -274,18 +274,23 @@ class _BattleScreenState extends State<BattleScreen> {
|
||||
: "Armor";
|
||||
String successRate = "";
|
||||
|
||||
double baseChance = 0.0;
|
||||
switch (risk) {
|
||||
case RiskLevel.safe:
|
||||
successRate = "100%";
|
||||
baseChance = 1.0;
|
||||
break;
|
||||
case RiskLevel.normal:
|
||||
successRate = "80%";
|
||||
baseChance = 0.8;
|
||||
break;
|
||||
case RiskLevel.risky:
|
||||
successRate = "40%";
|
||||
baseChance = 0.4;
|
||||
break;
|
||||
}
|
||||
|
||||
double finalChance = baseChance + (player.totalLuck / 100.0);
|
||||
if (finalChance > 1.0) finalChance = 1.0;
|
||||
successRate = "${(finalChance * 100).toInt()}%";
|
||||
|
||||
infoText =
|
||||
"Success: $successRate, Eff: ${(efficiency * 100).toInt()}% ($expectedValue $valueUnit)";
|
||||
|
||||
|
||||
@@ -47,6 +47,11 @@ class InventoryScreen extends StatelessWidget {
|
||||
"${player.gold} G",
|
||||
color: Colors.amber,
|
||||
),
|
||||
_buildStatItem(
|
||||
"Luck",
|
||||
"${player.totalLuck}",
|
||||
color: Colors.green,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
@@ -575,6 +580,7 @@ class InventoryScreen extends StatelessWidget {
|
||||
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");
|
||||
if (item.luck > 0) stats.add("+${item.luck} Luck");
|
||||
|
||||
// Include effects
|
||||
List<String> effectTexts = item.effects.map((e) => e.description).toList();
|
||||
|
||||
Reference in New Issue
Block a user