CAFE

CK 모드 게시판

[CK2 모딩 팁]내멋대로 쓰는 Crusader King 2 모딩 매뉴얼 (3) 스코프 - 개정판 (2015/10/08 수정)

작성자tacitus|작성시간15.02.13|조회수2,929 목록 댓글 29

내멋대로 쓰는 Crusader Kings 2 모딩 매뉴얼 - 개정판

4. 디시전 파일의 작성

지난회에서 일반적인 디시전 파일의 구조에 대해서 살펴봤습니다. 이번부터 몇 회에 걸쳐 설명하는 내용들은 디시전에서 뿐만 아니라, 이벤트 등 다른 대부분의 곳에 적용되는 내용입니다. 모딩의 기초에 관한 내용으로, 이 내용을 모르면 답이 없습니다. 최대한 자세히 반복적으로 설명하겠으니, 이해하려고 노력해 보십시오. 다만, 우리가 현재까지 살펴본 내용은 오직 디시전 하나 뿐인 만큼, 설명은 디시전의 조건 및 효과 구현에 바탕을 두고 설명할 것입니다. (다만, 디시전에 한정된 내용이 아니라는 점은 꼭 명심하십시오!) 조금 어려운 내용이 될 수도 있습니다.

(4) 스코프

■ 스코프의 이해

앞에서 우리는 디시전의 구조에 대해서 보고 있었죠. 그리고 효과 부분을 그냥 날로 먹고 건너뛰었었습니다. 뼈다구만 던저주고 살은 하나도 안 붙여주면 어쩌란 말이냐... 그래서 이번엔 거기에 살을 좀 붙여볼까 합니다. 그런 의미에서 잠깐 앞으로 돌아가 보죠. 앞에서 보았던 코드를 다시 가져왔습니다.

vassal_decisions = {
  test_decision = {
    from_potential = {
      ai = no
      in_command = no
      prisoner = no
      NOT = { trait = incapable }
    }
    potential = {
      is_alive = yes
      prisoner = no
      NOT = { trait = incapable }
    }
    allow = {
      age = 16
      trait = ambitious
    }

    ...
  }
}

코드 자체는 지난 회에 다 설명드린 내용이니 읽을 수 있겠죠?

지금까지 아무 생각 없이 써 왔습니다. 예제의 vassal_decisions 에서, from_potential 안에는 플레이어와 관련된 조건을 적었고, potential 안에는 (상대) 봉신/가신 등에 관련한 조건을 적었죠. allow 에서는 특별히 이야기를 하지 않았지만 어쨌거나 상대방에 관련된 조건들을 적었던 것 같습니다. 즉, "이 섹션에서는 기본적으로 이 인물에 대해서 기술을 하겠다"라고 정해진 게 있다는 뜻이 되겠죠? 이렇게 특정한 인물, 장소, 타이틀 등을 가리키는 표지를 우리는 스코프라고 부릅니다.

아직까지는 이런 스코프를 명시적으로 선언하지 않았었습니다. (사용할 수 없다는 게 아니라 사용할 필요가 없었던 것 뿐입니다. 만약 사용할 필요가 있다면 사용해도 됩니다.) 각각의 섹션의 기본 스코프를 사용해도 충분했으니까요. 그런데, effect 에 오면, 어떤 효과는 플레이어에게 발생시켜야 할 수도 있고, 어떤 효과는 상대방에게 발생시켜야 할 수도 있습니다. 예를 들면, 특정한 봉신이 매우 밉습니다. 그래서 이 봉신을 불이익 없이 가두거나 작위를 빼앗을 수 있도록 하는 치트 디시전을 만들고 싶습니다. 그렇다면, 작위를 빼앗을 수 있다는 플래그는 해당 봉신에게 주어야 하니 그 이벤트는 봉신에게 일으켜야겠고, 그 이벤트가 정상적으로 일어났다는 것을 플레이어가 알 수 있게 하려면 플레이어에게 뭔가 메시지 창을 띄워줘야 하는데, 그건 플레이어에게 이벤트를 일으켜야겠죠? 그렇다면 같은 effect 항목 내에서 이들을 분리해서 쓸 뭔가가 필요할 겁니다.

■ 기본 스코프 : ROOT / FROM

이제 기본 스코프 표시자인 ROOT 와 FROM 을 먼저 확인해 봅시다. 어떤 이벤트나 디시전에서 ROOT 는, 거의 예외 없이 해당 이벤트를 받는 자(당하는 자)를 가리킵니다. 그리고 FROM 은 예외가 좀 있지만 일반적으로 그 이벤트를 주는 자(실행시킨 자)를 가리킵니다. 바로 위에 예를 든, 봉신에게 없는 죄 뒤집어 씌우기 디시전이 실제로 있다고 할 때, 디시전 내에서 ROOT 는 누구고 FROM 은 누굴까요? 네. FROM 은 해당 디시전을 실행시킨 플레이어가 되고, ROOT 는 생사람 잡히는 바로 그 봉신이 되는 겁니다.

이런 FROM 과 ROOT 의 할당은 바로 그 이벤트/디시전 내에서는 전체적으로 유효합니다. 따라서, 이 디시전 내의 어느 부분에서도, FROM 스코프는 플레이어이고, ROOT 스코프는 견제를 당하는 봉신이 되는 겁니다.

그럼 FROM 과 ROOT 를 써서, 디시전의 effect 섹션을 완성해 보도록 하죠.

vassal_decisions = {
  test_decision = {
    from_potential = {
      ai = no
      in_command = no
      prisoner = no
      NOT = { trait = incapable }
    }
    potential = {
      is_alive = yes
      prisoner = no
      NOT = { trait = incapable }
      liege = { character = FROM }
      host = { character = ROOT }
    }
    allow = {
      age = 16
      trait = ambitious
    }
    effect = {
      FROM = {
        hidden_tooltip = {
          character_event = {
            id = TST.1001
          }
        }
      }
      ROOT = {
        hidden_tooltip = {
          character_event = {
            id = TST.1002
          }
        }
      }
    }

    ...
  }
}

potential = { } 에 liege = { character = FROM }, host = { character = ROOT } 의 두 줄이 추가로 들어갔습니다. 함께 설명드릴 요량으로 넣은 부분인데, 이 부분에 대해서는 뒤에서 따로 설명을 드리겠습니다. 일단은 없다고 생각하고 읽어주세요.

아직 이벤트는 작성하지 않았지만, TST.1001 이벤트는 플레이어에게 이제 그 봉신은 니 멋대로 작위를 빼앗아도 된다고 알려주는 창을 띄우는 이벤트고, TST.1002 이벤트는 지정한 봉신에게 생사람 잡는 죄를 뒤집어 씌우는 이벤트입니다. 아직 작성은 안 했지만, 그런 이벤트라고만 생각하고 넘어갑시다.

위 예제 소스를 보면, 당연하게도 FROM (플레이어) 에게는 이벤트 ID가 TST.1001 인 이벤트를 실행시키고, ROOT (봉신) 에게는 이벤트 ID가 TST.1002 인 이벤트를 실행시키고 있죠. character_event = { } 는 해당 스코프(의 인물)을 향해서 지정한 이벤트를 발생시키는 명령이니 여기서 반드시 알고 넘어갑시다. 이걸로 여러분은 디시전을 통해서 특정한 이벤트를 실행시키는 방법까지 아시게 된 겁니다. ^^

이벤트에는 character_event, province_event, letter_event 등의 종류가 있습니다. 이 경우는 캐릭터에게 이벤트가 발생하는 것이니 character_event = { } 를 사용하겠습니다. 이 내용들은 나중에 이벤트 파일을 작성할 때 다시 보게 될 내용이니 그때까지만 참으세요.

