# Battle System Reference

이 문서는 사용자가 제공한 플레이/위키 기반 전투 시스템 정보를 정리한다. 여기의
규칙은 원본 게임 동작을 재현할 때 참고하는 기준이며, EXE에서 직접 확인된 항목과
아직 검증이 필요한 항목을 구분한다.

## Battle Modes

전투 중 캐릭터는 모드를 변경할 수 있다.

| 모드 | 의미 | 행동순서 | 메모 |
| --- | --- | --- | --- |
| 선제 | 행동순서 중시 | 가장 빠름 | 행동 종료 후 빈틈이 크다. |
| 보통 | 공격/방어/회피 균형 | 보통 | 기준 모드. |
| 돌격 | 공격 중시 | 보통 | 공격력이 올라가고 방어가 약해진다. |
| 방어 | 수비 중시 | 느림 | 카운터/회복 대기에도 사용 가능. |
| 반격 | 적 행동 후 반격 | 가장 느림 | 적의 턴이 지난 뒤 행동하는 것으로 고정된다. |

행동순서의 큰 흐름은 `선제 > 보통/돌격 > 방어 > 반격`이다. 반격은 회복
스킬이나 회복 아이템을 적 공격 이후에 쓰는 용도로 유리하다.

아직 EXE에서 확인할 항목:

- 모드 enum 값.
- 공격/방어/회피/순발 보정 배율.
- 선제 행동 후 취약 상태가 어떤 필드 또는 공식으로 적용되는지.
- `PageUp`/`PageDown` action bit 소비 루틴과 모드 증감 처리.

## Battle Timing / Frame Gate

전투 표시 VM의 frame gate 값은 브라우저 ms가 아니라 원본 EXE의 내부 update tick
단위로 처리한다. EXE main/update loop를 정적 분석한 결과, 핵심 타이밍은 다음으로
확정한다.

- `Sleep`, `timeGetTime`, `QueryPerformanceCounter` import는 없다.
- `timeBeginPeriod(2)`로 타이머 정밀도를 올린다. 확인 위치: `0x004018f0`.
- `timeSetEvent` 콜백 `0x00402117`은 메시지를 깨우는 보조 타이머로 쓰인다.
- 메인 루프는 `GetTickCount`를 사용한다. 확인 위치: `0x0040197c` 부근.
- update 기준값은 `0x59e37c = 0x30`, 즉 48ms다.
- 경과 시간이 밀리면 update step을 최대 3개까지 catch-up한다.

따라서 전투 표시 gate를 wall-clock preview로 환산할 때의 기준은 아래와 같다.

| gate | 원본 tick 환산 |
| ---: | ---: |
| 1 | 48ms |
| 2 | 96ms |
| 3 | 144ms |
| 6 | 288ms |

즉 브라우저 프리뷰/계산기/러너에서 gate 기반 애니메이션을 재생할 때는
`durationMs = max(1, gate) * 48`을 기본 정책으로 둔다. 단, `0xbf`/`0xc1` 같은 wait
barrier는 고정 ms delay가 아니라 result/reaction/actor-flag barrier이므로 frame gate
합산과 구분한다.

## Battle Skill Timeline Verification

플레이어 스킬 표시는 `out/battle_skill_timeline_canonical.json`의 EXE 정적 타임라인을
기준으로 삼고, `out/battle_action_mapping.json`은 이름/MP/페이로드 보조 메타만
병합한다. 웹 소비 경로는 `web/engine/battle/animation.js`의
`BattleAnimation.mergePlayerActions()`를 통과해야 한다.

아래 정적 검증은 런타임이나 브라우저 없이, 과거에 발생했던 스킬 밀림 회귀를
직접 확인한다.

```bash
python3 tools/verify_battle_skill_canonical_binding.py
```

현재 이 검증은 156개 플레이어 액션 수, 린샹 `도발`/`꼬챙이 꿰기`/`안면백조권`
1-4단계, 아타호 `맹호룬룬권` 1/4단계의 canonical frame sequence와 hitEvents, 그리고
`battle_skill_timeline_review.html`, `battle_formula_calculator.html`,
`battle_simulator.html`의 canonical merge 사용 여부를 확인한다. 이는 스킬 프레임
소비 경로 검증이며, 브라우저 캔버스 렌더링 자체의 픽셀 검증은 아니다.

## Status Effects

| 상태 | 효과 | 회복 |
| --- | --- | --- |
| 기절 | HP 0, 명령 입력 불가, 최대 HP 감소, 일반 회복 스킬 영향 없음 | 리프레시 워터 또는 마수석. 감소한 최대 HP는 여관/세이브포인트/회복의 두루마리로 회복 |
| 독 | 모든 능력치 감소, 모드 변경 불가 | 해독초, 기공독치료 |
| 넘어짐 | 그 턴 행동 불가 | 다음 턴 자동 회복 |
| 행동정지 | 그 턴 행동 불가 | 다음 턴 자동 회복 |
| 휙 날아감 | 그 턴 행동 불가 | 다음 턴 자동 회복 |
| 마비 | 모든 능력치 크게 감소, 명령 입력 불가 | 해독초, 기공독치료 |

현재 기술 페이로드 분석의 `status` 필드는 아래 enum 후보와 맞는다.

| 값 | 후보 상태 |
| ---: | --- |
| 0 | 없음 |
| 1 | 넘어짐 |
| 2 | 휙 날아감 |
| 3 | 행동정지 |
| 4 | 독 |
| 5 | 마비 |

