이 EUD 지도는 지원되지 않습니다 - i EUD jidoneun jiwondoeji anhseubnida

이 EUD 지도는 지원되지 않습니다 - i EUD jidoneun jiwondoeji anhseubnida

EUD가 무엇인가요?

“Extended Unit Death”의 준말인 EUD는 스타크래프트 지도 편집기에 사용되는 트리거의 한 종류입니다. 초기에 지도 제작자분들께서 이 트리거를 당초 예상하지 못한 방법으로 활용하여 그 전에는 구현이 불가능하던 새로운 게임플레이 작동 방식을 만들어 내기도 했습니다. 이를 통해 탄막 슈팅 게임, 영상 지도, 리듬 게임, 카드 게임 등등 새로운 게임 장르를 스타크래프트에서 구현하기도 했죠. 하지만, 이러한 EUD 트리거가 지도 제작자분들께 유용하게 쓰일 수 있었던 요소가 한편으로는 악용될 수 있는 여지가 있었습니다. 따라서, 스타크래프트 플레이어분들과 게임의 보안을 위해, EUD 지도의 사용을 막아야 했습니다.

EUD를 다시 돌아보며

스타크래프트: 리마스터 개발 과정에서 EUD 지도의 인기와 수요에 대한 피드백을 지속적으로 확인할 수 있었고, 따라서 게임이 위험에 노출되는 위험 없이 EUD 트리거를 다시 추가하기 위한 방법을 모색해 왔습니다. 이제 1.21.0 패치와 함께 적용되는 EUD 에뮬레이터 기능을 통해 PC와 Mac 사용자 모두가 랜덤 타워 디펜스 등의 인기 있던 1.16.1 EUD 지도 일부를 플레이하실 수 있게 될 예정이라는 기쁜 소식을 전합니다!

에뮬레이터의 특성상 이전의 모든 EUD 기능이 지원되지는 않는다는 점을 말씀드립니다. 예를 들어, 스타크래프트의 그래픽을 조작하는 EUD 트리거는 지원되지 않을 예정입니다. 호환되지 않는 EUD 지도를 실행하려 할 경우, 오류 메시지가 표시되며 지도가 실행되지 않을 것입니다. 하지만, 앞으로도 EUD에 대한 지원을 계속해 나갈 예정이므로, 실행되지 않는 지도나 향후 지원되기를 바라는 지도가 있다면 토론장을 통해 저희에게 말씀해주시기 바라며, 향후 패치를 통해 에뮬레이터를 업데이트해나갈 예정입니다.

스타크래프트: 리마스터에 EUD를 다시 지원하게 되어 기쁘며, 앞으로도 커뮤니티 여러분께서 멋진 지도를 제작해주실 것이라 기대합니다. 의견이 있으시다면 토론장을 통해 저희에게 말씀해 주세요.

다음 글

  1. 긴급 수정 사항: 2022년 9월 29일

    긴급 수정 사항: 2022년 9월 29일

    월드 오브 워크래프트와 관련하여 적용되거나 수정된 내용을 안내해 드립니다.

    4시간 전

주요 소식

강좌에 사용된 에디터는 SCM 드래프트2 2018.07.24 버전입니다.

1. 각종 번호 (코드, Unit ID)

각 유닛에는 유닛별로 정해진 번호가 정해져있는데 그것을 유닛 번호(유닛 코드, 유닛 타입)라고 합니다.

예를 들면

마린 = 0

고스트 = 1

벌쳐 = 2

...

테란 베스핀 가스 탱크 타입 2 = 227

까지 총 228종류의 유닛이 있습니다.

이렇게 EUD 에디터에서 유닛 왼쪽에 붙어있는 번호가 유닛 번호입니다.

전에도 언급된 내용이지만 플레이어도 마찬가지로

Player 1 = 0

Player 2 = 1

...

Current Player = 13

...

이런식으로 각각 번호가 붙어있습니다.

CreateUnit(1, 8, "Location 5", 13);

그래서 이 액션은 플레이어 번호 13(= Current Player)의 유닛 번호 8(= 레이쓰) 1마리를 "Location 5"에 생성한다

라는 뜻이 됩니다.