위의 예제에서는 이벤트를 실행시켰습니다만, 꼭 이벤트를 호출할 것 없이, 간단한 커맨드는 직접 적어줘도 됩니다. 예를 들면,

vassal_decisions = {
  test_decision = {
    ...
    effect = {
      FROM = {
        change_intrigue = 1
      }
      ROOT = {
        prestige = 1
      }
    }
    ...
  }
}

이렇게 간단한 내용은 굳이 별도의 이벤트를 호출하지 않고, 디시전의 effect 섹션에 일어날 일을 모두 적은 후 별도의 이벤트를 일으키지 않을 수도 있습니다. 다만 이렇게 적으면 실제 이 이벤트가 일어난건지 아닌지를 플레이어가 알아채기 어렵다는 문제가 있기 때문에, 최소한 알림 이벤트나 메시지 이벤트 정도는 띄워 주는 게 사용하기 좋습니다.

또 다시 CKII 모드 기본 상식 시간. change_intrigue 는 해당 캐릭터의 음모(Intrigue) 수치를 증가/감소시킵니다. prestige 는 해당 캐릭터의 명성 수치를 1 올려주고요.

그런데, 좀 이상하죠? 우리의 일반적인 상식에 비추어 보자면, 보통 xxx = N(숫자) 이라는 수식구는 xxx 의 값을 N 으로 만들라는 정의(definition) 명령이 되는 게 보통입니다. 그런데 저는 분명히 바로 위에서, Intrigue 수치나 Prestige 수치를 1로 "만드는" 것이 아니라, 1을 "증가"시킨다고 말씀드렸지요.

이건 매우 중요한 내용인데, CKII 모드의 명령문 중 숫자값을 입력받는 명령문의 경우, 어떤 변수나 데이터를 어떤 값으로 "정의" 하는 예는 극히 드뭅니다. 대부분의 경우 값을 증가시키거나 감소시키는 것입니다. (저도 지금 가만히 생각을 해 봤는데, 값을 정의하는 명령어 중 당장 생각나는 것은 set_variable = { } 명령어 하나 뿐입니다.) 따라서, 어떤 숫자값을 집어넣는 명령어를 만났다면, 일단 이건 지정한 값만큼 증가/감소시키라는 명령어다 라고 아시면 거의 틀리지 않습니다. (정의의 의미가 되는 경우는 글이 진행되면서 관련 내용이 나오면 분명히 말씀드립니다.)

따라서, prestige = 1 명령어는 명예 수치를 1로 만들라는 의미가 아니라, 명예 수치를 1 증가시키라는 명령어가 되는 거고, change_intrigue = 1 명령어는 음모력 수치를 1 증가시키라는 의미가 되는 겁니다.

하나 더 알아두실 것. 이렇게 값을 증감시키는 경우, 숫자에 + 기호는 잘 쓰지 않습니다. 써도 상관 없지만, 굳이 쓰지 않는다는 의미입니다. 안 쓰면 알아서 + 로 생각해서 값을 증가시켜 줘요. 숫자에 - 기호를 붙여 주면 값을 감소시킨다는 의미가 됩니다.

음. FROM 에 관련해서 하나 말씀드릴 내용이 남았습니다. 지난 회에서, decisions = { } 안에 정의되는 일반적인 디시전의 경우에, from_potential = { } 섹션을 정의하지 않는다고 말씀드렸지요. 이제 FROM 을 알고 계시니, 그 이유를 설명드리기가 좀 더 편해졌네요.

디시전이건 이벤트이건, 그것을 받아서 실행되는 자는 언제나 ROOT 이고, 따라서 ROOT 가 없는 경우는 없습니다. 그 결과로 FROM 이 무의미해지는 경우가 생깁니다. 이 경우도 그렇습니다. 자신에게 실행되는 디시전이어서 FROM = ROOT 가 되어 FROM 이 무의미하고, 따라서 정의하지 않으며, FROM 이 정의되지 않으므로 FROM 의 조건을 정의하는 from_potential = { } 섹션도 무의미하여 정의하지 않는 것입니다.

내부적으로는 이런 경우 FROM 에도 ROOT 와 같은 값을 넣어두는 것 같긴 합니다. (오류가 발생하지 않는 것을 보면요.) 따라서, ROOT = FROM 이라고 설명해도 됩니다. 그렇게 설명하지 않는 이유는, 일반 디시전에서 from_potential = { } 섹션을 정의하지 않는 이유를 FROM 값과 연계하여 이해시키기 위해서입니다. ^^

또한, 특수한 이벤트나, 디시전과 이벤트 외의 다른 부분에서 FROM 과 ROOT 가 쓰일 때는, FROM 과 ROOT 의 값이 콕 찝어서 지정되는 경우가 있습니다. on_events 의 경우가 그러한데, 지금은 그런 경우도 있다는 것만 봐두시고 잊어버리십시오. 그 때 가서 다시 말씀드리겠습니다.

■ 이벤트의 연결과 ROOT/FROM

지금 우리는 FROM, ROOT 의 기본 스코프와, 디시전을 통해 특정한 이벤트를 실행시키는 법까지 살펴봤는데요. 아직 이벤트 파일을 만들진 않았지만 만들었다 치고, TST.1001 과 TST.1002 이벤트를 통해서 기본 스코프에 대한 걸 복습해 보도록 하죠. 위의 예제에서, TST.1001 이벤트는 FROM 스코프를 향해 실행시켰고, TST.1002 이벤트는 ROOT 스코프를 향해 실행시켰습니다.

퀴즈 1. TST.1001 이벤트 내에서는 FROM 과 ROOT 가 누구를 의미하게 될까요?
퀴즈 2. TST.1002 이벤트 내에서는 FROM 과 ROOT 가 누구를 의미하게 될까요?

FROM과 ROOT 기본 스코프는 하나의 이벤트 내에서 유효하다고 앞에서 말씀드렸었죠. 그 이야기는, 다른 이벤트가 발생한다면, 새로 실행된 이벤트 내에서는 그들은 또 다른 값을 갖게 될 수 있다는 것을 의미합니다. 우리가 위의 예제 디시전을 실행시켰을 때, 그 디시전 내에서는 FROM 은 플레이어, ROOT 는 봉신이었습니다. 바꾸어 말해서, 그 디시전을 하나의 이벤트라고 생각했을 때, 디시전 이벤트 내에서 그 이벤트가 실행된 애는 ROOT(=봉신)가 되고, 그 이벤트를 날린 애는 FROM(=플레이어)이라는 의미가 됩니다.

그렇다면, 그 디시전에서 다른 이벤트를 호출한다면, 그 이벤트를 누군가에게 던지고 있는 애는 누굴까요? 플레이어는 봉신에게 디시전(이라는 이벤트)을 던졌을 뿐입니다. 현재 디시전이 실행되고 있는 애, 즉 이 디시전의 ROOT는 봉신이죠. 따라서 이 디시전이 다른 이벤트를 호출한다면, 그 이벤트를 실행시키는 주체는 봉신이고, 따라서 이 이벤트를 통해 실행된 TST.1001과 TST.1002 모두, 그 이벤트 내에서의 FROM 값은 봉신이 되는 것입니다. (이걸 이해를 못 하시면 모딩의 길이 에베레스트만큼 험준해지는 거죠.)