아직 EXE에서 확인할 항목:

- 상태 플래그 저장 위치.
- 독/마비 능력치 감소 배율.
- 기절 시 최대 HP 감소량과 회복 루틴.
- 자동 회복 상태가 턴 종료 시 어디에서 clear되는지.

## Character Stats

| 능력치 | 의미 |
| --- | --- |
| 체력 | HP |
| 기력 | MP |
| 경험 | EXP |
| 공격력 | 공격 강도. 무기로 변동 |
| 방어력 | 방어 강도. 방어구로 변동 |
| 기술력 | 명중률 |
| 순발력 | 행동순서와 회피 |
| 운 | 크리티컬과 특수효과 발동률. 레벨업 시 랜덤 변동 |

표시 능력치는 순수 능력치와 장비 보정이 합산된 값으로 봐야 한다. 장비 해제 개념이
없으므로 시작 장비의 보정도 상태창 수치에 포함된다.

## Initial Stats And Level-Up Ranges

초기 스탯 순서는 `HP/MP/공격/방어/기술/순발`이다.

| 캐릭터 | 초기 스탯 |
| --- | --- |
| 아타호 | 30 / 18 / 22 / 7 / 22 / 15 |
| 린샹 | 26 / 24 / 14 / 8 / 22 / 18 |
| 스마슈 | 32 / 16 / 6 / 10 / 24 / 20 |

레벨업 증가 범위도 같은 순서다.

| 캐릭터 | HP | MP | 공격 | 방어 | 기술 | 순발 |
| --- | ---: | ---: | ---: | ---: | ---: | ---: |
| 아타호 | 3-5 | 2-3 | 3-4 | 3-4 | 2-4 | 2-4 |
| 린샹 | 2-4 | 3-4 | 2-3 | 2-4 | 3-4 | 3-4 |
| 스마슈 | 3-5 | 2-3 | 2-4 | 2-4 | 2-4 | 2-4 |

레벨에 따라 능력치가 산출되는 방식이 아니라, 레벨업 시 증가한 결과가 누적되는
방식이다. 따라서 세이브 데이터나 런타임 상태는 레벨만으로 능력치를 재계산하면
안 된다.

아직 EXE에서 확인할 항목:

- 상승치별 확률. 확률은 균등하지 않은 것으로 알려져 있다.
- 운의 레벨별 최소/최대 범위와 랜덤 변동 공식.
- 레벨업 시 기절로 감소한 최대 HP가 증가량에 영향을 주는 방식.

## Experience And Level-Up

- 몬스터 처치 경험치는 레벨 차가 커도 몬스터 1마리당 최소 1 이상이다.
- 레벨업 시 HP/MP가 회복된다.
- 최대 레벨은 99이다.
- 레벨 99에서 경험치를 채워도 레벨은 더 오르지 않지만 회복은 가능하다.
- EXP 99에서 몬스터 여러 마리를 동시에 잡을 때 overflow가 기대값보다 1 낮게
  보일 수 있다는 제보가 있다.

아직 EXE에서 확인할 항목:

- 몬스터 원본 경험치 값과 레벨 보정 공식.
- 최소 EXP 1 clamp 위치.
- 레벨업 기준 EXP와 overflow 처리.
- 레벨 99 회복 처리.

## Input Mapping

원본 EXE의 입력 테이블은 `out/input_keymap.md`와 `docs/DIRECTINPUT_NOTES.md`에
정리되어 있다. 사용자가 제공한 조작 정보와 현재 추출 결과는 대체로 일치한다.

| 기능 | 키보드 | EXE action bit 후보 |
| --- | --- | --- |
| 이동 | 방향키 | 0-3 |
| 선택 | Enter, Space, Z | 4, 6, 8 계열 |
| 취소 | Esc, X, Numpad 0 | 5, 7, 9 계열 |
| 스킬 설명 | C | 10 |
| 전투모드 변경 | PageUp / PageDown | 14 / 15 |

패드 조작은 이동 조이스틱, 선택 A, 취소 B, 스킬 설명 X, 전투모드 변경
Back/Start로 알려져 있다. EXE 입력 테이블의 `state+0x100` 이상 값들은 패드 또는
확장 입력 상태일 가능성이 있으며, 생산 루틴은 아직 완전히 이름 붙이지 않았다.

## EXE Investigation Targets

현재 정보로 바로 조사할 가치가 있는 항목:

1. `PageUp`/`PageDown` action bit 소비 루틴을 추적해 전투 모드 enum과 증감 로직 찾기.
2. 기술 페이로드의 `status` enum 후보를 위 상태표와 대조해 확정하기.
3. 레벨업 루틴에서 초기 스탯, 증가 범위, 증가 확률 테이블, 레벨 99 처리 찾기.
4. 전투 보상 루틴에서 EXP 최소 1 clamp와 overflow 처리 찾기.
5. 기절 처리 루틴에서 최대 HP 감소량과 회복 장소/아이템 복구 조건 찾기.
6. 전투 공식 루틴에서 공격/방어/기술/순발/운과 모드 보정이 들어가는 위치 찾기.
7. 아타호 취함, 린샹 도발, 스마슈 눈요기 같은 캐릭터 고유 상태를 일반 상태와
   분리해 찾기.

현재로서는 이 문서의 규칙을 기준표로 두고, EXE에서 각 항목이 확인될 때마다
`확정`으로 승격하는 방식이 안전하다.