업그레이드나 각종 기술연구, 명령 등 에도 모두 각 항목에 해당하는 번호가 부여되어 있습니다.

2. 인덱스 (Index)

유닛 번호가 유닛의 종류를 구별해주는 번호였다면 유닛 인덱스는 각 유닛 자체를 구별해주는 번호입니다.

똑같은 마린이라도 서로 체력이 다를 수 있고 플레이어가 다를 수 있기 때문에

유닛끼리 구별할 수 있는 일종의 번호표를 붙인 것이 인덱스입니다.

SCM 드래프트2에서 유닛을 더블클릭하면 유닛의 인덱스를 볼 수 있습니다.

현재 선택한 마린의 유닛 인덱스는 71번입니다.

SCM 드래프트2에서는 미리 배치된 유닛/건물들이 요 인덱스 순서대로 배치됩니다.

예를들면 크립콜로니 옆 크립 위에 테란 건물이 배치되어있다고 하면

크립콜로니 인덱스가 1, 테란 건물이 2일 때는 크립콜로니가 먼저 배치된걸로 취급되어 맵을 실행해보면 크립 위에 테란 건물이

올라가있는채로 생성되고, 반대로 테란 건물이 1, 크립콜로니가 2면 테란 건물 아래에는 크립이 깔리지 않게 됩니다.

유닛 인덱스가 서로 같은 유닛은 존재할 수 없으며,

EUD맵 기준으로 유닛 인덱스는 0번부터 1699번까지 총 1700개의 인덱스가 존재합니다.

(유닛 제한, 일명 캔낫이 유닛 1700마리인 이유)

Notice! 스캐럽, 인터셉터, 라바, 맵 리빌러 등 유닛으로 취급되는 모든 것이 유닛 인덱스에 포함되며,

시즈탱크와 골리앗의 경우에는 몸통과 머리가 둘 다 유닛 취급되기 때문에  탱크와 골리앗은 인덱스 2개를 차지합니다.

Notice! 유닛 스프라이트(Unit Sprite)로 생성된 유닛과 군사기지(Installation) 지형의 문과 트랩류 두뎃들로 배치된 유닛들은

나머지 유닛보다 먼저 인덱스 0번부터 차례로 할당받습니다. (SCMD2 에디터에서 표기된 인덱스에는 이 점이 반영되지 않습니다.)

Tip. 스타트 로케이션은 유닛 인덱스에 포함되지 않습니다.

유닛 뿐만이 아니라 로케이션에도 인덱스가 붙어있습니다.

맨 위의 로케이션은 0번 인덱스, 그 아래 순서대로 각각 1,2,3,4번입니다.

물론 중간에 로케이션을 삭제하면 중간에 빈 인덱스가 생길 수도 있으니 위 방식이 100% 맞지는 않습니다.

Tip. 로케이션 생성/삭제시 SCMD2 아래의 콘솔창에 몇번 인덱스의 로케이션을 생성/삭제했는지 로그가 뜹니다.

Tip. Anywhere 로케이션은 63번입니다.

Notice! : 트리거에서는 로케이션 칸에 해당 로케이션 + 1을 해야 합니다.

위 스샷에서 "Location 1"에 유닛 생성을 하고 싶다면

CreateUnit(1, "Terran Marine", 2, CurrentPlayer);

이렇게 로케이션 칸에 1이 아닌 2를 적어야 합니다.

이렇게 1을 더하는건 트리거 조건과 액션의 로케이션 적는 칸에서만 이렇고,

그 외의 나머지 모든 곳에서는 그냥 로케이션 인덱스 그대로 쓰시면 됩니다.

3. 오프셋 (Offset)

Tip여기는 개념적인 이야기라 "이 뭔 개소리야?" 라는 반응이 나올 수도 있으니

이해가 잘 안되면 아래 4~6번을 먼저 본 후에 이 부분을 보는것도 좋은 방법입니다.

오프셋이란 특정 메모리의 위치를 나타내는 주소입니다. 한 오프셋에는 0~4294967295(=0xFFFFFFFF)의 값이 들어갈 수 있습니다.

특정 오프셋의 값을 Set Memory 액션을 통해 조작할 수 있고, Memory 조건을 통해 인식할 수 있습니다.

