refactor(model): freezed 패키지 도입으로 보일러플레이트 제거

- ItemStats, CombatStats, EquipmentItem을 freezed로 마이그레이션
- copyWith, toJson/fromJson 자동 생성
- 세이브 파일 호환성 유지
This commit is contained in:
JiWoong Sul
2026-01-15 17:05:26 +09:00
parent f466e1c408
commit e77c3c4a05
11 changed files with 2337 additions and 481 deletions

View File

@@ -1,12 +1,18 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:asciineverdie/src/core/model/class_traits.dart';
import 'package:asciineverdie/src/core/model/game_state.dart';
import 'package:asciineverdie/src/core/model/race_traits.dart';
part 'combat_stats.freezed.dart';
part 'combat_stats.g.dart';
/// 전투용 파생 스탯
///
/// 기본 Stats와 Equipment를 기반으로 계산되는 전투 관련 수치.
/// 불변(immutable) 객체로 설계되어 상태 변경 시 새 인스턴스 생성.
class CombatStats {
@freezed
class CombatStats with _$CombatStats {
// ============================================================================
// 레벨 페널티 상수 (Phase 12)
// ============================================================================
@@ -38,121 +44,65 @@ class CombatStats {
// ============================================================================
/// 레벨 차이에 따른 확률 감소 배율 (플레이어 전용)
///
/// - levelDiff = monsterLevel - playerLevel (몬스터가 높으면 양수)
/// - 0레벨 차이: 1.0 (100% 유지)
/// - 10레벨 이상 차이: 0.2 (20% = 최저)
/// - 상승 없음 (플레이어가 높아도 보너스 없음)
static double _getLevelPenalty(int playerLevel, int monsterLevel) {
final levelDiff = monsterLevel - playerLevel;
if (levelDiff <= 0) return 1.0; // 플레이어가 높거나 같으면 페널티 없음
// 1레벨당 8%씩 감소 (100% → 92% → 84% → ... → 20%)
if (levelDiff <= 0) return 1.0;
final penalty = 1.0 - (levelDiff * _levelPenaltyPerLevel);
return penalty.clamp(_minLevelMultiplier, 1.0);
}
const CombatStats({
// 기본 스탯 (Stats에서 복사)
required this.str,
required this.con,
required this.dex,
required this.intelligence,
required this.wis,
required this.cha,
// 파생 스탯
required this.atk,
required this.def,
required this.magAtk,
required this.magDef,
required this.criRate,
required this.criDamage,
required this.evasion,
required this.accuracy,
required this.blockRate,
required this.parryRate,
required this.attackDelayMs,
const CombatStats._();
const factory CombatStats({
// 기본 스탯
/// 힘: 물리 공격력 보정
required int str,
/// 체력: HP, 방어력 보정
required int con,
/// 민첩: 회피율, 크리티컬율, 명중률, 공격 속도
required int dex,
/// 지능: 마법 공격력, MP
required int intelligence,
/// 지혜: 마법 방어력, MP 회복
required int wis,
/// 매력: 상점 가격, 드롭률 보정
required int cha,
// 파생 스탯 (전투용)
/// 물리 공격력
required int atk,
/// 물리 방어력
required int def,
/// 마법 공격력
required int magAtk,
/// 마법 방어력
required int magDef,
/// 크리티컬 확률 (0.0 ~ 1.0)
required double criRate,
/// 크리티컬 데미지 배율 (1.5 ~ 3.0)
required double criDamage,
/// 회피율 (0.0 ~ 0.5)
required double evasion,
/// 명중률 (0.8 ~ 1.0)
required double accuracy,
/// 방패 방어율 (0.0 ~ 0.4)
required double blockRate,
/// 무기로 쳐내기 확률 (0.0 ~ 0.3)
required double parryRate,
/// 공격 딜레이 (밀리초)
required int attackDelayMs,
// 자원
required this.hpMax,
required this.hpCurrent,
required this.mpMax,
required this.mpCurrent,
});
/// 최대 HP
required int hpMax,
/// 현재 HP
required int hpCurrent,
/// 최대 MP
required int mpMax,
/// 현재 MP
required int mpCurrent,
}) = _CombatStats;
// ============================================================================
// 기본 스탯
// ============================================================================
/// 힘: 물리 공격력 보정
final int str;
/// 체력: HP, 방어력 보정
final int con;
/// 민첩: 회피율, 크리티컬율, 명중률, 공격 속도
final int dex;
/// 지능: 마법 공격력, MP
final int intelligence;
/// 지혜: 마법 방어력, MP 회복
final int wis;
/// 매력: 상점 가격, 드롭률 보정
final int cha;
// ============================================================================
// 파생 스탯 (전투용)
// ============================================================================
/// 물리 공격력
final int atk;
/// 물리 방어력
final int def;
/// 마법 공격력
final int magAtk;
/// 마법 방어력
final int magDef;
/// 크리티컬 확률 (0.0 ~ 1.0)
final double criRate;
/// 크리티컬 데미지 배율 (1.5 ~ 3.0)
final double criDamage;
/// 회피율 (0.0 ~ 0.5)
final double evasion;
/// 명중률 (0.8 ~ 1.0)
final double accuracy;
/// 방패 방어율 (0.0 ~ 0.4)
final double blockRate;
/// 무기로 쳐내기 확률 (0.0 ~ 0.3)
final double parryRate;
/// 공격 딜레이 (밀리초)
final int attackDelayMs;
// ============================================================================
// 자원
// ============================================================================
/// 최대 HP
final int hpMax;
/// 현재 HP
final int hpCurrent;
/// 최대 MP
final int mpMax;
/// 현재 MP
final int mpCurrent;
factory CombatStats.fromJson(Map<String, dynamic> json) =>
_$CombatStatsFromJson(json);
// ============================================================================
// 유틸리티
@@ -190,66 +140,11 @@ class CombatStats {
return withHp(hpCurrent + amount);
}
CombatStats copyWith({
int? str,
int? con,
int? dex,
int? intelligence,
int? wis,
int? cha,
int? atk,
int? def,
int? magAtk,
int? magDef,
double? criRate,
double? criDamage,
double? evasion,
double? accuracy,
double? blockRate,
double? parryRate,
int? attackDelayMs,
int? hpMax,
int? hpCurrent,
int? mpMax,
int? mpCurrent,
}) {
return CombatStats(
str: str ?? this.str,
con: con ?? this.con,
dex: dex ?? this.dex,
intelligence: intelligence ?? this.intelligence,
wis: wis ?? this.wis,
cha: cha ?? this.cha,
atk: atk ?? this.atk,
def: def ?? this.def,
magAtk: magAtk ?? this.magAtk,
magDef: magDef ?? this.magDef,
criRate: criRate ?? this.criRate,
criDamage: criDamage ?? this.criDamage,
evasion: evasion ?? this.evasion,
accuracy: accuracy ?? this.accuracy,
blockRate: blockRate ?? this.blockRate,
parryRate: parryRate ?? this.parryRate,
attackDelayMs: attackDelayMs ?? this.attackDelayMs,
hpMax: hpMax ?? this.hpMax,
hpCurrent: hpCurrent ?? this.hpCurrent,
mpMax: mpMax ?? this.mpMax,
mpCurrent: mpCurrent ?? this.mpCurrent,
);
}
// ============================================================================
// 팩토리 메서드
// ============================================================================
/// Stats와 Equipment에서 CombatStats 생성
///
/// [stats] 캐릭터 기본 스탯
/// [equipment] 장착 장비 (장비 스탯 적용)
/// [level] 캐릭터 레벨 (스케일링용)
/// [race] 종족 특성 (선택사항, Phase 5)
/// [klass] 클래스 특성 (선택사항, Phase 5)
/// [monsterLevel] 상대 몬스터 레벨 (레벨 페널티 계산용, Phase 12)
factory CombatStats.fromStats({
required Stats stats,
required Equipment equipment,
@@ -321,7 +216,6 @@ class CombatStats {
final parryRate = (baseParryRate + equipStats.parryRate).clamp(0.0, 0.4);
// 공격 속도: 무기 기본 공속 + DEX 보정
// 무기 attackSpeed가 0이면 기본값 1000ms 사용
final weaponItem = equipment.items[0]; // 무기 슬롯
final weaponSpeed = weaponItem.stats.attackSpeed;
final baseAttackSpeed = weaponSpeed > 0 ? weaponSpeed : 1000;
@@ -339,32 +233,27 @@ class CombatStats {
// 종족 패시브 적용 (Phase 5)
// ========================================================================
// HP 보너스 (Heap Troll: +20%)
final raceHpBonus = race?.getPassiveValue(PassiveType.hpBonus) ?? 0.0;
if (raceHpBonus > 0) {
totalHpMax = (totalHpMax * (1 + raceHpBonus)).round();
}
// MP 보너스 (Pointer Fairy: +20%)
final raceMpBonus = race?.getPassiveValue(PassiveType.mpBonus) ?? 0.0;
if (raceMpBonus > 0) {
totalMpMax = (totalMpMax * (1 + raceMpBonus)).round();
}
// 마법 데미지 보너스 (Null Elf: +15%)
final raceMagicBonus =
race?.getPassiveValue(PassiveType.magicDamageBonus) ?? 0.0;
if (raceMagicBonus > 0) {
baseMagAtk = (baseMagAtk * (1 + raceMagicBonus)).round();
}
// 방어력 보너스 (Buffer Dwarf: +10%)
final raceDefBonus = race?.getPassiveValue(PassiveType.defenseBonus) ?? 0.0;
if (raceDefBonus > 0) {
baseDef = (baseDef * (1 + raceDefBonus)).round();
}
// 크리티컬 보너스 (Stack Goblin: +5%)
final raceCritBonus =
race?.getPassiveValue(PassiveType.criticalBonus) ?? 0.0;
criRate += raceCritBonus;
@@ -373,40 +262,34 @@ class CombatStats {
// 클래스 패시브 적용 (Phase 5)
// ========================================================================
// HP 보너스 (Garbage Collector: +30%)
final classHpBonus =
klass?.getPassiveValue(ClassPassiveType.hpBonus) ?? 0.0;
if (classHpBonus > 0) {
totalHpMax = (totalHpMax * (1 + classHpBonus)).round();
}
// 물리 공격력 보너스 (Bug Hunter: +20%)
final classPhysBonus =
klass?.getPassiveValue(ClassPassiveType.physicalDamageBonus) ?? 0.0;
if (classPhysBonus > 0) {
baseAtk = (baseAtk * (1 + classPhysBonus)).round();
}
// 방어력 보너스 (Debugger Paladin: +15%)
final classDefBonus =
klass?.getPassiveValue(ClassPassiveType.defenseBonus) ?? 0.0;
if (classDefBonus > 0) {
baseDef = (baseDef * (1 + classDefBonus)).round();
}
// 마법 데미지 보너스 (Compiler Mage: +25%)
final classMagBonus =
klass?.getPassiveValue(ClassPassiveType.magicDamageBonus) ?? 0.0;
if (classMagBonus > 0) {
baseMagAtk = (baseMagAtk * (1 + classMagBonus)).round();
}
// 회피율 보너스 (Refactor Monk: +15%)
final classEvasionBonus =
klass?.getPassiveValue(ClassPassiveType.evasionBonus) ?? 0.0;
evasion += classEvasionBonus;
// 크리티컬 보너스 (Pointer Assassin: +20%)
final classCritBonus =
klass?.getPassiveValue(ClassPassiveType.criticalBonus) ?? 0.0;
criRate += classCritBonus;
@@ -415,13 +298,11 @@ class CombatStats {
// 레벨 페널티 및 최종 클램핑 (Phase 12)
// ========================================================================
// 레벨 페널티 적용 (크리/회피/블록/패리)
criRate *= levelPenalty;
evasion *= levelPenalty;
var finalBlockRate = blockRate * levelPenalty;
var finalParryRate = parryRate * levelPenalty;
// 최종 클램핑 (새 캡 적용)
criRate = criRate.clamp(0.05, _maxCriRate);
evasion = evasion.clamp(0.0, _maxEvasion);
finalBlockRate = finalBlockRate.clamp(0.0, _maxBlockRate);
@@ -452,60 +333,6 @@ class CombatStats {
);
}
/// JSON으로 직렬화
Map<String, dynamic> toJson() {
return {
'str': str,
'con': con,
'dex': dex,
'intelligence': intelligence,
'wis': wis,
'cha': cha,
'atk': atk,
'def': def,
'magAtk': magAtk,
'magDef': magDef,
'criRate': criRate,
'criDamage': criDamage,
'evasion': evasion,
'accuracy': accuracy,
'blockRate': blockRate,
'parryRate': parryRate,
'attackDelayMs': attackDelayMs,
'hpMax': hpMax,
'hpCurrent': hpCurrent,
'mpMax': mpMax,
'mpCurrent': mpCurrent,
};
}
/// JSON에서 역직렬화
factory CombatStats.fromJson(Map<String, dynamic> json) {
return CombatStats(
str: json['str'] as int,
con: json['con'] as int,
dex: json['dex'] as int,
intelligence: json['intelligence'] as int,
wis: json['wis'] as int,
cha: json['cha'] as int,
atk: json['atk'] as int,
def: json['def'] as int,
magAtk: json['magAtk'] as int,
magDef: json['magDef'] as int,
criRate: (json['criRate'] as num).toDouble(),
criDamage: (json['criDamage'] as num).toDouble(),
evasion: (json['evasion'] as num).toDouble(),
accuracy: (json['accuracy'] as num).toDouble(),
blockRate: (json['blockRate'] as num).toDouble(),
parryRate: (json['parryRate'] as num).toDouble(),
attackDelayMs: json['attackDelayMs'] as int,
hpMax: json['hpMax'] as int,
hpCurrent: json['hpCurrent'] as int,
mpMax: json['mpMax'] as int,
mpCurrent: json['mpCurrent'] as int,
);
}
/// 테스트/디버그용 기본값
factory CombatStats.empty() => const CombatStats(
str: 10,

View File

@@ -0,0 +1,733 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'combat_stats.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models',
);
CombatStats _$CombatStatsFromJson(Map<String, dynamic> json) {
return _CombatStats.fromJson(json);
}
/// @nodoc
mixin _$CombatStats {
// 기본 스탯
/// 힘: 물리 공격력 보정
int get str => throw _privateConstructorUsedError;
/// 체력: HP, 방어력 보정
int get con => throw _privateConstructorUsedError;
/// 민첩: 회피율, 크리티컬율, 명중률, 공격 속도
int get dex => throw _privateConstructorUsedError;
/// 지능: 마법 공격력, MP
int get intelligence => throw _privateConstructorUsedError;
/// 지혜: 마법 방어력, MP 회복
int get wis => throw _privateConstructorUsedError;
/// 매력: 상점 가격, 드롭률 보정
int get cha => throw _privateConstructorUsedError; // 파생 스탯 (전투용)
/// 물리 공격력
int get atk => throw _privateConstructorUsedError;
/// 물리 방어력
int get def => throw _privateConstructorUsedError;
/// 마법 공격력
int get magAtk => throw _privateConstructorUsedError;
/// 마법 방어력
int get magDef => throw _privateConstructorUsedError;
/// 크리티컬 확률 (0.0 ~ 1.0)
double get criRate => throw _privateConstructorUsedError;
/// 크리티컬 데미지 배율 (1.5 ~ 3.0)
double get criDamage => throw _privateConstructorUsedError;
/// 회피율 (0.0 ~ 0.5)
double get evasion => throw _privateConstructorUsedError;
/// 명중률 (0.8 ~ 1.0)
double get accuracy => throw _privateConstructorUsedError;
/// 방패 방어율 (0.0 ~ 0.4)
double get blockRate => throw _privateConstructorUsedError;
/// 무기로 쳐내기 확률 (0.0 ~ 0.3)
double get parryRate => throw _privateConstructorUsedError;
/// 공격 딜레이 (밀리초)
int get attackDelayMs => throw _privateConstructorUsedError; // 자원
/// 최대 HP
int get hpMax => throw _privateConstructorUsedError;
/// 현재 HP
int get hpCurrent => throw _privateConstructorUsedError;
/// 최대 MP
int get mpMax => throw _privateConstructorUsedError;
/// 현재 MP
int get mpCurrent => throw _privateConstructorUsedError;
/// Serializes this CombatStats to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
/// Create a copy of CombatStats
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$CombatStatsCopyWith<CombatStats> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $CombatStatsCopyWith<$Res> {
factory $CombatStatsCopyWith(
CombatStats value,
$Res Function(CombatStats) then,
) = _$CombatStatsCopyWithImpl<$Res, CombatStats>;
@useResult
$Res call({
int str,
int con,
int dex,
int intelligence,
int wis,
int cha,
int atk,
int def,
int magAtk,
int magDef,
double criRate,
double criDamage,
double evasion,
double accuracy,
double blockRate,
double parryRate,
int attackDelayMs,
int hpMax,
int hpCurrent,
int mpMax,
int mpCurrent,
});
}
/// @nodoc
class _$CombatStatsCopyWithImpl<$Res, $Val extends CombatStats>
implements $CombatStatsCopyWith<$Res> {
_$CombatStatsCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of CombatStats
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? str = null,
Object? con = null,
Object? dex = null,
Object? intelligence = null,
Object? wis = null,
Object? cha = null,
Object? atk = null,
Object? def = null,
Object? magAtk = null,
Object? magDef = null,
Object? criRate = null,
Object? criDamage = null,
Object? evasion = null,
Object? accuracy = null,
Object? blockRate = null,
Object? parryRate = null,
Object? attackDelayMs = null,
Object? hpMax = null,
Object? hpCurrent = null,
Object? mpMax = null,
Object? mpCurrent = null,
}) {
return _then(
_value.copyWith(
str: null == str
? _value.str
: str // ignore: cast_nullable_to_non_nullable
as int,
con: null == con
? _value.con
: con // ignore: cast_nullable_to_non_nullable
as int,
dex: null == dex
? _value.dex
: dex // ignore: cast_nullable_to_non_nullable
as int,
intelligence: null == intelligence
? _value.intelligence
: intelligence // ignore: cast_nullable_to_non_nullable
as int,
wis: null == wis
? _value.wis
: wis // ignore: cast_nullable_to_non_nullable
as int,
cha: null == cha
? _value.cha
: cha // ignore: cast_nullable_to_non_nullable
as int,
atk: null == atk
? _value.atk
: atk // ignore: cast_nullable_to_non_nullable
as int,
def: null == def
? _value.def
: def // ignore: cast_nullable_to_non_nullable
as int,
magAtk: null == magAtk
? _value.magAtk
: magAtk // ignore: cast_nullable_to_non_nullable
as int,
magDef: null == magDef
? _value.magDef
: magDef // ignore: cast_nullable_to_non_nullable
as int,
criRate: null == criRate
? _value.criRate
: criRate // ignore: cast_nullable_to_non_nullable
as double,
criDamage: null == criDamage
? _value.criDamage
: criDamage // ignore: cast_nullable_to_non_nullable
as double,
evasion: null == evasion
? _value.evasion
: evasion // ignore: cast_nullable_to_non_nullable
as double,
accuracy: null == accuracy
? _value.accuracy
: accuracy // ignore: cast_nullable_to_non_nullable
as double,
blockRate: null == blockRate
? _value.blockRate
: blockRate // ignore: cast_nullable_to_non_nullable
as double,
parryRate: null == parryRate
? _value.parryRate
: parryRate // ignore: cast_nullable_to_non_nullable
as double,
attackDelayMs: null == attackDelayMs
? _value.attackDelayMs
: attackDelayMs // ignore: cast_nullable_to_non_nullable
as int,
hpMax: null == hpMax
? _value.hpMax
: hpMax // ignore: cast_nullable_to_non_nullable
as int,
hpCurrent: null == hpCurrent
? _value.hpCurrent
: hpCurrent // ignore: cast_nullable_to_non_nullable
as int,
mpMax: null == mpMax
? _value.mpMax
: mpMax // ignore: cast_nullable_to_non_nullable
as int,
mpCurrent: null == mpCurrent
? _value.mpCurrent
: mpCurrent // ignore: cast_nullable_to_non_nullable
as int,
)
as $Val,
);
}
}
/// @nodoc
abstract class _$$CombatStatsImplCopyWith<$Res>
implements $CombatStatsCopyWith<$Res> {
factory _$$CombatStatsImplCopyWith(
_$CombatStatsImpl value,
$Res Function(_$CombatStatsImpl) then,
) = __$$CombatStatsImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({
int str,
int con,
int dex,
int intelligence,
int wis,
int cha,
int atk,
int def,
int magAtk,
int magDef,
double criRate,
double criDamage,
double evasion,
double accuracy,
double blockRate,
double parryRate,
int attackDelayMs,
int hpMax,
int hpCurrent,
int mpMax,
int mpCurrent,
});
}
/// @nodoc
class __$$CombatStatsImplCopyWithImpl<$Res>
extends _$CombatStatsCopyWithImpl<$Res, _$CombatStatsImpl>
implements _$$CombatStatsImplCopyWith<$Res> {
__$$CombatStatsImplCopyWithImpl(
_$CombatStatsImpl _value,
$Res Function(_$CombatStatsImpl) _then,
) : super(_value, _then);
/// Create a copy of CombatStats
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? str = null,
Object? con = null,
Object? dex = null,
Object? intelligence = null,
Object? wis = null,
Object? cha = null,
Object? atk = null,
Object? def = null,
Object? magAtk = null,
Object? magDef = null,
Object? criRate = null,
Object? criDamage = null,
Object? evasion = null,
Object? accuracy = null,
Object? blockRate = null,
Object? parryRate = null,
Object? attackDelayMs = null,
Object? hpMax = null,
Object? hpCurrent = null,
Object? mpMax = null,
Object? mpCurrent = null,
}) {
return _then(
_$CombatStatsImpl(
str: null == str
? _value.str
: str // ignore: cast_nullable_to_non_nullable
as int,
con: null == con
? _value.con
: con // ignore: cast_nullable_to_non_nullable
as int,
dex: null == dex
? _value.dex
: dex // ignore: cast_nullable_to_non_nullable
as int,
intelligence: null == intelligence
? _value.intelligence
: intelligence // ignore: cast_nullable_to_non_nullable
as int,
wis: null == wis
? _value.wis
: wis // ignore: cast_nullable_to_non_nullable
as int,
cha: null == cha
? _value.cha
: cha // ignore: cast_nullable_to_non_nullable
as int,
atk: null == atk
? _value.atk
: atk // ignore: cast_nullable_to_non_nullable
as int,
def: null == def
? _value.def
: def // ignore: cast_nullable_to_non_nullable
as int,
magAtk: null == magAtk
? _value.magAtk
: magAtk // ignore: cast_nullable_to_non_nullable
as int,
magDef: null == magDef
? _value.magDef
: magDef // ignore: cast_nullable_to_non_nullable
as int,
criRate: null == criRate
? _value.criRate
: criRate // ignore: cast_nullable_to_non_nullable
as double,
criDamage: null == criDamage
? _value.criDamage
: criDamage // ignore: cast_nullable_to_non_nullable
as double,
evasion: null == evasion
? _value.evasion
: evasion // ignore: cast_nullable_to_non_nullable
as double,
accuracy: null == accuracy
? _value.accuracy
: accuracy // ignore: cast_nullable_to_non_nullable
as double,
blockRate: null == blockRate
? _value.blockRate
: blockRate // ignore: cast_nullable_to_non_nullable
as double,
parryRate: null == parryRate
? _value.parryRate
: parryRate // ignore: cast_nullable_to_non_nullable
as double,
attackDelayMs: null == attackDelayMs
? _value.attackDelayMs
: attackDelayMs // ignore: cast_nullable_to_non_nullable
as int,
hpMax: null == hpMax
? _value.hpMax
: hpMax // ignore: cast_nullable_to_non_nullable
as int,
hpCurrent: null == hpCurrent
? _value.hpCurrent
: hpCurrent // ignore: cast_nullable_to_non_nullable
as int,
mpMax: null == mpMax
? _value.mpMax
: mpMax // ignore: cast_nullable_to_non_nullable
as int,
mpCurrent: null == mpCurrent
? _value.mpCurrent
: mpCurrent // ignore: cast_nullable_to_non_nullable
as int,
),
);
}
}
/// @nodoc
@JsonSerializable()
class _$CombatStatsImpl extends _CombatStats {
const _$CombatStatsImpl({
required this.str,
required this.con,
required this.dex,
required this.intelligence,
required this.wis,
required this.cha,
required this.atk,
required this.def,
required this.magAtk,
required this.magDef,
required this.criRate,
required this.criDamage,
required this.evasion,
required this.accuracy,
required this.blockRate,
required this.parryRate,
required this.attackDelayMs,
required this.hpMax,
required this.hpCurrent,
required this.mpMax,
required this.mpCurrent,
}) : super._();
factory _$CombatStatsImpl.fromJson(Map<String, dynamic> json) =>
_$$CombatStatsImplFromJson(json);
// 기본 스탯
/// 힘: 물리 공격력 보정
@override
final int str;
/// 체력: HP, 방어력 보정
@override
final int con;
/// 민첩: 회피율, 크리티컬율, 명중률, 공격 속도
@override
final int dex;
/// 지능: 마법 공격력, MP
@override
final int intelligence;
/// 지혜: 마법 방어력, MP 회복
@override
final int wis;
/// 매력: 상점 가격, 드롭률 보정
@override
final int cha;
// 파생 스탯 (전투용)
/// 물리 공격력
@override
final int atk;
/// 물리 방어력
@override
final int def;
/// 마법 공격력
@override
final int magAtk;
/// 마법 방어력
@override
final int magDef;
/// 크리티컬 확률 (0.0 ~ 1.0)
@override
final double criRate;
/// 크리티컬 데미지 배율 (1.5 ~ 3.0)
@override
final double criDamage;
/// 회피율 (0.0 ~ 0.5)
@override
final double evasion;
/// 명중률 (0.8 ~ 1.0)
@override
final double accuracy;
/// 방패 방어율 (0.0 ~ 0.4)
@override
final double blockRate;
/// 무기로 쳐내기 확률 (0.0 ~ 0.3)
@override
final double parryRate;
/// 공격 딜레이 (밀리초)
@override
final int attackDelayMs;
// 자원
/// 최대 HP
@override
final int hpMax;
/// 현재 HP
@override
final int hpCurrent;
/// 최대 MP
@override
final int mpMax;
/// 현재 MP
@override
final int mpCurrent;
@override
String toString() {
return 'CombatStats(str: $str, con: $con, dex: $dex, intelligence: $intelligence, wis: $wis, cha: $cha, atk: $atk, def: $def, magAtk: $magAtk, magDef: $magDef, criRate: $criRate, criDamage: $criDamage, evasion: $evasion, accuracy: $accuracy, blockRate: $blockRate, parryRate: $parryRate, attackDelayMs: $attackDelayMs, hpMax: $hpMax, hpCurrent: $hpCurrent, mpMax: $mpMax, mpCurrent: $mpCurrent)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$CombatStatsImpl &&
(identical(other.str, str) || other.str == str) &&
(identical(other.con, con) || other.con == con) &&
(identical(other.dex, dex) || other.dex == dex) &&
(identical(other.intelligence, intelligence) ||
other.intelligence == intelligence) &&
(identical(other.wis, wis) || other.wis == wis) &&
(identical(other.cha, cha) || other.cha == cha) &&
(identical(other.atk, atk) || other.atk == atk) &&
(identical(other.def, def) || other.def == def) &&
(identical(other.magAtk, magAtk) || other.magAtk == magAtk) &&
(identical(other.magDef, magDef) || other.magDef == magDef) &&
(identical(other.criRate, criRate) || other.criRate == criRate) &&
(identical(other.criDamage, criDamage) ||
other.criDamage == criDamage) &&
(identical(other.evasion, evasion) || other.evasion == evasion) &&
(identical(other.accuracy, accuracy) ||
other.accuracy == accuracy) &&
(identical(other.blockRate, blockRate) ||
other.blockRate == blockRate) &&
(identical(other.parryRate, parryRate) ||
other.parryRate == parryRate) &&
(identical(other.attackDelayMs, attackDelayMs) ||
other.attackDelayMs == attackDelayMs) &&
(identical(other.hpMax, hpMax) || other.hpMax == hpMax) &&
(identical(other.hpCurrent, hpCurrent) ||
other.hpCurrent == hpCurrent) &&
(identical(other.mpMax, mpMax) || other.mpMax == mpMax) &&
(identical(other.mpCurrent, mpCurrent) ||
other.mpCurrent == mpCurrent));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hashAll([
runtimeType,
str,
con,
dex,
intelligence,
wis,
cha,
atk,
def,
magAtk,
magDef,
criRate,
criDamage,
evasion,
accuracy,
blockRate,
parryRate,
attackDelayMs,
hpMax,
hpCurrent,
mpMax,
mpCurrent,
]);
/// Create a copy of CombatStats
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$CombatStatsImplCopyWith<_$CombatStatsImpl> get copyWith =>
__$$CombatStatsImplCopyWithImpl<_$CombatStatsImpl>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$CombatStatsImplToJson(this);
}
}
abstract class _CombatStats extends CombatStats {
const factory _CombatStats({
required final int str,
required final int con,
required final int dex,
required final int intelligence,
required final int wis,
required final int cha,
required final int atk,
required final int def,
required final int magAtk,
required final int magDef,
required final double criRate,
required final double criDamage,
required final double evasion,
required final double accuracy,
required final double blockRate,
required final double parryRate,
required final int attackDelayMs,
required final int hpMax,
required final int hpCurrent,
required final int mpMax,
required final int mpCurrent,
}) = _$CombatStatsImpl;
const _CombatStats._() : super._();
factory _CombatStats.fromJson(Map<String, dynamic> json) =
_$CombatStatsImpl.fromJson;
// 기본 스탯
/// 힘: 물리 공격력 보정
@override
int get str;
/// 체력: HP, 방어력 보정
@override
int get con;
/// 민첩: 회피율, 크리티컬율, 명중률, 공격 속도
@override
int get dex;
/// 지능: 마법 공격력, MP
@override
int get intelligence;
/// 지혜: 마법 방어력, MP 회복
@override
int get wis;
/// 매력: 상점 가격, 드롭률 보정
@override
int get cha; // 파생 스탯 (전투용)
/// 물리 공격력
@override
int get atk;
/// 물리 방어력
@override
int get def;
/// 마법 공격력
@override
int get magAtk;
/// 마법 방어력
@override
int get magDef;
/// 크리티컬 확률 (0.0 ~ 1.0)
@override
double get criRate;
/// 크리티컬 데미지 배율 (1.5 ~ 3.0)
@override
double get criDamage;
/// 회피율 (0.0 ~ 0.5)
@override
double get evasion;
/// 명중률 (0.8 ~ 1.0)
@override
double get accuracy;
/// 방패 방어율 (0.0 ~ 0.4)
@override
double get blockRate;
/// 무기로 쳐내기 확률 (0.0 ~ 0.3)
@override
double get parryRate;
/// 공격 딜레이 (밀리초)
@override
int get attackDelayMs; // 자원
/// 최대 HP
@override
int get hpMax;
/// 현재 HP
@override
int get hpCurrent;
/// 최대 MP
@override
int get mpMax;
/// 현재 MP
@override
int get mpCurrent;
/// Create a copy of CombatStats
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$CombatStatsImplCopyWith<_$CombatStatsImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@@ -0,0 +1,57 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'combat_stats.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_$CombatStatsImpl _$$CombatStatsImplFromJson(Map<String, dynamic> json) =>
_$CombatStatsImpl(
str: (json['str'] as num).toInt(),
con: (json['con'] as num).toInt(),
dex: (json['dex'] as num).toInt(),
intelligence: (json['intelligence'] as num).toInt(),
wis: (json['wis'] as num).toInt(),
cha: (json['cha'] as num).toInt(),
atk: (json['atk'] as num).toInt(),
def: (json['def'] as num).toInt(),
magAtk: (json['magAtk'] as num).toInt(),
magDef: (json['magDef'] as num).toInt(),
criRate: (json['criRate'] as num).toDouble(),
criDamage: (json['criDamage'] as num).toDouble(),
evasion: (json['evasion'] as num).toDouble(),
accuracy: (json['accuracy'] as num).toDouble(),
blockRate: (json['blockRate'] as num).toDouble(),
parryRate: (json['parryRate'] as num).toDouble(),
attackDelayMs: (json['attackDelayMs'] as num).toInt(),
hpMax: (json['hpMax'] as num).toInt(),
hpCurrent: (json['hpCurrent'] as num).toInt(),
mpMax: (json['mpMax'] as num).toInt(),
mpCurrent: (json['mpCurrent'] as num).toInt(),
);
Map<String, dynamic> _$$CombatStatsImplToJson(_$CombatStatsImpl instance) =>
<String, dynamic>{
'str': instance.str,
'con': instance.con,
'dex': instance.dex,
'intelligence': instance.intelligence,
'wis': instance.wis,
'cha': instance.cha,
'atk': instance.atk,
'def': instance.def,
'magAtk': instance.magAtk,
'magDef': instance.magDef,
'criRate': instance.criRate,
'criDamage': instance.criDamage,
'evasion': instance.evasion,
'accuracy': instance.accuracy,
'blockRate': instance.blockRate,
'parryRate': instance.parryRate,
'attackDelayMs': instance.attackDelayMs,
'hpMax': instance.hpMax,
'hpCurrent': instance.hpCurrent,
'mpMax': instance.mpMax,
'mpCurrent': instance.mpCurrent,
};

View File

@@ -1,51 +1,38 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:asciineverdie/src/core/model/equipment_slot.dart';
import 'package:asciineverdie/src/core/model/item_stats.dart';
part 'equipment_item.freezed.dart';
part 'equipment_item.g.dart';
/// 장비 아이템
///
/// 개별 장비의 이름, 슬롯, 레벨, 스탯 등을 포함하는 클래스.
/// 불변(immutable) 객체로 설계됨.
class EquipmentItem {
const EquipmentItem({
required this.name,
required this.slot,
required this.level,
required this.weight,
required this.stats,
required this.rarity,
});
@freezed
class EquipmentItem with _$EquipmentItem {
const EquipmentItem._();
/// 아이템 이름 (예: "Flaming Sword of Doom")
final String name;
const factory EquipmentItem({
/// 아이템 이름 (예: "Flaming Sword of Doom")
required String name,
/// 장착 슬롯
@JsonKey(fromJson: _slotFromJson, toJson: _slotToJson)
required EquipmentSlot slot,
/// 아이템 레벨
required int level,
/// 무게 (STR 기반 휴대 제한용)
required int weight,
/// 아이템 스탯 보정치
required ItemStats stats,
/// 희귀도
@JsonKey(fromJson: _rarityFromJson, toJson: _rarityToJson)
required ItemRarity rarity,
}) = _EquipmentItem;
/// 장착 슬롯
final EquipmentSlot slot;
/// 아이템 레벨
final int level;
/// 무게 (STR 기반 휴대 제한용)
final int weight;
/// 아이템 스탯 보정치
final ItemStats stats;
/// 희귀도
final ItemRarity rarity;
/// 가중치 (자동 장착 비교용)
///
/// 가중치 = 기본값 + (레벨 * 10) + (희귀도 보너스) + (스탯 합계)
int get itemWeight {
const baseValue = 10;
return baseValue + (level * 10) + rarity.weightBonus + stats.totalStatValue;
}
/// 빈 아이템 여부
bool get isEmpty => name.isEmpty;
/// 유효한 아이템 여부
bool get isNotEmpty => name.isNotEmpty;
factory EquipmentItem.fromJson(Map<String, dynamic> json) =>
_$EquipmentItemFromJson(json);
/// 빈 아이템 생성 (특정 슬롯)
factory EquipmentItem.empty(EquipmentSlot slot) {
@@ -54,7 +41,7 @@ class EquipmentItem {
slot: slot,
level: 0,
weight: 0,
stats: ItemStats.empty,
stats: const ItemStats(),
rarity: ItemRarity.common,
);
}
@@ -71,59 +58,39 @@ class EquipmentItem {
);
}
EquipmentItem copyWith({
String? name,
EquipmentSlot? slot,
int? level,
int? weight,
ItemStats? stats,
ItemRarity? rarity,
}) {
return EquipmentItem(
name: name ?? this.name,
slot: slot ?? this.slot,
level: level ?? this.level,
weight: weight ?? this.weight,
stats: stats ?? this.stats,
rarity: rarity ?? this.rarity,
);
/// 가중치 (자동 장착 비교용)
///
/// 가중치 = 기본값 + (레벨 * 10) + (희귀도 보너스) + (스탯 합계)
int get itemWeight {
const baseValue = 10;
return baseValue + (level * 10) + rarity.weightBonus + stats.totalStatValue;
}
/// JSON으로 직렬화
Map<String, dynamic> toJson() {
return {
'name': name,
'slot': slot.name,
'level': level,
'weight': weight,
'stats': stats.toJson(),
'rarity': rarity.name,
};
}
/// 빈 아이템 여부
bool get isEmpty => name.isEmpty;
/// JSON에서 역직렬화
factory EquipmentItem.fromJson(Map<String, dynamic> json) {
final slotName = json['slot'] as String? ?? 'weapon';
final rarityName = json['rarity'] as String? ?? 'common';
return EquipmentItem(
name: json['name'] as String? ?? '',
slot: EquipmentSlot.values.firstWhere(
(s) => s.name == slotName,
orElse: () => EquipmentSlot.weapon,
),
level: json['level'] as int? ?? 0,
weight: json['weight'] as int? ?? 0,
stats: json['stats'] != null
? ItemStats.fromJson(json['stats'] as Map<String, dynamic>)
: ItemStats.empty,
rarity: ItemRarity.values.firstWhere(
(r) => r.name == rarityName,
orElse: () => ItemRarity.common,
),
);
}
/// 유효한 아이템 여부
bool get isNotEmpty => name.isNotEmpty;
@override
String toString() => name.isEmpty ? '(empty)' : name;
}
// JSON 변환 헬퍼 (세이브 파일 호환성 유지)
EquipmentSlot _slotFromJson(String? value) {
return EquipmentSlot.values.firstWhere(
(s) => s.name == value,
orElse: () => EquipmentSlot.weapon,
);
}
String _slotToJson(EquipmentSlot slot) => slot.name;
ItemRarity _rarityFromJson(String? value) {
return ItemRarity.values.firstWhere(
(r) => r.name == value,
orElse: () => ItemRarity.common,
);
}
String _rarityToJson(ItemRarity rarity) => rarity.name;

View File

@@ -0,0 +1,335 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'equipment_item.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models',
);
EquipmentItem _$EquipmentItemFromJson(Map<String, dynamic> json) {
return _EquipmentItem.fromJson(json);
}
/// @nodoc
mixin _$EquipmentItem {
/// 아이템 이름 (예: "Flaming Sword of Doom")
String get name => throw _privateConstructorUsedError;
/// 장착 슬롯
@JsonKey(fromJson: _slotFromJson, toJson: _slotToJson)
EquipmentSlot get slot => throw _privateConstructorUsedError;
/// 아이템 레벨
int get level => throw _privateConstructorUsedError;
/// 무게 (STR 기반 휴대 제한용)
int get weight => throw _privateConstructorUsedError;
/// 아이템 스탯 보정치
ItemStats get stats => throw _privateConstructorUsedError;
/// 희귀도
@JsonKey(fromJson: _rarityFromJson, toJson: _rarityToJson)
ItemRarity get rarity => throw _privateConstructorUsedError;
/// Serializes this EquipmentItem to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
/// Create a copy of EquipmentItem
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$EquipmentItemCopyWith<EquipmentItem> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $EquipmentItemCopyWith<$Res> {
factory $EquipmentItemCopyWith(
EquipmentItem value,
$Res Function(EquipmentItem) then,
) = _$EquipmentItemCopyWithImpl<$Res, EquipmentItem>;
@useResult
$Res call({
String name,
@JsonKey(fromJson: _slotFromJson, toJson: _slotToJson) EquipmentSlot slot,
int level,
int weight,
ItemStats stats,
@JsonKey(fromJson: _rarityFromJson, toJson: _rarityToJson)
ItemRarity rarity,
});
$ItemStatsCopyWith<$Res> get stats;
}
/// @nodoc
class _$EquipmentItemCopyWithImpl<$Res, $Val extends EquipmentItem>
implements $EquipmentItemCopyWith<$Res> {
_$EquipmentItemCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of EquipmentItem
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? name = null,
Object? slot = null,
Object? level = null,
Object? weight = null,
Object? stats = null,
Object? rarity = null,
}) {
return _then(
_value.copyWith(
name: null == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String,
slot: null == slot
? _value.slot
: slot // ignore: cast_nullable_to_non_nullable
as EquipmentSlot,
level: null == level
? _value.level
: level // ignore: cast_nullable_to_non_nullable
as int,
weight: null == weight
? _value.weight
: weight // ignore: cast_nullable_to_non_nullable
as int,
stats: null == stats
? _value.stats
: stats // ignore: cast_nullable_to_non_nullable
as ItemStats,
rarity: null == rarity
? _value.rarity
: rarity // ignore: cast_nullable_to_non_nullable
as ItemRarity,
)
as $Val,
);
}
/// Create a copy of EquipmentItem
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$ItemStatsCopyWith<$Res> get stats {
return $ItemStatsCopyWith<$Res>(_value.stats, (value) {
return _then(_value.copyWith(stats: value) as $Val);
});
}
}
/// @nodoc
abstract class _$$EquipmentItemImplCopyWith<$Res>
implements $EquipmentItemCopyWith<$Res> {
factory _$$EquipmentItemImplCopyWith(
_$EquipmentItemImpl value,
$Res Function(_$EquipmentItemImpl) then,
) = __$$EquipmentItemImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({
String name,
@JsonKey(fromJson: _slotFromJson, toJson: _slotToJson) EquipmentSlot slot,
int level,
int weight,
ItemStats stats,
@JsonKey(fromJson: _rarityFromJson, toJson: _rarityToJson)
ItemRarity rarity,
});
@override
$ItemStatsCopyWith<$Res> get stats;
}
/// @nodoc
class __$$EquipmentItemImplCopyWithImpl<$Res>
extends _$EquipmentItemCopyWithImpl<$Res, _$EquipmentItemImpl>
implements _$$EquipmentItemImplCopyWith<$Res> {
__$$EquipmentItemImplCopyWithImpl(
_$EquipmentItemImpl _value,
$Res Function(_$EquipmentItemImpl) _then,
) : super(_value, _then);
/// Create a copy of EquipmentItem
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? name = null,
Object? slot = null,
Object? level = null,
Object? weight = null,
Object? stats = null,
Object? rarity = null,
}) {
return _then(
_$EquipmentItemImpl(
name: null == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String,
slot: null == slot
? _value.slot
: slot // ignore: cast_nullable_to_non_nullable
as EquipmentSlot,
level: null == level
? _value.level
: level // ignore: cast_nullable_to_non_nullable
as int,
weight: null == weight
? _value.weight
: weight // ignore: cast_nullable_to_non_nullable
as int,
stats: null == stats
? _value.stats
: stats // ignore: cast_nullable_to_non_nullable
as ItemStats,
rarity: null == rarity
? _value.rarity
: rarity // ignore: cast_nullable_to_non_nullable
as ItemRarity,
),
);
}
}
/// @nodoc
@JsonSerializable()
class _$EquipmentItemImpl extends _EquipmentItem {
const _$EquipmentItemImpl({
required this.name,
@JsonKey(fromJson: _slotFromJson, toJson: _slotToJson) required this.slot,
required this.level,
required this.weight,
required this.stats,
@JsonKey(fromJson: _rarityFromJson, toJson: _rarityToJson)
required this.rarity,
}) : super._();
factory _$EquipmentItemImpl.fromJson(Map<String, dynamic> json) =>
_$$EquipmentItemImplFromJson(json);
/// 아이템 이름 (예: "Flaming Sword of Doom")
@override
final String name;
/// 장착 슬롯
@override
@JsonKey(fromJson: _slotFromJson, toJson: _slotToJson)
final EquipmentSlot slot;
/// 아이템 레벨
@override
final int level;
/// 무게 (STR 기반 휴대 제한용)
@override
final int weight;
/// 아이템 스탯 보정치
@override
final ItemStats stats;
/// 희귀도
@override
@JsonKey(fromJson: _rarityFromJson, toJson: _rarityToJson)
final ItemRarity rarity;
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$EquipmentItemImpl &&
(identical(other.name, name) || other.name == name) &&
(identical(other.slot, slot) || other.slot == slot) &&
(identical(other.level, level) || other.level == level) &&
(identical(other.weight, weight) || other.weight == weight) &&
(identical(other.stats, stats) || other.stats == stats) &&
(identical(other.rarity, rarity) || other.rarity == rarity));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode =>
Object.hash(runtimeType, name, slot, level, weight, stats, rarity);
/// Create a copy of EquipmentItem
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$EquipmentItemImplCopyWith<_$EquipmentItemImpl> get copyWith =>
__$$EquipmentItemImplCopyWithImpl<_$EquipmentItemImpl>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$EquipmentItemImplToJson(this);
}
}
abstract class _EquipmentItem extends EquipmentItem {
const factory _EquipmentItem({
required final String name,
@JsonKey(fromJson: _slotFromJson, toJson: _slotToJson)
required final EquipmentSlot slot,
required final int level,
required final int weight,
required final ItemStats stats,
@JsonKey(fromJson: _rarityFromJson, toJson: _rarityToJson)
required final ItemRarity rarity,
}) = _$EquipmentItemImpl;
const _EquipmentItem._() : super._();
factory _EquipmentItem.fromJson(Map<String, dynamic> json) =
_$EquipmentItemImpl.fromJson;
/// 아이템 이름 (예: "Flaming Sword of Doom")
@override
String get name;
/// 장착 슬롯
@override
@JsonKey(fromJson: _slotFromJson, toJson: _slotToJson)
EquipmentSlot get slot;
/// 아이템 레벨
@override
int get level;
/// 무게 (STR 기반 휴대 제한용)
@override
int get weight;
/// 아이템 스탯 보정치
@override
ItemStats get stats;
/// 희귀도
@override
@JsonKey(fromJson: _rarityFromJson, toJson: _rarityToJson)
ItemRarity get rarity;
/// Create a copy of EquipmentItem
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$EquipmentItemImplCopyWith<_$EquipmentItemImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@@ -0,0 +1,27 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'equipment_item.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_$EquipmentItemImpl _$$EquipmentItemImplFromJson(Map<String, dynamic> json) =>
_$EquipmentItemImpl(
name: json['name'] as String,
slot: _slotFromJson(json['slot'] as String?),
level: (json['level'] as num).toInt(),
weight: (json['weight'] as num).toInt(),
stats: ItemStats.fromJson(json['stats'] as Map<String, dynamic>),
rarity: _rarityFromJson(json['rarity'] as String?),
);
Map<String, dynamic> _$$EquipmentItemImplToJson(_$EquipmentItemImpl instance) =>
<String, dynamic>{
'name': instance.name,
'slot': _slotToJson(instance.slot),
'level': instance.level,
'weight': instance.weight,
'stats': instance.stats,
'rarity': _rarityToJson(instance.rarity),
};

View File

@@ -1,3 +1,8 @@
import 'package:freezed_annotation/freezed_annotation.dart';
part 'item_stats.freezed.dart';
part 'item_stats.g.dart';
/// 아이템 희귀도
enum ItemRarity {
common,
@@ -29,80 +34,55 @@ enum ItemRarity {
///
/// 장비 아이템이 제공하는 스탯 보너스.
/// 모든 값은 기본 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,
});
@freezed
class ItemStats with _$ItemStats {
const ItemStats._();
/// 물리 공격력 보정
final int atk;
const factory ItemStats({
/// 물리 공격력 보정
@Default(0) int atk,
/// 물리 방어력 보정
@Default(0) int def,
/// 마법 공격력 보정
@Default(0) int magAtk,
/// 마법 방어력 보정
@Default(0) int magDef,
/// 크리티컬 확률 보정 (0.0 ~ 1.0)
@Default(0.0) double criRate,
/// 회피율 보정 (0.0 ~ 1.0)
@Default(0.0) double evasion,
/// 방패 방어율 (방패 전용, 0.0 ~ 1.0)
@Default(0.0) double blockRate,
/// 무기 쳐내기 확률 (무기 전용, 0.0 ~ 1.0)
@Default(0.0) double parryRate,
/// HP 보너스
@Default(0) int hpBonus,
/// MP 보너스
@Default(0) int mpBonus,
/// STR 보너스
@Default(0) int strBonus,
/// CON 보너스
@Default(0) int conBonus,
/// DEX 보너스
@Default(0) int dexBonus,
/// INT 보너스
@Default(0) int intBonus,
/// WIS 보너스
@Default(0) int wisBonus,
/// CHA 보너스
@Default(0) int chaBonus,
/// 무기 공격속도 (밀리초, 무기 전용)
///
/// 0이면 기본값(1000ms) 사용, 값이 클수록 느린 공격.
/// 느린 무기는 높은 기본 데미지를 가짐.
@Default(0) int attackSpeed,
}) = _ItemStats;
/// 물리 방어력 보정
final int def;
factory ItemStats.fromJson(Map<String, dynamic> json) =>
_$ItemStatsFromJson(json);
/// 마법 공격력 보정
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;
/// 빈 스탯 (보너스 없음)
static const empty = ItemStats();
/// 스탯 합계 (가중치 계산용)
int get totalStatValue {
@@ -124,55 +104,6 @@ class ItemStats {
chaBonus * 5;
}
/// 빈 스탯 (보너스 없음)
static const empty = ItemStats();
/// JSON으로 직렬화
Map<String, dynamic> 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<String, dynamic> 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는 합산 대상 아님 (무기 슬롯 단일 값)
@@ -197,44 +128,4 @@ class ItemStats {
// 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,
);
}
}

View File

@@ -0,0 +1,651 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'item_stats.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models',
);
ItemStats _$ItemStatsFromJson(Map<String, dynamic> json) {
return _ItemStats.fromJson(json);
}
/// @nodoc
mixin _$ItemStats {
/// 물리 공격력 보정
int get atk => throw _privateConstructorUsedError;
/// 물리 방어력 보정
int get def => throw _privateConstructorUsedError;
/// 마법 공격력 보정
int get magAtk => throw _privateConstructorUsedError;
/// 마법 방어력 보정
int get magDef => throw _privateConstructorUsedError;
/// 크리티컬 확률 보정 (0.0 ~ 1.0)
double get criRate => throw _privateConstructorUsedError;
/// 회피율 보정 (0.0 ~ 1.0)
double get evasion => throw _privateConstructorUsedError;
/// 방패 방어율 (방패 전용, 0.0 ~ 1.0)
double get blockRate => throw _privateConstructorUsedError;
/// 무기 쳐내기 확률 (무기 전용, 0.0 ~ 1.0)
double get parryRate => throw _privateConstructorUsedError;
/// HP 보너스
int get hpBonus => throw _privateConstructorUsedError;
/// MP 보너스
int get mpBonus => throw _privateConstructorUsedError;
/// STR 보너스
int get strBonus => throw _privateConstructorUsedError;
/// CON 보너스
int get conBonus => throw _privateConstructorUsedError;
/// DEX 보너스
int get dexBonus => throw _privateConstructorUsedError;
/// INT 보너스
int get intBonus => throw _privateConstructorUsedError;
/// WIS 보너스
int get wisBonus => throw _privateConstructorUsedError;
/// CHA 보너스
int get chaBonus => throw _privateConstructorUsedError;
/// 무기 공격속도 (밀리초, 무기 전용)
///
/// 0이면 기본값(1000ms) 사용, 값이 클수록 느린 공격.
/// 느린 무기는 높은 기본 데미지를 가짐.
int get attackSpeed => throw _privateConstructorUsedError;
/// Serializes this ItemStats to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
/// Create a copy of ItemStats
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$ItemStatsCopyWith<ItemStats> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $ItemStatsCopyWith<$Res> {
factory $ItemStatsCopyWith(ItemStats value, $Res Function(ItemStats) then) =
_$ItemStatsCopyWithImpl<$Res, ItemStats>;
@useResult
$Res call({
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,
});
}
/// @nodoc
class _$ItemStatsCopyWithImpl<$Res, $Val extends ItemStats>
implements $ItemStatsCopyWith<$Res> {
_$ItemStatsCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of ItemStats
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? atk = null,
Object? def = null,
Object? magAtk = null,
Object? magDef = null,
Object? criRate = null,
Object? evasion = null,
Object? blockRate = null,
Object? parryRate = null,
Object? hpBonus = null,
Object? mpBonus = null,
Object? strBonus = null,
Object? conBonus = null,
Object? dexBonus = null,
Object? intBonus = null,
Object? wisBonus = null,
Object? chaBonus = null,
Object? attackSpeed = null,
}) {
return _then(
_value.copyWith(
atk: null == atk
? _value.atk
: atk // ignore: cast_nullable_to_non_nullable
as int,
def: null == def
? _value.def
: def // ignore: cast_nullable_to_non_nullable
as int,
magAtk: null == magAtk
? _value.magAtk
: magAtk // ignore: cast_nullable_to_non_nullable
as int,
magDef: null == magDef
? _value.magDef
: magDef // ignore: cast_nullable_to_non_nullable
as int,
criRate: null == criRate
? _value.criRate
: criRate // ignore: cast_nullable_to_non_nullable
as double,
evasion: null == evasion
? _value.evasion
: evasion // ignore: cast_nullable_to_non_nullable
as double,
blockRate: null == blockRate
? _value.blockRate
: blockRate // ignore: cast_nullable_to_non_nullable
as double,
parryRate: null == parryRate
? _value.parryRate
: parryRate // ignore: cast_nullable_to_non_nullable
as double,
hpBonus: null == hpBonus
? _value.hpBonus
: hpBonus // ignore: cast_nullable_to_non_nullable
as int,
mpBonus: null == mpBonus
? _value.mpBonus
: mpBonus // ignore: cast_nullable_to_non_nullable
as int,
strBonus: null == strBonus
? _value.strBonus
: strBonus // ignore: cast_nullable_to_non_nullable
as int,
conBonus: null == conBonus
? _value.conBonus
: conBonus // ignore: cast_nullable_to_non_nullable
as int,
dexBonus: null == dexBonus
? _value.dexBonus
: dexBonus // ignore: cast_nullable_to_non_nullable
as int,
intBonus: null == intBonus
? _value.intBonus
: intBonus // ignore: cast_nullable_to_non_nullable
as int,
wisBonus: null == wisBonus
? _value.wisBonus
: wisBonus // ignore: cast_nullable_to_non_nullable
as int,
chaBonus: null == chaBonus
? _value.chaBonus
: chaBonus // ignore: cast_nullable_to_non_nullable
as int,
attackSpeed: null == attackSpeed
? _value.attackSpeed
: attackSpeed // ignore: cast_nullable_to_non_nullable
as int,
)
as $Val,
);
}
}
/// @nodoc
abstract class _$$ItemStatsImplCopyWith<$Res>
implements $ItemStatsCopyWith<$Res> {
factory _$$ItemStatsImplCopyWith(
_$ItemStatsImpl value,
$Res Function(_$ItemStatsImpl) then,
) = __$$ItemStatsImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({
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,
});
}
/// @nodoc
class __$$ItemStatsImplCopyWithImpl<$Res>
extends _$ItemStatsCopyWithImpl<$Res, _$ItemStatsImpl>
implements _$$ItemStatsImplCopyWith<$Res> {
__$$ItemStatsImplCopyWithImpl(
_$ItemStatsImpl _value,
$Res Function(_$ItemStatsImpl) _then,
) : super(_value, _then);
/// Create a copy of ItemStats
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? atk = null,
Object? def = null,
Object? magAtk = null,
Object? magDef = null,
Object? criRate = null,
Object? evasion = null,
Object? blockRate = null,
Object? parryRate = null,
Object? hpBonus = null,
Object? mpBonus = null,
Object? strBonus = null,
Object? conBonus = null,
Object? dexBonus = null,
Object? intBonus = null,
Object? wisBonus = null,
Object? chaBonus = null,
Object? attackSpeed = null,
}) {
return _then(
_$ItemStatsImpl(
atk: null == atk
? _value.atk
: atk // ignore: cast_nullable_to_non_nullable
as int,
def: null == def
? _value.def
: def // ignore: cast_nullable_to_non_nullable
as int,
magAtk: null == magAtk
? _value.magAtk
: magAtk // ignore: cast_nullable_to_non_nullable
as int,
magDef: null == magDef
? _value.magDef
: magDef // ignore: cast_nullable_to_non_nullable
as int,
criRate: null == criRate
? _value.criRate
: criRate // ignore: cast_nullable_to_non_nullable
as double,
evasion: null == evasion
? _value.evasion
: evasion // ignore: cast_nullable_to_non_nullable
as double,
blockRate: null == blockRate
? _value.blockRate
: blockRate // ignore: cast_nullable_to_non_nullable
as double,
parryRate: null == parryRate
? _value.parryRate
: parryRate // ignore: cast_nullable_to_non_nullable
as double,
hpBonus: null == hpBonus
? _value.hpBonus
: hpBonus // ignore: cast_nullable_to_non_nullable
as int,
mpBonus: null == mpBonus
? _value.mpBonus
: mpBonus // ignore: cast_nullable_to_non_nullable
as int,
strBonus: null == strBonus
? _value.strBonus
: strBonus // ignore: cast_nullable_to_non_nullable
as int,
conBonus: null == conBonus
? _value.conBonus
: conBonus // ignore: cast_nullable_to_non_nullable
as int,
dexBonus: null == dexBonus
? _value.dexBonus
: dexBonus // ignore: cast_nullable_to_non_nullable
as int,
intBonus: null == intBonus
? _value.intBonus
: intBonus // ignore: cast_nullable_to_non_nullable
as int,
wisBonus: null == wisBonus
? _value.wisBonus
: wisBonus // ignore: cast_nullable_to_non_nullable
as int,
chaBonus: null == chaBonus
? _value.chaBonus
: chaBonus // ignore: cast_nullable_to_non_nullable
as int,
attackSpeed: null == attackSpeed
? _value.attackSpeed
: attackSpeed // ignore: cast_nullable_to_non_nullable
as int,
),
);
}
}
/// @nodoc
@JsonSerializable()
class _$ItemStatsImpl extends _ItemStats {
const _$ItemStatsImpl({
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,
}) : super._();
factory _$ItemStatsImpl.fromJson(Map<String, dynamic> json) =>
_$$ItemStatsImplFromJson(json);
/// 물리 공격력 보정
@override
@JsonKey()
final int atk;
/// 물리 방어력 보정
@override
@JsonKey()
final int def;
/// 마법 공격력 보정
@override
@JsonKey()
final int magAtk;
/// 마법 방어력 보정
@override
@JsonKey()
final int magDef;
/// 크리티컬 확률 보정 (0.0 ~ 1.0)
@override
@JsonKey()
final double criRate;
/// 회피율 보정 (0.0 ~ 1.0)
@override
@JsonKey()
final double evasion;
/// 방패 방어율 (방패 전용, 0.0 ~ 1.0)
@override
@JsonKey()
final double blockRate;
/// 무기 쳐내기 확률 (무기 전용, 0.0 ~ 1.0)
@override
@JsonKey()
final double parryRate;
/// HP 보너스
@override
@JsonKey()
final int hpBonus;
/// MP 보너스
@override
@JsonKey()
final int mpBonus;
/// STR 보너스
@override
@JsonKey()
final int strBonus;
/// CON 보너스
@override
@JsonKey()
final int conBonus;
/// DEX 보너스
@override
@JsonKey()
final int dexBonus;
/// INT 보너스
@override
@JsonKey()
final int intBonus;
/// WIS 보너스
@override
@JsonKey()
final int wisBonus;
/// CHA 보너스
@override
@JsonKey()
final int chaBonus;
/// 무기 공격속도 (밀리초, 무기 전용)
///
/// 0이면 기본값(1000ms) 사용, 값이 클수록 느린 공격.
/// 느린 무기는 높은 기본 데미지를 가짐.
@override
@JsonKey()
final int attackSpeed;
@override
String toString() {
return 'ItemStats(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)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$ItemStatsImpl &&
(identical(other.atk, atk) || other.atk == atk) &&
(identical(other.def, def) || other.def == def) &&
(identical(other.magAtk, magAtk) || other.magAtk == magAtk) &&
(identical(other.magDef, magDef) || other.magDef == magDef) &&
(identical(other.criRate, criRate) || other.criRate == criRate) &&
(identical(other.evasion, evasion) || other.evasion == evasion) &&
(identical(other.blockRate, blockRate) ||
other.blockRate == blockRate) &&
(identical(other.parryRate, parryRate) ||
other.parryRate == parryRate) &&
(identical(other.hpBonus, hpBonus) || other.hpBonus == hpBonus) &&
(identical(other.mpBonus, mpBonus) || other.mpBonus == mpBonus) &&
(identical(other.strBonus, strBonus) ||
other.strBonus == strBonus) &&
(identical(other.conBonus, conBonus) ||
other.conBonus == conBonus) &&
(identical(other.dexBonus, dexBonus) ||
other.dexBonus == dexBonus) &&
(identical(other.intBonus, intBonus) ||
other.intBonus == intBonus) &&
(identical(other.wisBonus, wisBonus) ||
other.wisBonus == wisBonus) &&
(identical(other.chaBonus, chaBonus) ||
other.chaBonus == chaBonus) &&
(identical(other.attackSpeed, attackSpeed) ||
other.attackSpeed == attackSpeed));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(
runtimeType,
atk,
def,
magAtk,
magDef,
criRate,
evasion,
blockRate,
parryRate,
hpBonus,
mpBonus,
strBonus,
conBonus,
dexBonus,
intBonus,
wisBonus,
chaBonus,
attackSpeed,
);
/// Create a copy of ItemStats
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$ItemStatsImplCopyWith<_$ItemStatsImpl> get copyWith =>
__$$ItemStatsImplCopyWithImpl<_$ItemStatsImpl>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$ItemStatsImplToJson(this);
}
}
abstract class _ItemStats extends ItemStats {
const factory _ItemStats({
final int atk,
final int def,
final int magAtk,
final int magDef,
final double criRate,
final double evasion,
final double blockRate,
final double parryRate,
final int hpBonus,
final int mpBonus,
final int strBonus,
final int conBonus,
final int dexBonus,
final int intBonus,
final int wisBonus,
final int chaBonus,
final int attackSpeed,
}) = _$ItemStatsImpl;
const _ItemStats._() : super._();
factory _ItemStats.fromJson(Map<String, dynamic> json) =
_$ItemStatsImpl.fromJson;
/// 물리 공격력 보정
@override
int get atk;
/// 물리 방어력 보정
@override
int get def;
/// 마법 공격력 보정
@override
int get magAtk;
/// 마법 방어력 보정
@override
int get magDef;
/// 크리티컬 확률 보정 (0.0 ~ 1.0)
@override
double get criRate;
/// 회피율 보정 (0.0 ~ 1.0)
@override
double get evasion;
/// 방패 방어율 (방패 전용, 0.0 ~ 1.0)
@override
double get blockRate;
/// 무기 쳐내기 확률 (무기 전용, 0.0 ~ 1.0)
@override
double get parryRate;
/// HP 보너스
@override
int get hpBonus;
/// MP 보너스
@override
int get mpBonus;
/// STR 보너스
@override
int get strBonus;
/// CON 보너스
@override
int get conBonus;
/// DEX 보너스
@override
int get dexBonus;
/// INT 보너스
@override
int get intBonus;
/// WIS 보너스
@override
int get wisBonus;
/// CHA 보너스
@override
int get chaBonus;
/// 무기 공격속도 (밀리초, 무기 전용)
///
/// 0이면 기본값(1000ms) 사용, 값이 클수록 느린 공격.
/// 느린 무기는 높은 기본 데미지를 가짐.
@override
int get attackSpeed;
/// Create a copy of ItemStats
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$ItemStatsImplCopyWith<_$ItemStatsImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@@ -0,0 +1,49 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'item_stats.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_$ItemStatsImpl _$$ItemStatsImplFromJson(Map<String, dynamic> json) =>
_$ItemStatsImpl(
atk: (json['atk'] as num?)?.toInt() ?? 0,
def: (json['def'] as num?)?.toInt() ?? 0,
magAtk: (json['magAtk'] as num?)?.toInt() ?? 0,
magDef: (json['magDef'] as num?)?.toInt() ?? 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 num?)?.toInt() ?? 0,
mpBonus: (json['mpBonus'] as num?)?.toInt() ?? 0,
strBonus: (json['strBonus'] as num?)?.toInt() ?? 0,
conBonus: (json['conBonus'] as num?)?.toInt() ?? 0,
dexBonus: (json['dexBonus'] as num?)?.toInt() ?? 0,
intBonus: (json['intBonus'] as num?)?.toInt() ?? 0,
wisBonus: (json['wisBonus'] as num?)?.toInt() ?? 0,
chaBonus: (json['chaBonus'] as num?)?.toInt() ?? 0,
attackSpeed: (json['attackSpeed'] as num?)?.toInt() ?? 0,
);
Map<String, dynamic> _$$ItemStatsImplToJson(_$ItemStatsImpl instance) =>
<String, dynamic>{
'atk': instance.atk,
'def': instance.def,
'magAtk': instance.magAtk,
'magDef': instance.magDef,
'criRate': instance.criRate,
'evasion': instance.evasion,
'blockRate': instance.blockRate,
'parryRate': instance.parryRate,
'hpBonus': instance.hpBonus,
'mpBonus': instance.mpBonus,
'strBonus': instance.strBonus,
'conBonus': instance.conBonus,
'dexBonus': instance.dexBonus,
'intBonus': instance.intBonus,
'wisBonus': instance.wisBonus,
'chaBonus': instance.chaBonus,
'attackSpeed': instance.attackSpeed,
};