# Battle Damage Formula Trace Review

## 요약
- 확정: 0x433f0e가 hit unit payload를 선택하고 unit byte 0..2/5/7을 전투 결과 필드로 넘기는 지점이다.
- 확정: hit unit byte[3]은 현재 추출된 모든 unit에서 0x00으로 고정되어 reserved/unused로 둔다.
- 확정: hit unit byte[4]는 target scope id다. 0x01 self/setup, 0x05 all allies, 0x06 all enemies, 0x09 one ally, 0x0a one enemy로 분리된다.
- 확정: 0x433649는 payload hit-unit byte[4]를 읽고, 0x433545/0x4335c6은 이를 runtime actor +0x67 target selector에 쓴다.
- 확정: 0x40fa6d는 target scope bit 0x08로 selected-target branch를 가르고, 0x40f57c action setup은 selected target latch 0x0059e347을 actor +0x61로 복사한다.
- 확정: 0x433c99/0x433dc0은 actor +0x67 low nibble과 +0x61 selected target index로 target loop의 start/end actor index를 계산하고, 0x435538은 같은 selector로 hit-unit target loop를 돈다.
- 확정: hit unit byte[6]은 hit/avoid class index다. 0x4342e8..0x4342ee가 unit[6]을 읽어 target +0x36+index 명중 보정 테이블을 참조한다.
- 확정: byte[6] 0..3은 내부 명중 판정 class로 승격한다. 0=상단/공중/상승, 1=일반, 2=하단/지면/다운, 3=잡기/밀착 특수 판정이다.
- 확정: actor row +0x28..+0x2b는 target +0x36..+0x39 hit/avoid class table과 같은 계열의 전투 보정 테이블로 쓰인다.
- 확정: 0x00546970은 hit unit family byte로 인덱싱되는 family handler table이다.
- 확정: 0x4340ae는 target +0x6d result mode dispatcher이다. mode 0은 HP damage, mode 2는 HP recovery로 분기한다.
- 확정: 0x4353f8은 target +0x08 current HP 감소 함수, 0x435295는 target +0x08 HP 회복 함수, 0x435356은 MP 회복 함수로 확인된다.
- 확정: payload status byte target +0x6c는 0x4344ab에서 성공/실패 검사를 거쳐 실패 시 0으로 지워진다.
- 확정: target +0x62 bit 0x20/0x08의 표시 분기는 battle_result_display_branch_review와 battle_result_helper_label_review에서 각각 full miss / guard-glancing chip result로 확정됐다.
- 확정: target +0x6e result value는 battle_damage_digit_display_review에서 btl_etc F54..F63 숫자 표시 입력으로 확정됐다.
- 확정: attacker +0x62 bit 0x10은 stat/random gate로 세워지는 alternate result bit이며, alternate damage formula와 0xc2 alt result sound/helper를 선택한 뒤 소비 시 지워진다.
- 확정: actor +0x28은 0x4343db에서 attacker-side RNG range/base로 쓰여 +0x62 bit 0x10 critical/alternate 판정을 만들고, 0x4344ab 상태 성공 gate에서도 attacker-side 계수로 참여한다. 상태창/장비/레벨업 운 경로와 분리된 숨은 전투 발동률 계수다.
- 확정: 0x40ef16 result consumer는 +0x10일 때 stream +3 WLK를 읽고 helper runner 0x402321 / child script table [0x442da1+0x150] 경로를 사용한 뒤 +0x10을 지운다.
- 확정: battle_stat_flag_status_semantics_review에서 actor +0x1c/+0x20/+0x22/+0x24/+0x26은 공격력/방어력/기술력/순발력/운으로 승격됐다.
- 확정: critical은 별도 텍스트가 아니라 섬광·전용 사운드·높은 데미지로 인지된다는 수동 관찰이 있고, 이는 0x10의 alternate damage/result sound/helper 경로와 맞다.
- 미확정: critical alternate WLK id 14와 palette flash/fade child script는 확인됐다. 남은 것은 브라우저 러너에서 VM tick을 wall-clock ms로 환산하는 미세 타이밍이다.

