이 블로그 검색

2022년 4월 12일 화요일

랑그릿사2 리버싱 - PC판 마법적용 방식

읽다간 뭔가 선행지식이 필요하다 싶으시면,

https://langrisser2.blogspot.com/2019/08/7-2.html 

위 링크로 가셔서 앞부분을 학습하시기 바랍니다. 저도 저기서 많이 배웠습니다.  

뭔가 바이너리가 달라서 오프셋이 서로 일치하지 않는 문제가 있지만, 게임이 통째로 바뀔 정도로 

변혁이 있는건 아니기 때문에 참조하시기 충분합니다. 


1. 마법 적용 

오프셋 0041012c에 마법데미지 계산을 준비하는 함수가 있습니다. 

해당 함수에서는 마법공격력과 마법방어력에 대해, 마법과 아이템의 의한 변수를 미리 계산하여, 최종 마법 방어력을 계산하고, 마법별 공식과 상관이 없는 마법공격 변수를 구합니다. 

처음 만나는 if 함수에서 Resist마법이 걸려있는지 체크합니다. 랑그릿사에서는 마법 플레그가 걸려있는게 1인지 안걸려있는게 1인지 기준이 없습니다.  Resist는 또 1이 걸린거네요. 돌겠습니다. 
머리가 아픕니다. 

 그걸 잘 고려하셔서 해석하시면 되겠습니다. 

1. 레지스트가 걸려있으면, 마법방어력을 50으로 아니면 0으로 합니다. 

2-1. 지휘관일 경우, 마법데미지를 올리는 착용아이템의 효과의 합을 구합니다. 
    이어서, 마법방어력을 올리는 착용아이템의 효과의 합을 구합니다. 
  그리고 지휘관의  마법 방어력과 합합니다. 
(강제로 슬롯을 무시해 착용해도 작동함)

2-2. 지휘관이 아닐 시,  1에서 구한 마법방어력에 클래스별 고정 마법방어력 값을 더해줍니다. 
   방어구를 체크하여, 아뮬렛을 착용했으면, 마법 방어력을 15 더합니다. 

https://strategywiki.org/wiki/Langrisser_II/Spells#Attack_Spells
에서는 마법 방어력 아이템의 경우 x2를 적용 한다고 되어있지만, 그렇지 않습니다. 
저 분이 사용하신 게임과 제가 분석하는 게임이 다른 듯합니다. PC판 랑그릿사2는 
사실 굉장히 애매한 프로그램이라 그러려니 해주셔야 합니다. 

3. 디클레인이 걸려있는지 체크한 후 걸려있으면, 마법방어력을 15 뺍니다. 에러를 방지하기위해 15보다 작을시 미리 15로 값을 변경하는 로직이 있습니다. 

4. 마법방어력이 99보다 큰지 체크하여 크면, 100으로 고정합니다. 

5. 이유는 모르지만 마지막으로 글로벌 유닛타입변수에 해당 유닛의 유닛타입을 저장합니다. 


오프셋 0040ffd3에 마법을 타겟에 적용하는 함수가 있습니다. 

위의 일이 먼저 일어나고, 보너스마법데미지를 0으로 한후 ,
마법을 타겟에 적용하는 함수가 콜 됍니다. 

해당 파트는 들어가면 switch 문으로 현재 사용중인 마법을 적용하여 

해당 마법 코드를 작동합니다.  타겟이 이미 정해졌기 때문인지, 포스힐1 힐1은 같은 함수를 

호출합니다. 

현재사용중인 마법값이 소환마법일 경우는 이미 발키리로 고정되어 있습니다. 

2. 공격마법

고정되는 부분이 있어 먼저 설명합니다. 
 
데미지 계산식에  Lv >> 1 이라는 식으 무조건 들어갑니다. 그렇다보니 
https://strategywiki.org/wiki/Langrisser_II/Spells#Attack_Spells
에서는 이 부분을 MLv라고 부릅니다. 저도 그냥 그렇게 부르겠습니다.   대부분이 
저 곳에서의 값과 같습니다만, 다른 부분들이 꽤 있습니다. 아무래도 포팅하다가 코드를 건드려서 버그가 터진게 아닐까라는 생각이 듭니다. 

