はじめてのPythonMOD 6

はじめに

  • その5のつづき
  • XMLとPythonの合わせ技・XML編
  • あくまでPythonのチュートリアルなので、XMLの詳しい話にはあまり踏み入りません

構想

これまでは既存の動作を変更してばかりでした。
Pythonでしかできない効果を持った新しい建造物を作りましょう!
とりあえず”いつもの”を作ります。

└─kujira_fert
    └─Assets
        └─Python
            ├─KujiraEventManager.py
            │
            └─Entrypoints
                 └─CvEventInterface.py

XML

新しい建造物を追加します。
編集するのはCIV4BuildingClassInfos.xmlCIV4BuildingInfos.xmlです。

C:\Program Files (x86)\CYBERFRONT\Sid Meier's Civilization 4(J)\Beyond the Sword(J)\Assets\XML\Buildings

1

から同じフォルダ階層にコピーします。

ここまででファイル構成はこうなっているはずです。

└─kujira_fert
    └─Assets
        ├─Python
        │  ├─KujiraEventManager.py
        │  │
        │  └─Entrypoints
        │      └─CvEventInterface.py
        │
        └─XML
            └─Buildings
                ├─CIV4BuildingClassInfos.xml
                └─CIV4BuildingInfos.xml

ちょっとだけXMLの話

キー一覧を見ていただくとわかりやすいのですが、
建造物の種類一つ一つにBuildingType
UBどうしをひとまとめにしたものにBuildingClassTypeが割り当てられています。
例えばストーンヘンジで各都市に無償で供給されるのは、
正確には「BUILDING_OBELISKという建造物」ではなく、
「BUILDINGCLASS_OBELISKに属する建造物のうち、その文明に合ったもの」なのです。
(ですから、例えばアメリカ先住民がストヘンを建てるとちゃんとトーテムポールが配置されるのですね)

UBが存在しない建造物であっても自分一人をメンバーとしたBuildingClassが必ずあります。
というより、Buildingを作るときに所属先であるBuildingClassを自己申告するタグがあり、
それは省略できません。
なのでオレオレ建造物を追加するときは、
(そのBuildingひとつだけを含む予定の)BuildingClassと、
(そのBuildingClassに所属する)Building本体とを
一緒に作ってあげなければいけません。

CIV4BuildingClassInfos.xml

というわけでCIV4BuildingClassInfos.xml

↓ここに

↓こんな感じのを追加しておきます。

        <BuildingClassInfo>
            <Type>BUILDINGCLASS_FERTILIZE_SHRINE</Type>
            <Description>TXT_KEY_FERTIRIZE_SHRINE</Description>
            <iMaxGlobalInstances>-1</iMaxGlobalInstances>
            <iMaxTeamInstances>-1</iMaxTeamInstances>
            <iMaxPlayerInstances>-1</iMaxPlayerInstances>
            <iExtraPlayerInstances>0</iExtraPlayerInstances>
            <bNoLimit>0</bNoLimit>
            <bMonument>0</bMonument>
            <DefaultBuilding>BUILDING_FERTILIZE_SHRINE</DefaultBuilding>
            <VictoryThresholds/>
        </BuildingClassInfo>

CIV4BuildingInfos.xml

CIV4BuildingInfos.xmlはタグが多すぎて1からでは無理なのでBUILDING_RECYCLING_CENTERを元に改変することにして、

↓ここから

↑ここまでを

↓ここに貼り付けます。



そのあと、貼り付けた部分の一部を修正していきます。

            <BuildingClass>BUILDINGCLASS_FERTILIZE_SHRINE</BuildingClass>
            <Type>BUILDING_FERTILIZE_SHRINE</Type>
            <SpecialBuildingType>NONE</SpecialBuildingType>
            <Description>TXT_KEY_BUILDING_FERTILIZE_SHRINE</Description>
            <Civilopedia>TXT_KEY_BUILDING_FERTILIZE_SHRINE_PEDIA</Civilopedia>
            <Strategy>TXT_KEY_BUILDING_FERTILIZE_SHRINE_STRATEGY</Strategy>

<BuildingClass><Type>を指定、それから各種テキストキーをそれっぽい名前にしておいて、

            <Help>TXT_KEY_BUILDING_FERTILIZE_SHRINE_HELP</Help>

<Help>というタグを追加しておきます。

            <PrereqTech>TECH_BIOLOGY</PrereqTech>

↑解禁技術を生物学にして、

            <iCost>10</iCost>

↑(開発中の一時的な措置として)ハンマーを軽くしておいて、

            <bBuildingOnlyHealthy>0</bBuildingOnlyHealthy>