## 파이프라인
- a6 target loop
- 0x433a30 target eligibility
- 0x433f0e hit unit select: payload + 0x16 + hitIndex*8
- unit byte0..2 × attacker +0x80/+0x82/+0x84 -> attacker +0x70/+0x72/+0x74
- unit byte3 -> reserved/unused constant 0x00 in current records
- unit byte4 -> 0x433649 -> actor +0x67 target selector; selected target latch 0x0059e347 -> actor +0x61
- unit byte5 -> target +0x6b family -> 0x00546970[family]
- unit byte6 -> hit/avoid class index used against runtime actor +0x36 table
- unit byte7 -> target +0x6c status effect id
- family handler computes result into temporary +0x6e and target +0x6d mode
- 0x4340ae applies target result: damage/recover/display state
- target +0x68 display update spawns target result object script and 0xc2 result sound

## 필드 근거
- `+0x08`: current HP - 0x4353f8 subtracts from it; 0x435295 adds to it
- `+0x0a`: max HP - 0x435295 clamps +0x08 to it
- `+0x0e`: current MP - 0x435356 adds to it
- `+0x10`: max MP - 0x435356 clamps +0x0e to it
- `+0x28`: 숨은 상태/크리티컬 발동률 계수 - 0x4343db에서 attacker-side RNG range/base로 쓰이고 +0x62 bit 0x10 판정을 만든다. 0x4344ab 상태 성공 gate에서도 attacker-side 계수로 읽힌다. 상태창/장비/레벨업 운 경로에는 나타나지 않는다
- `+0x58`: special action family switch - 0x433f0e alternate table 0x546a38 path if nonzero
- `+0x59`: skill id - 0x433f0e payload table index
- `+0x61`: selected target actor index - 0x40f65f copies selected target latch 0x0059e347 into actor +0x61; 0x433c99/0x433dc0/0x435538 consume it as a single-target range
- `+0x62`: battle result/status flags - 0x20/0x08 branch flags, 0x10 alternate-result, 0x40 zero-HP/death, 0x80 unavailable/down state
- `+0x68`: display update flag - state/result functions set it to 1
- `+0x6a`: target last skill id - 0x433f0e copies attacker +0x59 into target +0x6a
- `+0x6b`: hit family id - unit byte5 is copied here and indexes target resistance table
- `+0x6c`: status effect/result id - unit byte7 copied here; 0x4344ab may clear it when the status gate fails
- `+0x6d`: result apply mode - 0x4340ae switch: 0 damage, 1 no apply, 2 recovery
- `+0x6e`: result value - runtime damage number; 0x4353f8/0x435295 consume it
- `unit byte[4]`: target scope id - 0x433649 reads payload +0x16 + hitIndex*8 + 4, 0x433545/0x4335c6 write it to actor +0x67, 0x40fa6d uses bit 0x08 to branch into nested target-selection script
- `unit byte[6]`: hit/avoid class index - 0x4342e8 reads unit[6], then 0x4342ee indexes target actor +0x36+unitByte6. Labels: 0=상단/공중/상승, 1=일반, 2=하단/지면/다운, 3=잡기/밀착 특수
- `+0x70/+0x72/+0x74`: unit-scaled attack components - unit bytes 0..2 multiply attacker +0x80/+0x82/+0x84
- `+0x80/+0x82/+0x84`: skill/context coefficients - source operands for unit byte0..2 scaling

## Family Handler Groups
- `0x004357d0`: 22 families, 0x00, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x30 / default/no-op or shared fallback
- `0x0043414d`: 10 families, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19 / common physical damage family
- `0x00434a4a`: 9 families, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c / character mode/buff gauge family
- `0x004357db`: 8 families, 0x32, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f / small special handler family
- `0x0043487a`: 3 families, 0x20, 0x21, 0x23 / recovery-like family: HP/MP branch by family
- `0x0043485e`: 1 families, 0x01 / simple flag set family
- `0x0043497d`: 1 families, 0x22 / pose/state reset family
- `0x00434cbb`: 1 families, 0x2d / pose cycle family
- `0x00434d8d`: 1 families, 0x2e / random pose/timer family
- `0x00434e29`: 1 families, 0x2f / clear fields +0x2f..+0x31
- `0x00000000`: 1 families, 0x31 / unclassified family
- `0x004357e6`: 1 families, 0x33 / small special handler family
- `0x00435810`: 1 families, 0x34 / small special handler family
- `0x0043583c`: 1 families, 0x35 / small special handler family
- `0x004358ab`: 1 families, 0x36 / small special handler family
- `0x004358d5`: 1 families, 0x37 / small special handler family
- `0x0043590d`: 1 families, 0x38 / small special handler family

