도타 업데이트는 하나하나 새로운 영웅, 아이템, 능력을 게임에 소개하는 기회가 됩니다. 헤아릴 수 없이 많은 기존 내용을 손보는 기회임은 두말할 나위도 없고요. 그런 까닭에 도타는 계속 진화해 나가지만, 동시에 무수히 많은 상호작용이 일어날 수 있는 게임이 되었습니다. 이는 매치마다 항상 새로운 경험을 할 수 있지만, 그러면서도 일부 변경 사항으로 가끔 버그가 한두 개 생길 가능성이 높아진다는 뜻입니다. 스무 개쯤 될 수도 있고요.
다행히, 도타 커뮤니티는 끊임없이 실험하고 탐구하며 빠르게 숨겨진 장점, 새로운 메타, 그리고 저희조차 깜짝 놀랄 만큼 명백하고도 심각한 버그를 찾아냅니다.
기술단의 끈끈이 폭탄 버그가 바로 그 완벽한 예입니다. 해당 버그의 기원은 지난해 기술단 업데이트에서 능력과 플레이스타일을 개편했을 때까지 거슬러 올라갑니다. 당시 개편으로, 기술단의 끈끈이 폭탄이 만료되지 않는 버그가 생겨났으며, 시전한 플레이어가 제어할 수 있는 사례도 일부 있었습니다. 하지만 흥미롭게도, 그 당시 게임의 매개 변수 때문에 해당 버그가 매치에서 실제로 나타나는 상황은 없었습니다. 그러다 지난봄, 7.33 신개척자 업데이트로 쌍둥이 관문이 등장하면서 수면 위로 불거졌습니다.
그러다 갑자기 기술단 플레이어는 유도 끈끈이 폭탄을 만들어 지도 여기저기로 옮겨 다니며 적 플레이어에게 치명적인 폭발물을 무제한으로 퍼부을 수 있었습니다. 이건 약간... 이득을 얻는 사항이었죠. 얼마 지나지 않아 도타 github이 시끄러워지기 시작했습니다.
일반적인 게임플레이 프로그래밍, 특히 도타에서는 보통 기존에 있는 사항(제대로 작동하며 게임을 망치지 않는 것)과 비슷한 것을 찾아 그것을 시작점으로 하여 점차 변화시켜 나가면서 새로운(그리고 게임을 망치지 않는) 것을 만들기 마련입니다. 끈끈이 폭탄은 기존 기술단의 원격 지뢰를 바탕으로 만들어졌습니다. 'npc_dota_techies_remote_mine'을 소환하는 것으로 구현되었는데, 이는 기존 원격 지뢰와 같은 기본 NPC 유형입니다.
기술단의 끈끈이 폭탄은 '던지기'/'추격'/'초읽기 후 폭발'의 시퀀스를 활용하는데, 이는 NPC에 부여된 일련의 서버 측 한정자(강화 효과)로 관리되면서 시퀀스 내 각 단계에서의 유닛 움직임과 동작을 처리합니다. '추격' 및 '초읽기' 한정자는 한정자 자체의 상태 플래그를 통해 플레이어의 명령을 방지했습니다. '던지기' 한정자가 npc_dota_techies_remote_mine 자체의 특성과 더불어 동작을 제어하도록 한 결과, 여러 유형의 플레이어 명령이 방지되었습니다. (특히, NPC의 공격 능력 속성(AttackCapability)이 DOTA_UNIT_CAP_NO_ATTACK으로 설정됨)
원격 지뢰는 기술단이 지뢰 자체에 있는 능력을 사용하여 수동으로 터뜨릴 수 있었기에, 원격 지뢰 NPC는 능력을 사용하는 것이 허용되었습니다. 즉, 시전 플레이어(처치 인정 목적)가 소유한 것이자 동시에 시전 플레이어가 제어할 수 있는 것으로 지정되었다는 뜻입니다. 쌍둥이 관문(또는 정신을 집중하여 사용하는 지도 개체)을 오른 클릭하면 공격 클릭을 정신 집중 대상에 대한 능력 시전으로 전환하여 기계적으로 기능합니다. (정신을 집중하는 동안 쌍둥이 관문에 '시전'하는 것임) 다른 지도 개체는 정신 집중을 수행하려면 영웅이 필요합니다. 그러나, 로샨이 쌍둥이 관문을 이용할 수 있기에, 비영웅 유닛도 정신 집중을 하는 것이 허용되었습니다.
이에 따라 끈끈이 폭탄 버그가 생겼습니다. 던져진 끈끈이 폭탄이 아주 짧게 공중에 떠 있는 시간 동안 플레이어가 통합 유닛 명령으로 기술단과 폭탄 두 가지를 모두 선택한 상태로 쌍둥이 관문을 클릭하면, 폭탄도 쌍둥이 관문에 정신 집중을 시전했습니다. 이렇게 하면 끈적이 폭탄이 정신 집중 상태가 되어 '던지기'를 끝내고 한정자 시퀀스를 중단함으로써, 의도하지 않았던 동작을 초래했습니다.
해결책은 이 모든 상황을 이해하고 나니 의외로 간단했습니다. 끈끈이 폭탄은 시전 플레이어가 제어해야 할 필요가 전혀 없습니다. 끈끈이 폭탄에서 해당 플래그를 제거하면 예정된 한정자 시퀀스가 언제나 예상대로 실행되고 결국 폭발로 이어지는 것이었습니다.
수많은 다른 버그들도 마찬가지지만, 버그를 수정하는 시간의 99%는 해당 버그를 추적하는 데 쓰입니다. 실제 해결 방법은 보통 코드 단 한 줄을 바꾸는 일로 귀결됩니다. 어쩌면, 이전 버그를 수정하려고 넣었던 그 코드열일 수도 있습니다. (그래서, 종종 코드 디버깅은 살인자이자 탐정으로서 살인 사건을 해결하려는 것과 같다고들 합니다.)
그러니까, 이렇게 끈끈이 폭탄 버그가 우연히 생겨났고, 짧게 혼란이 일어났다가, 커뮤니티 덕분에 저희에게 알려졌고, 결국 수정되었다는 얘기입니다. 다음은 어떻게 될까요? 이제 기존 버그를 고치려고 넣은 코드열을 삭제함으로써 새로 어떤 버그가 만들어졌을지 알아낼 때까지 기다리는 수밖에요. 혹시 우연히 발견하신다면, GitHub에 올려주시기 바랍니다.
(IP보기클릭)106.101.***.***
(IP보기클릭)119.200.***.***
(IP보기클릭)183.108.***.***
(IP보기클릭)223.39.***.***
(IP보기클릭)211.109.***.***