그럼 각각의 이벤트에서 ROOT는요? 이건 쉽죠. 지금 누구에게 실행되고 있는지 보면 되니까요. TST.1001 은 디시전에서 FROM 스코프(=플레이어)를 향해 실행되었으니, TST.1001의 ROOT는 플레이어죠. 그리고 TST.1002 는 디시전에서 ROOT 스코프(=봉신)를 향해 실행되었으니, TST.1002의 ROOT는 봉신이 되는 겁니다. 즉 답은,

  • TST.1001에서, FROM : 봉신, ROOT : 플레이어
  • TST.1002에서, FROM : 봉신, ROOT : 봉신

따라서, TST.1001 에서는, 봉신에게 효과를 발생시키겠다면 FROM 스코프 내에, 플레이어에게 효과를 발생시키겠다면 ROOT 스코프 내에 적어야 하는 겁니다.

■ FROM 스코프의 이어쓰기

이제 어느 정도 FROM 과 ROOT 스코프에 대해서 이해가 되셨으리라 생각합니다. 그런데, 한 가지 의문이 있네요. 앞의 결과에서, TST.1002 는 ROOT 도 봉신, FROM 도 봉신입니다. 그럼 TST.1002 이벤트 내에서는 플레이어에게는 어떤 효과도 발생시킬 수 없나요?

이럴 때에 사용할 수 있는 것이 바로 FROM 의 이어쓰기입니다. FROMFROM 이라고 적으면, 바로 앞 이벤트에서의 FROM 을 가리킬 수 있습니다. 즉, TST.1002 에서 플레이어에게 어떤 효과를 주고 싶다면, FROMFROM 스코프를 향해 무언가를 날리면 되는 거죠. 참고로 FROM 은 4회까지(2.2.x 버전까지는 3회) 이어쓰기할 수 있습니다. FROMFROMFROMFROM 까지 가능하다는 거죠.

그럼 ROOT 도 이어쓰기가 될까요? 안 됩니다. 어째서일까요? 필요가 없거든요. ROOTROOT 는 FROM 과 같잖아요?

이와 관련하여 한 가지 첨언하자면, 최소한 저는, 최근에는 Vassal Decision 에서 이벤트를 호출할 때 ROOT 를 향하여 호출하는 방식은 잘 쓰지 않습니다. 왜냐 하면, Vaildator 에서 이 부분에 대해서 지속적으로 문제를 제기하기 때문입니다.

예를 들어, 어떤 Vassal Decision 에서 ROOT 스코프로 이벤트를 실행시켰다고 합시다. 그럼 이 이벤트에서는 위에서 본 바와 같이 ROOT : 봉신, FROM : 봉신, FROMFROM : 플레이어 가 될 것입니다. 이 상태에서 실제로 FROMFROM 을 스코프로 하여 무언가를 실행하면 아무 문제 없이 실행이 됩니다. 그러나 Validator 에서는 FROMFROM 이 디시전으로 거슬러 올라가기 때문에, 이것이 실제로 의도한 것인지 오타인지 알 수 없다는 이유로 계속 이에 대해서 주의를 환기시킵니다. 영 신경쓰이는 일이죠. 그래서 중간에 스코프를 뒤집는 히든 이벤트를 하나 더 집어넣는 방식으로 이를 회피합니다.

■ 스코프의 중첩

우리는 지금까지 너와 나 사이의 문제로서 FROM 과 ROOT 스코프를 바라봤었습니다. 그런데, 어떤 이벤트와 디시전이 항상 너와 나 사이의 양자관계로 마무리되는 건 아닙니다. 이벤트에 등장하는 인물, 장소, 작위 등과 관련하여 삼각관계나 사각관계가 출현할 수도 있죠.

이처럼 이벤트에서 여러 개의 개체가 등장하는 경우, 이벤트의 발생을 나와 너 외의 다른 조건에 결부시켜야 하는 경우, 이벤트의 결과로 캐릭터 이외의 다른 요소들에게 효과를 발생시켜야 하는 경우 등처럼 ROOT 와 FROM 이외에 제3, 제4의 스코프가 필요해지는 경우가 있습니다. 이제 너와 나 이외의 인물, 장소, 작위 등을 어떤 식으로 표현할 수 있는지를 확인하겠습니다.

1) 스코프의 연결

예를 들어, 이벤트의 발생 조건을 ROOT 가 아니라 ROOT 의 아버지에게 연계시키고 싶습니다. 나의 가신들 중에서 아버지가 아직 살아 있는 가신들을 조건으로 하는 vassal decision 을 만들 참입니다. 그렇다면 ROOT 의 아버지를 표현할 방법이 필요해지네요.

  potential = {
    ROOT = {
      father = {
        is_alive = yes
      }
    }
    host = { character = FROM }
  }

일단 is_alive 는 지난 회에서도 한번 나왔지만, 현재 스코프의 캐릭터가 현재 살아 있는지를 확인하는 조건문입니다. 값이 yes 이므로 현재 살아 있는 캐릭터만을 대상으로 하는 거죠.

host = { character = FROM } 에 대해서는 잠시 후에 설명드리겠습니다. 일단 이 줄이 들어감으로써, ROOT의 범위에서 직접봉신이 빠지고 가신만 포함되게 된다는 점만 아시면 됩니다. (가신을 대상으로 하는 디시전을 만들 때 꽤 많이 사용되는 조건이니 눈에 익혀 두시면 쓸 일이 많습니다.)

문제는 father = { } 입니다. 이 father = { } 는 캐릭터 스코프에서 사용되며, 현재 스코프 캐릭터의 아버지 캐릭터를 향하여 스코프를 열어줍니다. 즉 ROOT = { } 안쪽은 ROOT 캐릭터의 스코프이지만, 그 안쪽의 father = { } 중괄호 안쪽은 ROOT 의 스코프가 아니라 ROOT 의 아버지 스코프라는 것입니다. 이제 위의 조건은 쉽게 해석이 되시겠죠?

갑자기 캐릭터 스코프라는 말을 강조하고 있습니다. 사실 그동안 나왔던 모든 스코프가 다 캐릭터였는데 말이죠. FROM도, ROOT도, 그동안 봤던 디시전 섹션들의 기본 스코프도 모두 캐릭터였습니다. 그렇기 때문에 고민할 필요도 없었죠.

그런데, 사실 스코프는 반드시 캐릭터만 가능한 것은 아닙니다. 특정한 작위를 나타낼 수도 있고, 특정한 프로빈스(지역)를 나타낼 수도 있습니다. 아직은 예가 없었지만, 이런 예들 바로 다음에 보게 되니 기대하시고요.

현재 스코프가 어떤 스코프인지 아는 것이 왜 중요한가 하면, 각종 명령어나 조건문을 쓸 때에, 현재의 스코프가 어떤 스코프냐에 따라서 사용할 수 있는 명령어, 조건문 또는 스코프 지시자 등이 달라지기 때문입니다. 위의 예만 하더라도, ROOT 가 캐릭터 스코프가 아니라면 father = { } 스코프 지시자를 쓸 수가 없지 않겠습니까? 장소나 타이틀에 아버지가 있을 리가 없잖아요? 캐릭터니까 아버지가 있는 거지.

다른 경우도 마찬가집니다. 장소나 타이틀에 대해서 쓸 수 있는 명령어는 캐릭터 스코프 내에서는 사용할 수가 없는 겁니다. 특정한 장소에 건물 지으라는 명령을 캐릭터나 타이틀에 대해서 쓰면, 캐릭터 머리 위에 건물을 올릴 겁니까, 작위 위에 건물을 올릴 겁니까. 안 되겠죠? 컴퓨터는 깡통이라서, 융통성 따위는 눈꼽만큼도 없기 때문에, 이런 것을 다 맞춰 주어야 합니다.

