ad

Oculus Blog

질(Zeal) 공격속도 계산 과정의 메커니즘(Mechanism) (쉽게)

조회 수 2,922 추천 수 0
위에 올린 글이 diablo.exe를 분해하여 십육진수를 다루는 글이라 너무 어려운 것 같아

조금 쉽게 풀어보고자 합니다.

아마존페이즈 블레이드에 만든 열정(Passion) 룬워드질(Zeal)을 썼을 때 동작은 각각 어떤 이유로, 어떤 동작에 의해 나오게 되는건지 1프레임(0.04초) 단위로 분석하면서 질 공격속도 계산 과정의 메커니즘을 알아보고자 합니다.

-1프레임 : 몬스터에게 접근합니다. 하지만 아직 때리지 않았습니다.

0프레임 : 몬스터의 머리에 대고 질 스킬을 사용합니다.

이 때, 컴퓨터는 "아마존이 공격을 시작한다"라고 인식하고 AMA11HS.cof라는 애니메이션 관련 파일을 불러옵니다.

AMA11HS는 AM(아마존)A1(공격1)1HS(한손 휘두르는 무기)라는 뜻으로

페이즈 블레이드를 들고 공격을 했을 때 어떤 동작을 내보낼 지에 대한 정보가 담겨있습니다.

Cof Name AMA11HS
Number of Frame per direction 0x10 (16)
AnimationSpeed = 0x100 (256)
FrameData00=0
FrameData01=0
FrameData02=0
FrameData03=0
FrameData04=0
FrameData05=0
FrameData06=0
FrameData07=0
FrameData08=0
FrameData09=0
FrameData0A=1
FrameData0B=0
FrameData0C=0
FrameData0D=0
FrameData0E=0
FrameData0F=0
FrameData10=0

되게 어려워보입니다! 하지만 하나하나 분석해드릴 것이므로 걱정하지 않으셔도 됩니다.

Number of Frame per direction 0x10 (16) 이라고 써진 것은, 아마존이 한손무기를 들고 때리는 동작은 모두 16장의 그림으로 구성되어있다는 뜻입니다.

질(Zeal) 공격속도 계산 과정의 메커니즘(Mechanism) (쉽게) - 1질(Zeal) 공격속도 계산 과정의 메커니즘(Mechanism) (쉽게) - 2질(Zeal) 공격속도 계산 과정의 메커니즘(Mechanism) (쉽게) - 3질(Zeal) 공격속도 계산 과정의 메커니즘(Mechanism) (쉽게) - 4질(Zeal) 공격속도 계산 과정의 메커니즘(Mechanism) (쉽게) - 5질(Zeal) 공격속도 계산 과정의 메커니즘(Mechanism) (쉽게) - 6

이런 식으로 무기를 휘두르는 동작이 16장으로 나뉘어지는 것이죠.
(좋은 그림을 구하지 못해 컴퓨터 구석에 처박혀있는 그림을 올렸습니다...)

AnimationSpeed = 0x100 (256)는 디아블로가 1/256프레임(0.04초의 256분의 1) 단위로 계산을 함을 말하는 것입니다. 디아블로는 25프레임 게임(1초에 25장의 연속동작이 지나감)입니다만 컴퓨터는 1프레임(0.04초)을 256으로 나누어 계산을 하고 있다는 뜻이죠.

FrameData는 각 동작을 나타냅니다. 무기를 휘두르는 16장의 동작에 번호가 00부터 0F(십진수로는 15입니다)까지 붙어있는 것이죠.

그리고 FrameData0A의 값이 1이라고 되어있는데, 이것은 "10번째 동작에서 적에게 데미지가 들어가게 된다"는 의미입니다.

FrameData10(17번째 동작)도 데이터에는 들어있지만, 디아블로는 맨 마지막 동작을 화면에 보여주지 않습니다. 그냥 형식적으로 있는 동작이죠.


Diablo.exe는 "AMA11HS 상태(아마존이 한손무기를 들고 공격을 할 때)에서 질을 쓸 때에는 02번 동작부터 시작한다"라고 프로그래밍 되어있습니다. A라는 메모리에 십육진수로 200이라는 숫자가 저장됩니다. 그래서 00번과 01번 동작은 생략합니다.

그리고 D2common.10376이라는 파일을 불러옵니다. 이 파일은 "지금은 무슨 동작을 보여주어야 할까?"에 대한 계산을 하는 파일입니다.

애니메이션 가속도라는 값을 계산해야 합니다.

애니메이션 가속도 = (100 - 무기 기본공속 + 유효공속)/100

페이즈 블레이드의 무기 기본공속은 [-30]

열정 룬워드에 붙어있는 '+25% 공격 속도 증가'를 유효공속으로 바꾸면 20

따라서 애니메이션 가속도는 (100+30+20)/100=1.5입니다.

1프레임마다 1.5장의 동작이 지나가는 것을 뜻하죠. 이걸 컴퓨터가 이해할 수 있게 256을 곱하고 십육진수로 바꾸면 180이 됩니다. 이걸 B라는 메모리에 저장합니다.

그리고 D2common.10349라는 파일을 불러옵니다. 이 파일은 "이 연속동작이 언제 끝날 것인가"에 대한 정보를 담고 있습니다.

디아블로는 보이는 것보다 256배 정밀한 값을 다룬다고 했죠? FramesPerDirection이라는 값에 256을 곱하면 16*256 => (십육진수로 바꿈) => 10*100 = 1000 입니다. 이걸 C라는 메모리에 저장합니다.

이 모든게 결정되면 D2client.dll이라는 파일은 "화면에 02번 동작을 띄워라"라고 명령을 내립니다.