오프셋은 16진수 수 6자리로 이루어져 있으며

오프셋 1에는 1바이트(256가지 = 0x00~0xFF)의 정보가 들어갈 수 있습니다.

(0x000001 오프셋에 1바이트, 0x000002 오프셋에 1바이트, 0x000003 오프셋에 1바이트 ... 등)

참고로 16진수는 16개의 문자로 숫자를 표현하는 방식으로 한 자리에 0, 1, 2... 9, A, B, C, D, E, F의 문자가 들어갈 수 있습니다.

A부터 F까지는 각각 10부터 15까지를 의미합니다.

16진수를 표현할때는 수 맨 앞에 "0x"라는 문자를 붙입니다.

예를들어 0x04 라고 하면 16진수로 4라는 의미며 이것은 십진수로 4입니다.

0x0B라고 하면 십진수로 11입니다.

0x13이라고 하면 십진수로 1*16 + 3*1 = 19 입니다.

0x3C라고 하면 십진수로 3*16 + 12*1 = 60 입니다.

Memory 조건과 Set Memory 액션은 오프셋을 4바이트 단위로 읽고 쓸 수 있습니다.

예를들어

SetMemory(0x100000, SetTo, 2181300765);

여기서 2181300765는 16진수로 0x8204021D 입니다. 그래서 위는 아래 코드와 같습니다.

SetMemory(0x100000, SetTo, 0x8204021D);

아까부터 바이트 바이트 하는데 1바이트 = 8비트 = 2^8 = 256만큼의 공간이며 말 그대로 0~255의 수를 표현할 수 있습니다.

0~255의 수는 16진수로 표현하면 두 자리 수의 16진수 숫자를 표현할 수 있습니다. (0x00~0xFF)

SetMemory 액션은 정확히는 0x100000 이 주소 단 하나만을 의미하는게 아닌

0x100000 ~ 0x100003 범위의 오프셋 (4개니까 총 4바이트)를 한번에 바꾼다는 이야기입니다.

오프셋

0x100000

0x12345678

0x100004

0xFFFFFFFF

0x100008

0x00000ABC

이런식으로 보통 오프셋 하나라고 하면 0x100000 ~ 0x100003 오프셋을 묶어서 말하는 것이며

"0x100000라는 오프셋에는 0x12345678라는 값이 있다" 라고 합니다.

오프셋

각 오프셋의 값

0x100003

0x100002

0x100001

0x100000

0x100000

0x12000000

0x00340000

0x00005600

0x00000078

0x100004

0xFF000000

0x00FF0000

0x0000FF00

0x000000FF

오프셋 하나하나를 자세히 보면 이렇습니다.

아무튼 이런식으로 오프셋은 4바이트 단위로 읽고 쓰기 때문에 오프셋에는 4의 배수의 오프셋만 들어갈 수 있습니다.

SetMemory(0x100003, Add, 0x42);

따라서 위와 같은 액션에서 0x100003은 4의 배수가 아니기 때문에 이런 액션은 안됩니다. 애초에 컴파일 되지 않습니다.

Tip. 오프셋의 각 자리 수를 각 바이트별로 10진수로 보기 좋게 표현하려면

0x05140B20 = 85199648 인데 이렇게 표현하면 더러우니

0x05*16777216 + 0x14*65536 + 0x0B*256 + 0x20*1 = 5*16777216 + 20*65536 + 11*256 + 32*1

이런식으로도 표현할 수 있습니다.

당연하겠지만 모든 어떤 오프셋이 무슨 기능인지 모두 외울수는 없기 때문에 아래 링크에서 여러 오프셋 정보를 알 수 있습니다.

리마스터 이후 지원되지 않는 오프셋도 있으니 주의.

EUDDB : http://farty1billion.dyndns.org/euddb/

4. 4바이트 단위로 저장되는 정보

가장 단순한(?) 형태의 정보입니다.

위에서 오프셋은 4바이트 단위로 읽고 쓸 수 있다고 했는데 이 4바이트 전체가 하나의 정보를 의미하는 오프셋입니다.

