{"version":1,"kind":"hwanse-battle-player-actor-stat-layout-review","source":{"script":"tools/build_battle_player_actor_stat_layout_review.py","exe":"Hwanse2.exe","uiGridMappings":"out/ui_cns_grid_mappings.json"},"status":"player-actor-exp-luck-grounded","tables":{"playerRowTableVa":4552528,"playerRowTableVaHex":"0x00457750","playerRowStride":216,"playerRowStrideHex":"0xd8","battleCopySize":72,"battleCopySizeHex":"0x48","equipmentPointerTableVa":4764124,"equipmentPointerTableVaHex":"0x0048b1dc"},"summary":["플레이어 전투 actor 초기화는 파티 slot -> character index -> 0x00457750 + index*0xd8 row를 찾아 첫 0x48바이트를 actor로 복사한다.","player row/actor +0x14는 현재 EXP다. 승리 보상 루프가 0x42157b 산출값을 살아있는 player actor +0x14에 더한다.","row +0x48/+0x49는 현재 무기/방어구 내부 id이고, 장비 포인터 테이블 0x0048b1dc[id]를 통해 장비 상세 레코드를 읽는다.","장비 상세 레코드 +0x10..+0x14는 공격/방어/기술/순발/운 보정이며, player base +0xbe/+0xc2/+0xc4/+0xc6/+0xc8에 더해 actor +0x1c/+0x20/+0x22/+0x24/+0x26에 기록된다.","레벨업 루틴은 +0xc8과 +0x26에 rand(100) + level/2 + 1을 써서 운을 재설정한다. 따라서 플레이어 actor +0x26은 운으로 확정할 수 있다.","actor +0x28은 플레이어도 100/100/40처럼 별도 값이며 상태창 표시/장비 운 보정/레벨업 운 공식 대상이 아니다. 0x4343db의 critical/alternate 판정과 0x4344ab의 상태 성공 gate에서 attacker-side random range/base로 쓰이는 숨은 전투 발동률 계수다.","몬스터 actor +0x26도 같은 공식 축으로 쓰지만, 몬스터에는 플레이어 장비/레벨업 루틴이 없으므로 UI 이름은 전투 공식 축으로 보존한다."],"playerRows":[{"slot":0,"name":"아타호","nameEn":"Ataho","rowVa":4552528,"rowVaHex":"0x00457750","battleCopyHex":"00 00 00 00 01 00 01 00 1e 00 1e 00 1e 00 12 00 12 00 12 00 00 00 64 00 0a 00 00 00 16 00 32 00 11 00 16 00 14 00 32 00 64 00 01 00 64 64 64 78 64 64 64 96 7d 64 4b 64 7d 64 7d 7d 7d 7d 7d 00 00 00 00 00 00 00 00 00","level":1,"hp":30,"maxHp":30,"baseHp":30,"mp":18,"maxMp":18,"baseMp":18,"exp":0,"weaponId":1,"weaponName":"맨주먹","armorId":7,"armorName":"인민복","weaponStatSummary":"능력치 증가 없음","armorStatSummary":"방어력 +10 순발력 +5","baseAttack":22,"weaponAttack":0,"armorAttack":0,"actorAttack":22,"calcAttack":22,"baseDefense":7,"weaponDefense":0,"armorDefense":10,"actorDefense":17,"calcDefense":17,"baseTechnique":22,"weaponTechnique":0,"armorTechnique":0,"actorTechnique":22,"calcTechnique":22,"baseAgility":15,"weaponAgility":0,"armorAgility":5,"actorAgility":20,"calcAgility":20,"baseLuck":50,"weaponLuck":0,"armorLuck":0,"actorLuck":50,"calcLuck":50,"actorCoeff28":100,"matchesEquipmentFormula":true},{"slot":1,"name":"린샹","nameEn":"Rinshan","rowVa":4552744,"rowVaHex":"0x00457828","battleCopyHex":"00 00 00 00 01 01 01 00 1a 00 1a 00 1a 00 18 00 18 00 18 00 00 00 64 00 00 00 00 00 18 00 3c 00 12 00 16 00 12 00 4d 00 64 00 01 00 64 64 64 64 50 78 78 96 af 64 4b 64 7d 64 64 50 64 7d 7d 00 00 00 00 00 00 00 00 00","level":1,"hp":26,"maxHp":26,"baseHp":26,"mp":24,"maxMp":24,"baseMp":24,"exp":0,"weaponId":13,"weaponName":"고양이 발톱","armorId":19,"armorName":"드레스","weaponStatSummary":"공격력 +10","armorStatSummary":"방어력 +10","baseAttack":14,"weaponAttack":10,"armorAttack":0,"actorAttack":24,"calcAttack":24,"baseDefense":8,"weaponDefense":0,"armorDefense":10,"actorDefense":18,"calcDefense":18,"baseTechnique":22,"weaponTechnique":0,"armorTechnique":0,"actorTechnique":22,"calcTechnique":22,"baseAgility":18,"weaponAgility":0,"armorAgility":0,"actorAgility":18,"calcAgility":18,"baseLuck":77,"weaponLuck":0,"armorLuck":0,"actorLuck":77,"calcLuck":77,"actorCoeff28":100,"matchesEquipmentFormula":true},{"slot":2,"name":"스마슈","nameEn":"Smash","rowVa":4552960,"rowVaHex":"0x00457900","battleCopyHex":"00 00 00 00 01 02 01 00 20 00 20 00 20 00 10 00 10 00 10 00 00 00 64 00 00 00 00 00 1a 00 28 00 14 00 18 00 14 00 0a 00 28 00 01 00 64 64 64 78 64 50 64 96 96 64 4b 64 7d 64 96 64 7d 50 50 00 00 00 00 00 00 00 00 00","level":1,"hp":32,"maxHp":32,"baseHp":32,"mp":16,"maxMp":16,"baseMp":16,"exp":0,"weaponId":25,"weaponName":"닌자도","armorId":31,"armorName":"스마슈타이츠","weaponStatSummary":"공격력 +20 기술력 +15","armorStatSummary":"방어력 +10 순발력 +10","baseAttack":6,"weaponAttack":20,"armorAttack":0,"actorAttack":26,"calcAttack":26,"baseDefense":10,"weaponDefense":0,"armorDefense":10,"actorDefense":20,"calcDefense":20,"baseTechnique":9,"weaponTechnique":15,"armorTechnique":0,"actorTechnique":24,"calcTechnique":24,"baseAgility":10,"weaponAgility":0,"armorAgility":10,"actorAgility":20,"calcAgility":20,"baseLuck":10,"weaponLuck":0,"armorLuck":0,"actorLuck":10,"calcLuck":10,"actorCoeff28":40,"matchesEquipmentFormula":true}],"layoutRows":[{"actorOffset":"+0x14","baseOffset":"+0x14","equipmentOffset":"","role":"현재 경험치 EXP","status":"확정","evidence":"0x40e085..0x40e095가 0x42157b에서 계산한 경험치를 live player actor +0x14에 더한다. player row의 첫 0x48바이트가 actor로 복사되므로 row +0x14와 같은 슬롯이다."},{"actorOffset":"+0x1c","baseOffset":"+0xbe","equipmentOffset":"+0x10","role":"공격력","status":"확정","evidence":"0x422b95가 base +0xbe + weapon/armor +0x10을 actor +0x1c에 기록한다."},{"actorOffset":"+0x20","baseOffset":"+0xc2","equipmentOffset":"+0x11","role":"방어력","status":"확정","evidence":"0x422b95가 base +0xc2 + weapon/armor +0x11을 actor +0x20에 기록한다."},{"actorOffset":"+0x22","baseOffset":"+0xc4","equipmentOffset":"+0x12","role":"기술력","status":"확정","evidence":"0x422b95가 base +0xc4 + weapon/armor +0x12를 actor +0x22에 기록한다."},{"actorOffset":"+0x24","baseOffset":"+0xc6","equipmentOffset":"+0x13","role":"순발력","status":"확정","evidence":"0x422b95가 base +0xc6 + weapon/armor +0x13을 actor +0x24에 기록한다."},{"actorOffset":"+0x26","baseOffset":"+0xc8","equipmentOffset":"+0x14","role":"운","status":"확정","evidence":"0x422b95 장비 재계산과 0x4219a6 레벨업 random luck 공식이 같은 offset을 사용한다."},{"actorOffset":"+0x28","baseOffset":"","equipmentOffset":"","role":"숨은 상태/크리티컬 발동률 계수","status":"역할 확정 / UI 비표시","evidence":"상태창 표시 루틴, 장비 운 보정, 레벨업 운 공식의 대상이 아니다. 상태창 쪽은 base +0xbe/+0xc2/+0xc4/+0xc6/+0xc8 및 장비 +0x10..+0x14를 visible stat으로 쓰지만 +0x28은 표시하지 않는다. 0x4343db에서 attacker +0x28이 RNG range/base로 쓰이고, 통과 시 attacker +0x62 bit 0x10을 세운다. 0x4344ab 상태 성공 gate에서도 attacker-side 계수로 읽힌다."}],"disassemblyEvidence":[{"label":"player actor initialization path","vaHex":"0x0040be38","keyLines":["  40be6f:\t0f 85 40 00 00 00    \tjne    0x40beb5","  40be75:\t6a 48                \tpush   0x48","  40be77:\t8b 45 f8             \tmov    eax,DWORD PTR [ebp-0x8]","  40be7a:\t33 c9                \txor    ecx,ecx","  40be7c:\t8a 88 e9 76 45 00    \tmov    cl,BYTE PTR [eax+0x4576e9]","  40be82:\t8d 04 49             \tlea    eax,[ecx+ecx*2]","  40be88:\t8d 04 c0             \tlea    eax,[eax+eax*8]","  40be8b:\t05 50 77 45 00       \tadd    eax,0x457750","  40be90:\t50                   \tpush   eax","  40be9a:\t83 c4 0c             \tadd    esp,0xc","  40be9d:\t6a 58                \tpush   0x58","  40be9f:\t6a 00                \tpush   0x0","  40bea1:\t8b 45 fc             \tmov    eax,DWORD PTR [ebp-0x4]","  40bea4:\t83 c0 48             \tadd    eax,0x48","  40bea7:\t50                   \tpush   eax"]},{"label":"save/load row ranges","vaHex":"0x00423319","keyLines":[]},{"label":"victory EXP fanout","vaHex":"0x0040dfb8","keyLines":["  40e013:\tf6 c1 40             \ttest   cl,0x40","  40e04a:\tf6 c1 80             \ttest   cl,0x80","  40e06e:\te8 08 35 01 00       \tcall   0x42157b","  40e085:\t66 8b 51 14          \tmov    dx,WORD PTR [ecx+0x14]","  40e095:\t66 89 41 14          \tmov    WORD PTR [ecx+0x14],ax","  40e0a9:\te8 88 76 02 00       \tcall   0x435736"]},{"label":"EXP reward formula","vaHex":"0x0042157b","keyLines":["  421589:\t66 8b 48 06          \tmov    cx,WORD PTR [eax+0x6]","  421592:\t66 8b 50 06          \tmov    dx,WORD PTR [eax+0x6]","  4215a3:\t66 8b 48 06          \tmov    cx,WORD PTR [eax+0x6]","  4215ac:\t66 8b 50 06          \tmov    dx,WORD PTR [eax+0x6]","  4215c0:\t66 8b 48 06          \tmov    cx,WORD PTR [eax+0x6]","  4215c9:\t66 8b 50 06          \tmov    dx,WORD PTR [eax+0x6]","  4215f2:\t66 8b 48 06          \tmov    cx,WORD PTR [eax+0x6]","  4215fb:\t66 8b 50 06          \tmov    dx,WORD PTR [eax+0x6]","  42160c:\t66 8b 48 14          \tmov    cx,WORD PTR [eax+0x14]","  421615:\t66 8b 50 14          \tmov    dx,WORD PTR [eax+0x14]","  42163d:\t66 8b 48 14          \tmov    cx,WORD PTR [eax+0x14]","  421666:\t66 8b 48 14          \tmov    cx,WORD PTR [eax+0x14]","  4216a9:\t8a 8c c0 98 77 45 00 \tmov    cl,BYTE PTR [eax+eax*8+0x457798]","  4216d5:\tc1 e8 01             \tshr    eax,0x1","  421710:\t8a 8c c0 99 77 45 00 \tmov    cl,BYTE PTR [eax+eax*8+0x457799]","  42173c:\tc1 e8 01             \tshr    eax,0x1"]},{"label":"equipment stat recalculation","vaHex":"0x00422b95","keyLines":["  422ba1:\t66 8b 80 be 00 00 00 \tmov    ax,WORD PTR [eax+0xbe]","  422bb1:\t8a 48 48             \tmov    cl,BYTE PTR [eax+0x48]","  422bb4:\t8b 04 cd dc b1 48 00 \tmov    eax,DWORD PTR [ecx*8+0x48b1dc]","  422bbb:\t0f be 40 10          \tmovsx  eax,BYTE PTR [eax+0x10]","  422bce:\t8a 48 49             \tmov    cl,BYTE PTR [eax+0x49]","  422bd1:\t8b 04 cd dc b1 48 00 \tmov    eax,DWORD PTR [ecx*8+0x48b1dc]","  422bd8:\t0f be 40 10          \tmovsx  eax,BYTE PTR [eax+0x10]","  422bf7:\t66 89 41 1c          \tmov    WORD PTR [ecx+0x1c],ax","  422bfe:\t66 8b 80 c2 00 00 00 \tmov    ax,WORD PTR [eax+0xc2]","  422c0e:\t8a 48 48             \tmov    cl,BYTE PTR [eax+0x48]","  422c11:\t8b 04 cd dc b1 48 00 \tmov    eax,DWORD PTR [ecx*8+0x48b1dc]","  422c18:\t0f be 40 11          \tmovsx  eax,BYTE PTR [eax+0x11]","  422c2b:\t8a 48 49             \tmov    cl,BYTE PTR [eax+0x49]","  422c2e:\t8b 04 cd dc b1 48 00 \tmov    eax,DWORD PTR [ecx*8+0x48b1dc]","  422c35:\t0f be 40 11          \tmovsx  eax,BYTE PTR [eax+0x11]","  422c54:\t66 89 41 20          \tmov    WORD PTR [ecx+0x20],ax","  422c5b:\t66 8b 80 c4 00 00 00 \tmov    ax,WORD PTR [eax+0xc4]","  422c6b:\t8a 48 48             \tmov    cl,BYTE PTR [eax+0x48]","  422c6e:\t8b 04 cd dc b1 48 00 \tmov    eax,DWORD PTR [ecx*8+0x48b1dc]","  422c75:\t0f be 40 12          \tmovsx  eax,BYTE PTR [eax+0x12]","  422c88:\t8a 48 49             \tmov    cl,BYTE PTR [eax+0x49]","  422c8b:\t8b 04 cd dc b1 48 00 \tmov    eax,DWORD PTR [ecx*8+0x48b1dc]","  422c92:\t0f be 40 12          \tmovsx  eax,BYTE PTR [eax+0x12]","  422cb1:\t66 89 41 22          \tmov    WORD PTR [ecx+0x22],ax","  422cb8:\t66 8b 80 c6 00 00 00 \tmov    ax,WORD PTR [eax+0xc6]","  422cc8:\t8a 48 48             \tmov    cl,BYTE PTR [eax+0x48]","  422ccb:\t8b 04 cd dc b1 48 00 \tmov    eax,DWORD PTR [ecx*8+0x48b1dc]","  422cd2:\t0f be 40 13          \tmovsx  eax,BYTE PTR [eax+0x13]","  422ce5:\t8a 48 49             \tmov    cl,BYTE PTR [eax+0x49]","  422ce8:\t8b 04 cd dc b1 48 00 \tmov    eax,DWORD PTR [ecx*8+0x48b1dc]","  422cef:\t0f be 40 13          \tmovsx  eax,BYTE PTR [eax+0x13]","  422d0e:\t66 89 41 24          \tmov    WORD PTR [ecx+0x24],ax","  422d15:\t66 8b 80 c8 00 00 00 \tmov    ax,WORD PTR [eax+0xc8]","  422d25:\t8a 48 48             \tmov    cl,BYTE PTR [eax+0x48]","  422d28:\t8b 04 cd dc b1 48 00 \tmov    eax,DWORD PTR [ecx*8+0x48b1dc]","  422d2f:\t0f be 40 14          \tmovsx  eax,BYTE PTR [eax+0x14]","  422d42:\t8a 48 49             \tmov    cl,BYTE PTR [eax+0x49]","  422d45:\t8b 04 cd dc b1 48 00 \tmov    eax,DWORD PTR [ecx*8+0x48b1dc]","  422d4c:\t0f be 40 14          \tmovsx  eax,BYTE PTR [eax+0x14]","  422d6b:\t66 89 41 26          \tmov    WORD PTR [ecx+0x26],ax"]},{"label":"level-up luck formula","vaHex":"0x00421800","keyLines":["  421836:\te8 f5 5e 00 00       \tcall   0x427730","  421892:\te8 99 5e 00 00       \tcall   0x427730","  4218da:\te8 51 5e 00 00       \tcall   0x427730","  421922:\te8 09 5e 00 00       \tcall   0x427730","  42196a:\te8 c1 5d 00 00       \tcall   0x427730","  4219a6:\t6a 64                \tpush   0x64","  4219a8:\te8 83 5d 00 00       \tcall   0x427730","  4219b8:\t66 8b 51 06          \tmov    dx,WORD PTR [ecx+0x6]","  4219bc:\tc1 fa 01             \tsar    edx,0x1","  4219cd:\t66 89 81 c8 00 00 00 \tmov    WORD PTR [ecx+0xc8],ax","  421abe:\t66 89 41 26          \tmov    WORD PTR [ecx+0x26],ax","  421ac6:\te8 ca 10 00 00       \tcall   0x422b95"]},{"label":"status window equipment comparison","vaHex":"0x0042005b","keyLines":["  420106:\t66 8b 80 be 00 00 00 \tmov    ax,WORD PTR [eax+0xbe]","  420114:\t8b 04 c5 dc b1 48 00 \tmov    eax,DWORD PTR [eax*8+0x48b1dc]","  42011b:\t0f be 40 10          \tmovsx  eax,BYTE PTR [eax+0x10]","  42012c:\t8b 04 c5 dc b1 48 00 \tmov    eax,DWORD PTR [eax*8+0x48b1dc]","  420133:\t0f be 40 10          \tmovsx  eax,BYTE PTR [eax+0x10]","  420184:\t66 8b 80 c2 00 00 00 \tmov    ax,WORD PTR [eax+0xc2]","  420192:\t8b 04 c5 dc b1 48 00 \tmov    eax,DWORD PTR [eax*8+0x48b1dc]","  420199:\t0f be 40 11          \tmovsx  eax,BYTE PTR [eax+0x11]","  4201aa:\t8b 04 c5 dc b1 48 00 \tmov    eax,DWORD PTR [eax*8+0x48b1dc]","  4201b1:\t0f be 40 11          \tmovsx  eax,BYTE PTR [eax+0x11]","  420202:\t66 8b 80 c4 00 00 00 \tmov    ax,WORD PTR [eax+0xc4]","  420210:\t8b 04 c5 dc b1 48 00 \tmov    eax,DWORD PTR [eax*8+0x48b1dc]","  420217:\t0f be 40 12          \tmovsx  eax,BYTE PTR [eax+0x12]","  420228:\t8b 04 c5 dc b1 48 00 \tmov    eax,DWORD PTR [eax*8+0x48b1dc]","  42022f:\t0f be 40 12          \tmovsx  eax,BYTE PTR [eax+0x12]","  420280:\t66 8b 80 c6 00 00 00 \tmov    ax,WORD PTR [eax+0xc6]","  42028e:\t8b 04 c5 dc b1 48 00 \tmov    eax,DWORD PTR [eax*8+0x48b1dc]","  420295:\t0f be 40 13          \tmovsx  eax,BYTE PTR [eax+0x13]","  4202a6:\t8b 04 c5 dc b1 48 00 \tmov    eax,DWORD PTR [eax*8+0x48b1dc]","  4202ad:\t0f be 40 13          \tmovsx  eax,BYTE PTR [eax+0x13]","  4202fe:\t66 8b 80 c8 00 00 00 \tmov    ax,WORD PTR [eax+0xc8]","  42030c:\t8b 04 c5 dc b1 48 00 \tmov    eax,DWORD PTR [eax*8+0x48b1dc]","  420313:\t0f be 40 14          \tmovsx  eax,BYTE PTR [eax+0x14]","  420324:\t8b 04 c5 dc b1 48 00 \tmov    eax,DWORD PTR [eax*8+0x48b1dc]","  42032b:\t0f be 40 14          \tmovsx  eax,BYTE PTR [eax+0x14]"]}],"openQuestions":[]}