03b4d72ef1c03daf69b196e758c12a3a972c1de264d51074acb0a71a


글이 이해하기 좀 힘들 수도 있음

이 글에서 사용된 스크립트는 파이썬으로 작성함


이 글에서는 엘든 링에서 생명력 스탯에 따른 HP를 계산해볼 것임

현재 생명력 스탯은 47로 가정함






엘든 링과 다크 소울 3에서 스탯 및 표기 대미지를 계산하는 메서드는 getCorrectGraphValue(a,r)임.

getCorrectGraphValue(a,r)는 a와 r이라는 두 개의 정수형 매개변수를 받고 실수값을 리턴함.



a = CalcCorrectGraph의 인덱스


CalcCorrectGraph는 Smithbox로 편집할 수 있는 매개변수 객체(Param) 중 하나인데, Param은 배열만을 요소로 지님.

예를 들어 CalcCorrectGraph[100]은 생명력 스탯에 따른 HP 증가를 다루는 배열로, 아래와 같다.

  {1, 25, 40, 60, 99, 300, 800, 1450, 1900, 2100, 1.5, 1.1, -1.2, -1.2, 1, 0, 0, 0, 0, 0}


여기서 [0~4]는 Threshold Point(스탯 기준점), [5~9]는 Threshold Coefficient(기준계수), [10~14]는 Adjustment Factor(조정계수)라는 이름을 지님.

  -[15~18]은 레벨에 따른 레벨업 요구 룬을 계산할 때만 사용되는 값.


스탯 기준점과 기준계수, 조정계수는 연결되는데, 연결되는 값들은 5만큼 띄어져 있음.

[0]은 [5], +과 연결되고 [1]은 [6], [11]과 연결되는 식.


CalcCorrectGraph[100] 기준으로 스탯 기준점은 생명력 스탯, 기준계수는 해당 스탯 기준점에서의 HP를 의미함.

생명력이 1일 때 HP는 300, 25일 때는 800인 식.

  -조정계수는 뒤에서 다룸.



r = 스탯값

말 그대로 스탯. a가 100(생명력)이라면 r은 현재 생명력 스탯의 값임.

  ex) a = 100, r = 50일 경우 생명력이 50일 때의 HP를 계산함.

현재 생명력은 글 처음에서 말했듯 47.



getCorrectGraphValue(100, 47)

이제 이 메서드가 HP를 구하는 과정을 보자.






s = CalcCorrectGraph[a]

변수 s를 선언하고, CalcCorrectGraph 배열에서 a의 위치에 존재하는 값을 변수 s에 할당하여 초기화함.

a = 100이었고, CalcCorrectGraph[100]은 {1, 25, ... , 0}이었으므로 s = {1, 25, ... , 0}.






S = 0

변수 S를 선언 및 초기화.


S = 0 if r < s[1] else 1 if r >= s[1] and r < s[2] else 2 if r >= s[2] and r < s[3] else 3

e = (r - s[S]) / (s[S + 1] - s[S])

조건에 따라 S에 값을 할당한 후 해당 값을 토대로 e를 선언 및 초기화함.

e는 r이 이전 기준점부터 이후 기준점의 사이 구간에서 위치한 비율을 의미함.


일단 S부터 계산한다.

이렇게 긴 삼항 연산자는 보기 더럽기 때문에 조건문 형식으로 풀었음.


S = 0 if r < s[1] else 1 if r >= s[1] and r < s[2] else 2 if r >= s[2] and r < s[3] else 3

->

if r < s[1]:

        S = 0

    elif r >= s[1] and r < s[2]:

        S = 1

    elif r >= s[2] and r < s[3]:

        S = 2

    else:

        S = 3


즉, 현재 생명력 스탯인 r의 값이 어느 구간 사이에 존재하는지 파악한 후 값을 할당하는 식임.

r = 47이고 47은 s[2]인 40과 s[3]인 60 사이이므로 S = 2.




e = (r - s[S]) / (s[S + 1] - s[S])

r = 47, S = 2를 대입한다.


e = (47 - s[2]) / (s[2 + 1] - s[2])

e = (47 - 40) / (60 - 40)

e = 7 / 20

e = 0.35


따라서 e는 0.35.




l = s[S + 10]

변수 l를 선언하고 값을 할당함.

s[S+10]는 s[10~14]이고 이는 조정계수값. 즉, l에 조정계수값을 할당하는 식이다.


계산 결과 l은 s[12]이며, s[12] = -1.2이므로 l = -1.2.




o = pow(e, l) if l > 0 else 1 - pow(1 - e, abs(l))

실수형 변수 o를 선언하고, 조건에 따라 o에 값을 할당함.

o은 구간 내에서 스탯이 증가할 때 어떤 형태로 증가하는지를 결정한다.


o가 0보다 클 경우 구간 초기에는 스탯당 HP 증가량이 적지만, 구간 후기로 갈수록 스탯당 HP 증가량이 늘어난다. 

o가 0보다 작으면 그 반대. (단 o != 0)


조정계수값 l이 0보다 크면 o는 e^l, 0보다 작으면 1-e^|l|(절댓값 l)으로 계산한다.


l = -1.2, e = 0.35였으므로 1 - (1-0.35)^|-1.2|

o = 1 - 0.65^1.2

o = 1 - 0.5963

o = 0.4037


o는 0.4037이 된다.



return s[S + 5] + o * (s[S + 6] - s[S + 5])

getCorrectGraphValue(a,r)의 리턴값, 즉 실 HP 수치를 계산함.


HP = s[S + 5] + o * (s[S + 6] - s[S + 5])

HP = s[2 + 5] + 0.4037 * (s[2 + 6] - s[2 + 5])

HP = 1450 + 0.4037 * (1900 - 1450)

HP = 1450 + 0.4037 * 450

HP = 1450 + 181.665

HP = 1631.665


HP는 1631.665가 되며, 인게임에서는 소숫점 이하를 올림하므로 1632가 된다.

따라서 생명력 스탯이 47일 때 HP는 1632.



마지막으로, 생명력 스탯에 따른 HP를 그래프로 나타내면 아래와 같다.

x = r, y = getCorrectGraphValue(a,r)


24b0d121e09c28a8699fe8b115ef0469913ef0








정리-

def getcorrectgraphvalue(a, r):

    s = CalcCorrectGraph[a]

    S = 0


    S = 0 if r < s[1] else 1 if r >= s[1] and r < s[2] else 2 if r >= s[2] and r < s[3] else 3


    l = s[S + 10]

    o = pow(e, l) if l > 0 else 1 - pow(1 - e, abs(l))


    return s[S + 5] + o * (s[S + 6] - s[S + 5])


위의 스크립트를 통해 스탯에 따른 스테이터스 값을 구할 수 있다.






글에서는 생명력 스탯에 따른 HP를 구했지만, 이 스크립트는 무기의 표기 대미지나 주문위력보정을 구하는 데에도 쓰인다

표기 대미지를 구하는 방법은 다음 편에서 다룸