## 주요 함수
- `0x00433a30` target eligibility gate: a6가 대상에게 0x433f0e를 호출하기 전에 쓰는 대상 가능 여부 검사. target +0x62 bit 0x80과 attacker +0x58/+0x59를 본다.
- `0x00433f0e` hit unit loader and family dispatcher: skill payload를 찾고 hitIndex(0x0059e2a4)로 8-byte hit unit을 고른다. unit byte0..2를 attacker +0x80/+0x82/+0x84와 곱해 +0x70/+0x72/+0x74에 저장하고, family table 0x00546970으로 분기한다.
- `0x004340ae` target result mode dispatcher: target +0x6d가 0이면 0x4353f8(HP 감소) 후 0x434e84(상태/피격 자세), 2이면 0x435295(HP 회복), 1이면 적용 없이 종료한다.
- `0x0043414d` common physical family coordinator: family 0x10..0x19의 공통 진입점. result value를 초기화하고, branch flag 0x20/0x08, alt-result flag 0x10, status byte +0x6c, damage routine을 순서대로 처리한다.
- `0x00434218` hit/avoid branch flag test: attacker/target 전투 수치와 random(0x427730)을 비교해 target +0x62 bit 0x20 또는 0x08을 세운다. unit byte[6]을 target +0x36+index 명중 보정 테이블에 사용한다. 표시 분기는 full miss / guard-glancing chip result로 승격됐다.
- `0x004343db` alternate result / critical flag gate: 성공 시 attacker +0x62 bit 0x10을 세운다. 0xc2 handler가 이 비트로 normal/alt WLK operand를 고르고, user observation의 critical presentation(텍스트 없음, 섬광/전용음/높은 데미지)과 일치한다.
- `0x004344ab` status success gate: payload status byte target +0x6c가 있으면 attacker/target 수치 및 target status resistance table(+0x39+status)을 비교한다. 실패하면 target +0x6c를 0으로 지운다.
- `0x0043461f` normal damage formula: attacker +0x70, +0x1c, target +0x7a, +0x20, target resistance table(+0x1c+family) 등을 사용해 temporary result +0x6e를 만든다. 최소값 보정 random(1..3)이 있다.
- `0x00434737` alternate/critical damage formula: normal damage와 유사하지만 계산 비율이 다르고, 낮은 결과에서 random(1..5) 보정 후 attacker +0x62 bit 0x10을 끈다. 0x10 result sound/helper 소비와 연결되는 critical/alternate damage formula다.
- `0x00434e84` target state/pose display after damage: target +0x6c 상태 byte와 +0x62 flags를 보고 target +0x2a pose, +0x64 timer, +0x68 display update flag를 설정한다.
- `0x00435295` HP recovery apply: target +0x08 current HP를 +0x0a max HP까지 증가시키고, trace mode에서는 applied value를 +0x6e에 쓴다.
- `0x00435356` MP recovery apply: target +0x0e current MP를 +0x10 max MP까지 증가시키고, trace mode에서는 applied value를 +0x6e에 쓴다.
- `0x004353f8` HP damage apply: target +0x08 current HP에서 result를 빼고, 0 이하가 되면 HP 0, target +0x62 bit 0x40, death/knockout cleanup 0x4354eb를 호출한다.

## 다음 작업
- 0x10 critical path의 WLK id 14 sound role과 palette flash/fade child script는 확정됐다. 남은 작업은 browser runner에서 VM tick 기반 섬광 지속시간을 wall-clock으로 맞추는 것이다.
- browser 전투 엔진 반영은 지금 단계에서 HP/MP apply와 payload family/status/critical presentation 구조를 넣고, +0x28은 숨은 전투 발동률 계수로 표기한다.
