게임과 관련된 흥미로운 개발 이야기들.

Ultima Online

https://en.wikipedia.org/wiki/Ultima_Online

97년에 나온 2D MMORPG. 역사가 오래된 만큼 많은 게임들의 기반이 되는 시스템을 가지고 있다.

서버-클라이언트간 패킷이 공개되어 있다.
이를 이용하여 사설 서버, 매크로서드파티 프로그램이 개발되었다.

개발 관점에서 흥미롭고 학습하기 좋은 게임이다.

나같은 경우에도 학생때 매크로를 만들어 보면서 프로그래밍에 흥미를 가지는 계기가 되었다.

서버 프로젝트

이 게임에서 사설 서버를 Free Shard라고 부른다.

이런 사설 서버들이 사용하는 서버 프로젝트로 RunUO, ServUO가 있다.

둘 다 C#으로 오픈 소스로 개발되었다. RunUO는 2020년 이후로 업데이트가 없는 것으로 보이며, ServUO는 아직도 업데이트가 이어지고 있다.

ServUO

서버는 클라이언트를 컨트롤하기 위한 패킷을 보낸다.

게임 메시지를 보내거나 음식 섭취 효과음을 재생시킨다.

플레이어 캐릭터, NPC 등 움직이는 것은 Mobile을 기반으로 하고
아이템은 Item을 기반으로 한다.
모든 클래스는 IEntity를 구현한다.

내용이 방대해서 서버-클라이언트 모델을 가지는 게임을 개발하고 싶다면 학습하는데 좋은 예제가 될 것이다.

ServUO 코드 분석

BaseCreature

BaseCreature는 몬스터의 기반 클래스이다.

Zombie 몬스터의 경우
이름은 a zombie이고, Body 그래픽 ID는 3이다.

룻 품질Meager, 빈약한 품질을 가진다.


Mobile의 Body가 클라이언트에 보여줄 그래픽이 아닌가 추정한다.
그러니까, 클라이언트와 서버가 약속으로 정한 번호로 보여줄 그래픽을 결정하는 거 같다.

Mobile의 Deserialize는 데이터소스로부터 데이터를 읽어오는 메서드 같다.

Macro

게임 자체가 장황한 행동(낭만)을 요구하기 때문에 수동으로 플레이하기 버거운 편이다. 예를 들면 옷을 만드려면 양에게서 양모를 얻고, 베틀과 물레로 실을 만들고, 실로부터 천을 만들고, 천으로 옷을 만드는 과정을 거친다.

이런 일련의 작업을 자동화하기 위한 매크로 프로그램이 많다.

EasyUO

스크립트 기반 매크로 프로그램이다. 자체 언어를 사용한다.

EasyUO

Home: https://www.easyuo.com
Wiki: http://wiki.easyuo.com/index.php?title=Main_Page

플레이어 체력, 주변 몬스터 및 객체 등 게임 프로퍼티를 서버 패킷으로부터 분석하여 제공한다.

GUI를 전용으로 개발하기 위한 별도 프로그램이 있다.

finditem ENK C_ , #BACKPACKID
if #FINDSTACK < %cost
   gosub GetMetal
click %X %Y
gosub GetGump
if #WEIGHT > %maxWt
   gosub smelt
finditem %weapon C_ , #BACKPACKID
  • finditem은 컨테이너(캐릭터 가방, 땅, 상자 등)에서 아이템을 찾는 명령어다.
  • #FINDSTACK와 같이 #으로 시작하는 것은 게임 시스템 변수이다. 서버 패킷으로부터 갱신된다.
  • gosub은 사용자가 정의한 서브루틴(함수)을 호출하는 명령어이다.

마우스 이동과 클릭을 재현할 수 있다. 게임 클라이언트 내에서만 영향이 있기 때문에, 호스트에 영향을 미치지 않는다.

OpenEUO

EasyUO를 개선한 것으로, 스크립트 언어로 Lua를 사용한다.

http://www.easyuo.com/openeuo/wiki/index.php/First_Steps

Lua의 기능을 사용할 수 있기 때문에 파일에 접근하거나 모듈화를 더 쉽게 할 수 있다.