↑人口からの不衛生なしを解除して、

            <iHappiness>-10</iHappiness>

↑不幸+10にしてみました。

全部でどんな感じになったかは長いので章末に移動しました。おまけをご覧ください。

この時点で生物学解禁で、不幸を+10生む、そんな建造物ができているはずです。
ゲームを起動して、シヴィロペディアを見るなり、
WBで生物学を取って建ててみるなりしてみましょう。
もちろん、まだテキストキーの内容を定義していませんので、
生のTXT_KEY_...が出てきますが、
定義していない以上当然のことなので、気にしないことにしましょう。

Text

XML\Text\ に適当な名前のファイルを作ります。
今回はText_Kujira.xmlという名前にしましょう。
フォルダ構成はこうなりました。

└─kujira_fert
    └─Assets
        ├─Python
        │  ├─ KujiraEventManager.py
        │  │
        │  └─Entrypoints
        │      └─CvEventInterface.py
        │
        └─XML
            ├─Buildings
            │  ├─CIV4BuildingClassInfos.xml
            │  └─CIV4BuildingInfos.xml
            │
            └─Text
                └─Text_Kujira.xml

Text_Kujira.xmlの中身はこのようにします…

<?xml version="1.0" encoding="Shift_JIS"?>
<Civ4GameText xmlns="http://www.firaxis.com">
    <TEXT>
        <Tag>TXT_KEY_BUILDING_FERTILIZE_SHRINE</Tag>
        <English>Fartilize Shrine</English>
        <French>肥沃化の神殿</French>
        <German />
        <Italian />
        <Spanish />
        <Japanese>肥沃化の神殿</Japanese>
    </TEXT>
    <TEXT>
        <Tag>TXT_KEY_BUILDING_FERTILIZE_SHRINE_PEDIA</Tag>
        <English>Fartilize Shrine's Pedia</English>
        <French>肥沃化の神殿は適当に考えた例題用の建造物です。</French>
        <German />
        <Italian />
        <Spanish />
        <Japanese>肥沃化の神殿は適当に考えた例題用の建造物です。</Japanese>
    </TEXT>
    <TEXT>
        <Tag>TXT_KEY_BUILDING_FERTILIZE_SHRINE_STRATEGY</Tag>
        <English>Fartilize Shrine changes terrain in city area into glass in return for 10 unhappiness.</English>
        <French>この先10もの不幸を背負う代わりに、都市圏内のタイルを即座に草原にします。</French>
        <German />
        <Italian />
        <Spanish />
        <Japanese>この先10もの不幸を背負う代わりに、都市圏内のタイルを即座に草原にします。</Japanese>
    </TEXT>
    <TEXT>
        <Tag>TXT_KEY_BUILDING_FERTILIZE_SHRINE_HELP</Tag>
        <English>[ICON_BULLET]Fartilize Shrine changes terrain in city area into glass.</English>
        <French>[ICON_BULLET]完成時都市圏内のタイルを即座に草原にする</French>
        <German />
        <Italian />
        <Spanish />
        <Japanese>[ICON_BULLET]完成時都市圏内のタイルを即座に草原にする</Japanese>
    </TEXT>
</Civ4GameText>

こんな感じでしょうか。

この時点で生物学解禁、不幸を+10生む、説明にもそれっぽいことが書いてあるけれど
実際には草原化などしない(書いていませんからね)そんな 詐欺 建造物ができているはずです。
起動して、いろいろ遊んでみましょう。

ためす is 大事

こうして一歩進むごとにいちいち動作確認するのは重要です。
もしPythonをいじっていない今の状態でエラーが出るのなら、
XMLにまずいところがあるはずです。
もし一度目のお願いに従って動作確認をしていただいていて、
その時点では正しく動いていたなら、
いまいじったText_Kujira.xmlが必ずおかしいということになるはずです。
動作確認を怠れば怠るほど、どこが間違っているかの探索すべき範囲は
無制限に広くなっていき、
最悪どうにもこうにもならなくなり、すべてを捨てて最初から書きなおす、
なんてことになることもあります。

こまめに試すのは大事です。

つづく

XMLには深入りしないと言ったものの、変更するのと比べて新しく作るのは結構大変でした。
そのせいで字数が多くなり過ぎたので、
その7へ続きます。

おまけ