그리고 SP(스펠파워라고 부르자)라고, 클래스별 티어+1에 해당하는 값이 있다.  
클래스와 상관없이, 몇번째 전직인지가 중요한 값이다. 

마법데미지는 방무뎀과 마방적용 데미지로 나눠진다. 

방무뎀은 마법추가데미지와 (토네이도, 썬더용)  마법력강화 아이템으로 이루어진다. 

각 마법별로 달라지는 부분은 마방적용 데미지이다. 

완드와 같은 아이템이 제대로 작동하지 않는 느낌을 많이 받는데, 그 이유는 대부분 사용하는 마법이 파이어볼이고, 웬만하면 계산 결과가 damage* (100-마방)이   100보다 작아서 데미지가 0이라 하한값 1로 맞춰지기 때문입니다. 파이어볼만 죽어라 쓰기 때문이죠. 

매직에로우

매직에로우는 SP + MLV*2 이다.  

블라스트       

블라스트는 18 + MLV + SP 

썬더

썬더는 TileAttr이 타일이 수상(0x14)이거나 파괴지형이 수중(6)일 경우 보너스데미지 +1이 있다. 
썬더는  1+ MLv + SP 이다. 

파이어볼

파이어볼은 MLV + SP이다.    (가장 기본적이다. )

메테오

메테오는 6+ MLV + SP이다. 

블리자드, 토네이도, 어스퀘이크

불행하게도 모두 동일한 코드이다. 
(MLV + SP ) x 2 이다. 그냥 파이어볼 x2이다. 

토네이도 특이사항으로 비병에게 방무뎀이 +1 추가된다. 배우기 힘들어서 그렇지, 
유닛중심으로 쓰는 마법중 가장 강력하다. 그래서 버그로 보인다. 

특이 사항으로 어스퀘이크는 비병에게 적용되지 않는다. 

범위가 중요하긴 하겠지만, 마나소모가 2인친구가 가장 강력하고, 올라갈수록 약해지는건
뭔가 문제가 있다고 할 수 있다. 

외국위키와 비교.