UO.Macro(8,2)
wait(1000)
UO.Msg("Hi, my name is " .. UO.CharName .. "!\n")
print("UO.CharName = " .. UO.CharName)

UO 객체를 통해 게임에 접근한다.

UOSteam

게임 Assist 프로그램이다. 자체 매크로 기능을 제공하는데 자체 스크립트 언어를 사용한다.

https://www.uosteam.com/

이와같은 Assist 프로그램은 많이 있는데, 이 프로그램이 가장 유명하다. 게임 화면에 렌더링하기 전에 패킷을 가로채어(추정) 처리하기 때문에 매우 빠른 반응속도를 보인다.

예를들면 사용자에게 다이얼로그(Gump라 부른다)를 보여주고 클릭하는 것을 클라이언트에서 렌더링하기 전에 처리한다. 그러면 게임 클라이언트는 다이얼로그를 보여줄 필요 없이, 클릭한 내용을 서버로 전송한다. 그래서 이 프로그램으로 캐릭터를 조작하면 프로그램을 사용하지 않는 사용자보다 훨씬 유리한 상황이 된다.

usetype '0xf6c' 'any' 'ground' '2'
waitforgump 'any' 15000
replygump 0xdd8b146a 1

Classic Assist

Assist 프로그램. 오픈소스 프로젝트라 이런 프로그램은 어떻게 만드는지 알고 싶으면 공부가 되겠다.

https://github.com/Reetus/ClassicAssist

Classic Assist

UOSteam처럼 자체 매크로를 제공하는데, 스크립트언어로 파이썬을 사용한다! Lua는 장황하고, 자체 스크립트 언어는 단순하지만 확장성이 떨어지지만, 파이썬을 사용하니 가장 만족도가 높다.

Path Of Exile

일명 POE. 핵앤슬래시 게임이다.

Path Of Building

일명 POB. Path Of Exile의 빌드 계산기.

https://github.com/PathOfBuildingCommunity/PathOfBuilding

매우 복잡한 시스템을 가지고 있다. 수 많은 게임 속성이 있고, 대부분 게임 내에서 표기되지 않아서 사람이 수치를 계산하기 어려운 점이 많은 게임이다. POB는 보이지 않는 수치들을 시뮬레이션하여 계산하고 보여준다.

프로그램은 Lua로 100% 작성되어 있다.

게임은 상황에 따라서 DPS가 달라진다. 예를들어 1:1 전투나 1:N 전투에 따라서 DPS가 달라진다고 할 수 있는데, 이런 상황을 시뮬레이션할 수 있는 설정 기능을 제공한다.

POB의 최초 제작자는 POE 게임사인 ggg에 입사하였다.

PoeStack

PoeStack은 게임 API와 게임 디스코드 채널을 연동하여 거래를 시스템화한 서비스다. 디스코드의 거래 채팅(~를 ~에 팝니다)을 웹 사이트로 시스템화하여 보여준다.

https://poestack.com/

모든 기능을 사용하기 위해서 2가지 연동을 해야한다.

  • POE 계정 연동하여 아이템 창고를 조회 및 가치를 계산.
  • 디스코드 채널 연동하여 거래 메시지를 읽고, 거래 메시지를 작성한다.

반 자동화로 구현해서 느슨하게 잘 구현했다고 생각한다. 모든 기능을 자동화하면 게임의 변경 사항을 따라가기 어려웠을 것이다.

디스코드는 채팅 플랫폼일 뿐이지만, PoeStack을 통해서 거래 메시지를 양식에 맞춰서 전송한다. 양식에 맞춰져 있어서 거래 메시지를 읽어 들여서 웹 사이트에서 보여줄 수 있다.

게임을 연동했기 때문에 보유한 아이템에 대한 신뢰성을 제공한다. 단순히 거래 채팅만 수집했다면 시세를 조작하거나, 가짜 아이템 등 신뢰성이 떨어졌을 것이다. 게임 내에 많은 화폐 아이템들이 있는데, 교환비를 계산해주는 편리 기능도 제공한다.