이렇게 하나의 스코프 안에 다른 스코프가 나타나는 것을 저는 스코프의 중첩이라고 부릅니다. 공인된 용어는 아니지만, 어쨌거나 이 글에서 제가 계속적으로 사용할 용어이니 일단은 체크해 두십시오.

이와 같이, 스코프는 여러 차례 중첩하면서 새로운 스코프를 열어나갈 수 있습니다. 주목할 부분은, 뒤쪽에 중첩되는 스코프가 바로 직전의 스코프와 서로 무관계하지는 않다는 것입니다. 예를 들어 father = { } 만 있다면, 이 스코프는 대체 누구의 아버지를 의미하는 것인지 알기 어렵습니다. 그러나 그 father = { } 스코프 지시자는 ROOT 라는 캐릭터 스코프 안쪽에 있기 때문에, "아, ROOT 의 아버지!" 라고 바로 알 수 있는 것이죠.

이처럼 스코프가 중첩되는 경우에, 이전 스코프와 현재 스코프가 결합하여 새로운 대상에 대해 스코프가 형성되는 것을 저는 "스코프의 연결" 이라고 칭하겠습니다. (이 역시 공인된 용어는 아닙니다.)

이미 깨달으신 분도 계시겠지만, 사실 ROOT 는 없어도 상관 없죠. 왜? potential = { } 섹션의 기본 스코프가 ROOT 니까요. 다만 이건 설명을 위한 글이니까, 명확히 하기 위해 적었습니다.

이런 스코프의 연결 예는 상당히 많습니다. 자주 쓰이는 예들만 알아보겠습니다. 그냥 공식처럼 알아 두시는 것도 좋습니다.

  • 캐릭터 = { father = { } } : 특정한 캐릭터의 아버지를 향해 스코프를 전환합니다. father 이외에 mother 도 가능합니다.
  • 캐릭터 = { spouse = { } } : 특정한 캐릭터의 배우자를 향해 스코프를 전환합니다.
  • 캐릭터 = { liege = { } } : 특정한 캐릭터의 바로 위 군주를 향해 스코프를 전환합니다.
  • 캐릭터 = { host = { } } : 특정한 캐릭터의 주군을 향해 스코프를 전환합니다. (아래의 설명을 더 보세요)
  • 캐릭터 = { top_liege = { } } : 특정한 캐릭터가 속한 렐름 내에서 가장 높은 군주가 누구인지를 찾아 그에게 스코프를 전환합니다. 예를 들면, 왕국 내에서 공작의 봉신인 백작으로 플레이를 하고 있는 경우, 앞에 적었던 liege = { } 는 바로 위 주군인 공작을 가리키게 됩니다만, top_liege = { } 는 가장 높은 군주인 왕을 가리키게 됩니다.
  • 캐릭터 (또는 프로빈스) = { religion_head = { } } : 현재 캐릭터 또는 프로빈스가 가진 종교의 최고 지도자를 향해 스코프를 엽니다. 이 때 최고 지도자는 가톨릭 교황의 경우 대립교황도 포함됩니다.
  • 캐릭터 = { any_courtier = { } } : any_courtier = { } 스코프 지시자는 정말 무지막지하게 자주 쓰이죠. 특정한 캐릭터의 가신들 모두를 향해 스코프를 전환합니다. 보통 가신은 여러 사람이므로, 복수의 대상을 향해 스코프가 열리는 셈입니다.
  • 캐릭터 (또는 타이틀) = { any_vassal = { } } : 특정한 캐릭터의 봉신들 모두를 향해 스코프를 전환합니다. 마찬가지로, 보통 봉신은 여러 사람이므로, 복수의 대상을 향해 스코프가 열립니다.
  • 캐릭터 (또는 타이틀) = { any_realm_character = { } } : 특정한 캐릭터의 가신 및 봉신을 포함하여, 해당 캐릭터 또는 타이틀의 휘하에 있는 모든 캐릭터가 스코프 안으로 들어옵니다. (예를 들면, 캐릭터의 봉신의 가신, 캐릭터의 봉신의 봉신도 모두 스코프 안에 들어옵니다.)

이제 때가 됐군요. 앞에서 스크립트에 추가했던 liege = { character = FROM }, host = { character = ROOT } 의 두 줄에 대해서 말씀드릴 때가 왔습니다.

이제 liege = { } 가, 자신의 바로 위 군주를 나타낸다는 사실을 알고 계십니다. 일반적인 봉건 군주와 봉신 사이의 관계에서 자신의 주군을 표현하는 거죠. 문제는 host = { } 입니다. 가신의 주군을 봉건 영주의 주군과 구분해서 뭐라고 표현해야 할지 몰라서 위의 표현이 이상하게 되었는데, host 는 현재 내가 누구의 가신인가를 표시하는 것입니다. 일단 의미는 아시겠죠?

이 두 값은 서로 같을 수도 있고 다를 수도 있습니다. 만약 A라는 캐릭터가 B 군주 아래에 가신으로 있는 백수 캐릭터라면, host 와 liege 는 둘 다 B 를 가리키게 됩니다. 그러나, A 캐릭터가 B 군주 아래에 봉신으로 있는 봉건영주라면, liege 는 B 이지만 host 는 자기 자신도 영주이기 때문에(따라서 B 군주의 궁전에 있지 않고 자신의 궁전에 있게 되므로) 자기 자신인 A 를 가리키게 되는 것입니다.

이제 새로 추가했던 두 줄이 해석이 되시죠? liege 는 FROM 이지만 host 는 자기 자신인 자, 즉 FROM 휘하의 봉건 영주들만을 골라내기 위한 코드가 되는 겁니다. (중간에 host = { character = FROM } 이라는 코드도 이해 하시겠죠? FROM(=플레이어)의 가신일 것이라는 조건. 앞에서도 말씀드렸지만, 이건 정말 많이 쓰입니다.)

그러나, 이 코드는 완벽하지 않습니다. 왜? 봉건 영주임에도 불구하고 host 값이 자신의 주군을 가리킬 때가 있거든요. 언제일까요? host 값이 자신의 영주를 가리킨다는 것은 현재 그 봉건 영주가 자신의 주군의 궁에 와 있다(봉건 영주임에도 바로 위 주군의 가신이다)는 이야깁니다. 그런 경우가 있죠. 스스로 주군의 참사회원으로 일하고 있거나, 혹은 주군의 감옥에 갇혀 있는 경우가 그렇죠. 따라서, 위 코드는 봉신 영주들을 모두 포괄할 수 없을 수도 있습니다. (그야말로 설명을 위한 코드였습니다. 실제로 이런 용도로 사용되는 조건문이 따로 있습니다. liege 와 host 의 구별을 설명하기 위해서 투입한 것입니다. ^^)

이야기가 나온 김에 하나 더 이야기를 해 보죠. 감옥에 갇히게 되면 감옥에 갇힌 캐릭터는 그 감옥의 주인 캐릭터의 가신이 된다는 점을 앞에서 보셨습니다. 그래서 직접봉신일지라도 liege 값과 host 값이 모두 주군을 가리키게 된다고 말씀드렸죠. 그런데, 이번엔 반대로, 플레이어의 감옥에 있는 죄수여서 host 값은 플레이어를 가리키고 있지만 liege 값은 플레이어를 가리키지 않는 경우가 있습니다. 언제일까요? 네. 전쟁 포로의 경우가 그렇겠죠. 전쟁에서 포로로 잡히더라도 그 포로는 다른 누군가의 봉신 또는 독립 세력이니까, liege 값은 다른 주군 또는 자기 자신을 가리키고 있겠지만 현재 플레이어의 감옥에 있으므로 host 값은 플레이어가 되겠죠. 이를 이용해서, 외국과의 전쟁에서 잡힌 전쟁 포로와, 반란 또는 기타 이유로 감옥에 갇힌 플레이어의 가신/봉신 포로를 구분할 수 있습니다.