아래는 해당 외국위키에서 참조하였다. [https://strategywiki.org/wiki/Langrisser_II/Spells#Attack_Spells]

메테오와 블라스트만  뭔가 명맥이 살아있고, 뭔가 전작(??)과의 연결점이 어딘가로 다사라지고 없다. 
마법 

나머지 마법 데미지 공식

오프셋으로 0040f429에 나머지 계산이 이루어진다. 

먼저 뭔가 값을 하나 찾는다. 해당 값이 0이면서 100-마방이 0이 아닐 때 나머지 코드가 이루어진다. 

마법데미지는 다음과 같다. 

  Bonus_Dmg(tornado,thunder) + SpellDmgItem +   마법별데미지*(100-MDF)%

그리고 이렇게 구한 값을    bound[1,targetHP]  <--- total_dmg
계산을 적용한다.  

결과 값을 볼 때, 지금 내가 가지고 있는 바이너리는 어릴 때 하던 쥬얼로 구매한 2CD물건과 다른것 같다. 완드의 효력을 별로 못 본 것 같은데, 엄청 강력하게 보인다. 


이어 총 얼마만큼의 데미지를 줬는지 누적치를 저장하고, 총 몇 스택에 효과를 주었는지 타겟누적치 값을 올린다. 

특정 플래그가 1이면 즉시 타겟에 HP에 영향을 주고, HP가 0이되면 유닛을 죽이는 회로를 작동 시킵니다. 이 회로에는 죽인 유닛의 살해경험치 값을 누적하고, 누적경험치가 255를 넘어가면 계속해서 255로 고정하는 로직이 포함되어 있습니다. 죽인 숫자 전역변수에 값을 1 더합니다. 

유닛을 파괴하고 소리가 나오고 이런건, 모든 계산이 이루어진 후, 따로 죽인숫자가 1보다 클 때 적용하는 부분이 있을 것으로 보입니다. 

3. 메테오 및 어스퀘이크 (지형붕괴 로직)

2번과 연결되는 부분으로 찾은게 아니라, 마법번호를 사용하는 코드를 ghidra로 찾았습니다. 

오프셋 - 00409cc6 에 위치한 함수에 있습니다. 
오프셋 -00409df2에  있는 어셈부터 보시면 됩니다. 


CMP dword ptr [ 00487e34] , 04 라고 적힌 부분이 있습니다. 
앞에 있는 주소값은, 현재 사용중인 마법의 넘버가 저장되는 장소입니다. (전역변수)

뒤에 있는 0x4는 메테오의 넘버입니다.  

현재 사용중인 마법이 메테오일시, 마법시전 좌표에 지형부수기 로직을 발동합니다. 


메테오 지형뿌수기의 오프셋은 00411cee입니다. 위의 CALL명령은 상대주소값을 사용해서, 
다릅니다만, 다른바이너리를 가지신 분은 저 hex를 검색한다거나 하는 방식으로 쉽게 찾으시지 않을 까생각합니다. 

지형 타입2가 0xff(파괴금지)가 아닐 시, 
좌표 X,Y의    지형1(스프라이트)를   원본 지형2로 
해당 좌표의 지형2를     원본 지형 1번으로 바꿉니다. 



이어서 메테오 함수 바로 아래에  cmp [   ] , 0x8이 있습니다. 
어스퀘이크일 때 작동 합니다. 
 
왜 이렇게 코딩이 되있는지 모르겠지만, 맵전체를 전부 돌면서, 마법범위 내의 지형을 전부 구합니다. 

이 범위내에 자기자신의 위치가 포함되있는지는 모르겠습니다. 

해당 지형 갯수의 1/4 갯수의 횟수만큼,  저 위치중의 한군데씩 파괴합니다. 

매회 같은 장소도 선택될 수 있기 때문에, 실제 파괴되는 것은, 훨씬 적고, 
다시 마법을 사용해도 마찬가지입니다.  횟수에 따라 기대값이 매우 떨어집니다. 

4. 중요한 발견, 

여기서 우리는 랜덤함수를 발견합니다. 이건 매우 중요합니다. 게임에서는 임의성이 중요합니다. 

게임리버싱의 핵심은 자료구조와, 랜덤함수 호출을 쫓는 것입니다. 랜덤함수는, 유저가 조작하지 않는부분에서는 나오지 않기 때문입니다. 

히어로즈3에서는 랜덤함수를 행운 계산식을 어디서 찾아서 바로, 나머지 사용되는 곳을 찾는 방식으로 리버싱을 하고 있습니다. 하지만, 랑그릿사는 이미 자료구조 파악이 많이 되서 이게 어떤 큰 변화를 줄지는 모르겠습니다. 

사용되는 숫자를 검색하니, 바로 랜덤함수라고 구글이 알려주는 군요. 처음 발견했을 때는, 숫자들이 길어서 메모리 값인줄 알고 놓쳤습니다. 

5. 힐 마법 

즉발 마법이 아닌 버프마법들은 코드가 지저분해서, 플레그 설정하는게 너무 어렵습니다. 나중으로 미룹니다. 텔레포트는 이제 발견해서 아직 못봤습니다. 

힐1과 힐2는 비슷합니다. 다른 부분은 하나입니다. 

힐1은 먼저 HP를 구합니다. 10-HP로 피해량을 구합니다. 

피해량이 0이면 함수를 리턴합니다. 

피해량이 크면 3으로 바운드 합니다. (힐2는 없음)

누적효과 값에 해당 값을 더합니다. 누적 타겟값을 1 증가시킵니다. 

실행 플레그가 있으면, 즉시 HP를 변경합니다. 

변경 후 공격마법에서 유닛을 죽였을 때, 사용한 전역변수에 1을 더합니다. 회복량과 관계 없이
회복시 마다 경험치가 1씩 늘어나는 것으로 보입니다.  


포스힐도 동일합니다. 타겟을 다른데서 정하기 때문입니다. 


감사합니다. 



6. 버프마법 디버프 마법

나중에...

댓글 없음:

댓글 쓰기

가장 많이 본 글