기능 요약:

  • 창고 아이템을 조회해서 화폐 가치를 계산한다.
  • 아이템 판매를 위해 디스코드 채널에 전송할 메시지를 자동 전송한다.
  • 아이템 구매를 위해 디스코드 채널에 전송된 메시지를 읽어서 웹 사이트에서 보여준다.
  • 여러 품목들을 카테고리화하여 큐레이션한다.
  • 실제 게임 내에서 거래할 수 있도록 귓속말 양식을 복사한다.(이 게임은 전세계 사용자들과 플레이하기 때문에 언어 문제가 있다.)
  • 화폐 아이템 가치를 현재 환율에 맞게 자동 계산해준다.

GitHub Organization이 존재하는데, PoeStack 프로젝트는 공개되지 않은 것으로 보인다. https://github.com/PoeStack

GGG 개발진의 컨텐츠 개발 속도 이야기

패스 오브 엑자일은 시즌이라고 부르는 리그를 3개월 주기로 업데이트한다. 각 시즌마다 새로운 컨텐츠를 추가하고, 기존 컨텐츠를 개선하는데, 그 양이 방대하다. 24년 3월에 진행된 3.24 시즌 패치노트를 보면, 스크롤을 한참 내려야 한다. 이 게임을 플레이 하면서도 매번 어떻게 많은 컨텐츠를 생산해 내는지 의문이다. 내 업무는 부끄러울 정도의 속도와 분량이다. 이런데도 사용자들은 금방 지루해한다. 그래서 이 게임을 경험한 사용자들은 다른 게임에서 금방 질려하는 편이다.

디스코드에 개발 속도와 관련해서 이야기한 것을 누군가 번역해서 올렸다.

내 관점으로는

1. 프로그래밍 작업을 처음부터 시작할 필요가 거의 없도록 발달하고 확장된 코드 기반.

2. 모든 것에 프로그래밍이 필요한 대신 여러 역할을 중심으로 새로운 컨텐츠를 생성하고 연결할 수 있는 기능을 확장시킬 수 있는 강력한 내부 툴

3. 5번의 회의를 먼저 하는 것이 아니라 "일단 완료한 후 반복"하는 사내 문화

1, 2는 회사 차원에서 잘 정리하고 격려해야 가능한 일이라 생각한다. 덧글에도 비슷한 의견이 있는데, 플레이어라면 공감할 수 밖에 없는 이야기다:

GGG 개발하는걸 보면, 일관성이나 규격화 하는걸 정말 좋아한다. 3.13 때 뜬금없이 폭풍보주, 겨울보주, 서리폭탄 등을 별도 ORB 태그로 분류한거라던가. 이거 태그 때문에 헷갈린다 싶어서 마그마 오브를 롤링 마그마로 이름 바꾼다던가. 이런 일관성들이 쌓여서 저런 개발 속도가 나올 수 있는 것 같음.

시스템을 만드는 모든 이해관계자들이 규격화에 공감하고, 노력해야 가능한 일이 아닐까? 개인이 거시적인 시각을 가지고 있고, 회사 구성원이 모두 그 방향성을 공감하고 있어야 가능한 일이다. 가끔은 내 작업을 설득할 생각부터 지쳐서, 그냥 필요한 작업만 한다. 내가 찾는 회사 문화는 이런 것에서 편안한 느낌을 받는 것이다.

2023년 7월 29일에 있었던 ExileCon의 Wacky PoE 1 Mechanics Q&A 시간에서 개발 속도가 어떻게 빠를 수 있는지 조금 엿볼 수 있다. 게임 디렉터와 개발자들이 플레이어들과 소통하는 시간인데, 그 주제가 "게임 메커니즘"이다. 상술했듯 이 게임은 광범위한 메커니즘을 가지고 있는데, 예를들어 게임 내 밸런스를 위해 제한한 능력을 해제하면 어떻게 되는지 등이다. 이를 단순 구두 설명하는 것이 아니라, 개발자가 게임 내에서 직접 시연한다! 게임 내에서 디버그 명령어로 몬스터를 소환하고, 능력을 조절한다.

chat commands

