feat(animation): 종족별 캐릭터 애니메이션 시스템 추가

- 21개 종족별 고유 ASCII 캐릭터 프레임 데이터 추가
  - 각 종족당 5가지 상태 애니메이션: idle, prepare, attack, hit, recover
  - 종족 특성에 맞는 시각적 차별화 (마법사 ~, 기사 ♦, 언데드 ☠ 등)
- 캐릭터 생성 화면 종족 미리보기 위젯 추가
- 프론트 화면 Hero vs Boss 애니메이션 개선
- 게임 플레이 화면 애니메이션 패널 연동 강화
This commit is contained in:
JiWoong Sul
2025-12-23 20:00:41 +09:00
parent 549851f693
commit 7219f58853
11 changed files with 1186 additions and 64 deletions

View File

@@ -5,6 +5,7 @@ import 'package:askiineverdie/src/core/animation/canvas/ascii_cell.dart';
import 'package:askiineverdie/src/core/animation/canvas/ascii_layer.dart';
import 'package:askiineverdie/src/core/animation/character_frames.dart';
import 'package:askiineverdie/src/core/animation/monster_size.dart';
import 'package:askiineverdie/src/core/animation/race_character_frames.dart';
import 'package:askiineverdie/src/core/animation/weapon_category.dart';
import 'package:askiineverdie/src/core/animation/weapon_effects.dart';
@@ -18,6 +19,7 @@ class CanvasBattleComposer {
required this.hasShield,
required this.monsterCategory,
required this.monsterSize,
this.raceId,
});
final WeaponCategory weaponCategory;
@@ -25,6 +27,9 @@ class CanvasBattleComposer {
final MonsterCategory monsterCategory;
final MonsterSize monsterSize;
/// 종족 ID (Phase 4: 종족별 캐릭터 애니메이션)
final String? raceId;
/// 프레임 상수
static const int frameWidth = 60;
static const int frameHeight = 8;
@@ -94,8 +99,25 @@ class CanvasBattleComposer {
}
/// 캐릭터 레이어 생성 (z=1)
///
/// Phase 4: 종족별 캐릭터 프레임 지원
AsciiLayer _createCharacterLayer(BattlePhase phase, int subFrame) {
var charFrame = getCharacterFrame(phase, subFrame);
CharacterFrame charFrame;
// 종족 ID가 있으면 종족별 프레임 사용
if (raceId != null && raceId!.isNotEmpty) {
final raceData = RaceCharacterFrames.get(raceId!);
if (raceData != null) {
final frames = raceData.getFrames(phase);
charFrame = frames[subFrame % frames.length];
} else {
// 종족 데이터 없으면 기본 프레임 사용
charFrame = getCharacterFrame(phase, subFrame);
}
} else {
charFrame = getCharacterFrame(phase, subFrame);
}
if (hasShield) {
charFrame = charFrame.withShield();
}

View File

@@ -1,9 +1,12 @@
// 프론트 화면용 Hero vs Glitch God ASCII 애니메이션 데이터
// 작은 용사가 거대한 Glitch God에 맞서는 장면을 표현
// 작은 용사(3줄)가 거대한 Glitch God(10줄)에 맞서는 장면
// 캐릭터 해부학: 머리(1개), 양팔(2개), 양다리(2개)
/// 애니메이션 프레임 (10줄, 6프레임 루프)
/// 애니메이션 프레임 (10줄, 12프레임 루프)
const frontScreenAnimationFrames = [
// 프레임 0: 대치 상태 (방패 들고 대기)
// ========================================================================
// 프레임 0: 대치 상태 1 (숨쉬기 - 들숨)
// ========================================================================
'''
░░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░
░▓▓ G L I T C H ▓▓░
@@ -11,12 +14,44 @@ const frontScreenAnimationFrames = [
░▓▓▓ ◈◈ ◈◈ ▓▓▓░
░▓▓▓▓ ▼▼▼ ▓▓▓▓░
░▓▓▓▓▓ ████████ ▓▓▓▓▓░
o ░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░
[]|- ░▓▓▓ G O D ▓▓▓░
/ \\ ░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░
o ░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░
/|\\ ░▓▓▓ G O D ▓▓▓░
/ \\ ░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░
~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~''',
// 프레임 1: 용사 전진 (방패 앞으로)
// ========================================================================
// 프레임 1: 대치 상태 2 (숨쉬기 - 날숨)
// ========================================================================
'''
░░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░
░▓▓ G L I T C H ▓▓░
░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░
░▓▓▓ ◉◉ ◉◉ ▓▓▓░
░▓▓▓▓ ~~~ ▓▓▓▓░
░▓▓▓▓▓ ████████ ▓▓▓▓▓░
O ░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░
/|\\ ░▓▓▓ G O D ▓▓▓░
| | ░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░
~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~''',
// ========================================================================
// 프레임 2: 용사 전진 1
// ========================================================================
'''
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓ G L I T C H ▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓ ◈◈ ◈◈ ▓▓▓▓
▓▓▓▓▓ ▼▼▼ ▓▓▓▓▓
o ▓▓▓▓▓▓ ████████ ▓▓▓▓▓▓
/|\\ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
/ \\ ▓▓▓▓ G O D ▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~''',
// ========================================================================
// 프레임 3: 용사 전진 2
// ========================================================================
'''
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓ G L I T C H ▓▓
@@ -24,66 +59,134 @@ const frontScreenAnimationFrames = [
▓▓▓▓ ◉◉ ◉◉ ▓▓▓▓
▓▓▓▓▓ ~~~ ▓▓▓▓▓
o ▓▓▓▓▓▓ ████████ ▓▓▓▓▓▓
[]|> ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
/ \\ ▓▓▓▓ G O D ▓▓▓▓
/|\\ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
| | ▓▓▓▓ G O D ▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~''',
// 프레임 2: 용사 공격 준비 (방패 방어 자세)
// ========================================================================
// 프레임 4: 공격 준비 1 (무기 들기)
// ========================================================================
'''
▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒
▒▓ G L I T C H ▓▒
▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒
▒▓▓▓ ◈◈ ◈◈ ▓▓▓▒
▒▓▓▓▓ ▼▼▼ ▓▓▓▓▒
o\\ ▒▓▓▓▓▓ ████████ ▓▓▓▓▓▒
[]=|== ▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒
o ▒▓▓▓▓▓ ████████ ▓▓▓▓▓▒
\\| ▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒
/ \\ ▒▓▓▓ G O D ▓▓▓▒
▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒
~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~''',
// 프레임 3: 용사 공격 (글리치 갓 데미지)
'''
░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░
░▓ G#L@I*T&C!H ▓░
░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░
░▓▓▓ X X X X ▓▓▓░
o\\ ░▓▓▓▓ !!! ▓▓▓▓░
[]=|===> ░▓▓▓▓▓ ████████ ▓▓▓▓▓░
/ \\ ░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░
░▓▓▓ G O D ▓▓▓░
░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░
~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~''',
// 프레임 4: 글리치 갓 반격 준비 (방패로 방어)
'''
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓ G L I T C H ▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓ @@ @@ ▓▓▓▓
▓▓▓▓▓ <=== ▓▓▓▓▓
[]o ▓▓▓▓▓▓ ████████ ▓▓▓▓▓▓
|\\ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
/ \\ ▓▓▓▓ G O D ▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~''',
// 프레임 5: 글리치 갓 공격 (용사 방패로 막기)
// ========================================================================
// 프레임 5: 공격 준비 2 (무기 뒤로)
// ========================================================================
'''
▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒
▒▓ G L I T C H ▓▒
▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒
▒▓▓▓ ◉◉ ◉◉ ▓▓▓▒
▒▓▓▓▓ <====== ▓▓▓▓▒
[]o * ▒▓▓▓▓▓ ████████ ▓▓▓▓▓▒
|/ ▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒
|\\ ▒▓▓▓ G O D ▓▓▓▒
▒▓▓▓▓ ~~~ ▓▓▓▓▒
o ▒▓▓▓▓▓ ████████ ▓▓▓▓▓▒
\\|/ ▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒
/ \\ ▒▓▓▓ G O D ▓▓▓▒
▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒
~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~''',
// ========================================================================
// 프레임 6: 공격 1 (휘두르기)
// ========================================================================
'''
░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░
░▓ G L I T C H ▓░
░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░
░▓▓▓ ◈◈ ◈◈ ▓▓▓░
░▓▓▓▓ ▼▼▼ ▓▓▓▓░
o ░▓▓▓▓▓ ████████ ▓▓▓▓▓░
\\|- ░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░
/ \\ ░▓▓▓ G O D ▓▓▓░
░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░
~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~''',
// ========================================================================
// 프레임 7: 공격 2 (이펙트 + 히트)
// ========================================================================
'''
░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░
░▓ G#L@I*T&C!H ▓░
░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░
░▓▓▓ X X X X ▓▓▓░
░▓▓▓▓ !!! ▓▓▓▓░
o ░▓▓▓▓▓ ████████ ▓▓▓▓▓░
\\|-=>* ░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░
/ \\ ░▓▓▓ G O D ▓▓▓░
░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░
~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~''',
// ========================================================================
// 프레임 8: 보스 반격 준비 1
// ========================================================================
'''
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓ G L I T C H ▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓ @@ @@ ▓▓▓▓
▓▓▓▓▓ <=== ▓▓▓▓▓
o ▓▓▓▓▓▓ ████████ ▓▓▓▓▓▓
/|\\ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
/ \\ ▓▓▓▓ G O D ▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~''',
// ========================================================================
// 프레임 9: 보스 반격 2 (글리치 증가)
// ========================================================================
'''
▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒
▒▓ G L I T C H ▓▒
▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒
▒▓▓▓ ◉◉ ◉◉ ▓▓▓▒
▒▓▓▓▓ <====== ▓▓▓▓▒
o ▒▓▓▓▓▓ ████████ ▓▓▓▓▓▒
/|\\ ▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒
/ \\ ▒▓▓▓ G O D ▓▓▓▒
▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒
~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~''',
// ========================================================================
// 프레임 10: 방어 1 (방패 들기)
// ========================================================================
'''
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓ G L I T C H ▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓ @@ @@ ▓▓▓▓
▓▓▓▓▓ <==== ▓▓▓▓▓
o[] ▓▓▓▓▓▓ ████████ ▓▓▓▓▓▓
/| ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
/ \\ ▓▓▓▓ G O D ▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~''',
// ========================================================================
// 프레임 11: 방어 2 (충격파 막기)
// ========================================================================
'''
▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒
▒▓ G L I T C H ▓▒
▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒
▒▓▓▓ ◉◉ ◉◉ ▓▓▓▒
▒▓▓▓▓ <===== ▓▓▓▓▒
o[]* ▒▓▓▓▓▓ ████████ ▓▓▓▓▓▒
/| ▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒
/ \\ ▒▓▓▓ G O D ▓▓▓▒
▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒
~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~''',
];
/// 애니메이션 프레임 간격 (밀리초)
const frontScreenAnimationIntervalMs = 400;
const frontScreenAnimationIntervalMs = 350;
/// 애니메이션 총 프레임 수
const frontScreenAnimationFrameCount = 6;
const frontScreenAnimationFrameCount = 12;

View File

@@ -0,0 +1,754 @@
// 종족별 ASCII 캐릭터 프레임 데이터
// 모든 캐릭터는 3줄 × 6자 폭으로 통일 (보스 10줄과 대비)
import 'package:askiineverdie/src/core/animation/character_frames.dart';
/// 종족별 캐릭터 프레임 저장소
class RaceCharacterFrames {
RaceCharacterFrames._();
/// 종족 ID로 프레임 데이터 조회
static RaceFrameData? get(String raceId) => _raceFrames[raceId];
/// 기본 프레임 (종족 미지정 시)
static RaceFrameData get defaultFrames => _raceFrames['byte_human']!;
/// 모든 종족 ID 목록
static List<String> get allRaceIds => _raceFrames.keys.toList();
}
/// 종족별 프레임 데이터
class RaceFrameData {
const RaceFrameData({
required this.raceId,
required this.idle,
required this.prepare,
required this.attack,
required this.hit,
required this.recover,
});
final String raceId;
final List<CharacterFrame> idle; // 4 프레임
final List<CharacterFrame> prepare; // 3 프레임
final List<CharacterFrame> attack; // 5 프레임
final List<CharacterFrame> hit; // 3 프레임
final List<CharacterFrame> recover; // 3 프레임
/// BattlePhase로 프레임 목록 조회
List<CharacterFrame> getFrames(BattlePhase phase) {
return switch (phase) {
BattlePhase.idle => idle,
BattlePhase.prepare => prepare,
BattlePhase.attack => attack,
BattlePhase.hit => hit,
BattlePhase.recover => recover,
};
}
}
// ============================================================================
// 종족별 프레임 데이터 (21개 종족)
// 구조: [머리, 몸통+팔, 다리] - 모두 6자 폭
// ============================================================================
const _raceFrames = <String, RaceFrameData>{
// --------------------------------------------------------------------------
// 기본형 (Byte Human, Buffer Dwarf)
// --------------------------------------------------------------------------
'byte_human': RaceFrameData(
raceId: 'byte_human',
idle: [
CharacterFrame([r' o ', r' /|\ ', r' / \ ']),
CharacterFrame([r' o ', r' /|\ ', r' | | ']),
CharacterFrame([r' o ', r' /|\ ', r' / \ ']),
CharacterFrame([r' O ', r' /|\ ', r' / \ ']),
],
prepare: [
CharacterFrame([r' o ', r' \|\ ', r' / \ ']),
CharacterFrame([r' o ', r' \| ', r' / \ ']),
CharacterFrame([r' o ', r' \|/ ', r' / \ ']),
],
attack: [
CharacterFrame([r' o ', r' \| ', r' / \ ']),
CharacterFrame([r' o ', r' \|- ', r' / \ ']),
CharacterFrame([r' o ', r' \|-- ', r' / \ ']),
CharacterFrame([r' o ', r'\|-=>', r' / \ ']),
CharacterFrame([r' o ', r' /|\ ', r' / \ ']),
],
hit: [
CharacterFrame([r' o ', r'/|\* ', r' / \ ']),
CharacterFrame([r' o ', r'/|\ *', r' / \ ']),
CharacterFrame([r' o ', r' /|\ ', r' / \ ']),
],
recover: [
CharacterFrame([r' o ', r' /|\ ', r' | ']),
CharacterFrame([r' o ', r' /|\ ', r' / \ ']),
CharacterFrame([r' o ', r' /|\ ', r' / \ ']),
],
),
'buffer_dwarf': RaceFrameData(
raceId: 'buffer_dwarf',
idle: [
CharacterFrame([r' o ', r' /█\ ', r' / \ ']),
CharacterFrame([r' o ', r' /█\ ', r' | | ']),
CharacterFrame([r' o ', r' /█\ ', r' / \ ']),
CharacterFrame([r' O ', r' /█\ ', r' / \ ']),
],
prepare: [
CharacterFrame([r' o ', r' \█\ ', r' / \ ']),
CharacterFrame([r' o ', r' \█ ', r' / \ ']),
CharacterFrame([r' o ', r' \█/ ', r' / \ ']),
],
attack: [
CharacterFrame([r' o ', r' \█ ', r' / \ ']),
CharacterFrame([r' o ', r' \█- ', r' / \ ']),
CharacterFrame([r' o ', r' \█-- ', r' / \ ']),
CharacterFrame([r' o ', r'\█-=>', r' / \ ']),
CharacterFrame([r' o ', r' /█\ ', r' / \ ']),
],
hit: [
CharacterFrame([r' o ', r'/█\* ', r' / \ ']),
CharacterFrame([r' o ', r'/█\ *', r' / \ ']),
CharacterFrame([r' o ', r' /█\ ', r' / \ ']),
],
recover: [
CharacterFrame([r' o ', r' /█\ ', r' | ']),
CharacterFrame([r' o ', r' /█\ ', r' / \ ']),
CharacterFrame([r' o ', r' /█\ ', r' / \ ']),
],
),
// --------------------------------------------------------------------------
// 대형 (Kernel Giant, Heap Troll)
// --------------------------------------------------------------------------
'kernel_giant': RaceFrameData(
raceId: 'kernel_giant',
idle: [
CharacterFrame([r' O ', r' /█\ ', r' ┘ └ ']),
CharacterFrame([r' O ', r' /█\ ', r' | | ']),
CharacterFrame([r' O ', r' /█\ ', r' ┘ └ ']),
CharacterFrame([r' O ', r' /█\ ', r' ┘ └ ']),
],
prepare: [
CharacterFrame([r' O ', r' \█\ ', r' ┘ └ ']),
CharacterFrame([r' O ', r' \█ ', r' ┘ └ ']),
CharacterFrame([r' O ', r' \█/ ', r' ┘ └ ']),
],
attack: [
CharacterFrame([r' O ', r' \█ ', r' ┘ └ ']),
CharacterFrame([r' O ', r' \█- ', r' ┘ └ ']),
CharacterFrame([r' O ', r' \█-- ', r' ┘ └ ']),
CharacterFrame([r' O ', r'\█-=>', r' ┘ └ ']),
CharacterFrame([r' O ', r' /█\ ', r' ┘ └ ']),
],
hit: [
CharacterFrame([r' O ', r'/█\* ', r' ┘ └ ']),
CharacterFrame([r' O ', r'/█\ *', r' ┘ └ ']),
CharacterFrame([r' O ', r' /█\ ', r' ┘ └ ']),
],
recover: [
CharacterFrame([r' O ', r' /█\ ', r' || ']),
CharacterFrame([r' O ', r' /█\ ', r' ┘ └ ']),
CharacterFrame([r' O ', r' /█\ ', r' ┘ └ ']),
],
),
'heap_troll': RaceFrameData(
raceId: 'heap_troll',
idle: [
CharacterFrame([r' Ö ', r' /▓\ ', r' ┘ └ ']),
CharacterFrame([r' Ö ', r' /▓\ ', r' | | ']),
CharacterFrame([r' Ö ', r' /▓\ ', r' ┘ └ ']),
CharacterFrame([r' Ö ', r' /▓\ ', r' ┘ └ ']),
],
prepare: [
CharacterFrame([r' Ö ', r' \▓\ ', r' ┘ └ ']),
CharacterFrame([r' Ö ', r' \▓ ', r' ┘ └ ']),
CharacterFrame([r' Ö ', r' \▓/ ', r' ┘ └ ']),
],
attack: [
CharacterFrame([r' Ö ', r' \▓ ', r' ┘ └ ']),
CharacterFrame([r' Ö ', r' \▓- ', r' ┘ └ ']),
CharacterFrame([r' Ö ', r' \▓-- ', r' ┘ └ ']),
CharacterFrame([r' Ö ', r'\▓-=>', r' ┘ └ ']),
CharacterFrame([r' Ö ', r' /▓\ ', r' ┘ └ ']),
],
hit: [
CharacterFrame([r' Ö ', r'/▓\* ', r' ┘ └ ']),
CharacterFrame([r' Ö ', r'/▓\ *', r' ┘ └ ']),
CharacterFrame([r' Ö ', r' /▓\ ', r' ┘ └ ']),
],
recover: [
CharacterFrame([r' Ö ', r' /▓\ ', r' || ']),
CharacterFrame([r' Ö ', r' /▓\ ', r' ┘ └ ']),
CharacterFrame([r' Ö ', r' /▓\ ', r' ┘ └ ']),
],
),
// --------------------------------------------------------------------------
// 전사형 (Protocol Paladin, Flag Knight, Array Orc)
// --------------------------------------------------------------------------
'protocol_paladin': RaceFrameData(
raceId: 'protocol_paladin',
idle: [
CharacterFrame([r' o ', r' /|+ ', r' / \ ']),
CharacterFrame([r' o ', r' /|+ ', r' | | ']),
CharacterFrame([r' o ', r' /|+ ', r' / \ ']),
CharacterFrame([r' O ', r' /|+ ', r' / \ ']),
],
prepare: [
CharacterFrame([r' o ', r' \|+ ', r' / \ ']),
CharacterFrame([r' o ', r' \| ', r' / \ ']),
CharacterFrame([r' o ', r' \|/ ', r' / \ ']),
],
attack: [
CharacterFrame([r' o ', r' \| ', r' / \ ']),
CharacterFrame([r' o ', r' \|- ', r' / \ ']),
CharacterFrame([r' o ', r' \|-- ', r' / \ ']),
CharacterFrame([r' o ', r'\|-+>', r' / \ ']),
CharacterFrame([r' o ', r' /|+ ', r' / \ ']),
],
hit: [
CharacterFrame([r' o ', r'/|+* ', r' / \ ']),
CharacterFrame([r' o ', r'/|+ *', r' / \ ']),
CharacterFrame([r' o ', r' /|+ ', r' / \ ']),
],
recover: [
CharacterFrame([r' o ', r' /|+ ', r' | ']),
CharacterFrame([r' o ', r' /|+ ', r' / \ ']),
CharacterFrame([r' o ', r' /|+ ', r' / \ ']),
],
),
'flag_knight': RaceFrameData(
raceId: 'flag_knight',
idle: [
CharacterFrame([r' ♦ ', r' /|] ', r' / \ ']),
CharacterFrame([r' ♦ ', r' /|] ', r' | | ']),
CharacterFrame([r' ♦ ', r' /|] ', r' / \ ']),
CharacterFrame([r' ◆ ', r' /|] ', r' / \ ']),
],
prepare: [
CharacterFrame([r' ♦ ', r' \|] ', r' / \ ']),
CharacterFrame([r' ♦ ', r' \| ', r' / \ ']),
CharacterFrame([r' ♦ ', r' \|/ ', r' / \ ']),
],
attack: [
CharacterFrame([r' ♦ ', r' \| ', r' / \ ']),
CharacterFrame([r' ♦ ', r' \|- ', r' / \ ']),
CharacterFrame([r' ♦ ', r' \|-- ', r' / \ ']),
CharacterFrame([r' ♦ ', r'\|-->', r' / \ ']),
CharacterFrame([r' ♦ ', r' /|] ', r' / \ ']),
],
hit: [
CharacterFrame([r' ♦ ', r'/|]* ', r' / \ ']),
CharacterFrame([r' ♦ ', r'/|] *', r' / \ ']),
CharacterFrame([r' ♦ ', r' /|] ', r' / \ ']),
],
recover: [
CharacterFrame([r' ♦ ', r' /|] ', r' | ']),
CharacterFrame([r' ♦ ', r' /|] ', r' / \ ']),
CharacterFrame([r' ♦ ', r' /|] ', r' / \ ']),
],
),
'array_orc': RaceFrameData(
raceId: 'array_orc',
idle: [
CharacterFrame([r' ö ', r' /▒\ ', r' / \ ']),
CharacterFrame([r' ö ', r' /▒\ ', r' | | ']),
CharacterFrame([r' ö ', r' /▒\ ', r' / \ ']),
CharacterFrame([r' Ö ', r' /▒\ ', r' / \ ']),
],
prepare: [
CharacterFrame([r' ö ', r' \▒\ ', r' / \ ']),
CharacterFrame([r' ö ', r' \▒ ', r' / \ ']),
CharacterFrame([r' ö ', r' \▒/ ', r' / \ ']),
],
attack: [
CharacterFrame([r' ö ', r' \▒ ', r' / \ ']),
CharacterFrame([r' ö ', r' \▒- ', r' / \ ']),
CharacterFrame([r' ö ', r' \▒-- ', r' / \ ']),
CharacterFrame([r' ö ', r'\▒-=>', r' / \ ']),
CharacterFrame([r' ö ', r' /▒\ ', r' / \ ']),
],
hit: [
CharacterFrame([r' ö ', r'/▒\* ', r' / \ ']),
CharacterFrame([r' ö ', r'/▒\ *', r' / \ ']),
CharacterFrame([r' ö ', r' /▒\ ', r' / \ ']),
],
recover: [
CharacterFrame([r' ö ', r' /▒\ ', r' | ']),
CharacterFrame([r' ö ', r' /▒\ ', r' / \ ']),
CharacterFrame([r' ö ', r' /▒\ ', r' / \ ']),
],
),
// --------------------------------------------------------------------------
// 마법형 (Loop Wizard, Lambda Druid, Recursive Sage)
// --------------------------------------------------------------------------
'loop_wizard': RaceFrameData(
raceId: 'loop_wizard',
idle: [
CharacterFrame([r' o~ ', r' /|) ', r' / \ ']),
CharacterFrame([r' o~ ', r' /|) ', r' | | ']),
CharacterFrame([r' o~ ', r' /|) ', r' / \ ']),
CharacterFrame([r' O~ ', r' /|) ', r' / \ ']),
],
prepare: [
CharacterFrame([r' o~ ', r' \|) ', r' / \ ']),
CharacterFrame([r' o~ ', r' \| ', r' / \ ']),
CharacterFrame([r' o~ ', r' \|/ ', r' / \ ']),
],
attack: [
CharacterFrame([r' o~ ', r' \| ', r' / \ ']),
CharacterFrame([r' o~ ', r' \|~ ', r' / \ ']),
CharacterFrame([r' o~ ', r' \|~~ ', r' / \ ']),
CharacterFrame([r' o~ ', r'\|~~*', r' / \ ']),
CharacterFrame([r' o~ ', r' /|) ', r' / \ ']),
],
hit: [
CharacterFrame([r' o~ ', r'/|)* ', r' / \ ']),
CharacterFrame([r' o~ ', r'/|) *', r' / \ ']),
CharacterFrame([r' o~ ', r' /|) ', r' / \ ']),
],
recover: [
CharacterFrame([r' o~ ', r' /|) ', r' | ']),
CharacterFrame([r' o~ ', r' /|) ', r' / \ ']),
CharacterFrame([r' o~ ', r' /|) ', r' / \ ']),
],
),
'lambda_druid': RaceFrameData(
raceId: 'lambda_druid',
idle: [
CharacterFrame([r' o♣ ', r' /|) ', r' / \ ']),
CharacterFrame([r' o♣ ', r' /|) ', r' | | ']),
CharacterFrame([r' o♣ ', r' /|) ', r' / \ ']),
CharacterFrame([r' O♣ ', r' /|) ', r' / \ ']),
],
prepare: [
CharacterFrame([r' o♣ ', r' \|) ', r' / \ ']),
CharacterFrame([r' o♣ ', r' \| ', r' / \ ']),
CharacterFrame([r' o♣ ', r' \|/ ', r' / \ ']),
],
attack: [
CharacterFrame([r' o♣ ', r' \| ', r' / \ ']),
CharacterFrame([r' o♣ ', r' \|~ ', r' / \ ']),
CharacterFrame([r' o♣ ', r' \|~~ ', r' / \ ']),
CharacterFrame([r' o♣ ', r'\|~~♣', r' / \ ']),
CharacterFrame([r' o♣ ', r' /|) ', r' / \ ']),
],
hit: [
CharacterFrame([r' o♣ ', r'/|)* ', r' / \ ']),
CharacterFrame([r' o♣ ', r'/|) *', r' / \ ']),
CharacterFrame([r' o♣ ', r' /|) ', r' / \ ']),
],
recover: [
CharacterFrame([r' o♣ ', r' /|) ', r' | ']),
CharacterFrame([r' o♣ ', r' /|) ', r' / \ ']),
CharacterFrame([r' o♣ ', r' /|) ', r' / \ ']),
],
),
'recursive_sage': RaceFrameData(
raceId: 'recursive_sage',
idle: [
CharacterFrame([r' o∞ ', r' /|) ', r' / \ ']),
CharacterFrame([r' o∞ ', r' /|) ', r' | | ']),
CharacterFrame([r' o∞ ', r' /|) ', r' / \ ']),
CharacterFrame([r' O∞ ', r' /|) ', r' / \ ']),
],
prepare: [
CharacterFrame([r' o∞ ', r' \|) ', r' / \ ']),
CharacterFrame([r' o∞ ', r' \| ', r' / \ ']),
CharacterFrame([r' o∞ ', r' \|/ ', r' / \ ']),
],
attack: [
CharacterFrame([r' o∞ ', r' \| ', r' / \ ']),
CharacterFrame([r' o∞ ', r' \|~ ', r' / \ ']),
CharacterFrame([r' o∞ ', r' \|~~ ', r' / \ ']),
CharacterFrame([r' o∞ ', r'\|~~∞', r' / \ ']),
CharacterFrame([r' o∞ ', r' /|) ', r' / \ ']),
],
hit: [
CharacterFrame([r' o∞ ', r'/|)* ', r' / \ ']),
CharacterFrame([r' o∞ ', r'/|) *', r' / \ ']),
CharacterFrame([r' o∞ ', r' /|) ', r' / \ ']),
],
recover: [
CharacterFrame([r' o∞ ', r' /|) ', r' | ']),
CharacterFrame([r' o∞ ', r' /|) ', r' / \ ']),
CharacterFrame([r' o∞ ', r' /|) ', r' / \ ']),
],
),
// --------------------------------------------------------------------------
// 언데드/엘프 (Coredump Undead, Null Elf, Callback Priest)
// --------------------------------------------------------------------------
'coredump_undead': RaceFrameData(
raceId: 'coredump_undead',
idle: [
CharacterFrame([r' ☠ ', r' /|\ ', r' / \ ']),
CharacterFrame([r' ☠ ', r' /|\ ', r' | | ']),
CharacterFrame([r' ☠ ', r' /|\ ', r' / \ ']),
CharacterFrame([r' ☠ ', r' /|\ ', r' / \ ']),
],
prepare: [
CharacterFrame([r' ☠ ', r' \|\ ', r' / \ ']),
CharacterFrame([r' ☠ ', r' \| ', r' / \ ']),
CharacterFrame([r' ☠ ', r' \|/ ', r' / \ ']),
],
attack: [
CharacterFrame([r' ☠ ', r' \| ', r' / \ ']),
CharacterFrame([r' ☠ ', r' \|- ', r' / \ ']),
CharacterFrame([r' ☠ ', r' \|-- ', r' / \ ']),
CharacterFrame([r' ☠ ', r'\|-~>', r' / \ ']),
CharacterFrame([r' ☠ ', r' /|\ ', r' / \ ']),
],
hit: [
CharacterFrame([r' ☠ ', r'/|\~ ', r' / \ ']),
CharacterFrame([r' ☠ ', r'/|\ ~', r' / \ ']),
CharacterFrame([r' ☠ ', r' /|\ ', r' / \ ']),
],
recover: [
CharacterFrame([r' ☠ ', r' /|\ ', r' | ']),
CharacterFrame([r' ☠ ', r' /|\ ', r' / \ ']),
CharacterFrame([r' ☠ ', r' /|\ ', r' / \ ']),
],
),
'null_elf': RaceFrameData(
raceId: 'null_elf',
idle: [
CharacterFrame([r' ö ', r' /|\ ', r' / \ ']),
CharacterFrame([r' ö ', r' /|\ ', r' | | ']),
CharacterFrame([r' ö ', r' /|\ ', r' / \ ']),
CharacterFrame([r' Ö ', r' /|\ ', r' / \ ']),
],
prepare: [
CharacterFrame([r' ö ', r' \|\ ', r' / \ ']),
CharacterFrame([r' ö ', r' \| ', r' / \ ']),
CharacterFrame([r' ö ', r' \|/ ', r' / \ ']),
],
attack: [
CharacterFrame([r' ö ', r' \| ', r' / \ ']),
CharacterFrame([r' ö ', r' \|~ ', r' / \ ']),
CharacterFrame([r' ö ', r' \|~~ ', r' / \ ']),
CharacterFrame([r' ö ', r'\|~~*', r' / \ ']),
CharacterFrame([r' ö ', r' /|\ ', r' / \ ']),
],
hit: [
CharacterFrame([r' ö ', r'/|\* ', r' / \ ']),
CharacterFrame([r' ö ', r'/|\ *', r' / \ ']),
CharacterFrame([r' ö ', r' /|\ ', r' / \ ']),
],
recover: [
CharacterFrame([r' ö ', r' /|\ ', r' | ']),
CharacterFrame([r' ö ', r' /|\ ', r' / \ ']),
CharacterFrame([r' ö ', r' /|\ ', r' / \ ']),
],
),
'callback_priest': RaceFrameData(
raceId: 'callback_priest',
idle: [
CharacterFrame([r' ô ', r' /|\ ', r' / \ ']),
CharacterFrame([r' ô ', r' /|\ ', r' | | ']),
CharacterFrame([r' ô ', r' /|\ ', r' / \ ']),
CharacterFrame([r' Ô ', r' /|\ ', r' / \ ']),
],
prepare: [
CharacterFrame([r' ô ', r' \|\ ', r' / \ ']),
CharacterFrame([r' ô ', r' \| ', r' / \ ']),
CharacterFrame([r' ô ', r' \|/ ', r' / \ ']),
],
attack: [
CharacterFrame([r' ô ', r' \| ', r' / \ ']),
CharacterFrame([r' ô ', r' \|+ ', r' / \ ']),
CharacterFrame([r' ô ', r' \|++ ', r' / \ ']),
CharacterFrame([r' ô ', r'\|++*', r' / \ ']),
CharacterFrame([r' ô ', r' /|\ ', r' / \ ']),
],
hit: [
CharacterFrame([r' ô ', r'/|\+ ', r' / \ ']),
CharacterFrame([r' ô ', r'/|\ +', r' / \ ']),
CharacterFrame([r' ô ', r' /|\ ', r' / \ ']),
],
recover: [
CharacterFrame([r' ô ', r' /|\ ', r' | ']),
CharacterFrame([r' ô ', r' /|\ ', r' / \ ']),
CharacterFrame([r' ô ', r' /|\ ', r' / \ ']),
],
),
// --------------------------------------------------------------------------
// 소형 (Bit Halfling, Stack Goblin, Cache Imp)
// --------------------------------------------------------------------------
'bit_halfling': RaceFrameData(
raceId: 'bit_halfling',
idle: [
CharacterFrame([r' o ', r' /|\ ', r' Y ']),
CharacterFrame([r' o ', r' /|\ ', r' | ']),
CharacterFrame([r' o ', r' /|\ ', r' Y ']),
CharacterFrame([r' O ', r' /|\ ', r' Y ']),
],
prepare: [
CharacterFrame([r' o ', r' \|\ ', r' Y ']),
CharacterFrame([r' o ', r' \| ', r' Y ']),
CharacterFrame([r' o ', r' \|/ ', r' Y ']),
],
attack: [
CharacterFrame([r' o ', r' \| ', r' Y ']),
CharacterFrame([r' o ', r' \|- ', r' Y ']),
CharacterFrame([r' o ', r' \|-- ', r' Y ']),
CharacterFrame([r' o ', r'\|-=>', r' Y ']),
CharacterFrame([r' o ', r' /|\ ', r' Y ']),
],
hit: [
CharacterFrame([r' o ', r'/|\* ', r' Y ']),
CharacterFrame([r' o ', r'/|\ *', r' Y ']),
CharacterFrame([r' o ', r' /|\ ', r' Y ']),
],
recover: [
CharacterFrame([r' o ', r' /|\ ', r' | ']),
CharacterFrame([r' o ', r' /|\ ', r' Y ']),
CharacterFrame([r' o ', r' /|\ ', r' Y ']),
],
),
'stack_goblin': RaceFrameData(
raceId: 'stack_goblin',
idle: [
CharacterFrame([r' ◦ ', r' /|\ ', r' Y ']),
CharacterFrame([r' ◦ ', r' /|\ ', r' | ']),
CharacterFrame([r' ◦ ', r' /|\ ', r' Y ']),
CharacterFrame([r' ● ', r' /|\ ', r' Y ']),
],
prepare: [
CharacterFrame([r' ◦ ', r' \|\ ', r' Y ']),
CharacterFrame([r' ◦ ', r' \| ', r' Y ']),
CharacterFrame([r' ◦ ', r' \|/ ', r' Y ']),
],
attack: [
CharacterFrame([r' ◦ ', r' \| ', r' Y ']),
CharacterFrame([r' ◦ ', r' \|- ', r' Y ']),
CharacterFrame([r' ◦ ', r' \|-- ', r' Y ']),
CharacterFrame([r' ◦ ', r'\|-=>', r' Y ']),
CharacterFrame([r' ◦ ', r' /|\ ', r' Y ']),
],
hit: [
CharacterFrame([r' ◦ ', r'/|\* ', r' Y ']),
CharacterFrame([r' ◦ ', r'/|\ *', r' Y ']),
CharacterFrame([r' ◦ ', r' /|\ ', r' Y ']),
],
recover: [
CharacterFrame([r' ◦ ', r' /|\ ', r' | ']),
CharacterFrame([r' ◦ ', r' /|\ ', r' Y ']),
CharacterFrame([r' ◦ ', r' /|\ ', r' Y ']),
],
),
'cache_imp': RaceFrameData(
raceId: 'cache_imp',
idle: [
CharacterFrame([r' ^ ', r' /|\ ', r' Y ']),
CharacterFrame([r' ^ ', r' /|\ ', r' | ']),
CharacterFrame([r' ^ ', r' /|\ ', r' Y ']),
CharacterFrame([r' ^ ', r' /|\ ', r' Y ']),
],
prepare: [
CharacterFrame([r' ^ ', r' \|\ ', r' Y ']),
CharacterFrame([r' ^ ', r' \| ', r' Y ']),
CharacterFrame([r' ^ ', r' \|/ ', r' Y ']),
],
attack: [
CharacterFrame([r' ^ ', r' \| ', r' Y ']),
CharacterFrame([r' ^ ', r' \|- ', r' Y ']),
CharacterFrame([r' ^ ', r' \|-- ', r' Y ']),
CharacterFrame([r' ^ ', r'\|-->', r' Y ']),
CharacterFrame([r' ^ ', r' /|\ ', r' Y ']),
],
hit: [
CharacterFrame([r' ^ ', r'/|\* ', r' Y ']),
CharacterFrame([r' ^ ', r'/|\ *', r' Y ']),
CharacterFrame([r' ^ ', r' /|\ ', r' Y ']),
],
recover: [
CharacterFrame([r' ^ ', r' /|\ ', r' | ']),
CharacterFrame([r' ^ ', r' /|\ ', r' Y ']),
CharacterFrame([r' ^ ', r' /|\ ', r' Y ']),
],
),
// --------------------------------------------------------------------------
// 영체 (Thread Spirit, Pointer Fairy)
// --------------------------------------------------------------------------
'thread_spirit': RaceFrameData(
raceId: 'thread_spirit',
idle: [
CharacterFrame([r' ·o· ', r' | ', r' ~~~ ']),
CharacterFrame([r' ·o· ', r' | ', r' ~~ ']),
CharacterFrame([r' ·o· ', r' | ', r' ~~~ ']),
CharacterFrame([r' ·O· ', r' | ', r' ~~~ ']),
],
prepare: [
CharacterFrame([r' ·o· ', r' \| ', r' ~~~ ']),
CharacterFrame([r' ·o· ', r' \ ', r' ~~~ ']),
CharacterFrame([r' ·o· ', r' \/ ', r' ~~~ ']),
],
attack: [
CharacterFrame([r' ·o· ', r' \ ', r' ~~~ ']),
CharacterFrame([r' ·o· ', r' \~ ', r' ~~~ ']),
CharacterFrame([r' ·o· ', r' \~~ ', r' ~~~ ']),
CharacterFrame([r' ·o· ', r'\~~* ', r' ~~~ ']),
CharacterFrame([r' ·o· ', r' | ', r' ~~~ ']),
],
hit: [
CharacterFrame([r' ·o· ', r' |* ', r' ~~~ ']),
CharacterFrame([r' ·o· ', r' | * ', r' ~~~ ']),
CharacterFrame([r' ·o· ', r' | ', r' ~~~ ']),
],
recover: [
CharacterFrame([r' ·o· ', r' | ', r' ~~ ']),
CharacterFrame([r' ·o· ', r' | ', r' ~~~ ']),
CharacterFrame([r' ·o· ', r' | ', r' ~~~ ']),
],
),
'pointer_fairy': RaceFrameData(
raceId: 'pointer_fairy',
idle: [
CharacterFrame([r' *o* ', r' | ', r' ~~~ ']),
CharacterFrame([r' *o* ', r' | ', r' ~~ ']),
CharacterFrame([r' *o* ', r' | ', r' ~~~ ']),
CharacterFrame([r' *O* ', r' | ', r' ~~~ ']),
],
prepare: [
CharacterFrame([r' *o* ', r' \| ', r' ~~~ ']),
CharacterFrame([r' *o* ', r' \ ', r' ~~~ ']),
CharacterFrame([r' *o* ', r' \/ ', r' ~~~ ']),
],
attack: [
CharacterFrame([r' *o* ', r' \ ', r' ~~~ ']),
CharacterFrame([r' *o* ', r' \* ', r' ~~~ ']),
CharacterFrame([r' *o* ', r' \** ', r' ~~~ ']),
CharacterFrame([r' *o* ', r'\**+ ', r' ~~~ ']),
CharacterFrame([r' *o* ', r' | ', r' ~~~ ']),
],
hit: [
CharacterFrame([r' *o* ', r' |+ ', r' ~~~ ']),
CharacterFrame([r' *o* ', r' | + ', r' ~~~ ']),
CharacterFrame([r' *o* ', r' | ', r' ~~~ ']),
],
recover: [
CharacterFrame([r' *o* ', r' | ', r' ~~ ']),
CharacterFrame([r' *o* ', r' | ', r' ~~~ ']),
CharacterFrame([r' *o* ', r' | ', r' ~~~ ']),
],
),
// --------------------------------------------------------------------------
// 레인저형 (Index Ranger, Iterator Rogue)
// --------------------------------------------------------------------------
'index_ranger': RaceFrameData(
raceId: 'index_ranger',
idle: [
CharacterFrame([r' o ', r' /|\ ', r' λ \ ']),
CharacterFrame([r' o ', r' /|\ ', r' | | ']),
CharacterFrame([r' o ', r' /|\ ', r' λ \ ']),
CharacterFrame([r' O ', r' /|\ ', r' λ \ ']),
],
prepare: [
CharacterFrame([r' o ', r' \|\ ', r' λ \ ']),
CharacterFrame([r' o ', r' \| ', r' λ \ ']),
CharacterFrame([r' o ', r' \|/ ', r' λ \ ']),
],
attack: [
CharacterFrame([r' o ', r' \| ', r' λ \ ']),
CharacterFrame([r' o ', r' \|) ', r' λ \ ']),
CharacterFrame([r' o ', r' \|)) ', r' λ \ ']),
CharacterFrame([r' o ', r'\|))>', r' λ \ ']),
CharacterFrame([r' o ', r' /|\ ', r' λ \ ']),
],
hit: [
CharacterFrame([r' o ', r'/|\* ', r' λ \ ']),
CharacterFrame([r' o ', r'/|\ *', r' λ \ ']),
CharacterFrame([r' o ', r' /|\ ', r' λ \ ']),
],
recover: [
CharacterFrame([r' o ', r' /|\ ', r' | ']),
CharacterFrame([r' o ', r' /|\ ', r' λ \ ']),
CharacterFrame([r' o ', r' /|\ ', r' λ \ ']),
],
),
'iterator_rogue': RaceFrameData(
raceId: 'iterator_rogue',
idle: [
CharacterFrame([r' o ', r' /|\ ', r' λ \ ']),
CharacterFrame([r' o ', r' /|\ ', r' | | ']),
CharacterFrame([r' o ', r' /|\ ', r' λ \ ']),
CharacterFrame([r' o ', r' /|\ ', r' λ \ ']),
],
prepare: [
CharacterFrame([r' o ', r' \|\ ', r' λ \ ']),
CharacterFrame([r' o ', r' \| ', r' λ \ ']),
CharacterFrame([r' o ', r' \|/ ', r' λ \ ']),
],
attack: [
CharacterFrame([r' o ', r' \| ', r' λ \ ']),
CharacterFrame([r' o ', r' \|- ', r' λ \ ']),
CharacterFrame([r' o ', r' \|-- ', r' λ \ ']),
CharacterFrame([r' o ', r'\|--x', r' λ \ ']),
CharacterFrame([r' o ', r' /|\ ', r' λ \ ']),
],
hit: [
CharacterFrame([r' o ', r'/|\x ', r' λ \ ']),
CharacterFrame([r' o ', r'/|\ x', r' λ \ ']),
CharacterFrame([r' o ', r' /|\ ', r' λ \ ']),
],
recover: [
CharacterFrame([r' o ', r' /|\ ', r' | ']),
CharacterFrame([r' o ', r' /|\ ', r' λ \ ']),
CharacterFrame([r' o ', r' /|\ ', r' λ \ ']),
],
),
// --------------------------------------------------------------------------
// 노움 (Register Gnome)
// --------------------------------------------------------------------------
'register_gnome': RaceFrameData(
raceId: 'register_gnome',
idle: [
CharacterFrame([r' ô ', r' /|\ ', r' ∧ ']),
CharacterFrame([r' ô ', r' /|\ ', r' | ']),
CharacterFrame([r' ô ', r' /|\ ', r' ∧ ']),
CharacterFrame([r' Ô ', r' /|\ ', r' ∧ ']),
],
prepare: [
CharacterFrame([r' ô ', r' \|\ ', r' ∧ ']),
CharacterFrame([r' ô ', r' \| ', r' ∧ ']),
CharacterFrame([r' ô ', r' \|/ ', r' ∧ ']),
],
attack: [
CharacterFrame([r' ô ', r' \| ', r' ∧ ']),
CharacterFrame([r' ô ', r' \|* ', r' ∧ ']),
CharacterFrame([r' ô ', r' \|** ', r' ∧ ']),
CharacterFrame([r' ô ', r'\|**>', r' ∧ ']),
CharacterFrame([r' ô ', r' /|\ ', r' ∧ ']),
],
hit: [
CharacterFrame([r' ô ', r'/|\* ', r' ∧ ']),
CharacterFrame([r' ô ', r'/|\ *', r' ∧ ']),
CharacterFrame([r' ô ', r' /|\ ', r' ∧ ']),
],
recover: [
CharacterFrame([r' ô ', r' /|\ ', r' | ']),
CharacterFrame([r' ô ', r' /|\ ', r' ∧ ']),
CharacterFrame([r' ô ', r' /|\ ', r' ∧ ']),
],
),
};