자 예고대로...
평소의 개조론에 비해 설명(해석)이 좀 불친절 할 수는 있겠어.
근데 워낙 양이 많아서...정작 수정할 것은 별로 없지만 말야^^;


1. 시작 도시의 인구 설정
 이쪽은 뭐 매우 간단하기는 하지만...고정적이라는게 좀...
 CvEventManager.py에서 def onCityBuilt(self, argsList): 구문을 찾아가자.
def onCityBuilt(self, argsList):
'City Built'
city = argsList[0]
pPlot = city.plot()
pPlayer = gc.getPlayer(city.getOwner())
if pPlayer.getCivilizationType() == gc.getInfoTypeForString('CIVILIZATION_INFERNAL'):
city.setHasReligion(gc.getInfoTypeForString('RELIGION_THE_ASHEN_VEIL'), True, True, True)
city.setPopulation(3)
city.setNumRealBuilding(gc.getInfoTypeForString('BUILDING_ELDER_COUNCIL'), 1)
city.setNumRealBuilding(gc.getInfoTypeForString('BUILDING_TRAINING_YARD'), 1)
city.setNumRealBuilding(gc.getInfoTypeForString('BUILDING_OBSIDIAN_GATE'), 1)
city.setNumRealBuilding(gc.getInfoTypeForString('BUILDING_FORGE'), 1)
city.setNumRealBuilding(gc.getInfoTypeForString('BUILDING_MAGE_GUILD'), 1)
city.setNumRealBuilding(gc.getInfoTypeForString('BUILDING_DEMONIC_CITIZENS'), 1)
 밑으로도 죽 있지만 뭐...하려는 내용과는 상관 없으니 넘어가고.
 보면 알겠지만 구지 해석하면, 인페르날의 경우 도시를 새로 지으면
  그 도시는 인구가 1이 아니라 3으로 시작하며,
  잿빛 장막이 자동으로 전파되고
  원로원/훈련장/흑요석 문/대장간/메이지 길드/악마의 시민이 저절로 지어지게 하는 것이다.

 이것을 응용해서...그 밑에 추가로,(수정이 아니다!)
if pPlayer.isHuman() and pPlayer.hasTrait(gc.getInfoTypeForString('TRAIT_FALLOW')):
city.setPopulation(8)
 이렇게 붙이면 되겠지. 이러면 인간이 조종하는 불모의 특성을 가진 문명이 도시를 세울 때는 도시 인구가 8로 시작...
 8이 너무 크다고? 그런데 이것만 고칠 경우, 도시를 더이상 키울 수는 없거든.(이벤트로 가감이 약간 되기야 하겠다만) 그러니 미리 반경1 정도는...
 아 물론, 건물을 추가로 더 주거나 시작 지형(+보너스)을 바꾼다거나 유닛을 더 받는다거나 하는 응용도 가능하겠지. 근데 하면 할수록 게임 불감증에 걸린다는 거 조심하고...


2. 마네 받기
 원조는 역시 인페르날이 마네를 받는 조건인데...
 혹시 기억하는지 모르겠지만, 마네를 받는 경우는 두가지이다. 사악한놈이 죽었거나, 도시가 깔렸거나...
 둘다 구현 패턴은 비슷하지만 미치는 영향은 치명적으로 다른데...
 인페르날은 스스로 얻는 유닛이 죄다 이미 죽어있는 지라, 자기 유닛을 죽여서 마네를 받을 수가 없다. 적절한 밸런싱인 셈이지.
 한데...사악한 유닛이 죽어서 마네를 얻는 패턴을 고치는 경우, 지금 하려는 짓(보통 문명에 불모의 특성 주기)을 하면...심하게 마네가 많이 나온다;;
 그래서 그쪽은 그대로 두고...도시를 깔아뭉갰을 때 마네를 받도록 고쳐보겠다.

 파일은 동일하고, def onCityRazed(self, argsList): 구문을 찾아간다. 원문은 이렇다.
'City Razed'
city, iPlayer = argsList
iOwner = city.findHighestCulture()