이 장면에서 개발자가 게임 내 명령어로 속성을 조절하는 것을 보여준다. 디버그 명령어지만 자동 완성이 되고 있는 모습이다. 수 많은 능력치들이 자동 완성되고 있다. 개발자가 없더라도 빠르게 테스트할 수 있는 샌드박스 환경을 제공한다. GGG의 개발자는 게임을 만드는 것이 아니라, 게임을 만드는 플랫폼을 만드는 것이다.

이 장면은 사용한 명령어를 시간 순서대로 보여주고, 선택하는 장면이다. 개발 도구 경험을 향상시키기 위해 노력했다는 것을 알 수 있다.

chat commands whatis 흥미로운 장면은 게임 내에서 유명한 보스 몬스터 둘을 소환하고, 싸움을 붙이는 장면이다. 실제로 두 몬스터는 게임 내에서 싸울 일이 없다. 하지만 구조적으로 잘 설계되어서 적대 관계를 설정할 수 있고, 싸움을 붙일 수 있다. 명령어가 많다 보니, /whatis 명령어로 사용법을 확인하는 장면이 인상적이다.

우리가 만드는 시스템을 보통 이런 시스템이 아니다. 지속 가능성이 없다. 반면에 GGG의 철학은 지속 가능한 시스템을 만드는 것이다. 초기 비용은 들겠지만, 조금만 지나도 비용은 회수하고도 남는다. 내가 이런 시스템을 만들자고 다른 이들을 설득할 수 있을까?

Stardew Valley

농장 경영 게임. 내가 해 본 게임은 아니다. 그럼에도 지면을 할당하는 이유는 개발자 ConcernedApe(닉네임)가 흥미롭기 때문이다.

1인 개발자로 Stardew Valley를 개발했고, 스팀기준 리뷰만 59만개, 그 중 98%가 압도적 긍정 리뷰다.

3천만 판매를 기록한 Stardew Valley 개발자 "나는 게임을 만든 사람일 뿐, 아직도 하루 종일 컴퓨터에 굽신거리고 있다" 기사에서 인터뷰한 내용이 있다.

"My goal in life isn't about making money," Barone adds. "I want to create things and share them with the world. That's what it's all about. That's what I'm doing. That's what I will do, regardless of any other circumstances, as long as I can financially support myself to be able to do that. If I couldn't, I would get a job and spend my free time creating stuff to try to get back to doing that."

"제 인생의 목표는 돈을 버는 것이 아닙니다."라고 Barone은 덧붙입니다. "저는 무언가를 창조하고 그것을 세상과 공유하고 싶습니다. 그게 전부입니다. 그게 제가 하고 있는 일이죠. 다른 어떤 상황과도 상관없이 재정적으로 뒷받침할 수 있는 한 그렇게 할 것입니다. 그렇게 할 수 없다면 직업을 구하고 여가 시간을 활용해 다시 그 일을 하려고 노력할 것입니다."

겸손함이 보이는 대목이다.

"I was just making the game I wanted to play. What I would say is, I was tapping into a certain zeitgeist that I wasn't aware of, or conscious of, but I wasn't the only one who was feeling that way. We wanted to play games that were a little bit different. ... I think if I hadn't done it, someone else probably would have in a similar timeframe."

"저는 제가 하고 싶은 게임을 만들고 있었을 뿐입니다. 제가 알지 못하거나 의식하지 못했던 어떤 시대정신을 활용하고 있었지만 저만 그렇게 느낀 것은 아니었습니다. 조금은 다른 게임을 하고 싶었어요... 제가 하지 않았다면 아마 비슷한 시기에 다른 누군가가 했을 거라고 생각합니다."

본인이 하고 싶은 게임을 만들었다는 부분. 자신에게 만족스러운 게임을 만들기 위해서 노력했을 것이고, 아마 그 기준은 높을 것이다.

Starcraft

스타크래프트. 블리자드의 전략 게임.

맵 에디터

스타크래프트의 맵(Map)은 사용자가 직접 제작하고 공유할 수 있다. User Created Content(UCC) 개념이 만들어지기 전부터 있었고, UCC의 대표적인 예시가 아닐까.

Starcraft map editor

유즈맵은 일반 대전이 아닌 새로운 규칙을 만들 수 있어서, 새로운 재미를 선사한다. 그리고 지금 인기를 끄는 게임들도 유즈맵에서 시작한 경우도 있다.

