|
따라서, TST.1001 에서는, 봉신에게 효과를 발생시키겠다면 FROM 스코프 내에, 플레이어에게 효과를 발생시키겠다면 ROOT 스코프 내에 적어야 하는 겁니다.
이제 어느 정도 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의 스코프가 필요해지는 경우가 있습니다. 이제 너와 나 이외의 인물, 장소, 작위 등을 어떤 식으로 표현할 수 있는지를 확인하겠습니다.
예를 들어, 이벤트의 발생 조건을 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 니까요. 다만 이건 설명을 위한 글이니까, 명확히 하기 위해 적었습니다.
이런 스코프의 연결 예는 상당히 많습니다. 자주 쓰이는 예들만 알아보겠습니다. 그냥 공식처럼 알아 두시는 것도 좋습니다.
이제 때가 됐군요. 앞에서 스크립트에 추가했던 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의 주군의 모든 봉신들!)
스코프의 중첩 중에서 연결과 비슷하지만 약간 성격이 다른 것이 있습니다. 예를 들면 이런 것입니다.
현재 캐릭터가 위치하는 프로빈스의 종교와 캐릭터의 종교가 서로 다른 경우 캐릭터가 프로빈스의 종교로 개종하는 디시전을 만들고 싶습니다. 여기에서 등장하는 객체는? 나(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 을 시작으로 해서 그와 연관되는 다양한 캐릭터, 프로빈스, 타이틀 등으로 스코프를 전환하여 표현이 가능합니다. 보통 이벤트나 디시전을 짜다 보면 이런 종류의 스코프 전환을 정말 많이 사용하게 될 텐데요. 많이 사용하는 몇몇 스코프 지시자들은 아예 공식처럼 알아두는 것이 쓰기 좋습니다. (더 많습니다만, 정말 자주 쓰게 되는 것들만 적었습니다.)
어떤 스코프 안에서 쓰일 수 있는지만 제대로 맞춰준다면, 이처럼 여러 번의 중첩도 가능합니다. 이런 스코프의 중첩은 이벤트를 구성하는 데 있어서 굉장히 유용하게 쓰입니다. 물론, 스코프의 연결과 마찬가지로 두 번 이상의 중첩도 얼마든지 가능합니다.
potential = { ROOT = { location = { duchy = { holder_scope = { any_courtier = { is_female = yes } } } } } }
정말 예시를 위한 예시가 되었지만, 위의 스코프 중첩을 읽으실 수 있겠습니까? ROOT가 존재하는 프로빈스(location : 캐릭터 → 프로빈스)의 상위 공작령 타이틀(duchy : 프로빈스 → 타이틀)을 가진 자(holder_scope : 타이틀 → 캐릭터)의 모든 가신들(any_courtier) 중에서 여성(is_female = yes)이 있을 것을 조건으로 설정하는 potential = { } 섹션입니다. (대체 이런 걸 조건으로 하는 디시전이 어디 있겠어요? 진짜 어거지로 만든 예시입니다...)
스코프 지시자들 중에는, 바로 앞의 스코프가 무엇이었건 상관하지 않고, 항상 자신의 고유한 스코프를 나타내는 경우가 있습니다. 가장 가까운 예로 우리가 지금까지 내내 쓰고 있었던 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 스코프를 앞에 넣었느냐는 것이겠죠. 현재까지 가르쳐드린 것만으로는 그 의문은 해결되지 않습니다. 그러나 곧 해결됩니다. 바로 다음을 보시면요. ^^
지금까지 스코프가 중첩되는 여러 가지 예들을 보셨습니다. 이어지는 내용은 이런 스코프의 중첩을 더욱 더 확장하여, 아예 너와 나 이외의 다른 요소들끼리의 이벤트를 구성하는 예입니다. 아울러, 굉장히 중요한 새로운 스코프 지시자도 몇 가지 더 확인하게 될 겁니다.
초심자에게는 조금 복잡한 코드가 될 수도 있겠는데, 다음의 코드를 한번 보시죠.
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)는 문구가 있습니다만, 이는 나중에 이벤트에서 트리거를 보면서 설명할 부분입니다. 지금은 살짝 두 눈을 감아 주세요.
특정 스코프에 약간 제한을 가하여 스코프의 범위를 제한할 수 있습니다. 예를 들어서 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 에 정의되어 있습니다. 아직 여기까지 볼 건 아니예요. 이 글이 진행되다 보면 언젠가는 열어보게 됩니다.
첫댓글 내가 발생시킨 이벤트의 효과가 나한테 온다면
root도 나고, from도 내가 되는게 이론적으로 맞는거 아닌가요??
사실 발생시킨게 나니까 FROM = ROOT 라고 생각하는 것도 논리적으로 문제는 없습니다.
다만 CKII 모드위키에선 타겟이 정해지지 않은 디시전의 경우에 아예 FROM 에 대해서 언급을 안 하고 있습니다. 사용하는 걸 권장하지 않는다는 의미죠.
타겟이 없는 디시전의 경우에는 아예 from_potential 을 지정하지 않는다는 점에서 그렇다면 FROM 은 없다고 보는 것이 더 안전하지 않나 라는 생각입니다.
그 부분 문구를 고치는 게 나을까요?
아뇨아뇨 궁금해서 물어본거에요 ㅋ
흠... 글 읽어보니 어느정도 스코프에 대해 이해게 되는 감이 있네요.
근데 스코프 중에 primary_title 이라는 구문이 있던데, 이건 해당 캐릭터의 기본작위를 가리키는 거 맞죠?
이걸 플롯 이벤트에 넣는다 치면 해당 플롯을 작동시킨 캐릭터의 기본 작위를 가리키는 걸로 작동을 할지 궁금하네요.
아니면 스코프안에 스코프를 넣어야 하나...
네. 캐릭터 스코프 내에서 primary_title = { } 을 쓰면 기본 작위에 대한 타이틀 스코프가 됩니다. 이론적으로는 그럴 것 같은데요.
실험좀 해봤는데 되네요 감사합니다.
폐태자 모드에 실험결과 기본 작위에 대한 클레임을 폐태자에게 주는데 성공했습니다... 오랜만에 다시 올려봐야 겠군요 ㅋ...
그런데,
FROM = {
hidden_tooltip = {
reverse_opinion = {
modifier = grievously_dethronement
who = ROOT
years = 50 }
character = {
any_vassal = {
opinion = {
modifier = grievously_dethronement_vassal
who = FROM
years = 20 }
}
primary_title = {
add_pressed_claim = ROOT
}
}
}
}
이렇게 해서 성공은 했는데... 왜 성공한건지 좀 의문이 드네요 ㄷㄷㄷ;;; 일단 프럼이 플롯 이벤트 상으로는 플롯 대상자를 가리키는 것 같은데 거기 안에 캐릭터 구문을 집어넣으니 캐릭터 구문 안의 FROM이 플롯을 실행한 사람을 가리키고 ROOT가 플롯을 받는 사람을 가리키는거 같던데 왜 그렇게 되는건지 모르겠네요 ;;
일반 이벤트 파일인가요? FROM 이 사람을 가리킨다면 굳이 다시 character = { } 를 잡아줄 필요는 없거든요. 전후 문맥을 알지 못해서 해독이 어렵네요.
Objectives의 플롯 이벤트입니다. 해당 내용은 이펙트 구문 안에 들어가 있는 거구요...
플롯 이벤트라면 FROM 이 플롯의 타겟 캐릭터, ROOT 가 플롯을 세운 사람.. 이 되니까, 맞네요. 다만 중간에 character = { } 이 들어간 이유를 모르겠습니다. FROM 과 ROOT 모두 character 거든요.
흠.... 그냥 복붙하다보니 들어간거 같기도하고... 지우고 테스트 해볼게요.
캐릭터 없이도 적용 되네요 ㅋ...
근데 여전히 FROM이 플롯을 실행한 사람으로 인식하네요 왜죵...
FROM이 타겟 캐릭터 스코프니까 who = FROM 이면 타겟 캐릭터에게 오피니언이 적용되야 하는거 아닌건가 ㅜㅜ;;
어.. 그러고 보니 맞는게 아니라 뒤집혀 있군요...? 어레레...
오피니언은 vassal -> FROM 이고 FROM 은 타겟 캐릭터일텐데, 실행자로 인식하나요?
캐릭터를 지우고 보니 살짝 문제가 보이네요. any_vassal 은 FROM 의 any_vassal 로 인식이 될 것 같은데...
그러네여... 지금 테스트 결과 보니까 플롯을 실행한 사람의 봉신이 실행 시킨 사람에게 관계도 모디파이어를 적용시키고 있군요...
아다리(?)가 맞으려면 플롯을 준놈이 FROM이고 플롯을 받는 놈이 ROOT여야 하는 상황...
그런데 그렇게 보자니 맨 처음 FROM은 또 플롯 대상자를 가리키는게 맞는 거 같은데...
일단 저 부분만 놓고 보자면,
현재 정상적으로 동작하고 있는 게 맞다면, 공식 위키의 설명과는 다르게 FROM이 음모자, ROOT 가 음모의 타겟이어야 맞는 코드가 돼요. 뭔가 이상한데...
일단 해당 플롯 전문인데 뭔가 이상해요.... 프럼이 대상자인지 실행자인지... 거참;;
지금 모드를 다운로드 받아서 원문을 보고 있습니다. 음..
이펙트 다음의 FROM부분을 ROOT로 바꿔보니 이젠 음모대상자의 봉신이 저한테 모디파이어를 뿜는 군요 껄껄... 이말은 즉슨 ROOT가 음모 실행자고 FROM이 음모 대상자가 맞다는 소린데 ㅜㅜ....
뭘까요 이 오묘한 기분은....
과연 버그일까요 아니면 위키가 오류인걸까요...
되는데 왜 되는지를 모른다는게 참 답답허네요...
일단 되기는 하니까 뭐... 저는 일단 머리좀 식혀야 겠습니다.
넵. 고생하셨습니다. ^^
모딩을 처음 하시는 분들에게 알려드립니다...
스코프 솔직히 이해하기 쉽지 않죠...
그래서 저는 항상 FROM 및 ROOT 등 스코프를 사용하면 항상 옆에 "#대상" 을 바로바로 적습니다.
이렇게 사용하게 되면 약간 덜 헷갈리더군요...
작지만 다른 초보 모더분들에게 약간의 팁이 되었으면 좋겠네요 ㅎㅎ
(이걸 이해를 못 하시면 모딩의 길이 에베레스트만큼 험준해지는 거죠.)
라니 정확히 지금 제 상황이네요...
후우...
이해가 안 되시는 부분을 짚어주실 수 있다면 추가적으로 설명은 해 드릴 수 있습니다. 이게 보통 일련의 흐름 속에서 어디 한 부분을 오해하게 되면서 그 뒤가 줄줄이 꼬이는 경우가 많아서, 오해가 발생한 부분만 풀면 해결되는 경우가 많거든요..
모딩 게시판의 글에도 적었지만, 네이버 카페북의 새 버전 가이드는 이 글보다는 조금 쉽게 썼다고 생각합니다. 가능하시다면 그쪽 글도 한번 읽어봐 주세요.
네이버 쪽을 봐보겠습니다...만 내일 시험이니 슬슬 시험공부를 ㅠㅜ