iAngel = gc.getInfoTypeForString('UNIT_ANGEL')
iInfernal = gc.getInfoTypeForString('CIVILIZATION_INFERNAL')
iManes = gc.getInfoTypeForString('UNIT_MANES')
iMercurians = gc.getInfoTypeForString('CIVILIZATION_MERCURIANS')
pPlayer = gc.getPlayer(iPlayer)
if gc.getPlayer(city.getOriginalOwner()).getAlignment() == gc.getInfoTypeForString('ALIGNMENT_EVIL'):
if gc.getPlayer(city.getOriginalOwner()).getCivilizationType() != iInfernal:
for i in range(city.getPopulation()):
cf.giftUnit(iManes, iInfernal, 0, city.plot(), city.getOwner())

if gc.getPlayer(city.getOriginalOwner()).getAlignment() == gc.getInfoTypeForString('ALIGNMENT_NEUTRAL'):
for i in range((city.getPopulation() / 4) + 1):
cf.giftUnit(iManes, iInfernal, 0, city.plot(), city.getOwner())
cf.giftUnit(iManes, iInfernal, 0, city.plot(), city.getOwner())
cf.giftUnit(iAngel, iMercurians, 0, city.plot(), city.getOwner())

if gc.getPlayer(city.getOriginalOwner()).getAlignment() == gc.getInfoTypeForString('ALIGNMENT_GOOD'):
for i in range((city.getPopulation() / 2) + 1):
cf.giftUnit(iAngel, iMercurians, 0, city.plot(), city.getOwner())
 주석 처리된 부분은 미리 뺐다. 문명4 한글판에 있는 전설의 빨치산 버그...에 해당하는 부분이지. 주석이니까 정말로 지워도 상관 없다. 놔둬봐야 하는 일도 없잖아...
 역시 이전에 봤던 내용들이니 효과에 대한 설명은 필요 없겠지...이보다 아래쪽은 유닛 주는 부분이 아니니 생략...

 일단 인페르날이 마네를 받는 것에는 변함이 없도록 주의하며 고쳐야 할 것이다. 뭐 먼치킨 만들겠다면야 더 많은 구문을 추가해야 겠지만, 일단은...
 유닛을 선물하는 함수(customfunctions의 giftunit)는 원래 해당 문명 전체에 하는 거니까 그걸 염두에 두고...(인페르날이 2문명이면 두 문명 모두 준다는 소리)
 예시로 들 문명은...어제 시다 얘길 했으니 시다로 하지?
iAngel = gc.getInfoTypeForString('UNIT_ANGEL')
iInfernal = gc.getInfoTypeForString('CIVILIZATION_INFERNAL')
iManes = gc.getInfoTypeForString('UNIT_MANES')
iMercurians = gc.getInfoTypeForString('CIVILIZATION_MERCURIANS')
iSidar = gc.getInfoTypeForString('CIVILIZATION_SIDAR')
pPlayer = gc.getPlayer(iPlayer)
if gc.getPlayer(city.getOriginalOwner()).getAlignment() == gc.getInfoTypeForString('ALIGNMENT_EVIL'):
if gc.getPlayer(city.getOriginalOwner()).getCivilizationType() != iInfernal:
for i in range(city.getPopulation()):
cf.giftUnit(iManes, iInfernal, 0, city.plot(), city.getOwner())
cf.giftUnit(iManes, iSidar, 0, city.plot(), city.getOwner())

if gc.getPlayer(city.getOriginalOwner()).getAlignment() == gc.getInfoTypeForString('ALIGNMENT_NEUTRAL'):
for i in range((city.getPopulation() / 4) + 1):
cf.giftUnit(iManes, iInfernal, 0, city.plot(), city.getOwner())
cf.giftUnit(iManes, iInfernal, 0, city.plot(), city.getOwner())
cf.giftUnit(iAngel, iMercurians, 0, city.plot(), city.getOwner())
cf.giftUnit(iManes, iSidar, 0, city.plot(), city.getOwner())
cf.giftUnit(iManes, iSidar, 0, city.plot(), city.getOwner())
cf.giftUnit(iManes, iSidar, 0, city.plot(), city.getOwner())
cf.giftUnit(iManes, iSidar, 0, city.plot(), city.getOwner())