유즈맵이 많이 제작될 수 있었던 이유는, 초보자 친화적이기 때문이다. 후에 나온 워크래프트3는 좀 더 복잡하고, 블리자드의 마지막 RTS 게임인 스타크래프트2는 더욱 복잡하다. 그래서 시대가 지날수록 유즈맵 제작은 많이 줄어들었다. 퀄리티는 높아지긴 했다.

트리거(Trigger)

스타크래프트의 맵 에디터는 지형, 유닛 배치를 하고, 행동을 지정할 수 있는데 이것을 트리거라고 한다. 트리거는 "어떤 지역(Location)에 유닛이 들어오면 파괴한다" 같이 이벤트 조건(Condition) - 실행(Action)의 쌍으로 이루어져 있다. 맵의 가장 중요한 요소라고 할 수 있다.

Starcraft triggers

트리거는 프로그래밍과 유사한 개념이다. 분기문, 반복문, 변수, 함수가 없지만 이를 대체할 수 있는 기능을 제공하거나 흉내낸다. 이벤트를 10번 반복하고 싶다면 맵 구석에 유닛 10개를 생성해두고 이벤트를 실행할 때 마다 유닛을 제거하는 방식으로 구현할 수 있다.

Random 함수가 없지만, 스위치 개념을 이용하여 무작위 요소를 만들어낼 수 있다. 스위치는 0과 1을 가지는 변수인데, 에디터에서 스위치 수를 고정해 두었다(255개 였나?). 원하는 스위치를 0, 1 무작위로 변경하는 액션이 있기 때문에, 50%는 스위치 하나를 무작위로 변경하면 된다. 따라서 이진 표현만 가능하기 때문에 원하는 확률을 정확하게 표현하기는 어렵다.

재밌는 점은 "터보 트리거"라는 것이다. 외국에서는 "하이퍼 트리거"라 부른다. 트리거의 반복은 1초정도 지연이 있기 때문에, 유닛 100기를 순차 생성하더라도 최소 100초가 소요된다. 이를 회피할 수 있는데, wait 0ms 액션을 반복하는 트리거를 만드는 것이다. 맵에서는 아무 의미없는 트리거지만, wait 액션이 실행될 때 마다 다른 액션도 지연되지 않고 곧바로 실행된다.

유닛의 우선 순위가 있다는 점도 흥미롭다. 예를들어 지역에서 유닛을 1기씩 제거를 반복하는 액션을 만들었을 때, 가장 우선 선택되는 유닛은 항상 왼쪽 위 유닛이다. 왼쪽 -> 오른쪽, 위 -> 아래 순서로 우선순위가 결정된다. 이 규칙을 알고 있다면, 제거 순서에 영향받는 맵에서 배치를 조정하여 원하는 순서로 제거할 수 있다. 이러한 제약사항은 에디터의 단순함을 유지하기 위한 것이 아닌가 추측된다.

스타크래프트에서 제공하는 캠페인은 맵 에디터로 만들어지지 않은 것으로 추정한다. 오래전 본 글에서 럴커가 어느 지점에서 버러우하고 특정 시점에 버로우를 해제하는데, 이를 맵 에디터로 구현할 수 없다고 들었던 거 같다.

블리자드의 개발자들이 설립한 프로스트 자이언트 스튜디오의 RTS 게임, 2024년 7월에 출시될 예정인 스톰게이트도 맵 에디터를 지원한다고 밝혔다. 스타크래프트 2의 에디터가 너무 어려웠던 것을 인식했는지, 라이트 버전과 숙련자용 버전 모두 제공한다고 한다.1


  1. "개발사의 전작들처럼 맵 에디터가 지원된다. 워크래프트 3처럼 빠르고 쉽게 배울 수 있는 라이트 버전과 스타크래프트 2처럼 개발사 내부에서 사용하는 것과 동일 사양의 숙련자용 버전 두 가지로 제공한다." - https://namu.wiki/w/%EC%8A%A4%ED%86%B0%EA%B2%8C%EC%9D%B4%ED%8A%B8