참고로, 연결은 두 단계 이상으로 확장될 수도 있습니다. 예를 들면,

  ROOT = {
    liege = {
      any_vassal = {
        ...
      }
    }
  }

위의 예를 보시면, 자신이 봉신으로 있는 렐름의 다른 봉신들에 대해서 스코프를 열고 있는 것을 알 수 있습니다. (ROOT의 주군의 모든 봉신들!)

2) 스코프의 전환

스코프의 중첩 중에서 연결과 비슷하지만 약간 성격이 다른 것이 있습니다. 예를 들면 이런 것입니다.

현재 캐릭터가 위치하는 프로빈스의 종교와 캐릭터의 종교가 서로 다른 경우 캐릭터가 프로빈스의 종교로 개종하는 디시전을 만들고 싶습니다. 여기에서 등장하는 객체는? 나(ROOT)와, 현재 내가 존재하는 프로빈스죠. 등장 인물이 나 뿐이므로 디시전의 타겟이 정해지지 않는 디시전(decisions = { })으로 작성하면 될 테고, 이 조건은 potential = { } 또는 allow = { } 내에 정의하면 될 것 같군요. (또는 effect = { } 내에 if = { } 조건문으로 정의해도 됩니다만, 우린 아직 조건문 안 봤으니...) 디시전의 특성상 potential = { } 내에 적는 것이 좀 더 적합해 보입니다.

아 잠깐. 고민스러운 상황이 발생했네요. 내 캐릭터는 ROOT 로 표현할 수 있지만, 내 캐릭터가 있는 프로빈스는 어떻게 표현하면 되죠? 우리가 지금까지 보아 온 스코프는 FROM과 ROOT 뿐인데, 이걸로 프로빈스는 표현할 수가 없잖아요?

일단 아래의 코드를 보면서 설명드리도록 하죠.

decisions = {
  potential = {
    ROOT = {
      location = {
        NOT = { religion = ROOT }
      }
    }
  }
  ...(이하생략)...
}

앞에서 보았던 스코프의 중첩이 일어나고 있죠. ROOT 라는 스코프 지시자 안에 location = { } 이라는 스코프 지시자가 중첩적으로 사용되었잖아요? location = { } 은 캐릭터 스코프 내에서 쓰이면 그 안쪽의 스코프를 그 캐릭터가 위치하는 프로빈스의 스코프로 전환해 주는 스코프 지시자입니다. 따라서, ROOT = { } 의 안쪽은 캐릭터 스코프였습니다만, 그보다 더 깊은 location = { } 의 안쪽은 프로빈스 스코프가 되는 겁니다.

그리고, religion 조건문은 캐릭터 또는 프로빈스의 종교를 확인하는 조건문입니다. 현재의 스코프가 location = { } 스코프 안쪽이기 때문에, religion = ROOT 조건문은 ROOT 의 종교와 현재 스코프인 프로빈스의 종교를 비교하게 되는 데, 이것이 NOT = { } 안에 들어 있기 때문에 (지난 회에도 살짝 건드렸고 다음 회에도 다시 보게 될 겁니다만, NOT = { } 은 조건의 부정을 의미합니다.) ROOT 의 종교와 현재 프로빈스의 종교가 서로 다른 경우를 의미하게 됩니다.

참고로, 위키에서 religion 조건문을 찾아보면 캐릭터 스코프에서 사용 가능하다고 되어 있습니다만, 프로빈스 스코프에서도 사용이 가능합니다. 원본의 경우에 location = { } 안쪽에서 쓰인 예는 없습니다만, 같은 프로빈스 스코프 지시자인 capital_scope = { } 내에서는 사용된 예가 있습니다.

자, 여기에서의 스코프의 중첩을 한번 생각해 봅시다. ROOT 와 location 이 서로 중첩되고 있는데, 이것은 앞에서 보았던 스코프의 연결과 무슨 차이가 있을까요? 스코프의 연결에서는 두 개의 스코프가 연결되어 새로운 대상을 가리키게 되었지만, 그 성질이 캐릭터 스코프라는 점은 바뀌지 않았습니다. 그러나, 여기의 경우는 두 개의 스코프가 연결되어 새로운 대상을 가리키기 된 점은 연결과 같지만, 그 성질이 바뀌었죠. 캐릭터 스코프에서 프로빈스 스코프로 바뀌어 버렸습니다. 이처럼 중첩을 통해서 스코프의 대상 뿐만 아니라 성질도 바꿀 수 있는데, 이런 경우를 저는 스코프의 "전환"이라고 부르고 있습니다.

이처럼 캐릭터인 ROOT, FROM 을 시작으로 해서 그와 연관되는 다양한 캐릭터, 프로빈스, 타이틀 등으로 스코프를 전환하여 표현이 가능합니다. 보통 이벤트나 디시전을 짜다 보면 이런 종류의 스코프 전환을 정말 많이 사용하게 될 텐데요. 많이 사용하는 몇몇 스코프 지시자들은 아예 공식처럼 알아두는 것이 쓰기 좋습니다. (더 많습니다만, 정말 자주 쓰게 되는 것들만 적었습니다.)

  • 프로빈스 또는 타이틀 = { holder_scope = { } } : 프로빈스 또는 타이틀 스코프를 그 프로빈스 또는 타이틀의 소유자 스코프(캐릭터 스코프)로 전환합니다. (holder_scope 와 owner 는 서로 같은 역할입니다.)
  • 캐릭터 = { location = { } } : 캐릭터 스코프를 그 캐릭터가 현재 위치하는 프로빈스의 스코프(프로빈스 스코프)로 전환합니다.
  • 프로빈스 = { county = { } } : 프로빈스 스코프를 그 프로빈스의 백작령 타이틀을 나타내는 스코프(타이틀 스코프)로 전환합니다.
  • 캐릭터 = { capital_scope = { } } : 특정한 캐릭터의 수도 프로빈스를 향해 스코프를 엽니다. 따라서 이 안쪽의 스코프는 프로빈스 스코프가 되죠.

어떤 스코프 안에서 쓰일 수 있는지만 제대로 맞춰준다면, 이처럼 여러 번의 중첩도 가능합니다. 이런 스코프의 중첩은 이벤트를 구성하는 데 있어서 굉장히 유용하게 쓰입니다. 물론, 스코프의 연결과 마찬가지로 두 번 이상의 중첩도 얼마든지 가능합니다.

potential = {
  ROOT = {
    location = {
      duchy = {
        holder_scope = {
          any_courtier = {
            is_female = yes
          }
        }
      }
    }
  }
}

정말 예시를 위한 예시가 되었지만, 위의 스코프 중첩을 읽으실 수 있겠습니까? ROOT가 존재하는 프로빈스(location : 캐릭터 → 프로빈스)의 상위 공작령 타이틀(duchy : 프로빈스 → 타이틀)을 가진 자(holder_scope : 타이틀 → 캐릭터)의 모든 가신들(any_courtier) 중에서 여성(is_female = yes)이 있을 것을 조건으로 설정하는 potential = { } 섹션입니다. (대체 이런 걸 조건으로 하는 디시전이 어디 있겠어요? 진짜 어거지로 만든 예시입니다...)

3) 스코프의 단절

스코프 지시자들 중에는, 바로 앞의 스코프가 무엇이었건 상관하지 않고, 항상 자신의 고유한 스코프를 나타내는 경우가 있습니다. 가장 가까운 예로 우리가 지금까지 내내 쓰고 있었던 FROM, ROOT 가 있죠. 얘들은 스코프가 여러 차례 중첩되는 경우 어느 위치에 있건 바로 앞의 스코프를 잘라먹고 그 안쪽을 자신의 고유한 스코프로 바꾸어 버립니다. 아래의 예를 보시죠.