A, B, C는 모두 십육진수로 나타낼 것입니다. 십육진수 계산에 유의하세요.

1프레임

AC를 비교합니다.

A는 200, C는 1000으로

C가 아직 크기 때문에 애니메이션이 끝나지 않습니다.

D2common.17373을 불러와 "이번 프레임엔 몇 번 동작을 내보낼 것인가"를 정합니다.

A에 애니메이션 가속도인 B를 더하면

200+180=380

380이 됩니다. 이 값을 새롭게 A라고 이름붙입니다.

컴퓨터는 1프레임을 256으로 쪼개 계산할 지 몰라도 내보낼 땐 1프레임 단위로 내보내야 하니

380이란 값에서 256의 자리인 3 만 빼냅니다. 그리고 D2client.dll이 "화면에 03번 동작을 띄워라"라고 명령을 내립니다.

즉, 1프레임에서는 03번 동작을 보여준다는 것이죠.

2프레임

AC를 비교합니다.

A는 380, C는 1000으로

C가 아직 크기 때문에 애니메이션이 끝나지 않습니다.

AB를 더하면

380+180=500

500이 됩니다. 이 값을 새롭게 A라고 합니다.

2프레임에서는 05번 동작을 보여주겠네요.

이와 비슷한 계산을 반복합시다.

3프레임 : A=680, 06번 동작 보여줌
4프레임 : A=800, 08번 동작 보여줌
5프레임 : A=980, 09번 동작 보여줌
6프레임 : A=B00, 11번 동작 보여줌

그런데 10번째 동작인 FrameData0A의 값이 다른것과 다르게 1인 것을 알 수 있습니다. 이 때 적에게 데미지가 들어가게 되는 것이죠.

따라서 6프레임에서 11번 동작을 보여주는 동시에 적에게 데미지가 들어갑니다. 그리고 롤백(Rollback)이라는 게 일어납니다. 롤백에 대한 것은 '롤백(Rollback)에 대한 이해'(링크) 글을 참고하세요.

롤백은 "동작을 중간부분으로 되돌림"을 뜻합니다. 질(Zeal) 스킬은 예외로 처음으로 돌아갑니다. 따라서 롤백에 의해 A값이 0이 됩니다.

7프레임

AC를 비교합니다.

A는 0, C는 1000으로

C가 아직 크기 때문에 애니메이션이 끝나지 않습니다.

A에 애니메이션 가속도인 B를 더하면

0+180=180

180이 됩니다. 이 값을 새롭게 A라고 이름붙입니다.

7프레임에서는 01번 동작을 보여줍니다.

8프레임 : A=300, 03번 동작 보여줌
9프레임 : A=480, 04번 동작 보여줌
10프레임 : A=600, 06번 동작 보여줌
11프레임 : A=780, 07번 동작 보여줌
12프레임 : A=900, 09번 동작 보여줌
13프레임 : A=A80, 10번 동작 보여줌 (타격 일어남)
14프레임 : A=C00, 12번 동작 보여줌
15프레임 : A=D80, 13번 동작 보여줌
16프레임 : A=F00, 15번 동작 보여줌
17프레임 : A=1080, 동작없음

17프레임에 아무 동작도 일어나지 않는 것은, 디아블로가 "마지막 동작은 보여주지 않음"이라고 설정되어있기 때문입니다. 질 스킬이 끝난 후의 다음 예비동작을 준비하기 위한 것이죠.

이런 계산을 통해 연속적인 동작 중 어느 것이 언제 나올지를 정하게 되는 것입니다.

위 예제에서는 맨몸인 아마존이 열정 룬워드만 든 상태로 가정을 하였기 때문에 질 스킬레벨이 1이고, 2연타만 가능한 상태이기 때문에 17프레임으로 끝났습니다.

만약 5연타라면 6프레임, 13프레임, 20프레임, 27프레임, 34프레임에 타격이 일어나고 38프레임에 애니메이션이 끝날 것입니다.

A, B, C라고 표현된 것들은 모두 독자의 이해를 돕기 위해 쉽게 바꾼 것으로

실제 프로그램에서는 PtUnit[+44], PtUnit[+4C], PtUnit[+48]이라는 포인터(Pointer)로써 취급됩니다.

이런 지루한 내용의 글이 이해가 잘 되셨을 지 모르겠네요. 이만 마치겠습니다.

Oculus Blog

번호 제목 글쓴이 날짜 조회
공지 Oculus 2009.12.15 7.4k
공지 Oculus 2009.12.18 7.3k
공지 Oculus 2009.12.19 3.7k
공지 Oculus 2009.12.20 4.8k
공지 Oculus 2009.12.21 5.7k
공지 뮤리아 2020.10.16 340.1k
76 Oculus 2010.05.16 5.9k
75 Oculus 2010.02.14 153.6k
74 Oculus 2010.01.27 7.2k
73 Oculus 2010.01.11 18.4k
72 Oculus 2010.01.10 5.7k
71 Oculus 2010.01.10 3.6k
70 Oculus 2010.01.10 3.4k
69 Oculus 2010.01.07 3.8k
68 Oculus 2010.01.07 3.3k
67 Oculus 2010.01.07 2.8k
> Oculus 2010.01.07 2.9k
65 Oculus 2010.01.07 2.2k
64 Oculus 2010.01.07 2.7k
63 Oculus 2010.01.07 2.7k
62 Oculus 2009.12.26 3.8k
61 Oculus 2009.12.26 3.6k
60 Oculus 2009.12.26 4.2k
59 Oculus 2009.12.26 2.1k
58 Oculus 2009.12.26 4.9k
57 Oculus 2009.12.26 2.9k