해보고 싶은 거 다 해 보는 블로그

오토핫키 매크로 구상 시의 팁 본문

매크로/게임을 위한 매크로

오토핫키 매크로 구상 시의 팁

넌출월귤아속 2020. 4. 25. 01:41

오토핫키를 접한 지 얼마 안 된 분들은 대개 스크립트를 작성할 때 필요 이상으로 복잡하거나 단순하게 생각하는 경우가 있습니다. 저는 이렇게 되는 이유가 흔히 고난도의 기술을 요하는 것으로 알고 있는 프로그래밍을 내가 하고 있다는 느낌 때문에 비롯되는 것이 아닌가 생각합니다. 그래서 이 오토핫키라는 녀석을 과대평가하거나 내 스크립트 능력을 과소평가 함으로써 생기는 일이라는 것입니다. 

오토핫키는 일랜시아 매크로를 위해서 만들어진 스크립트 언어가 아닙니다. Imagesearch를 이용해서 몬스터의 좌표를 알아냈으면 그걸 클릭하게 만들어야 하고, 클릭하게 했으면 몬스터가 죽었다는 것을 인식시킬 방법을 생각해내거나 내 캐릭터가 얼마나 지나면 확실히 몬스터를 잡는지 알아내서 그만큼 스크립트가 대기하도록 해야 합니다. 아이템을 줍도록 하고 싶다면 다른 아이템과 겹쳐있을 때의 경우를 고민해야 합니다. 아이템을 주웠다는 것을 어떻게 인식하게 할지, 인벤토리가 꽉 차면 그것을 또 어떻게 인식하게 할 것인지 등, 고민이 점점 늘어납니다. 이런 고민들은 한 번 해결하면 자작 매크로의 영역이 몇 배 확장하게 되고 다음에 막히게 되면 더 쉽게 고민을 해결할 수 있게 되지만 갓 시작한 사람들을 포기하게 하기도 합니다. 어떤 고민을 해야 하는지 조차 모르겠고 의도와는 다른 매크로의 행동이 당황스러울 뿐입니다. 

제가 추천드리는 것은, 매크로 스크립트를 만들 때는 어머니에게 게임을 가르쳐드린다는 느낌으로 처음부터 끝까지 고려해야 한다고 마음 먹는 것입니다. 태어나서 한 번도 게임이라는 것을 접해보지 못한 어머니께 로랜시아 남쪽에서 암탉이라는 몬스터를 잡으라고 해보세요. 어머니는 캐릭터가 암탉을 때리도록 하는 법을 모를 수도 있고, 캐릭터가 주먹을 휘두를 때 이따금씩 암탉 머리 위로 튀어나오는 숫자의 존재 이유와 의미를 모르십니다. 암탉이 내 캐릭터를 때릴 수도 있다는 사실, 그게 캐릭터를 죽음에 이르게 할 수도 있다는 사실도 모르세요. 암탉이 죽었을 때는 달걀을 드랍할 수도 있다는 사실도 가르쳐드려야 하고, 암탉이 주변에 없으면 맵을 돌아다니며 다른 암탉을 찾아야 한다는 것도 가르쳐드려야 합니다. 스크립트를 짤 때도, 이렇게 하나부터 열까지 일어날 수 있는 상황을 상상하고 임해야 합니다. 이런 생각에 도움되는 것으로 저는 자주 하지는 않지만 알고리즘을 하나하나 그려보시는 것을 추천드립니다. 그리고 다음에 알고리즘에서 중요한 '어떻게 매크로가 상황 인식을 하도록 할 것인가?'를 중요하게 다뤄보도록 하겠습니다.

오토핫키의 한계는 명확합니다. 그중 하나는 멀티스레드가 극히 제한되어 있다는 것입니다. 일례로 한 스크립트를 보죠.

F1::
Loop
{
MsgBox, , , 안녕하세요, 1
}

F2::
Loop,5
{
MsgBox, , , 안녕히 가세요, 1
}

F3::
Exitapp

이 스크립트를 실행하고 F1을 누른 다음 F2를 누르면 어떻게 될까요? 멀티스레드가 자유롭다면 안녕하세요는 계속 출력되고 그동안 안녕히 가세요는 5번 출력될 겁니다. 중요한 것은 안녕하세요 출력이 멈추지 않아야 한다는 것인데, 실제로는 그렇지 않고, 안녕히 가세요가 5번 출력되는 5초 동안은 안녕하세요는 출력되지 않습니다. 멀티스레드가 제한되어 있어서, 먼저 실행 중이던 스레드가 잠시 멈춰진 채로 나중에 시작된 스레드가 실행되기 때문입니다. 그나마 이런 방식으로 제한되어 있기 때문에, 루프문이 진행 중인 와중에도 F3을 누르면 종료시킬 수 있는 식입니다. 좀 더 복잡한 예로, 제가 포스팅한 새싹 모자 매크로나 게임섬 매크로는 겉보기에는 여러 클라이언트를 동시에 제어하는 것처럼 보이지만, 실제로는 클라이언트를 번갈아가면서 하나씩 제어하고 있는 것입니다. 이렇게 하면 멀티스레드를 흉내 낼 수 있죠. 물론 하나만 제어하는 매크로를 제작하고 #singleinstance off를 추가해서 (하나의 ahk파일이나 exe파일을 여러 개 켤 수 있도록 하는 명령어입니다. 쉽게 이미 실행 중인 스크립트가 있으니 그걸 끄고 실행하겠냐는 오류창이 안 뜬다고 생각하시면 되겠습니다.) 쓰는 방법도 있겠지만, 저는 전자를 더 선호합니다. 매크로를 쓸 클라이언트를 한 번에 지정할 수 있어서 사용할 때 편리하고 깔끔하니까요. 물론 매번 머리는 좀 아픕니다. 이 멀티스레드 흉내를 어떻게 하는 건 지, 블로그에서 중요하게 다뤄 볼 예정입니다.