하나를 뽑자면 0x515BBC라는 오프셋이 있습니다.

이 오프셋은 "진동형 공격력이 대형 유닛에게 적용되는 공격력 비율" 입니다.

진동형의 공격이 대형 유닛을 공격하면 공격력의 25%만의 피해를 줍니다. 이 25%를 결정하는게 바로 저 오프셋입니다.

기본값은 64이고 256이면 100%를 의미합니다.

만약에 진동형 공격이 대형에게 오히려 2배의 피해를 입히게 만들고 싶다면 256의 두 배인 512를 넣으면 됩니다.

SetMemory(0x515BBC, SetTo, 512);

이렇게 말이죠.

그대로 TEP로 적용해보면...

이렇게 공격력 20의 벌처가 대형에게 오히려 두 배의 피해를 입히는걸 볼 수 있습니다.

20에서 방어력 먼저 적용되서 19. 여기서 2배가 적용되어 38의 데미지를 주었습니다.

아무튼 이런식으로 오프셋 하나 = 정보 하나인 경우에는 다루기 매우 쉽습니다.

문제는 그게 아닌 경우...

5. 2바이트 단위로 저장되는 정보

2바이트라면 4바이트의 절반이죠, 즉 하나의 오프셋에 2바이트짜리 정보가 2개 담겨있다는 겁니다.

예를 들어서 스파이더 마인의 공격 아이콘을 핵폭발 아이콘으로 바꿔보겠습니다.

스파이더 마인의 공격 아이콘이 들어있는 오프셋은 0x65678C 이며 핵폭발 아이콘은 311번입니다. 그래서...

SetMemory(0x65678C, SetTo, 311);

이런식으로 설정하면 어떻게 될까요?

이렇게 정상적으로 핵폭발 아이콘으로 적용이 됩니다. 그런데...

띠용? 뜬금없이 골리앗의 지상공격 아이콘이 덩달아서 마린으로 바뀌어버렸습니다! 이게 어떻게 된 일일까요?

스파이더 마인의 공격 아이콘이 들어있는 오프셋은 0x65678C이라고 했는데 이는 골리앗의 지상 공격 아이콘도 마찬가지입니다.

즉 0x65678C 오프셋에는 스파이더 마인 공격 아이콘과 골리앗 지상 공격 아이콘 두 정보가 둘 다 들어있는 오프셋인겁니다.

정확히 말하면 0x65678C 오프셋의 앞 2바이트는 골리앗 지상 공격 아이콘, 그 뒤의 2바이트는 마인 공격 아이콘입니다.

SetMemory(0x65678C, SetTo, 0xXXXXXXXX);

라고 하면 0xXXXXXXXX에서 파란색 부분(앞 2바이트)은 골리앗쪽 아이콘, 빨간색 부분(뒤 2바이트)은 마인 아이콘을 의미합니다.

왜 골리앗 아이콘이 바뀌었는지 이해가 되겠죠?

그래서 아까 마인 아이콘 변경 액션을 보면

SetMemory(0x65678C, SetTo, 311);

라고 했으니 311을 16진수로 바꾸면

SetMemory(0x65678C, SetTo, 0x00000137);

이 됩니다.

결국 골리앗 지상 공격 아이콘 정보를 담는 앞쪽 2바이트는 0000으로 되버리기 때문에

0번 아이콘인 마린 아이콘이 되어버리는겁니다.

그럼 골리앗 아이콘은 그대로 냅두고 마인만 바꾸고 싶다면 어떻게 해야 할까요?

골리앗 지상 공격 아이콘의 번호는 326이고 16진수로 0x0146입니다. 그러니까

SetMemory(0x65678C, SetTo, 0x01460137);

이렇게 하면 골리앗 지상 공격 아이콘은 그대로 기존 아이콘으로 설정돼고, 마인 아이콘도 핵폭발 아이콘으로 바뀌게 됩니다.

SetMemory(0x65678C, SetTo, 326*65536 + 311);

10진수로 하면 이렇게 표현할 수 있습니다. 이렇게 표현하면 각 아이콘 번호가 눈에 잘 들어오겠죠 (326번, 311번)

참고로 65536은 16^4이며 16진수로는 0x00010000입니다.

