From 93f29f6c33f978720513514006caa26ff6e0145d Mon Sep 17 00:00:00 2001 From: JiWoong Sul Date: Fri, 16 Jan 2026 00:13:24 +0900 Subject: [PATCH] =?UTF-8?q?feat(ui):=20=EC=82=AC=EB=A7=9D=20=ED=99=94?= =?UTF-8?q?=EB=A9=B4=20=EC=9E=83=EC=9D=80=20=EC=95=84=EC=9D=B4=ED=85=9C=20?= =?UTF-8?q?=ED=9D=AC=EA=B7=80=EB=8F=84=20=EC=83=89=EC=83=81=20=ED=91=9C?= =?UTF-8?q?=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - DeathInfo에 lostItemRarity 필드 추가 - 사망 처리 시 아이템 희귀도 저장 - 사망 오버레이에서 희귀도별 색상 적용 - Common: 회색, Uncommon: 녹색, Rare: 파랑 - Epic: 보라, Legendary: 주황 --- lib/src/core/engine/progress_service.dart | 4 ++ lib/src/core/model/game_state.dart | 6 +++ .../features/game/widgets/death_overlay.dart | 38 +++++++++++++++---- 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/lib/src/core/engine/progress_service.dart b/lib/src/core/engine/progress_service.dart index efd3d18..4832f2c 100644 --- a/lib/src/core/engine/progress_service.dart +++ b/lib/src/core/engine/progress_service.dart @@ -16,6 +16,7 @@ import 'package:asciineverdie/src/core/model/combat_stats.dart'; import 'package:asciineverdie/src/core/model/equipment_item.dart'; import 'package:asciineverdie/src/core/model/equipment_slot.dart'; import 'package:asciineverdie/src/core/model/game_state.dart'; +import 'package:asciineverdie/src/core/model/item_stats.dart'; import 'package:asciineverdie/src/core/model/monster_combat_stats.dart'; import 'package:asciineverdie/src/core/model/monster_grade.dart'; import 'package:asciineverdie/src/core/model/potion.dart'; @@ -970,6 +971,7 @@ class ProgressService { var lostCount = 0; String? lostItemName; EquipmentSlot? lostItemSlot; + ItemRarity? lostItemRarity; if (!isBossDeath) { // 무기(슬롯 0)를 제외한 장착된 장비 중 1개를 제물로 삭제 @@ -999,6 +1001,7 @@ class ProgressService { final lostItem = state.equipment.getItemByIndex(sacrificeIndex); lostItemName = lostItem.name; lostItemSlot = EquipmentSlot.values[sacrificeIndex]; + lostItemRarity = lostItem.rarity; // 해당 슬롯을 빈 장비로 교체 newEquipment = newEquipment.setItemByIndex( @@ -1015,6 +1018,7 @@ class ProgressService { lostEquipmentCount: lostCount, lostItemName: lostItemName, lostItemSlot: lostItemSlot, + lostItemRarity: lostItemRarity, goldAtDeath: state.inventory.gold, levelAtDeath: state.traits.level, timestamp: state.skillSystem.elapsedMs, diff --git a/lib/src/core/model/game_state.dart b/lib/src/core/model/game_state.dart index dedf65f..5f416f6 100644 --- a/lib/src/core/model/game_state.dart +++ b/lib/src/core/model/game_state.dart @@ -132,6 +132,7 @@ class DeathInfo { required this.timestamp, this.lostItemName, this.lostItemSlot, + this.lostItemRarity, this.lastCombatEvents = const [], }); @@ -150,6 +151,9 @@ class DeathInfo { /// 제물로 바친 아이템 슬롯 (null이면 없음) final EquipmentSlot? lostItemSlot; + /// 제물로 바친 아이템 희귀도 (null이면 없음) + final ItemRarity? lostItemRarity; + /// 사망 시점 골드 final int goldAtDeath; @@ -168,6 +172,7 @@ class DeathInfo { int? lostEquipmentCount, String? lostItemName, EquipmentSlot? lostItemSlot, + ItemRarity? lostItemRarity, int? goldAtDeath, int? levelAtDeath, int? timestamp, @@ -179,6 +184,7 @@ class DeathInfo { lostEquipmentCount: lostEquipmentCount ?? this.lostEquipmentCount, lostItemName: lostItemName ?? this.lostItemName, lostItemSlot: lostItemSlot ?? this.lostItemSlot, + lostItemRarity: lostItemRarity ?? this.lostItemRarity, goldAtDeath: goldAtDeath ?? this.goldAtDeath, levelAtDeath: levelAtDeath ?? this.levelAtDeath, timestamp: timestamp ?? this.timestamp, diff --git a/lib/src/features/game/widgets/death_overlay.dart b/lib/src/features/game/widgets/death_overlay.dart index 24dd28b..d792d23 100644 --- a/lib/src/features/game/widgets/death_overlay.dart +++ b/lib/src/features/game/widgets/death_overlay.dart @@ -5,6 +5,7 @@ import 'package:asciineverdie/src/core/l10n/game_data_l10n.dart'; import 'package:asciineverdie/src/core/model/combat_event.dart'; import 'package:asciineverdie/src/core/model/equipment_slot.dart'; import 'package:asciineverdie/src/core/model/game_state.dart'; +import 'package:asciineverdie/src/core/model/item_stats.dart'; import 'package:asciineverdie/src/shared/retro_colors.dart'; /// 사망 오버레이 위젯 (Phase 4) @@ -294,10 +295,8 @@ class DeathOverlay extends StatelessWidget { final expColor = RetroColors.expOf(context); final gold = RetroColors.goldOf(context); - // 슬롯명 + 아이템명 조합 - final lostItemDisplay = hasLostItem - ? '[${_getSlotName(deathInfo.lostItemSlot)}] ${deathInfo.lostItemName}' - : null; + // 희귀도에 따른 아이템 이름 색상 + final itemRarityColor = _getRarityColor(deathInfo.lostItemRarity); return Column( children: [ @@ -326,12 +325,23 @@ class DeathOverlay extends StatelessWidget { ), ), const SizedBox(height: 4), - Text( - lostItemDisplay!, - style: TextStyle( + // 슬롯명 (회색) + 아이템명 (희귀도 색상) + Text.rich( + TextSpan( + children: [ + TextSpan( + text: '[${_getSlotName(deathInfo.lostItemSlot)}] ', + style: TextStyle(color: muted), + ), + TextSpan( + text: deathInfo.lostItemName!, + style: TextStyle(color: itemRarityColor), + ), + ], + ), + style: const TextStyle( fontFamily: 'PressStart2P', fontSize: 13, - color: hpColor, ), ), ], @@ -695,4 +705,16 @@ class DeathOverlay extends StatelessWidget { EquipmentSlot.sollerets => l10n.slotSollerets, }; } + + /// 희귀도에 따른 색상 반환 + Color _getRarityColor(ItemRarity? rarity) { + if (rarity == null) return Colors.grey; + return switch (rarity) { + ItemRarity.common => Colors.grey, + ItemRarity.uncommon => Colors.green, + ItemRarity.rare => Colors.blue, + ItemRarity.epic => Colors.purple, + ItemRarity.legendary => Colors.orange, + }; + } }