글이 이해하기 좀 힘들 수도 있음
이 글에서 사용된 스크립트는 파이썬으로 작성함
이 글에서는 엘든 링에서 생명력 스탯에 따른 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)
정리-
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를 구했지만, 이 스크립트는 무기의 표기 대미지나 주문위력보정을 구하는 데에도 쓰인다
표기 대미지를 구하는 방법은 다음 편에서 다룸
완장감이군 - dc App
예?
그래서 너 때리면 스텟분배 해준단거지? ㄱㄷ - dc App
CalcCorrectGraph 배열이 하드코딩 돼 있는 거고 엘든링에서 사용되는 계수 계산에 왠만하면 다 쓰이는 배열인건가? 인덱스 따라서 어떤 계수 계산에 쓰일지 결정되는거고?
정확함