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/class_traits.dart';
import 'package:asciineverdie/src/core/model/game_state.dart'; import 'package:asciineverdie/src/core/model/game_state.dart';
import 'package:asciineverdie/src/core/model/race_traits.dart'; import 'package:asciineverdie/src/core/model/race_traits.dart';
part 'combat_stats.freezed.dart';
part 'combat_stats.g.dart';
/// 전투용 파생 스탯 /// 전투용 파생 스탯
/// ///
/// 기본 Stats와 Equipment를 기반으로 계산되는 전투 관련 수치. /// 기본 Stats와 Equipment를 기반으로 계산되는 전투 관련 수치.
/// 불변(immutable) 객체로 설계되어 상태 변경 시 새 인스턴스 생성. /// 불변(immutable) 객체로 설계되어 상태 변경 시 새 인스턴스 생성.
class CombatStats { @freezed
class CombatStats with _$CombatStats {
// ============================================================================ // ============================================================================
// 레벨 페널티 상수 (Phase 12) // 레벨 페널티 상수 (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) { static double _getLevelPenalty(int playerLevel, int monsterLevel) {
final levelDiff = monsterLevel - playerLevel; final levelDiff = monsterLevel - playerLevel;
if (levelDiff <= 0) return 1.0; // 플레이어가 높거나 같으면 페널티 없음 if (levelDiff <= 0) return 1.0;
// 1레벨당 8%씩 감소 (100% → 92% → 84% → ... → 20%)
final penalty = 1.0 - (levelDiff * _levelPenaltyPerLevel); final penalty = 1.0 - (levelDiff * _levelPenaltyPerLevel);
return penalty.clamp(_minLevelMultiplier, 1.0); return penalty.clamp(_minLevelMultiplier, 1.0);
} }
const CombatStats({ const CombatStats._();
// 기본 스탯 (Stats에서 복사)
required this.str, const factory CombatStats({
required this.con, // 기본 스탯
required this.dex, /// 힘: 물리 공격력 보정
required this.intelligence, required int str,
required this.wis, /// 체력: HP, 방어력 보정
required this.cha, required int con,
// 파생 스탯 /// 민첩: 회피율, 크리티컬율, 명중률, 공격 속도
required this.atk, required int dex,
required this.def, /// 지능: 마법 공격력, MP
required this.magAtk, required int intelligence,
required this.magDef, /// 지혜: 마법 방어력, MP 회복
required this.criRate, required int wis,
required this.criDamage, /// 매력: 상점 가격, 드롭률 보정
required this.evasion, required int cha,
required this.accuracy, // 파생 스탯 (전투용)
required this.blockRate, /// 물리 공격력
required this.parryRate, required int atk,
required this.attackDelayMs, /// 물리 방어력
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, /// 최대 HP
required this.hpCurrent, required int hpMax,
required this.mpMax, /// 현재 HP
required this.mpCurrent, required int hpCurrent,
}); /// 최대 MP
required int mpMax,
/// 현재 MP
required int mpCurrent,
}) = _CombatStats;
// ============================================================================ factory CombatStats.fromJson(Map<String, dynamic> json) =>
// 기본 스탯 _$CombatStatsFromJson(json);
// ============================================================================
/// 힘: 물리 공격력 보정
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;
// ============================================================================ // ============================================================================
// 유틸리티 // 유틸리티
@@ -190,66 +140,11 @@ class CombatStats {
return withHp(hpCurrent + amount); 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에서 CombatStats 생성
///
/// [stats] 캐릭터 기본 스탯
/// [equipment] 장착 장비 (장비 스탯 적용)
/// [level] 캐릭터 레벨 (스케일링용)
/// [race] 종족 특성 (선택사항, Phase 5)
/// [klass] 클래스 특성 (선택사항, Phase 5)
/// [monsterLevel] 상대 몬스터 레벨 (레벨 페널티 계산용, Phase 12)
factory CombatStats.fromStats({ factory CombatStats.fromStats({
required Stats stats, required Stats stats,
required Equipment equipment, required Equipment equipment,
@@ -321,7 +216,6 @@ class CombatStats {
final parryRate = (baseParryRate + equipStats.parryRate).clamp(0.0, 0.4); final parryRate = (baseParryRate + equipStats.parryRate).clamp(0.0, 0.4);
// 공격 속도: 무기 기본 공속 + DEX 보정 // 공격 속도: 무기 기본 공속 + DEX 보정
// 무기 attackSpeed가 0이면 기본값 1000ms 사용
final weaponItem = equipment.items[0]; // 무기 슬롯 final weaponItem = equipment.items[0]; // 무기 슬롯
final weaponSpeed = weaponItem.stats.attackSpeed; final weaponSpeed = weaponItem.stats.attackSpeed;
final baseAttackSpeed = weaponSpeed > 0 ? weaponSpeed : 1000; final baseAttackSpeed = weaponSpeed > 0 ? weaponSpeed : 1000;
@@ -339,32 +233,27 @@ class CombatStats {
// 종족 패시브 적용 (Phase 5) // 종족 패시브 적용 (Phase 5)
// ======================================================================== // ========================================================================
// HP 보너스 (Heap Troll: +20%)
final raceHpBonus = race?.getPassiveValue(PassiveType.hpBonus) ?? 0.0; final raceHpBonus = race?.getPassiveValue(PassiveType.hpBonus) ?? 0.0;
if (raceHpBonus > 0) { if (raceHpBonus > 0) {
totalHpMax = (totalHpMax * (1 + raceHpBonus)).round(); totalHpMax = (totalHpMax * (1 + raceHpBonus)).round();
} }
// MP 보너스 (Pointer Fairy: +20%)
final raceMpBonus = race?.getPassiveValue(PassiveType.mpBonus) ?? 0.0; final raceMpBonus = race?.getPassiveValue(PassiveType.mpBonus) ?? 0.0;
if (raceMpBonus > 0) { if (raceMpBonus > 0) {
totalMpMax = (totalMpMax * (1 + raceMpBonus)).round(); totalMpMax = (totalMpMax * (1 + raceMpBonus)).round();
} }
// 마법 데미지 보너스 (Null Elf: +15%)
final raceMagicBonus = final raceMagicBonus =
race?.getPassiveValue(PassiveType.magicDamageBonus) ?? 0.0; race?.getPassiveValue(PassiveType.magicDamageBonus) ?? 0.0;
if (raceMagicBonus > 0) { if (raceMagicBonus > 0) {
baseMagAtk = (baseMagAtk * (1 + raceMagicBonus)).round(); baseMagAtk = (baseMagAtk * (1 + raceMagicBonus)).round();
} }
// 방어력 보너스 (Buffer Dwarf: +10%)
final raceDefBonus = race?.getPassiveValue(PassiveType.defenseBonus) ?? 0.0; final raceDefBonus = race?.getPassiveValue(PassiveType.defenseBonus) ?? 0.0;
if (raceDefBonus > 0) { if (raceDefBonus > 0) {
baseDef = (baseDef * (1 + raceDefBonus)).round(); baseDef = (baseDef * (1 + raceDefBonus)).round();
} }
// 크리티컬 보너스 (Stack Goblin: +5%)
final raceCritBonus = final raceCritBonus =
race?.getPassiveValue(PassiveType.criticalBonus) ?? 0.0; race?.getPassiveValue(PassiveType.criticalBonus) ?? 0.0;
criRate += raceCritBonus; criRate += raceCritBonus;
@@ -373,40 +262,34 @@ class CombatStats {
// 클래스 패시브 적용 (Phase 5) // 클래스 패시브 적용 (Phase 5)
// ======================================================================== // ========================================================================
// HP 보너스 (Garbage Collector: +30%)
final classHpBonus = final classHpBonus =
klass?.getPassiveValue(ClassPassiveType.hpBonus) ?? 0.0; klass?.getPassiveValue(ClassPassiveType.hpBonus) ?? 0.0;
if (classHpBonus > 0) { if (classHpBonus > 0) {
totalHpMax = (totalHpMax * (1 + classHpBonus)).round(); totalHpMax = (totalHpMax * (1 + classHpBonus)).round();
} }
// 물리 공격력 보너스 (Bug Hunter: +20%)
final classPhysBonus = final classPhysBonus =
klass?.getPassiveValue(ClassPassiveType.physicalDamageBonus) ?? 0.0; klass?.getPassiveValue(ClassPassiveType.physicalDamageBonus) ?? 0.0;
if (classPhysBonus > 0) { if (classPhysBonus > 0) {
baseAtk = (baseAtk * (1 + classPhysBonus)).round(); baseAtk = (baseAtk * (1 + classPhysBonus)).round();
} }
// 방어력 보너스 (Debugger Paladin: +15%)
final classDefBonus = final classDefBonus =
klass?.getPassiveValue(ClassPassiveType.defenseBonus) ?? 0.0; klass?.getPassiveValue(ClassPassiveType.defenseBonus) ?? 0.0;
if (classDefBonus > 0) { if (classDefBonus > 0) {
baseDef = (baseDef * (1 + classDefBonus)).round(); baseDef = (baseDef * (1 + classDefBonus)).round();
} }
// 마법 데미지 보너스 (Compiler Mage: +25%)
final classMagBonus = final classMagBonus =
klass?.getPassiveValue(ClassPassiveType.magicDamageBonus) ?? 0.0; klass?.getPassiveValue(ClassPassiveType.magicDamageBonus) ?? 0.0;
if (classMagBonus > 0) { if (classMagBonus > 0) {
baseMagAtk = (baseMagAtk * (1 + classMagBonus)).round(); baseMagAtk = (baseMagAtk * (1 + classMagBonus)).round();
} }
// 회피율 보너스 (Refactor Monk: +15%)
final classEvasionBonus = final classEvasionBonus =
klass?.getPassiveValue(ClassPassiveType.evasionBonus) ?? 0.0; klass?.getPassiveValue(ClassPassiveType.evasionBonus) ?? 0.0;
evasion += classEvasionBonus; evasion += classEvasionBonus;
// 크리티컬 보너스 (Pointer Assassin: +20%)
final classCritBonus = final classCritBonus =
klass?.getPassiveValue(ClassPassiveType.criticalBonus) ?? 0.0; klass?.getPassiveValue(ClassPassiveType.criticalBonus) ?? 0.0;
criRate += classCritBonus; criRate += classCritBonus;
@@ -415,13 +298,11 @@ class CombatStats {
// 레벨 페널티 및 최종 클램핑 (Phase 12) // 레벨 페널티 및 최종 클램핑 (Phase 12)
// ======================================================================== // ========================================================================
// 레벨 페널티 적용 (크리/회피/블록/패리)
criRate *= levelPenalty; criRate *= levelPenalty;
evasion *= levelPenalty; evasion *= levelPenalty;
var finalBlockRate = blockRate * levelPenalty; var finalBlockRate = blockRate * levelPenalty;
var finalParryRate = parryRate * levelPenalty; var finalParryRate = parryRate * levelPenalty;
// 최종 클램핑 (새 캡 적용)
criRate = criRate.clamp(0.05, _maxCriRate); criRate = criRate.clamp(0.05, _maxCriRate);
evasion = evasion.clamp(0.0, _maxEvasion); evasion = evasion.clamp(0.0, _maxEvasion);
finalBlockRate = finalBlockRate.clamp(0.0, _maxBlockRate); 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( factory CombatStats.empty() => const CombatStats(
str: 10, 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/equipment_slot.dart';
import 'package:asciineverdie/src/core/model/item_stats.dart'; import 'package:asciineverdie/src/core/model/item_stats.dart';
part 'equipment_item.freezed.dart';
part 'equipment_item.g.dart';
/// 장비 아이템 /// 장비 아이템
/// ///
/// 개별 장비의 이름, 슬롯, 레벨, 스탯 등을 포함하는 클래스. /// 개별 장비의 이름, 슬롯, 레벨, 스탯 등을 포함하는 클래스.
/// 불변(immutable) 객체로 설계됨. /// 불변(immutable) 객체로 설계됨.
class EquipmentItem { @freezed
const EquipmentItem({ class EquipmentItem with _$EquipmentItem {
required this.name, const EquipmentItem._();
required this.slot,
required this.level,
required this.weight,
required this.stats,
required this.rarity,
});
/// 아이템 이름 (예: "Flaming Sword of Doom") const factory EquipmentItem({
final String name; /// 아이템 이름 (예: "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;
/// 장착 슬롯 factory EquipmentItem.fromJson(Map<String, dynamic> json) =>
final EquipmentSlot slot; _$EquipmentItemFromJson(json);
/// 아이템 레벨
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.empty(EquipmentSlot slot) { factory EquipmentItem.empty(EquipmentSlot slot) {
@@ -54,7 +41,7 @@ class EquipmentItem {
slot: slot, slot: slot,
level: 0, level: 0,
weight: 0, weight: 0,
stats: ItemStats.empty, stats: const ItemStats(),
rarity: ItemRarity.common, rarity: ItemRarity.common,
); );
} }
@@ -71,59 +58,39 @@ class EquipmentItem {
); );
} }
EquipmentItem copyWith({ /// 가중치 (자동 장착 비교용)
String? name, ///
EquipmentSlot? slot, /// 가중치 = 기본값 + (레벨 * 10) + (희귀도 보너스) + (스탯 합계)
int? level, int get itemWeight {
int? weight, const baseValue = 10;
ItemStats? stats, return baseValue + (level * 10) + rarity.weightBonus + stats.totalStatValue;
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,
);
} }
/// JSON으로 직렬화 /// 빈 아이템 여부
Map<String, dynamic> toJson() { bool get isEmpty => name.isEmpty;
return {
'name': name,
'slot': slot.name,
'level': level,
'weight': weight,
'stats': stats.toJson(),
'rarity': rarity.name,
};
}
/// JSON에서 역직렬화 /// 유효한 아이템 여부
factory EquipmentItem.fromJson(Map<String, dynamic> json) { bool get isNotEmpty => name.isNotEmpty;
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,
),
);
}
@override @override
String toString() => name.isEmpty ? '(empty)' : name; 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 { enum ItemRarity {
common, common,
@@ -29,80 +34,55 @@ enum ItemRarity {
/// ///
/// 장비 아이템이 제공하는 스탯 보너스. /// 장비 아이템이 제공하는 스탯 보너스.
/// 모든 값은 기본 0이며, 장착 시 플레이어 스탯에 가산됨. /// 모든 값은 기본 0이며, 장착 시 플레이어 스탯에 가산됨.
class ItemStats { @freezed
const ItemStats({ class ItemStats with _$ItemStats {
this.atk = 0, const ItemStats._();
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,
});
/// 물리 공격력 보정 const factory ItemStats({
final int atk; /// 물리 공격력 보정
@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;
/// 물리 방어력 보정 factory ItemStats.fromJson(Map<String, dynamic> json) =>
final int def; _$ItemStatsFromJson(json);
/// 마법 공격력 보정 /// 빈 스탯 (보너스 없음)
final int magAtk; static const empty = ItemStats();
/// 마법 방어력 보정
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 { int get totalStatValue {
@@ -124,55 +104,6 @@ class ItemStats {
chaBonus * 5; 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는 합산 대상 아님 (무기 슬롯 단일 값) /// attackSpeed는 합산 대상 아님 (무기 슬롯 단일 값)
@@ -197,44 +128,4 @@ class ItemStats {
// attackSpeed는 무기에서만 직접 참조 // 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,
};

View File

@@ -1,6 +1,22 @@
# Generated by pub # Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile # See https://dart.dev/tools/pub/glossary#lockfile
packages: packages:
_fe_analyzer_shared:
dependency: transitive
description:
name: _fe_analyzer_shared
sha256: da0d9209ca76bde579f2da330aeb9df62b6319c834fa7baae052021b0462401f
url: "https://pub.dev"
source: hosted
version: "85.0.0"
analyzer:
dependency: transitive
description:
name: analyzer
sha256: "974859dc0ff5f37bc4313244b3218c791810d03ab3470a579580279ba971a48d"
url: "https://pub.dev"
source: hosted
version: "7.7.1"
archive: archive:
dependency: transitive dependency: transitive
description: description:
@@ -41,6 +57,70 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.2" version: "2.1.2"
build:
dependency: transitive
description:
name: build
sha256: "51dc711996cbf609b90cbe5b335bbce83143875a9d58e4b5c6d3c4f684d3dda7"
url: "https://pub.dev"
source: hosted
version: "2.5.4"
build_config:
dependency: transitive
description:
name: build_config
sha256: "4ae2de3e1e67ea270081eaee972e1bd8f027d459f249e0f1186730784c2e7e33"
url: "https://pub.dev"
source: hosted
version: "1.1.2"
build_daemon:
dependency: transitive
description:
name: build_daemon
sha256: bf05f6e12cfea92d3c09308d7bcdab1906cd8a179b023269eed00c071004b957
url: "https://pub.dev"
source: hosted
version: "4.1.1"
build_resolvers:
dependency: transitive
description:
name: build_resolvers
sha256: ee4257b3f20c0c90e72ed2b57ad637f694ccba48839a821e87db762548c22a62
url: "https://pub.dev"
source: hosted
version: "2.5.4"
build_runner:
dependency: "direct dev"
description:
name: build_runner
sha256: "382a4d649addbfb7ba71a3631df0ec6a45d5ab9b098638144faf27f02778eb53"
url: "https://pub.dev"
source: hosted
version: "2.5.4"
build_runner_core:
dependency: transitive
description:
name: build_runner_core
sha256: "85fbbb1036d576d966332a3f5ce83f2ce66a40bea1a94ad2d5fc29a19a0d3792"
url: "https://pub.dev"
source: hosted
version: "9.1.2"
built_collection:
dependency: transitive
description:
name: built_collection
sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100"
url: "https://pub.dev"
source: hosted
version: "5.1.1"
built_value:
dependency: transitive
description:
name: built_value
sha256: "7931c90b84bc573fef103548e354258ae4c9d28d140e41961df6843c5d60d4d8"
url: "https://pub.dev"
source: hosted
version: "8.12.3"
characters: characters:
dependency: transitive dependency: transitive
description: description:
@@ -73,6 +153,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.2" version: "1.1.2"
code_builder:
dependency: transitive
description:
name: code_builder
sha256: "6a6cab2ba4680d6423f34a9b972a4c9a94ebe1b62ecec4e1a1f2cba91fd1319d"
url: "https://pub.dev"
source: hosted
version: "4.11.1"
collection: collection:
dependency: transitive dependency: transitive
description: description:
@@ -81,6 +169,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.19.1" version: "1.19.1"
convert:
dependency: transitive
description:
name: convert
sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68
url: "https://pub.dev"
source: hosted
version: "3.1.2"
crypto: crypto:
dependency: transitive dependency: transitive
description: description:
@@ -97,6 +193,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.8" version: "1.0.8"
dart_style:
dependency: transitive
description:
name: dart_style
sha256: "8a0e5fba27e8ee025d2ffb4ee820b4e6e2cf5e4246a6b1a477eb66866947e0bb"
url: "https://pub.dev"
source: hosted
version: "3.1.1"
fake_async: fake_async:
dependency: "direct dev" dependency: "direct dev"
description: description:
@@ -165,6 +269,70 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
freezed:
dependency: "direct dev"
description:
name: freezed
sha256: "59a584c24b3acdc5250bb856d0d3e9c0b798ed14a4af1ddb7dc1c7b41df91c9c"
url: "https://pub.dev"
source: hosted
version: "2.5.8"
freezed_annotation:
dependency: "direct main"
description:
name: freezed_annotation
sha256: c2e2d632dd9b8a2b7751117abcfc2b4888ecfe181bd9fca7170d9ef02e595fe2
url: "https://pub.dev"
source: hosted
version: "2.4.4"
frontend_server_client:
dependency: transitive
description:
name: frontend_server_client
sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694
url: "https://pub.dev"
source: hosted
version: "4.0.0"
glob:
dependency: transitive
description:
name: glob
sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de
url: "https://pub.dev"
source: hosted
version: "2.1.3"
graphs:
dependency: transitive
description:
name: graphs
sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0"
url: "https://pub.dev"
source: hosted
version: "2.3.2"
http:
dependency: transitive
description:
name: http
sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412"
url: "https://pub.dev"
source: hosted
version: "1.6.0"
http_multi_server:
dependency: transitive
description:
name: http_multi_server
sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8
url: "https://pub.dev"
source: hosted
version: "3.2.2"
http_parser:
dependency: transitive
description:
name: http_parser
sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571"
url: "https://pub.dev"
source: hosted
version: "4.1.2"
image: image:
dependency: transitive dependency: transitive
description: description:
@@ -181,14 +349,38 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.20.2" version: "0.20.2"
json_annotation: io:
dependency: transitive dependency: transitive
description:
name: io
sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b
url: "https://pub.dev"
source: hosted
version: "1.0.5"
js:
dependency: transitive
description:
name: js
sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc"
url: "https://pub.dev"
source: hosted
version: "0.7.2"
json_annotation:
dependency: "direct main"
description: description:
name: json_annotation name: json_annotation
sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.9.0" version: "4.9.0"
json_serializable:
dependency: "direct dev"
description:
name: json_serializable
sha256: c50ef5fc083d5b5e12eef489503ba3bf5ccc899e487d691584699b4bdefeea8c
url: "https://pub.dev"
source: hosted
version: "6.9.5"
just_audio: just_audio:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -245,6 +437,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.1.1" version: "5.1.1"
logging:
dependency: transitive
description:
name: logging
sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
url: "https://pub.dev"
source: hosted
version: "1.3.0"
matcher: matcher:
dependency: transitive dependency: transitive
description: description:
@@ -269,6 +469,22 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.16.0" version: "1.16.0"
mime:
dependency: transitive
description:
name: mime
sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6"
url: "https://pub.dev"
source: hosted
version: "2.0.0"
package_config:
dependency: transitive
description:
name: package_config
sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc
url: "https://pub.dev"
source: hosted
version: "2.2.0"
path: path:
dependency: transitive dependency: transitive
description: description:
@@ -349,6 +565,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.8" version: "2.1.8"
pool:
dependency: transitive
description:
name: pool
sha256: "978783255c543aa3586a1b3c21f6e9d720eb315376a915872c61ef8b5c20177d"
url: "https://pub.dev"
source: hosted
version: "1.5.2"
posix: posix:
dependency: transitive dependency: transitive
description: description:
@@ -357,6 +581,22 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.0.3" version: "6.0.3"
pub_semver:
dependency: transitive
description:
name: pub_semver
sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585"
url: "https://pub.dev"
source: hosted
version: "2.2.0"
pubspec_parse:
dependency: transitive
description:
name: pubspec_parse
sha256: "0560ba233314abbed0a48a2956f7f022cce7c3e1e73df540277da7544cad4082"
url: "https://pub.dev"
source: hosted
version: "1.5.0"
rxdart: rxdart:
dependency: transitive dependency: transitive
description: description:
@@ -421,11 +661,43 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.1" version: "2.4.1"
shelf:
dependency: transitive
description:
name: shelf
sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12
url: "https://pub.dev"
source: hosted
version: "1.4.2"
shelf_web_socket:
dependency: transitive
description:
name: shelf_web_socket
sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925"
url: "https://pub.dev"
source: hosted
version: "3.0.0"
sky_engine: sky_engine:
dependency: transitive dependency: transitive
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
source_gen:
dependency: transitive
description:
name: source_gen
sha256: "35c8150ece9e8c8d263337a265153c3329667640850b9304861faea59fc98f6b"
url: "https://pub.dev"
source: hosted
version: "2.0.0"
source_helper:
dependency: transitive
description:
name: source_helper
sha256: a447acb083d3a5ef17f983dd36201aeea33fedadb3228fa831f2f0c92f0f3aca
url: "https://pub.dev"
source: hosted
version: "1.3.7"
source_span: source_span:
dependency: transitive dependency: transitive
description: description:
@@ -450,6 +722,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.4" version: "2.1.4"
stream_transform:
dependency: transitive
description:
name: stream_transform
sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871
url: "https://pub.dev"
source: hosted
version: "2.1.1"
string_scanner: string_scanner:
dependency: transitive dependency: transitive
description: description:
@@ -482,6 +762,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.6" version: "0.7.6"
timing:
dependency: transitive
description:
name: timing
sha256: "62ee18aca144e4a9f29d212f5a4c6a053be252b895ab14b5821996cff4ed90fe"
url: "https://pub.dev"
source: hosted
version: "1.0.2"
typed_data: typed_data:
dependency: transitive dependency: transitive
description: description:
@@ -514,6 +802,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "15.0.2" version: "15.0.2"
watcher:
dependency: transitive
description:
name: watcher
sha256: "1398c9f081a753f9226febe8900fce8f7d0a67163334e1c94a2438339d79d635"
url: "https://pub.dev"
source: hosted
version: "1.2.1"
web: web:
dependency: transitive dependency: transitive
description: description:
@@ -522,6 +818,22 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.1" version: "1.1.1"
web_socket:
dependency: transitive
description:
name: web_socket
sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c"
url: "https://pub.dev"
source: hosted
version: "1.0.1"
web_socket_channel:
dependency: transitive
description:
name: web_socket_channel
sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8
url: "https://pub.dev"
source: hosted
version: "3.0.3"
xdg_directories: xdg_directories:
dependency: transitive dependency: transitive
description: description:

View File

@@ -38,11 +38,18 @@ dependencies:
path_provider: ^2.1.4 path_provider: ^2.1.4
shared_preferences: ^2.3.1 shared_preferences: ^2.3.1
just_audio: ^0.9.42 just_audio: ^0.9.42
# Code generation annotations
freezed_annotation: ^2.4.1
json_annotation: ^4.9.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
fake_async: ^1.3.2 fake_async: ^1.3.2
# Code generation
build_runner: ^2.4.13
freezed: ^2.5.7
json_serializable: ^6.8.0
# The "flutter_lints" package below contains a set of recommended lints to # The "flutter_lints" package below contains a set of recommended lints to
# encourage good coding practices. The lint set provided by the package is # encourage good coding practices. The lint set provided by the package is