feat: 초기 커밋

- Progress Quest 6.4 Flutter 포팅 프로젝트
- 게임 루프, 상태 관리, UI 구현
- 캐릭터 생성, 인벤토리, 장비, 주문 시스템
- 시장/판매/구매 메커니즘
This commit is contained in:
JiWoong Sul
2025-12-09 17:24:04 +09:00
commit 08054d97c1
168 changed files with 12876 additions and 0 deletions

View File

@@ -0,0 +1,389 @@
import 'dart:collection';
import 'package:askiineverdie/src/core/util/deterministic_random.dart';
/// Minimal skeletal state to mirror Progress Quest structures.
///
/// Logic will be ported faithfully from the Delphi source; this file only
/// defines containers and helpers for deterministic RNG.
class GameState {
GameState({
required DeterministicRandom rng,
Traits? traits,
Stats? stats,
Inventory? inventory,
Equipment? equipment,
SpellBook? spellBook,
ProgressState? progress,
QueueState? queue,
}) : rng = DeterministicRandom.clone(rng),
traits = traits ?? Traits.empty(),
stats = stats ?? Stats.empty(),
inventory = inventory ?? Inventory.empty(),
equipment = equipment ?? Equipment.empty(),
spellBook = spellBook ?? SpellBook.empty(),
progress = progress ?? ProgressState.empty(),
queue = queue ?? QueueState.empty();
factory GameState.withSeed({
required int seed,
Traits? traits,
Stats? stats,
Inventory? inventory,
Equipment? equipment,
SpellBook? spellBook,
ProgressState? progress,
QueueState? queue,
}) {
return GameState(
rng: DeterministicRandom(seed),
traits: traits,
stats: stats,
inventory: inventory,
equipment: equipment,
spellBook: spellBook,
progress: progress,
queue: queue,
);
}
final DeterministicRandom rng;
final Traits traits;
final Stats stats;
final Inventory inventory;
final Equipment equipment;
final SpellBook spellBook;
final ProgressState progress;
final QueueState queue;
GameState copyWith({
DeterministicRandom? rng,
Traits? traits,
Stats? stats,
Inventory? inventory,
Equipment? equipment,
SpellBook? spellBook,
ProgressState? progress,
QueueState? queue,
}) {
return GameState(
rng: rng ?? DeterministicRandom.clone(this.rng),
traits: traits ?? this.traits,
stats: stats ?? this.stats,
inventory: inventory ?? this.inventory,
equipment: equipment ?? this.equipment,
spellBook: spellBook ?? this.spellBook,
progress: progress ?? this.progress,
queue: queue ?? this.queue,
);
}
}
/// 태스크 타입 (원본 fTask.Caption 값들에 대응)
enum TaskType {
neutral, // heading 등 일반 이동
kill, // 몬스터 처치
load, // 로딩/초기화
plot, // 플롯 진행
market, // 시장으로 이동 중
sell, // 아이템 판매 중
buying, // 장비 구매 중
}
class TaskInfo {
const TaskInfo({required this.caption, required this.type});
final String caption;
final TaskType type;
factory TaskInfo.empty() =>
const TaskInfo(caption: '', type: TaskType.neutral);
TaskInfo copyWith({String? caption, TaskType? type}) {
return TaskInfo(caption: caption ?? this.caption, type: type ?? this.type);
}
}
class Traits {
const Traits({
required this.name,
required this.race,
required this.klass,
required this.level,
required this.motto,
required this.guild,
});
final String name;
final String race;
final String klass;
final int level;
final String motto;
final String guild;
factory Traits.empty() => const Traits(
name: '',
race: '',
klass: '',
level: 1,
motto: '',
guild: '',
);
Traits copyWith({
String? name,
String? race,
String? klass,
int? level,
String? motto,
String? guild,
}) {
return Traits(
name: name ?? this.name,
race: race ?? this.race,
klass: klass ?? this.klass,
level: level ?? this.level,
motto: motto ?? this.motto,
guild: guild ?? this.guild,
);
}
}
class Stats {
const Stats({
required this.str,
required this.con,
required this.dex,
required this.intelligence,
required this.wis,
required this.cha,
required this.hpMax,
required this.mpMax,
});
final int str;
final int con;
final int dex;
final int intelligence;
final int wis;
final int cha;
final int hpMax;
final int mpMax;
factory Stats.empty() => const Stats(
str: 0,
con: 0,
dex: 0,
intelligence: 0,
wis: 0,
cha: 0,
hpMax: 0,
mpMax: 0,
);
Stats copyWith({
int? str,
int? con,
int? dex,
int? intelligence,
int? wis,
int? cha,
int? hpMax,
int? mpMax,
}) {
return Stats(
str: str ?? this.str,
con: con ?? this.con,
dex: dex ?? this.dex,
intelligence: intelligence ?? this.intelligence,
wis: wis ?? this.wis,
cha: cha ?? this.cha,
hpMax: hpMax ?? this.hpMax,
mpMax: mpMax ?? this.mpMax,
);
}
}
class InventoryEntry {
const InventoryEntry({required this.name, required this.count});
final String name;
final int count;
InventoryEntry copyWith({String? name, int? count}) {
return InventoryEntry(name: name ?? this.name, count: count ?? this.count);
}
}
class Inventory {
const Inventory({required this.gold, required this.items});
final int gold;
final List<InventoryEntry> items;
factory Inventory.empty() => const Inventory(gold: 0, items: []);
Inventory copyWith({int? gold, List<InventoryEntry>? items}) {
return Inventory(gold: gold ?? this.gold, items: items ?? this.items);
}
}
class Equipment {
const Equipment({
required this.weapon,
required this.shield,
required this.armor,
required this.bestIndex,
});
final String weapon;
final String shield;
final String armor;
/// Tracks best slot index (mirror of Equips.Tag in original code; 0=weapon,1=shield,2=armor).
final int bestIndex;
factory Equipment.empty() => const Equipment(
weapon: 'Sharp Stick',
shield: '',
armor: '',
bestIndex: 0,
);
Equipment copyWith({
String? weapon,
String? shield,
String? armor,
int? bestIndex,
}) {
return Equipment(
weapon: weapon ?? this.weapon,
shield: shield ?? this.shield,
armor: armor ?? this.armor,
bestIndex: bestIndex ?? this.bestIndex,
);
}
}
class SpellEntry {
const SpellEntry({required this.name, required this.rank});
final String name;
final String rank; // e.g., Roman numerals
SpellEntry copyWith({String? name, String? rank}) {
return SpellEntry(name: name ?? this.name, rank: rank ?? this.rank);
}
}
class SpellBook {
const SpellBook({required this.spells});
final List<SpellEntry> spells;
factory SpellBook.empty() => const SpellBook(spells: []);
SpellBook copyWith({List<SpellEntry>? spells}) {
return SpellBook(spells: spells ?? this.spells);
}
}
class ProgressBarState {
const ProgressBarState({required this.position, required this.max});
final int position;
final int max;
factory ProgressBarState.empty() =>
const ProgressBarState(position: 0, max: 1);
ProgressBarState copyWith({int? position, int? max}) {
return ProgressBarState(
position: position ?? this.position,
max: max ?? this.max,
);
}
}
class ProgressState {
const ProgressState({
required this.task,
required this.quest,
required this.plot,
required this.exp,
required this.encumbrance,
required this.currentTask,
required this.plotStageCount,
required this.questCount,
});
final ProgressBarState task;
final ProgressBarState quest;
final ProgressBarState plot;
final ProgressBarState exp;
final ProgressBarState encumbrance;
final TaskInfo currentTask;
final int plotStageCount;
final int questCount;
factory ProgressState.empty() => ProgressState(
task: ProgressBarState.empty(),
quest: ProgressBarState.empty(),
plot: ProgressBarState.empty(),
exp: ProgressBarState.empty(),
encumbrance: ProgressBarState.empty(),
currentTask: TaskInfo.empty(),
plotStageCount: 1, // Prologue
questCount: 0,
);
ProgressState copyWith({
ProgressBarState? task,
ProgressBarState? quest,
ProgressBarState? plot,
ProgressBarState? exp,
ProgressBarState? encumbrance,
TaskInfo? currentTask,
int? plotStageCount,
int? questCount,
}) {
return ProgressState(
task: task ?? this.task,
quest: quest ?? this.quest,
plot: plot ?? this.plot,
exp: exp ?? this.exp,
encumbrance: encumbrance ?? this.encumbrance,
currentTask: currentTask ?? this.currentTask,
plotStageCount: plotStageCount ?? this.plotStageCount,
questCount: questCount ?? this.questCount,
);
}
}
class QueueEntry {
const QueueEntry({
required this.kind,
required this.durationMillis,
required this.caption,
this.taskType = TaskType.neutral,
});
final QueueKind kind;
final int durationMillis;
final String caption;
final TaskType taskType;
}
enum QueueKind { task, plot }
class QueueState {
QueueState({Iterable<QueueEntry>? entries})
: entries = Queue<QueueEntry>.from(entries ?? const []);
final Queue<QueueEntry> entries;
factory QueueState.empty() => QueueState(entries: const []);
QueueState copyWith({Iterable<QueueEntry>? entries}) {
return QueueState(entries: Queue<QueueEntry>.from(entries ?? this.entries));
}
}