effect = {
  ROOT = {
    top_liege = {
      FROM = {
        random_courtier = {
          ...(실행할 명령어)...
        }
      }
    }
  }
}

위의 예를 보시면 뭔가 이상하다는 느낌이 드실 겁니다. ROOT 의 top_liege 로 이어지던 스코프의 연결 과정에 뜬금없이 FROM 이 등장했죠? 일반적인 vassal_decisions 에서 FROM 은 앞의 스코프가 무엇이었건 언제나 이벤트를 실행한 자를 나타낸다고 했으니, 앞의 스코프가 무엇이었건 그 이하로는 FROM 을 나타내게 될 겁니다. 그 다음에 random_courtier = { } 는 FROM 과 연결되어 FROM 의 가신들 중 아무나 한 명을 나타내게 되고, 이제 선택된 그 가신 한 명에게 무언가 명령어가 실행되겠죠.

이처럼 이전의 스코프가 무엇이었건 상관 없이 자신의 고유한 스코프로 자신 이하를 바꿔 버리는 형태의 스코프의 중첩을 저는 "스코프의 단절"이라고 부릅니다. 이렇게 스코프의 단절을 가져오는 스코프 지시자들이 ROOT, FROM 말고도 몇 가지 더 있는데, 이에 대해서는 조금 아래에서 예시를 보실 수 있을 것입니다. 공통점은, 바로 이전의 스코프가 무엇이었건 상관 없이 쓸 수 있다는 것입니다. 어차피 끊어먹고 자기 멋대로 물줄기를 돌릴 거니까요.

다만, 아직도 해결되지 않은 의문은, 저럴 거면 왜 ROOT 와 top_liege 스코프를 앞에 넣었느냐는 것이겠죠. 현재까지 가르쳐드린 것만으로는 그 의문은 해결되지 않습니다. 그러나 곧 해결됩니다. 바로 다음을 보시면요. ^^

지금까지 스코프가 중첩되는 여러 가지 예들을 보셨습니다. 이어지는 내용은 이런 스코프의 중첩을 더욱 더 확장하여, 아예 너와 나 이외의 다른 요소들끼리의 이벤트를 구성하는 예입니다. 아울러, 굉장히 중요한 새로운 스코프 지시자도 몇 가지 더 확인하게 될 겁니다.

■ 스코프의 중첩과 PREV, THIS 스코프 지시자

초심자에게는 조금 복잡한 코드가 될 수도 있겠는데, 다음의 코드를 한번 보시죠.

e_byzantium = {
  holder_scope = {
    opinion = {
      who = ROOT
      modifier = opinion_unhappy
      months = 1200
    }
    hidden_tooltip = {
      k_papal_state = {
        holder_scope = {
          reverse_opinion = {
            who = PREVPREV
            modifier = opinion_unhappy
            months = 1200
          }
        }
      }
    }
  }
}

상당히 복잡해 보이죠? 지금 이 소스 하나를 통해서 스코프에 관한 내용을 작살내려는 참이니 하나씩 뜯어보도록 합시다. 이 소스는 원본의 realm_decisions.txt 파일에 포함되어 있는 내용입니다. 조건 섹션인 potential = { } 이 아닌, 효과 섹션인 effect = { } 섹션 안쪽에 있는 내용이예요. 따라서 조건문이 아니라 명령문으로 되어 있습니다.

자, 제일 처음에 e_byzantium 으로 시작하는데, 특정한 작위(=타이틀)를 스코프로 사용할 수 있습니다. (조금 뒤에 말씀드릴 내용이지만, 어차피 나왔으니...) e_ 로 시작하는 작위는 황제(emperor) 를 의미하고, k_ 은 왕(king), d_ 는 공작(duchy), c_ 는 백작(count), b_는 남작(baron) 타이틀을 의미합니다. 즉, e_byzantium 이라고 쓰면 비잔티움 황제 작위를 의미6)하게 되고, 이를 스코프로 사용하므로 이 안쪽의 스코프는 타이틀 스코프가 됩니다. 비잔티움 황제 타이틀에 대해서 그 이하의 내용을 실행하겠다 라는 의미겠죠. (바로 앞의 스코프가 무엇이었건, 이제부턴 비잔티움 황제 타이틀 스코프다 라고 하고 있으니, 중첩 유형 중에서 단절이죠?)

다음 줄의 holder_scope 는 이미 한번 본 스코프 지시자죠? 이제 이 안쪽은 이 타이틀을 갖고 있는 자를 의미하는 캐릭터 스코프가 되었습니다. (중첩 유형 중에서 전환이 되겠네요. 타이틀 스코프가 캐릭터 스코프로 바뀌었으니까요.)

그 안쪽의 opinion = { } 구는, 특정인의 특정인에 대한 오피니언 수치를 조정하는 명령어입니다. 현재의 스코프에 속하는 사람(즉, 비잔티움 황제 작위를 가진 사람)에게, who 에 지정된 사람(여기서는 ROOT 로 지정되어 있죠. 누군지는 이것만 갖곤 모릅니다)에 대해서 1200달(=100년)동안 opinion_unhappy 모디파이어에 지정된 오피니언을 적용하겠다는 겁니다. 이름으로 봐서는 오피니언 수치를 깎는 내용이겠군요. 뭔가 되게 어렵게 말했지만, 간단히 말해서 비잔티움 황제가 ROOT 를 싫어하게 된다는 의미가 되겠네요.

오피니언 모디파이어는 원본의 경우 common\\opinion_modifiers\00_opinion_modifiers.txt 에 정의되어 있으므로, 해당 파일을 열어서 opinion_unhappy 를 찾아보면 됩니다. 각종 모디파이어에 대해서는 이벤트로 넘어가서 설명할 기회가 있습니다.

그 다음에 hidden_tooltip = { } 은, 스코프를 나타내는 것이 아니라, 이 안쪽에 기록되는 내용은 플레이어에게 툴팁으로 알리지 말라는 의미가 됩니다. 이것도 자주 쓰이는 명령어이니 알아두시면 좋습니다.

자, 그 다음부터가 재미있는데, k_papal_state 라는 타이틀 스코프 정의가 나왔습니다. papal_state 는 교황령을 의미합니다. 바로 바깥의 스코프가 무엇이었건, 이제 k_papal_state (교황 타이틀) 안쪽으로는 다시 타이틀 스코프죠(단절). 다시 holder_scope 니까 그 타이틀을 가진 자, 즉 교황이라는 캐릭터 스코프입니다(전환). 그 다음에 나오는 reverse_opinion 은, 아까의 opinion 과 같이 오피니언 모디파이어를 적용하라는 명령이지만, 커맨드 앞에 reverse 가 붙었죠? 이건 화살표 방향이 바뀝니다. 아까 opinion 은 그 스코프의 캐릭터가 who 캐릭터에게 갖는 오피니언을 지정하지만, reverse_opinion 은 거꾸로 who 가 현재의 스코프의 캐릭터에게 갖는 오피니언을 지정하는 겁니다. 쓸 일은 많지 않지만, 알아두면 적용할 곳은 꽤 있습니다. 그게 중요한 게 아니고, 거기 who 에 PREVPREV 라는 처음 보는 녀석이 등장했다는 게 중요합니다. 사실 이 녀석을 쓰기 위해서, 도대체 왜 하는지 알 수 없었던 스코프 변경을 지금까지 몇 줄 동안 반복한 거거든요.