if gc.getPlayer(city.getOriginalOwner()).getAlignment() == gc.getInfoTypeForString('ALIGNMENT_GOOD'):
for i in range((city.getPopulation() / 2) + 1):
cf.giftUnit(iAngel, iMercurians, 0, city.plot(), city.getOwner())
cf.giftUnit(iManes, iSidar, 0, city.plot(), city.getOwner())
cf.giftUnit(iManes, iSidar, 0, city.plot(), city.getOwner())
 이렇게 하면, 모든 시다 문명은 뽀개진 도시의 원주인 성향에 관계 없이 인구수만큼의 마네를 얻게 된다.(뭐 엄밀히는 조금 다르다만 그정도는...)
 엉뚱하게 이용해서 이걸로 그냥 전투 유닛이나...심지어 위인을 줄 수도 있겠지--; 뭐 적당히 하라고. 허구헌날 도시를 부수는 위엄...


3. 인구 증가 주문
 조금 귀찮기는 하지만 유용하긴 하니까 알아볼까.
 일단 마네가 인구를 늘리니까, 그 주문이 어떻게 생겼는지 보면 되겠지. CIV4SpellInfos.xml의 주문 목록 바로 첫번째이다.
        <SpellInfo>
            <Type>SPELL_ADD_TO_CITY</Type>
            <Description>TXT_KEY_SPELL_ADD_TO_CITY</Description>
            <Civilopedia>TXT_KEY_SPELL_PLACEHOLDER_PEDIA</Civilopedia>
            <Help>TXT_KEY_SPELL_ADD_TO_CITY_HELP</Help>
            <UnitClassPrereq>UNITCLASS_MANES</UnitClassPrereq>
            <bAllowAI>1</bAllowAI>
            <bInBordersOnly>1</bInBordersOnly>
            <bInCityOnly>1</bInCityOnly>
            <iAIWeightCity>10</iAIWeightCity>
            <bDisplayWhenDisabled>1</bDisplayWhenDisabled>
            <bHasCasted>1</bHasCasted>
            <bAbility>1</bAbility>
            <bSacrificeCaster>1</bSacrificeCaster>
            <iChangePopulation>1</iChangePopulation>
            <Effect>EFFECT_SPELL1</Effect>
            <Sound>AS3D_SPELL_COMMANDER_JOIN</Sound>
            <Button>Art/Interface/Buttons/Spells/Add to City.dds</Button>
        </SpellInfo>
 크크 XML이라서 반갑다고 할 사람 많겠군...
 중간에 굵게 볼드체 처리된 부분이 바로 인구를 늘리는 태그지. 하나 늘어나게 되어있지? 뭐 숫자를 바꾸면 한번에 더 많이 늘릴 수도 있겠고...
 다만, 이건 마네밖에 못쓰니까, 어떻게 새로운 방법이 필요하겠지...

 간만에, python 쓰지 말고 대충 XML만 손보는 방법을 써보자. 역시 예시는 시다로...열었던 파일의 맨 끝(엄밀히, </SpellInfos>보다는 위) 정도에 이걸 끼워 넣도록 하자.
        <SpellInfo>
            <Type>SPELL_ZZZ</Type>
            <Description>TXT_KEY_SPELL_ADD_TO_CITY</Description>
            <Civilopedia>TXT_KEY_SPELL_PLACEHOLDER_PEDIA</Civilopedia>
            <Help>TXT_KEY_SPELL_ADD_TO_CITY_HELP</Help>
            <CivilizationPrereq>CIVILIZATION_SIDAR</CivilizationPrereq>
            <bCasterMustBeAlive>1</bCasterMustBeAlive>
            <bInBordersOnly>1</bInBordersOnly>
            <bInCityOnly>1</bInCityOnly>
            <iCasterMinLevel>9</iCasterMinLevel>
            <bDisplayWhenDisabled>1</bDisplayWhenDisabled>
            <bHasCasted>1</bHasCasted>
            <bAbility>1</bAbility>
            <bSacrificeCaster>1</bSacrificeCaster>
            <iChangePopulation>1</iChangePopulation>
            <Effect>EFFECT_SPELL1</Effect>
            <Sound>AS3D_SPELL_COMMANDER_JOIN</Sound>
            <Button>Art/Interface/Buttons/Spells/Add to City.dds</Button>
        </SpellInfo>
 시다의 레벨 9이상을 달성한 살아있는 유닛은 자국 도시에서 스스로를 희생하여 인구를 1 늘리도록 만든거야.
 6레벨에서 못참고 암영을 만드는 것도 나름 페널티 역할을 할테니 좋고...참고 더 키워서 9레벨까지 만들면 인구수에 도움이...
 다만, 이건 태그 순서를 꼭 지켜야해! 뭐 문법 파일이 따로 있기는 한데...그거 열어보고 꼭 거기 나열된 태그 순서대로 하도록.
 사실 이 부분은 python을 동원하면 구지 특정 문명 전용이 아닌, 특성 보유 여부에 따라 하게 만들 수 있겠지만...(예시는 시다 문명 전체가 해당하니까)
 파이썬인지 뱀인지 때문에 머리에 쥐나는 사람들을 구제할 방법이 하나라도 있어야 하지 않겠어;;