CIV4BuildingInfos.xml追加分の全文

        <BuildingInfo>
            <BuildingClass>BUILDINGCLASS_FERTILIZE_SHRINE</BuildingClass>
            <Type>BUILDING_FERTILIZE_SHRINE</Type>
            <SpecialBuildingType>NONE</SpecialBuildingType>
            <Description>TXT_KEY_BUILDING_FERTILIZE_SHRINE</Description>
            <Civilopedia>TXT_KEY_BUILDING_FERTILIZE_SHRINE_PEDIA</Civilopedia>
            <Strategy>TXT_KEY_BUILDING_FERTILIZE_SHRINE_STRATEGY</Strategy>
            <Help>TXT_KEY_BUILDING_FERTILIZE_SHRINE_HELP</Help>
            <Advisor>ADVISOR_GROWTH</Advisor>
            <ArtDefineTag>ART_DEF_BUILDING_RECYCLING_CENTER</ArtDefineTag>
            <MovieDefineTag>NONE</MovieDefineTag>
            <HolyCity>NONE</HolyCity>
            <ReligionType>NONE</ReligionType>
            <StateReligion>NONE</StateReligion>
            <bStateReligion>0</bStateReligion>
            <PrereqReligion>NONE</PrereqReligion>
            <PrereqCorporation>NONE</PrereqCorporation>
            <FoundsCorporation>NONE</FoundsCorporation>
            <GlobalReligionCommerce>NONE</GlobalReligionCommerce>
            <GlobalCorporationCommerce>NONE</GlobalCorporationCommerce>
            <VictoryPrereq>NONE</VictoryPrereq>
            <FreeStartEra>NONE</FreeStartEra>
            <MaxStartEra>NONE</MaxStartEra>
            <ObsoleteTech>NONE</ObsoleteTech>
            <PrereqTech>TECH_BIOLOGY</PrereqTech>
            <TechTypes/>
            <Bonus>NONE</Bonus>
            <PrereqBonuses/>
            <ProductionTraits/>
            <HappinessTraits/>
            <NoBonus>NONE</NoBonus>
            <PowerBonus>NONE</PowerBonus>
            <FreeBonus>NONE</FreeBonus>
            <iNumFreeBonuses>0</iNumFreeBonuses>
            <FreeBuilding>NONE</FreeBuilding>
            <FreePromotion>NONE</FreePromotion>
            <CivicOption>NONE</CivicOption>
            <GreatPeopleUnitClass>NONE</GreatPeopleUnitClass>
            <iGreatPeopleRateChange>0</iGreatPeopleRateChange>
            <iHurryAngerModifier>0</iHurryAngerModifier>
            <bBorderObstacle>0</bBorderObstacle>
            <bTeamShare>0</bTeamShare>
            <bWater>0</bWater>
            <bRiver>0</bRiver>
            <bPower>0</bPower>
            <bDirtyPower>0</bDirtyPower>
            <bAreaCleanPower>0</bAreaCleanPower>
            <DiploVoteType>NONE</DiploVoteType>
            <bForceTeamVoteEligible>0</bForceTeamVoteEligible>
            <bCapital>0</bCapital>
            <bGovernmentCenter>0</bGovernmentCenter>
            <bGoldenAge>0</bGoldenAge>
            <bAllowsNukes>0</bAllowsNukes>
            <bMapCentering>0</bMapCentering>
            <bNoUnhappiness>0</bNoUnhappiness>
            <bNoUnhealthyPopulation>0</bNoUnhealthyPopulation>
            <bBuildingOnlyHealthy>0</bBuildingOnlyHealthy>
            <bNeverCapture>0</bNeverCapture>
            <bNukeImmune>0</bNukeImmune>
            <bPrereqReligion>0</bPrereqReligion>
            <bCenterInCity>0</bCenterInCity>
            <iAIWeight>0</iAIWeight>
            <iCost>10</iCost>
            <iHurryCostModifier>0</iHurryCostModifier>
            <iAdvancedStartCost>100</iAdvancedStartCost>
            <iAdvancedStartCostIncrease>0</iAdvancedStartCostIncrease>
            <iMinAreaSize>-1</iMinAreaSize>
            <iConquestProb>66</iConquestProb>
            <iCitiesPrereq>0</iCitiesPrereq>
            <iTeamsPrereq>0</iTeamsPrereq>
            <iLevelPrereq>0</iLevelPrereq>
            <iMinLatitude>0</iMinLatitude>
            <iMaxLatitude>90</iMaxLatitude>
            <iGreatPeopleRateModifier>0</iGreatPeopleRateModifier>
            <iGreatGeneralRateModifier>0</iGreatGeneralRateModifier>
            <iDomesticGreatGeneralRateModifier>0</iDomesticGreatGeneralRateModifier>
            <iGlobalGreatPeopleRateModifier>0</iGlobalGreatPeopleRateModifier>
            <iAnarchyModifier>0</iAnarchyModifier>
            <iGoldenAgeModifier>0</iGoldenAgeModifier>
            <iGlobalHurryModifier>0</iGlobalHurryModifier>
            <iExperience>0</iExperience>
            <iGlobalExperience>0</iGlobalExperience>
            <iFoodKept>0</iFoodKept>
            <iAirlift>0</iAirlift>
            <iAirModifier>0</iAirModifier>
            <iAirUnitCapacity>0</iAirUnitCapacity>
            <iNukeModifier>0</iNukeModifier>
            <iNukeExplosionRand>0</iNukeExplosionRand>
            <iFreeSpecialist>0</iFreeSpecialist>
            <iAreaFreeSpecialist>0</iAreaFreeSpecialist>
            <iGlobalFreeSpecialist>0</iGlobalFreeSpecialist>
            <iMaintenanceModifier>0</iMaintenanceModifier>
            <iWarWearinessModifier>0</iWarWearinessModifier>
            <iGlobalWarWearinessModifier>0</iGlobalWarWearinessModifier>
            <iEnemyWarWearinessModifier>0</iEnemyWarWearinessModifier>
            <iHealRateChange>0</iHealRateChange>
            <iHealth>0</iHealth>
            <iAreaHealth>0</iAreaHealth>
            <iGlobalHealth>0</iGlobalHealth>
            <iHappiness>-10</iHappiness>
            <iAreaHappiness>0</iAreaHappiness>
            <iGlobalHappiness>0</iGlobalHappiness>
            <iStateReligionHappiness>0</iStateReligionHappiness>
            <iWorkerSpeedModifier>0</iWorkerSpeedModifier>
            <iMilitaryProductionModifier>0</iMilitaryProductionModifier>
            <iSpaceProductionModifier>0</iSpaceProductionModifier>
            <iGlobalSpaceProductionModifier>0</iGlobalSpaceProductionModifier>
            <iTradeRoutes>0</iTradeRoutes>
            <iCoastalTradeRoutes>0</iCoastalTradeRoutes>
            <iGlobalTradeRoutes>0</iGlobalTradeRoutes>
            <iTradeRouteModifier>0</iTradeRouteModifier>
            <iForeignTradeRouteModifier>0</iForeignTradeRouteModifier>
            <iGlobalPopulationChange>0</iGlobalPopulationChange>
            <iFreeTechs>0</iFreeTechs>
            <iDefense>0</iDefense>
            <iBombardDefense>0</iBombardDefense>
            <iAllCityDefense>0</iAllCityDefense>
            <iEspionageDefense>0</iEspionageDefense>
            <iAsset>6</iAsset>
            <iPower>0</iPower>
            <fVisibilityPriority>1.0</fVisibilityPriority>
            <SeaPlotYieldChanges/>
            <RiverPlotYieldChanges/>
            <GlobalSeaPlotYieldChanges/>
            <YieldChanges/>
            <CommerceChanges/>
            <ObsoleteSafeCommerceChanges/>
            <CommerceChangeDoubleTimes/>
            <CommerceModifiers/>
            <GlobalCommerceModifiers/>
            <SpecialistExtraCommerces/>
            <StateReligionCommerces/>
            <CommerceHappinesses/>
            <ReligionChanges/>
            <SpecialistCounts/>
            <FreeSpecialistCounts/>
            <CommerceFlexibles/>
            <CommerceChangeOriginalOwners/>
            <ConstructSound>AS2D_BUILD_RECYCLING_CENTER</ConstructSound>
            <BonusHealthChanges/>
            <BonusHappinessChanges/>
            <BonusProductionModifiers/>
            <UnitCombatFreeExperiences/>
            <DomainFreeExperiences/>
            <DomainProductionModifiers/>
            <BuildingHappinessChanges/>
            <PrereqBuildingClasses/>
            <BuildingClassNeededs/>
            <SpecialistYieldChanges/>
            <BonusYieldModifiers/>
            <ImprovementFreeSpecialists/>
            <Flavors>
                <Flavor>
                    <FlavorType>FLAVOR_GROWTH</FlavorType>
                    <iFlavor>10</iFlavor>
                </Flavor>
            </Flavors>
            <HotKey/>
            <bAltDown>0</bAltDown>
            <bShiftDown>0</bShiftDown>
            <bCtrlDown>0</bCtrlDown>
            <iHotKeyPriority>0</iHotKeyPriority>
        </BuildingInfo>

  1. パッケージ版の場合。Steam版の場合は C:Program Files (x86)\Steam\SteamApps\common\Sid Meier's Civilization IV Beyond the Sword\Beyond the Sword\Assets\XML\Buildings
    [return]