6. 1바이트 단위로 저장되는 정보

이러면 이것 역시 자동으로 이해되겠죠. 한 오프셋에 1바이트짜리 정보 4개가 들어있는 오프셋입니다.

대표적으로 업그레이드가 있습니다.

0x58D2B0 오프셋에는 플레이어1의

Terran Infanty Armor (테란 보병 방업),

Terran Vehicle Plating (테란 차량 방업),

Terran Ship Plating (테란 공중 방업)

Zerg Carapace (저그 지상 방업)

이렇게 4가지 정보가 들어가있습니다.

2바이트 단위 저장과 같은원리로 테란 보병 방업을 1업으로 만들고 싶다고

SetMemory(0x58D2B0, SetTo, 1);

라고 하면 테란 보병 방업이 1로 설정되면서 테란 차량, 테란 공중, 저그 지상 방업들도 다 0업으로 설정됩니다.

SetMemory(0x58D2B0, SetTo, 0xWWXXYYZZ);

라고 하면 0xWWXXYYZZ에서

ZZ는 테란 보병 방업, YY는 테란 차량 방업, XX는 테란 공중 방업, WW는 저그 지상 방업을 의미합니다.

테란 보병방업을 1업, 테란 차량 방업을 10업, 테란 공중 방업을 255업, 저그 지상 방업을 45업으로 만들고 싶다면

SetMemory(0x58D2B0, SetTo, 0x2DFF0A01);

가 되며 10진법으로 표현하면

SetMemory(0x58D2B0, SetTo, 45*16777216 + 255*65536 + 10*256 + 1*1);

이 됩니다.

여기서 업그레이드가 왜 최대 255업인지 알 수 있습니다.

업그레이드 하나당 1바이트(= 256가지)의 정보를 저장할 수 있으므로 0~255업까지 존재하는겁니다.

다른 예로 테란 공중 방업을 +3 한다고 하면

SetMemory(0x58D2B0, Add, 0x00030000);

가 되며 10진법으로 표현하면

SetMemory(0x58D2B0, Add, 3*65536);

이 됩니다.

Q. 그렇다면 Memory 조건으로 테란 보병 방업이 정확히 1일때를 인식하려면 어떻게 해야하나요?

A. Memory 조건으로 표현하면

Memory(0x58D2B0, Exactly, 0x00000001);

이렇게 되는데 이러면 테란 보병 방업이 정확히 1업이고 동시에 나머지 테란 차량, 공중 방업과 저그 지상 방업이 모두

0업일때를 인식합니다. 정확히 테란 보병 방업만을 인식하는건 경우의 수가 적다면 for문으로 노가다를 하면 되지만

아닐 경우에는 TEP에서는 구현하기 어렵습니다.

7. EUD 호환 오류 (미지원 오프셋)

Trigger {

players = {P1},

conditions = {

Always();

},

actions = {

SetMemory(0x00004C, SetTo, 0);

}

}

이렇게 0x4C라는 주소의 값을 0으로 만드는 트리거를 만들고 맵을 실행해봅시다.

그럼 "죄송합니다. 이 EUD 지도는 스타크래프트 리마스터와 호환되지 않습니다." 라는 오류가 뜨면서

확인 버튼을 누르면 스타 첫 화면으로 나가집니다.

이 오류는 스타크래프트 리마스터에서 지원하지 않는 오프셋 주소에 접근하면 발생하는 오류입니다.

위에서 0x4C라는 오프셋을 건드렸는데 이 주소는 리마스터에서 지원되지 않는 주소이기 때문에 오류가 뜨는겁니다.

아래에 EUD ERROR: 0xFFFFFFB3은 접근한 미지원 오프셋 주소를 의미합니다.

0xFFFFFFFF - (접근한 미지원 오프셋) = EUD ERROR 입니다.

0xFFFFFFFF - 0x4C = 0xFFFFFFB3 니까 0x4C라는 미지원 오프셋에 접근해서 생긴 오류라는 뜻입니다.

이 오류는 나중에 TE나 epScript 같은걸 다루게 되면 심심할 때마다 볼 오류창이기 때문에 잘 기억해두시는게 좋습니다.