PREV는 말이죠. 지금처럼 여러 번의 스코프가 중첩이 된 경우에, 현재 스코프의 바로 직전 스코프를 의미합니다. 그럼 PREVPREV는? 아까의 FROMFROM 처럼 스코프를 두 개 거슬러올라가라는 의미죠. PREV 역시 FROM 처럼 최대 4번까지 중첩이 가능합니다. 자, e_byzantium 부터 시작해서 스코프가 어떻게 중첩되었는지 한 번 볼까요?

e_byzantium(타이틀) → holder_scope (캐릭터) → k_papal_state (타이틀) → holder_scope (캐릭터, 현재)

그렇다면, 현재 스코프로부터 2개를 거슬러 올라가면? 앞쪽의 holder_scope, 즉 비잔티움 황제위를 갖고 있는 캐릭터가 되는 거죠. 따라서 저 reverse_opinion 커맨드를 해석해 보면, 비잔티움 황제위를 가진 캐릭터가 교황에게 갖는 오피니언opinion_unhappy 로 100년간 지정하라는 것(현재 스코프가 교황이지만, reverse니까 방향이 뒤집힌다고 앞에서 말씀드렸죠)입니다.

이전 항목에서 보았던 스코프의 중첩은, 캐릭터 이벤트 내에서 캐릭터와 관련된 다른 대상들 - 다른 캐릭터, 타이틀, 프로빈스 등 - 을 다루기 위해서였습니다. 그러나, 이번 항목에서 보는 스코프의 중첩은, 아예 ROOT 도 FROM 도 아닌 다른 주체들간(예를 든 비잔티움 황제와 가톨릭 교황 사이의 관계)의 일도 이벤트에서 제어할 수 있는 가능성을 보여주죠. 이처럼 PREV 스코프 지시자는 이해하기가 쉽지 않지만, 상당히 중요한 역할을 담당하고 있습니다. 만약 PREV 가 없이 FROM, ROOT 만으로 이 이벤트를 구성한다고 하면, 불가능하지는 않지만 단일 이벤트 내에서는 불가능하고, 여러 개의 이벤트를 거쳐서 구현해야만 합니다.

PREV 와 비슷한 범주이지만 조금 다른 것으로 THIS 라는 것도 있는데요. 이것은 문자 그대로 현재의 스코프를 의미합니다. 이게 쓰이는 경우는 그리 많지 않은데, 가끔 조건문 등에서 써야 할 때가 있습니다. 알아만 두십시오. 아, THIS 는 ROOT 와 FROM 으로 둘러싸여 있더라도 스코프가 바뀌지 않는다는 점이 PREV와 차이점입니다. 위키의 예가 매우 간결하더군요.

any_realm_character = {
  ROOT = { is_liege_of = THIS }
}

현재 THIS 가 ROOT = { } 안에 있지만, ROOT 나 FROM 은 THIS 를 변경시키지 않기 때문에, THIS 는 ROOT 가 아니라 any_realm_character 를 의미합니다! is_liege_of 는 조건문으로, 현재 스코프의 캐릭터(예문에서는 ROOT)가 뒤에 따라오는 캐릭터(여기서는 THIS)의 Liege (주군) 이라면 참이 됩니다. 조건문은 다음에 보게 되니 조금만 참으세요.

저도 PREV 와 THIS 가 위키의 내용을 아무리 읽어봐도 이해가 안 되어서 게시판에 질문을 했었는데, 어떤 분께서 깔끔하게 설명을 해 주셨었죠. 단적으로, FROM과 ROOT는 이벤트 혹은 이벤트 체인, PREV와 THIS 는 하나의 이벤트 내에서 스코프 또는 스코프 체인에서 사용되는 것으로 그 층위를 완전히 달리하는 것입니다. 위키의 양놈들이 그냥 chain 이라고만 적어놔서 쓸데없이 헛갈렸잖아..

■ 기타 스코프를 지정하는 방법들

특이한 경우로서, 숫자로 지정된 스코프를 보실 수 있습니다.

333 = {
  ...
}

이런 숫자는 프로빈스 번호를 의미합니다. 즉 이건 프로빈스 스코프를 의미한다는 겁니다. (333 은 로마를 의미해요. 프로빈스 번호를 확인하시려면 원본의 history/provinces 폴더의 내용을 확인하시거나, map/definition.csv 파일을 열어보시면 됩니다.) 정확히 특정된 프로빈스에서 이벤트가 시작되는 이벤트들에서 이런 식의 정의가 종종 사용됩니다. (예를 들면 종교 기사단의 등장 이벤트 같은 경우)

앞에서 봤던 것이지만, 타이틀의 이름으로 스코프를 지정하실 수도 있습니다. 이 경우에는 그 안쪽은 그 타이틀을 의미하는 타이틀 스코프가 되죠.

k_papal_state = {
  ...
}

마찬가지로 좀 특이하지만, 트레잇으로 스코프를 지정할 수도 있습니다. 이 경우, 해당 트레잇을 가지고 있는 모든 캐릭터가 그 스코프 안으로 들어오게 됩니다.

on_hajj = {
  ...
}

트레잇을 스코프로 사용할 경우에는 항상 조심할 필요가 있습니다. 어떤 트레잇의 경우 엄청나게 많은 캐릭터가 가지고 있을 수 있기 때문에, 잘못 사용하면 엄청난 랙을 유발할 수 있기 때문입니다. 이에 대해서는 나중에 트레잇을 설명할 때에 한 번 더 설명할 기회가 있을 겁니다.

■ 스코프 지시자 목록표

누구를 스코프로 묶을 수 있는가는 어떤 기능이 구현가능한지의 여부를 판단하는 데에 굉장히 중요한 요소가 될 수 있으므로, 필요할 때마다 찾아보시면 좋습니다. CKII 위키에 가 보시면 이것이 깔끔하게 표로 정리되어 있습니다.

간단히 표를 보는 법을 알려드리자면, List of scopes 라고 되어 있고, 그 밑에 Character, Title, Province 의 순으로 정리되어 있는데, 이는 그 스코프가 무엇에 대한 스코프인지를 나타내는 것입니다. 즉 Character 아래에 있는 표는 그 스코프들은 모두 캐릭터를 나타내는 스코프라는 의미입니다. 즉, any_courtier 는 누군가를 특정하지 않은 모든 가신들(캐릭터)이라는 거죠.

표에서 Used in vanilla 는 원본 게임에서 사용되고 있는 스코프라는 의미입니다. 제작사가 원본 이벤트에서 이미 사용하고 있는 스코프 구문이므로 정상적으로 동작하는 것이 검증된 것이겠죠. 마음 놓고 씁시다. 체크 안 된 건 조심해서 쓰십시오. 아니, 안 쓰시는 게 정신건강에 좋습니다.

From Scope 는 해당 스코프 정의 구문을 어떤 스코프 내에서 쓸 수 있는가 라는 것입니다. 예를 들면 앞에서 holder_scope 라는 걸 봤었는데, 그걸 표에서 찾아보면 캐릭터 스코프이고 From Scope 는 Title, Province 라고 되어 있죠? 즉, 현재 스코프가 타이틀이나 프로빈스이고, 그 타이틀 또는 프로빈스의 소유자 캐릭터를 가리키고 싶을 때에 그 안쪽에 holder_scope 를 쓰면 된다는 겁니다. 뒤집어 말하면, 현재 스코프가 타이틀이나 프로빈스가 아니라면 holder_scope 를 쓸 수 없다는 의미도 되죠! 참고로, Any 라고 되어 있다면 어떤 스코프 내에서건 쓸 수 있다는 의미입니다. (즉, Any 라고 되어 있는 애들은 주로 바로 앞에서 말씀드린 스코프의 연결을 잘라먹는 스코프 지시자들입니다. 중첩되는 경우 단절의 유형을 가지는 거죠)