4. 인구 증가 조건
 어떻게 보면...인구 증가 주문을 자동으로 사용하게(그리고 임의로 쓰지는 못하게) 하는 것이라고 봐도 되겠다.
 물론 마네를 받을 수도 있는데...그러면 도시에 특정하게 한다는 조건이 안되잖아. 고정이라도 시킨다면 모를까...게다가 유닛으로 써버리면 뭐...
 따라서 도시에서 일어나는 특정 이벤트에 반응하여, 그 경우에 해당 도시의 인구를 늘리는 방법을 쓰는 거지.

 자, 역시 봐야할 것은...CvEventManager.py에서 찾아야겠지. 그게 이벤트 전반을 관장하니까 자주 볼 수밖에 없어.
 거기서 뭘 볼거냐면...def onCultureExpansion(self, argsList): 구문을 찾아가 보자고. 다른 구문도 있지만 이걸로 정했는데...
 선택 이유는 대충 이름만 봐도 짐작이 되지? 도시의 문화 영역이 확장될 때마다 반응하는 구문이다.
def onCultureExpansion(self, argsList):
'City Culture Expansion'
pCity = argsList[0]
iPlayer = argsList[1]
CvUtil.pyPrint("City %s's culture has expanded" %(pCity.getName(),))
 보통은 메시지 출력--;에만 사용되는...참으로 할 일 없는 구문이다만...지금은 유용하게 사용될 기회이지^^;
 문화도가 증가할 때마다 인구가 늘어난다고 하면--; 완전 말도 안되는 소리고...문화 범위가 증가할 때마다 인구도 하나씩 늘어나게 한다면 나름 밸런스가...

 복잡할 것이 별로 없는데, 끝에 이것만 추가해 주자. 역시 전부 다 늘어나면 안되고 나만 이득을 봐야하니까...
if gc.getPlayer(iPlayer).hasTrait(gc.getInfoTypeForString('TRAIT_FALLOW')):
pCity.changePopulation(1)
 불모의 특성을 가지고 있을 경우로 한정한 것. 다만 이러면 인페르날로 할 경우 더 좋아지겠지^^;

 시다로 한정해서 한다 치면...위의 추가 구문에서 if문만 이렇게 바꾸고 붙여줘라.
if gc.getPlayer(iPlayer).getCivilizationType() == gc.getInfoTypeForString('CIVILIZATION_SIDAR'):
 이러면 시다 한정으로 바뀌겠지?


오늘의 예시들은 뭐 하나만 써도 되고...전부 다--; 쓸 수도 있겠지...게다가 응용까지 하면 뭐...
문명 불감증 오면 책임 안지니까 적당히 해라--;;;; 나도 허구헌날 고쳐대지만 난 먼치킨 만들면 그만큼 AI에게 반대급부를 충실히 줘서 불감증을 막고 있다구.
현게 태워서 소위...구제해 주는 거니 오히려 착한 일 하는 거야? ㅇㅇ
 
죠니 사사키가 작성한 글입니다.
,