import 'package:asciineverdie/src/core/animation/canvas/ascii_cell.dart'; /// 아이템 희귀도 enum ItemRarity { common, uncommon, rare, epic, legendary; /// 희귀도 배율 (스탯 계산용) double get multiplier => switch (this) { common => 1.0, uncommon => 1.3, rare => 1.7, epic => 2.2, legendary => 3.0, }; /// 가중치 보너스 int get weightBonus => switch (this) { common => 0, uncommon => 50, rare => 150, epic => 400, legendary => 1000, }; /// 공격 이펙트 셀 색상 (Phase 9: 무기 등급별 이펙트) /// /// common은 기본 positive(시안), 나머지는 등급별 고유 색상 AsciiCellColor get effectCellColor => switch (this) { ItemRarity.common => AsciiCellColor.positive, ItemRarity.uncommon => AsciiCellColor.rarityUncommon, ItemRarity.rare => AsciiCellColor.rarityRare, ItemRarity.epic => AsciiCellColor.rarityEpic, ItemRarity.legendary => AsciiCellColor.rarityLegendary, }; } /// 아이템 스탯 보정치 /// /// 장비 아이템이 제공하는 스탯 보너스. /// 모든 값은 기본 0이며, 장착 시 플레이어 스탯에 가산됨. class ItemStats { const ItemStats({ this.atk = 0, this.def = 0, this.magAtk = 0, this.magDef = 0, this.criRate = 0.0, this.evasion = 0.0, this.blockRate = 0.0, this.parryRate = 0.0, this.hpBonus = 0, this.mpBonus = 0, this.strBonus = 0, this.conBonus = 0, this.dexBonus = 0, this.intBonus = 0, this.wisBonus = 0, this.chaBonus = 0, this.attackSpeed = 0, }); /// 물리 공격력 보정 final int atk; /// 물리 방어력 보정 final int def; /// 마법 공격력 보정 final int magAtk; /// 마법 방어력 보정 final int magDef; /// 크리티컬 확률 보정 (0.0 ~ 1.0) final double criRate; /// 회피율 보정 (0.0 ~ 1.0) final double evasion; /// 방패 방어율 (방패 전용, 0.0 ~ 1.0) final double blockRate; /// 무기 쳐내기 확률 (무기 전용, 0.0 ~ 1.0) final double parryRate; /// HP 보너스 final int hpBonus; /// MP 보너스 final int mpBonus; /// STR 보너스 final int strBonus; /// CON 보너스 final int conBonus; /// DEX 보너스 final int dexBonus; /// INT 보너스 final int intBonus; /// WIS 보너스 final int wisBonus; /// CHA 보너스 final int chaBonus; /// 무기 공격속도 (밀리초, 무기 전용) /// /// 0이면 기본값(1000ms) 사용, 값이 클수록 느린 공격. /// 느린 무기는 높은 기본 데미지를 가짐. final int attackSpeed; /// 스탯 합계 (가중치 계산용) int get totalStatValue { return atk + def + magAtk + magDef + (criRate * 100).round() + (evasion * 100).round() + (blockRate * 100).round() + (parryRate * 100).round() + hpBonus + mpBonus + strBonus * 5 + conBonus * 5 + dexBonus * 5 + intBonus * 5 + wisBonus * 5 + chaBonus * 5; } /// 빈 스탯 (보너스 없음) static const empty = ItemStats(); /// JSON으로 직렬화 Map toJson() { return { 'atk': atk, 'def': def, 'magAtk': magAtk, 'magDef': magDef, 'criRate': criRate, 'evasion': evasion, 'blockRate': blockRate, 'parryRate': parryRate, 'hpBonus': hpBonus, 'mpBonus': mpBonus, 'strBonus': strBonus, 'conBonus': conBonus, 'dexBonus': dexBonus, 'intBonus': intBonus, 'wisBonus': wisBonus, 'chaBonus': chaBonus, 'attackSpeed': attackSpeed, }; } /// JSON에서 역직렬화 factory ItemStats.fromJson(Map json) { return ItemStats( atk: json['atk'] as int? ?? 0, def: json['def'] as int? ?? 0, magAtk: json['magAtk'] as int? ?? 0, magDef: json['magDef'] as int? ?? 0, criRate: (json['criRate'] as num?)?.toDouble() ?? 0.0, evasion: (json['evasion'] as num?)?.toDouble() ?? 0.0, blockRate: (json['blockRate'] as num?)?.toDouble() ?? 0.0, parryRate: (json['parryRate'] as num?)?.toDouble() ?? 0.0, hpBonus: json['hpBonus'] as int? ?? 0, mpBonus: json['mpBonus'] as int? ?? 0, strBonus: json['strBonus'] as int? ?? 0, conBonus: json['conBonus'] as int? ?? 0, dexBonus: json['dexBonus'] as int? ?? 0, intBonus: json['intBonus'] as int? ?? 0, wisBonus: json['wisBonus'] as int? ?? 0, chaBonus: json['chaBonus'] as int? ?? 0, attackSpeed: json['attackSpeed'] as int? ?? 0, ); } /// 두 스탯 합산 /// /// attackSpeed는 합산 대상 아님 (무기 슬롯 단일 값) ItemStats operator +(ItemStats other) { return ItemStats( atk: atk + other.atk, def: def + other.def, magAtk: magAtk + other.magAtk, magDef: magDef + other.magDef, criRate: criRate + other.criRate, evasion: evasion + other.evasion, blockRate: blockRate + other.blockRate, parryRate: parryRate + other.parryRate, hpBonus: hpBonus + other.hpBonus, mpBonus: mpBonus + other.mpBonus, strBonus: strBonus + other.strBonus, conBonus: conBonus + other.conBonus, dexBonus: dexBonus + other.dexBonus, intBonus: intBonus + other.intBonus, wisBonus: wisBonus + other.wisBonus, chaBonus: chaBonus + other.chaBonus, // attackSpeed는 무기에서만 직접 참조 ); } ItemStats copyWith({ int? atk, int? def, int? magAtk, int? magDef, double? criRate, double? evasion, double? blockRate, double? parryRate, int? hpBonus, int? mpBonus, int? strBonus, int? conBonus, int? dexBonus, int? intBonus, int? wisBonus, int? chaBonus, int? attackSpeed, }) { return ItemStats( atk: atk ?? this.atk, def: def ?? this.def, magAtk: magAtk ?? this.magAtk, magDef: magDef ?? this.magDef, criRate: criRate ?? this.criRate, evasion: evasion ?? this.evasion, blockRate: blockRate ?? this.blockRate, parryRate: parryRate ?? this.parryRate, hpBonus: hpBonus ?? this.hpBonus, mpBonus: mpBonus ?? this.mpBonus, strBonus: strBonus ?? this.strBonus, conBonus: conBonus ?? this.conBonus, dexBonus: dexBonus ?? this.dexBonus, intBonus: intBonus ?? this.intBonus, wisBonus: wisBonus ?? this.wisBonus, chaBonus: chaBonus ?? this.chaBonus, attackSpeed: attackSpeed ?? this.attackSpeed, ); } }