참고로, 일부 스코프 구문의 Description 에는 트리거로 사용될 수 없다(Cannot be used as a trigger)는 문구가 있습니다만, 이는 나중에 이벤트에서 트리거를 보면서 설명할 부분입니다. 지금은 살짝 두 눈을 감아 주세요.

■ 스코프의 제한: Limit

특정 스코프에 약간 제한을 가하여 스코프의 범위를 제한할 수 있습니다. 예를 들어서 any_courtier 스코프는 모든 가신을 다 의미하는데, 만약 여성 가신만을 범위로 하고 싶다면?

effect = {
  any_courtier = {
    limit = {
      is_female = yes
    }
    ...(실행할 내용)...
  }
}

이러면 됩니다. 더 할 말 없습니다. 단, limit = { } 을 사용한 스코프의 제한은 명령문의 문맥에서만 가능합니다. (예시의 섹션이 effect = { } 임을 유의하십시오.) 태생적으로 조건문만이 와야 하는 일부 섹션(예: potential = { }, from_potential = { }, allow = { } 등)에서는 limit = { } 를 사용할 수 없습니다(사용할 필요가 없기도 합니다). 예를 들면, 바로 위의 예는 조건문이라면 limit = { } 없이 다음과 같이 써야 합니다.

potential = {
  any_courtier = {
    is_female = yes
  }
}

limit = { } 자체 및 limit 안쪽에 들어가는 조건들은 다음에 더 자세히 살펴볼 기회가 있을 겁니다.

■ 스코프의 저장과 삭제

이벤트를 구성하다 보면, FROM, ROOT 등으로 지정할 수 있는 캐릭터나 프로빈스, 타이틀 이외에 꽤 자주 호출되는 스코프가 있을 수 있습니다. 그 특정한 스코프를 임시로 저장해 두고 이벤트 체인 내에서 여러 번 재사용할 수 있다면 상당히 편리할 것 같지 않나요? 이 편리한 기능이 2.3.0에 와서야 구현되었습니다.

아래의 예를 보십시오. 이 구문은 제 Nemo Mod에 있는 구문으로 세 명의 ruler 를 보기로 주고 플레이어가 선택을 하도록 하기 위해서 그 준비를 하는 부분입니다. 한 명에 대한 부분만 예를 들겠습니다. (immediate = { } 는 디시전이 아닌 이벤트에서 사용되는 섹션 이름으로, 이벤트가 실행되는 즉시 무언가의 내용을 실행할 때에 사용됩니다. 디시전에서는 이 명령어에 대한 예시를 들기가 애매해서 어쩔 수 없이 이벤트의 예를 끌어왔습니다.)

immediate = {
  random_playable_ruler = {
    limit = {
      is_adult = yes
      NOT = { character = FROM }
      NOT = { dynasty = FROM }
      any_liege = {
        NOT = { character = FROM }
        NOT = { dynasty = FROM }
      }
    }
    save_event_target_as = mod_target_candidate_ruler_1
  }
}

random_playable_ruler 는 위의 스코프 목록에 찾아보면 현재 게임상에 남아 있는 모든 군주(남작위 포함)들 중 랜덤으로 한 명을 선택하는 구문입니다. 그리고 그 밑에 limit 로 추가로 제한을 걸었죠. 성인 군주(is_adult = yes)여야 하고, 플레이어 또는 플레이어의 가문이 아니어야 하고(여기서 FROM 이 플레이어입니다), 플레이어 또는 플레이어의 가문의 휘하가 아니어야 하는 조건이 걸려 있습니다. 그리고 그렇게 스코프가 확정이 되면, 그것을 save_event_target_as 구문을 사용하여 mod_target_candidate_ruler_1 에 저장을 합니다. (이름은 코드를 쓰시는 분이 마음대로 지정하시면 됩니다.)

이렇게 저장된 스코프는 현재의 이벤트 체인(현재의 이벤트가 아니라 현재의 이벤트 체인입니다. 즉 계속 이벤트가 끊어지지 않는 한, 이벤트 체인이 이어지고 있는 겁니다) 내에서는 제한 없이 사용이 가능합니다. 다음과 같이 사용하죠.

event_target:mod_target_candidate_ruler_1 = {
  character_event = {
    id = ADO.5057
  }
}

위의 예처럼 event_target: 뒤에 저장한 이름을 입력하면 그것이 스코프처럼 동작을 하게 됩니다.

만약 다 사용을 했다면, 아래와 같이 명령을 주어 이를 메모리에서 삭제할 수 있습니다.

clear_event_target = mod_target_candidate_ruler_1

■ 스코프의 비교

마지막으로 볼 내용입니다. 위키에도 나와있는 이야기입니다만, 스코프는 스코프끼리 직접 비교가 불가능합니다. 스코프 지시자는 스코프의 영역을 설정하는 것이지 조건문이 아니기 때문입니다. 예를 들면 current_heir = FROM 과 같은 식으로 쓸 수 없다는 거죠. 따라서, 다음과 같이 돌아서 갑니다. (특정한 스코프의 { 캐릭터/타이틀/프로빈스 = 또 다른 스코프 } 의 방식으로 씁니다.)

current_heir = {
  character = FROM
}

6) 작위에 관한 내용은 common\landed_titles\landed_titles.txt 에 정의되어 있습니다. 아직 여기까지 볼 건 아니예요. 이 글이 진행되다 보면 언젠가는 열어보게 됩니다.

다음검색
현재 게시글 추가 기능 열기

댓글

댓글 리스트
  • 답댓글 작성자tacitus 작성자 본인 여부 작성자 | 작성시간 15.02.13 넵. 고생하셨습니다. ^^
  • 작성자netus | 작성시간 16.04.21 모딩을 처음 하시는 분들에게 알려드립니다...
    스코프 솔직히 이해하기 쉽지 않죠...
    그래서 저는 항상 FROM 및 ROOT 등 스코프를 사용하면 항상 옆에 "#대상" 을 바로바로 적습니다.
    이렇게 사용하게 되면 약간 덜 헷갈리더군요...
    작지만 다른 초보 모더분들에게 약간의 팁이 되었으면 좋겠네요 ㅎㅎ
  • 작성자공상이몽 | 작성시간 16.04.24 (이걸 이해를 못 하시면 모딩의 길이 에베레스트만큼 험준해지는 거죠.)
    라니 정확히 지금 제 상황이네요...
    후우...
  • 답댓글 작성자tacitus 작성자 본인 여부 작성자 | 작성시간 16.04.24 이해가 안 되시는 부분을 짚어주실 수 있다면 추가적으로 설명은 해 드릴 수 있습니다. 이게 보통 일련의 흐름 속에서 어디 한 부분을 오해하게 되면서 그 뒤가 줄줄이 꼬이는 경우가 많아서, 오해가 발생한 부분만 풀면 해결되는 경우가 많거든요..
    모딩 게시판의 글에도 적었지만, 네이버 카페북의 새 버전 가이드는 이 글보다는 조금 쉽게 썼다고 생각합니다. 가능하시다면 그쪽 글도 한번 읽어봐 주세요.
  • 답댓글 작성자공상이몽 | 작성시간 16.04.24 네이버 쪽을 봐보겠습니다...만 내일 시험이니 슬슬 시험공부를 ㅠㅜ
댓글 전체보기

CK 모드 게시판 다른글

현재페이지 1234
맨위로

카페 검색

카페 검색어 입력폼