How to do unit missions in C2C

Joined
Jul 5, 2004
Messages
23,562
Location
Canberra, Australia
This is a work in progress I will be adding to it as I do the work. It may be all over the place as far as content is concerned as I get things straight. ;)

In normal and BUG versions of Civ IV you need to do some python work in the main interface code to add missions to a unit. This is not the case in C2C where we can define missions and outcomes from the missions sometimes with very little python at all.

All files are WoC modular but it is best to include all the relevant files in the one module while you are building and testing the new missions. To this end i will be describing how to set up the module as well.

Missions are the actions that a unit can perform. An example is the spy mission "Bribe City". That particular example is coded in the dll.

Outcomes are a list of things that can happen when the mission is done. The outcomes may require Python to validate that particular outcome or to do the actual action.

Unit Actions this links the outcomes and missions to a particular unit or unit class.

Spoiler :
There are a couple of missions I a considering using as examples
  • Great General action Rally which creates 24 Warriors. Note: number depends on World Size, Type depends on Conscript available (original by Platyping)
  • Thief or Rogue stealing money from another nation

What do you need before you start
Art work for the mission.

What the mission does when successful, partly successful and fails. The probabilities and costs for these.

Where it can happen. What preconditions are there and what modifies the chances of success.​

There are three parts to defining a mission, two are done in XML (mission and outcomes) and there may be a need for some Python as well. AI for the missions may be needed but is out of scope for this document. AI may also be done in Python.

Missions are defined in XML but are not WoC compatible so they must be defined in the core area. Not only that any you add must be at the end of the file because some are defined to the dll by the order they appear.

Outcomes on the other hand can be modular so can be defined in the XML of optional modules. This is the way to control when the mission is in game or not.

Python code is defined in the Event code so is also not modular. (Check this SO has suggested that it may be possible to have it modular.)

Setting up
Create the module folder in this case Assets/Modules/Platyping/Advanced_GP. I am putting this inside the Platyping folder because it is his ideas we are using. If we do a lot more than he did or change it all significantly we may move the mod up to the Modules file but keep a dedication somewhere indicating where the original idea came from. We all do this for free so credit is the only reward we can give.

While building and testing I keep the art in the module folder but have it in the same structures as it will be when transferred into the core area for inclusion in the FPK files. So now create the folders under this Art/Interface/Buttons/Missions and put Rally.dds in this folder.​

Define the mission
Copy the file C2C_CIV4UnitSchema.XML into the Advanced_GP folder and rename it to Advanced_GP_CIV4UnitSchema.XML.

I then usually copy the file I want to work on next from some other module so I can use it as a template. Copy the file CIV4MissionInfos.XML into the Advanced_GP folder and rename it Advanced_GP_CIV4MissionInfos.XML. Edit this file and rename the schema file at the top and delete all missions except the last which we are going to use as a template.

The Advanced_GP_CIV4MissionInfos.XML should look like
Spoiler :
Code:
<?xml version="1.0"?>
	<!-- edited with XMLSPY v2004 rel. 2 U (http://www.xmlspy.com) by Jon Shafer (Firaxis Games) -->
	<!-- Sid Meier's Civilization 4 -->
	<!-- Copyright Firaxis Games 2005 -->
	<!-- -->
	<!-- Mission Infos -->
<Civ4MissionInfos xmlns="x-schema:Advanced_GP_CIV4UnitSchema.xml">
	<MissionInfos>
		<MissionInfo>
			<Type>MISSION_RECORD_TALE_ORAL</Type>
			<Description>TXT_KEY_MISSION_RECORD_TALE</Description>
			<Help>TXT_KEY_MISSION_RECORD_TALE_HELP</Help>
			<Waypoint>NONE</Waypoint>
			<EntityEventType>ENTITY_EVENT_GREAT_EVENT</EntityEventType>
			<iTime>0</iTime>
			<bTarget>0</bTarget>
			<bBuild>0</bBuild>
			<bSound>0</bSound>
			<bVisible>1</bVisible>
			<Button>Art/Interface/Buttons/Missions/RecordOral.dds</Button>
		</MissionInfo>
	</MissionInfos>
</Civ4MissionInfos>

Change the names in the missions file to the one we are using GG_RALLY and put the correct button name in. I expect we will also have a HERO_RALLY mission at some stage which will use the same button but have different outcomes.

It should now look like
Spoiler :
Code:
<?xml version="1.0"?>
	<!-- edited with XMLSPY v2004 rel. 2 U (http://www.xmlspy.com) by Jon Shafer (Firaxis Games) -->
	<!-- Sid Meier's Civilization 4 -->
	<!-- Copyright Firaxis Games 2005 -->
	<!-- -->
	<!-- Mission Infos -->
<Civ4MissionInfos xmlns="x-schema:Advanced_GP_CIV4UnitSchema.xml">
	<MissionInfos>
		<MissionInfo>
			<Type>MISSION_GG_RALLY</Type>
			<Description>TXT_KEY_MISSION_GG_RALLY</Description>
			<Help>TXT_KEY_MISSION_GG_RALLY_HELP</Help>
			<Waypoint>NONE</Waypoint>
			<EntityEventType>ENTITY_EVENT_GREAT_EVENT</EntityEventType>
			<iTime>0</iTime>
			<bTarget>0</bTarget>
			<bBuild>0</bBuild>
			<bSound>0</bSound>
			<bVisible>1</bVisible>
			<Button>Art/Interface/Buttons/Missions/Rally.dds</Button>
		</MissionInfo>
	</MissionInfos>
</Civ4MissionInfos>

Define the text for the mission
Again I prefer to copy an existing text file and work with it as a template. Given that I don't know other languages and C2C now handles the text files so that many more languages work all I need do is define the text in English.

The name of the XML file holding the text will be Adbvanced_GP_CIV4GameText.XML. NB: It is very important that the text files end with the suffix _CIV4GameText, if they don't they will be ignored.
Spoiler :
Code:
<?xml version="1.0" encoding="UTF8"?>
<Civ4GameText xmlns="http://www.firaxis.com">
	<TEXT>
   		<Tag>TXT_KEY_MISSION_GG_RALLY</Tag>
   		<English>Rally Troops</English>
	</TEXT>
	<TEXT>
   		<Tag>TXT_KEY_MISSION_GG_RALLY_HELP</Tag>
   		<English>[COLOR_HIGHLIGHT_TEXT]Rally[COLOR_REVERT][NEWLINE]Creates some combat units.[NEWLINE]It consumes the Great Person.</English>
	</TEXT>
</Civ4GameText>

Defining what you want to happen and who does it when.

We now move onto outcomes.

- how on earth do I give the correct number of units and their type? Do I do that in the outcome?

So far there is nothing to see in game. We now need to add these missions to units using Outcomes.



The important files
CIV4OutcomeInfos
Tag name|Type|Optional|Description
Type|text|no|Mission ID
bTypeDependency|boolean|yes|
bForceOverwrite|boolean|yes|
bForceDelete|boolean|yes|
iForceInsertLocation|integer|yes|
AndDependencyTypes|list|yes|WoC and dependencies
OrDependencyTypes|list|yes|WoC or dependencies (check)
Description|text ID|no|Name of the outcome displayed in game
Message|text ID|no|Text displayed when the mission is done.
PrereqTech|text ID|yes|Text ID of the prerequisite technology
ObsoleteTech|text ID|yes|Text ID of the technology that obsoletes this outcome
PrereqCivic|text ID|yes|Text ID of the prerequisite Civic
bToCoastalCity|boolean|yes|Send the unit to the nearest coastal city if send to city set on.
bFriendlyTerritory|boolean|yes|can be done in friendly territory
bNeutralTerritory|boolean|yes|can be done in neutral territory
bHostileTerritory|boolean|yes|can be done in hostile territory
bBarbarianTerritory|boolean|yes|can be done in barbarian territory
bCity|boolean|yes|must be done in a city
bNotCity|boolean|yes|can't be done in a city
PrereqBuildings|list|yes|list of prerequisite buildings
ExtraChancePromotions|list|yes|list of adjustments to the probability based on the promotions of the unit
ReplaceOutcomes"|list|yes|list of outcomes this outcome replaces
 
Example 1. Trade merchants.
The trade merchant line currently work the same way as the Great Engineer and use his mission. That mission was designed to enable the GE to build any one wonder in one turn. With the trade merchants we want all the :hammers: we have put into building the unit to be fully used especially when the game option multi production is chosen.

This is a fairly easy mission to implement as it is all XML and we can reuse the same button as we currently use.

Step 1 - setup
Create a folder for this to go into and link the folder to the game. All the XML changes can be done in a modular fashion. I'll create one in my area of the modules.
Assets/Modules/DancingHoskuld/TradeMerchant
Edit the MLF file to load this folder i.e. add the following at the end of the Modules section of the file MLF_CIV4ModularLoadingControls.XML
Code:
				<Module>
					<Directory>TradeMerchant</Directory>
					<bLoad>1</bLoad>
				</Module>
Copy into here all the schema files we are going to use.
  • C2C_CIV4UnitSchema.XML from Assets/XML/Units
  • C2C_CIV4GameInfoSchema from Assets/XML/GameInfo
Rename these so that the prefix is TradeMerchants
Step 2 - Define the mission etc.
Create a Mission Infos file. I usually copy the one from the Assets/XML/Units folder, remove all but one of the missions from it and rename the schema file at the top. I then edit the existing mission to do what I want. In this case the work has already been done and is in the mission file in the core files so we don't need to do anything here. If we did th file would look like.
Code:
<Civ4MissionInfos xmlns="x-schema:TradeMerchant_CIV4UnitSchema.xml">
	<MissionInfos>
		<MissionInfo>
			<Type>MISSION_HURRY_PRODUCTION</Type>
			<Description>TXT_KEY_MISSION_HURRY_PRODUCTION</Description>
			<Help>TXT_KEY_MISSION_HURRY_PRODUCTION_HELP</Help>
			<Waypoint>NONE</Waypoint>
			<EntityEventType>ENTITY_EVENT_GREAT_EVENT</EntityEventType>
			<iTime>0</iTime>
			<bTarget>0</bTarget>
			<bBuild>0</bBuild>
			<bSound>0</bSound>
			<bVisible>1</bVisible>
			<Button>,Art/Interface/Buttons/Actions/Hurry.dds,Art/Interface/Buttons/Actions_Builds_LeaderHeads_Specialists_Atlas.dds,2,3</Button>
		</MissionInfo>
	</MissionInfos>
</Civ4MissionInfos>
The only thing I would change is to replace ENTITY_EVENT_GREAT_EVENT with NONE as that value is a delay so that you can see the great person animation.

Next create the Outcome file this is simple as there will only be one outcome for this mission. The file (TradeMerchant_CIV4OutcomeInfos.XML) looks like
Code:
<Civ4OutcomeInfos xmlns="x-schema:TradeMerchant_CIV4GameInfoSchema.xml">
	<OutcomeInfos>
		<OutcomeInfo>
			<Type>OUTCOME_HURRY_PRODUCTION</Type>
			<Description>TXT_KEY_OUTCOME_HURRY_PRODUCTION</Description>
			<Message>TXT_KEY_OUTCOME_HURRY_PRODUCTION_MISSION</Message>
			<PrereqTech>NONE</PrereqTech>
			<bNeutralTerritory>0</bNeutralTerritory>
			<bHostileTerritory>0</bHostileTerritory>
			<bCity>1</bCity>
		</OutcomeInfo>
	</OutcomeInfos>
</Civ4OutcomeInfos>
Notice that we only want this mission to work in one of our cities. If you wanted it to work in both your and other friendly cities then you would set bNeutralTerritory to 1.​

Lastly we need to connect these missions to the units. Create a unit infos file in the mod folder with the bare bones of the units we are going to add the missions to.
Spoiler :
Should be called TradeMerchant_CIV4UnitInfos.XML and look like
Code:
<Civ4UnitInfos xmlns="x-schema:TradeMerchant_CIV4UnitSchema.xml">
	<UnitInfos>
		<UnitInfo>
			<Class>UNITCLASS_EARLY_MERCHANT_C2C</Class>
			<Type>UNIT_EARLY_MERCHANT_C2C</Type>
		</UnitInfo>
		<UnitInfo>
			<Class>UNITCLASS_TRADE_CARAVAN</Class>
			<Type>UNIT_TRADE_CARAVAN</Type>
		</UnitInfo>
		<UnitInfo>
			<Class>UNITCLASS_SUPPLY_TRAIN</Class>
			<Type>UNIT_SUPPLY_TRAIN</Type>
		</UnitInfo>
		<UnitInfo>
			<Class>UNITCLASS_FREIGHT</Class>
			<Type>UNIT_FREIGHT</Type>
		</UnitInfo>
	</UnitInfos>
</Civ4UnitInfos>
Now we start adding the actions for these units. In this case they will all be the same except for the values in the :hammers: field. There is only one outcome and it happens 100% of the time.
Code:
			<Actions>
				<Action>
					<MissionType>MISSION_HURRY_PRODUCTION</MissionType>
					<ActionOutcomes>
						<Outcome>
							<OutcomeType>OUTCOME_HURRY_PRODUCTION</OutcomeType>
							<iChance>100</iChance>
							<Yields>
								<iYield>0</iYield>
								<iYield>[B][COLOR="Red"]1000[/COLOR][/B]</iYield>
								<iYield>0</iYield>
							</Yields>
						</Outcome>
					</ActionOutcomes>
				</Action>
			</Actions>
We just have to figure out what we want in place of the 1000:hammers:. Firstly we want it to adjust itself for game speed etc so it becomes
Code:
								<iYield>
									<Adapt>
										<ID>ADAPT_DEFAULT</ID>
										<Constant>[B][COLOR="Red"]1000[/COLOR][/B]</Constant>
									</Adapt>
								</iYield>

My view is that each should be able to build a basic production building for their era in one go. This would give:-
Unit|Buildings|Hurry value
Early Merchant|Clay Pit or Tar Pit or Drying Frame
Merchant|Charcoal burner
Supply Train|Forge
Freight|Foundry

Problem: this does not quite work properly because we will have both the new mission and the Great Engineer mission appearing for the units. To fix that we need to set the iBaseHurry tag to zero and you can't reset to the default value using the WoC method so to finish this off will require that all this be moved out of the module and put into the core. I'll do that after testing.​

Example 2: New worker and explorer action for exploring city ruins.
 
Example 2: Some of Platyping's extended great people missions.

Great General (all use up the Great General)
2.1 Train Troops (tech: Military Training)
- requires player to be at peace with all but the barbarians
- all units get +2 exp​

2.2 Rally (tech: Warfare)
- requires player to be at war with at least one other nation
- gives a number (based on world size) of conscript units at the plot the GG is on.​

2.5 Great War Path (tech: Leadership)
- requires player to be at war with at least one non minor nation
- gives all land units an +1 movement​

2.4 Sun never sets (tech: Leadership)
- requires player to be at war with at least one non minor nation
- gives all sea units an +1 movement​

2.3 Charge (tech: Logistics)
- requires player to be at war with at least two non minor nation
- restores all attack and movement of all units​
 
First example is up - in post #2. I have to test it to make sure it works and finalise the hurry values. Then I'll go back and describe the files and their values.
 
What is dreaded about that file when you are a python modder.
For instance, I can make a mission available only for particular civics or during golden age.
Doesn't seem possible here.
 
It is very possible here. I have not gotten to the examples that call python yet. You can call it for both when the mission can occur and what it does. It basically uses the Event mechanism. The main benefit is that the hover over and other text is just part of the XML as are other things. Which means some of the AI for when the mission is done by the AI is there, you don't have to program it.
 
What is dreaded about that file when you are a python modder.
For instance, I can make a mission available only for particular civics or during golden age.
Doesn't seem possible here.
There are two tags on outcome missions that allow this kind of thing:
UnitCondition and PlotCondition

They are boolean expression tags and can be used to query quite a lot of different things.
For instance you can make the mission only available if you have CIVIC_X active with the following XML added to the outcome mission:
Code:
<UnitCondition>
  <Has>
    <GOMType>GOM_CIVIC</GOMType>
    <ID>CIVIC_X</ID>
  </Has>
</UnitCondition>

Golden age has not been added either to BoolExpr or IntExpr yet but you could make a Python function that returns the number of golden age turns named something like GetGoldenAgeTurns and then interface it to the mission like this:
Code:
<UnitCondition>
  <Greater>
    <Python>GetGoldenAgeTurns</Python>
    <Constant>0</Constant>
  </Greater>
</UnitCondition>

Outcome missions can also be added to unit combat types so they are available for all units of a certain type (and C2C allows multiple combat types to be on a unit).

Another example:
It is possible to check that a player has a certain wonder before you make a mission available like this:
Code:
<UnitCondition>
  <IntegrateOr>
    <RelationType>RELATION_ASSOCIATED</RelationType>
    <GameObjectType>GAMEOBJECT_PLAYER</RelationType>
    <Has>
      <GOMType>GOM_BUILDING</GOMType>
      <ID>BUILDING_WONDER_X</ID>
    </Has>
  </IntegrateOr>
</UnitCondition>
Querying the unit directly with Has would check if there is that building on the units current plot, so it takes the associated player (the owner) and queries that instead.
To make the mission only available once every X turns a property could be added to the player from the wonder at 1 per turn and then this mission could have a property cost of X of that property.
 
In post #3 I have listed 5 of platypings enhanced missions for great generals that I am going to do as an example for this tutorial. Any comments on the restrictions, Tech requirements etc..
 
2.2 Rally

Short answer: I think this should require appropriate civics. Doesn't have to be Conscription, but Intolerant and the feudal one would also do (and there may be others).

Long answer: I think Great Generals raise morale rather than rallying troops per se. The rallying is done by the 'worldview' (ie. civics). Come to think of it (cynicism alert...), it is (more?) often by propaganda, but here again the great generals themselves are (afaik without exception...and to their credit lol) no great help;).
 
In post #3 I have listed 5 of platypings enhanced missions for great generals that I am going to do as an example for this tutorial. Any comments on the restrictions, Tech requirements etc..

Excellent, btw where is this from pt??

2.2 Rally

Short answer: I think this should require appropriate civics. Doesn't have to be Conscription, but Intolerant and the feudal one would also do (and there may be others).

Long answer: I think Great Generals raise morale rather than rallying troops per se. The rallying is done by the 'worldview' (ie. civics). Come to think of it (cynicism alert...), it is (more?) often by propaganda, but here again the great generals themselves are (afaik without exception...and to their credit lol) no great help;).

I like the long answer, Patton as one :mischief:
 
Long answer: I think Great Generals raise morale rather than rallying troops per se. The rallying is done by the 'worldview' (ie. civics). Come to think of it (cynicism alert...), it is (more?) often by propaganda, but here again the great generals themselves are (afaik without exception...and to their credit lol) no great help;).

I disagree - that is what Great Commanders do:lol::mischief:

How about?
Rally requires Society Civic - Feudal or Military Civic - Conscription, Mercenaries or Vassalage or Rule Civic - Vassalage or Martial Law.

Train Troops requires Education Civic - Military Training or Propaganda.​
 
I disagree - that is what Great Commanders do:lol::mischief:

How about?
Rally requires Society Civic - Feudal or Military Civic - Conscription, Mercenaries or Vassalage or Rule Civic - Vassalage or Martial Law.

Train Troops requires Education Civic - Military Training or Propaganda.​

My main point was to see civic prereqs - I'm not too fussed which ones.

I do think Propaganda would be a good prereq for Rally (even better than for Train Troops).
 
Looks like the mission outcomes are coded so that there can only be one prerequisite civic. Which means I can do many but only if they are in the same civic set.
 
Looks like the mission outcomes are coded so that there can only be one prerequisite civic. Which means I can do many but only if they are in the same civic set.
UnitCondition with several Has for GOM_CIVIC combined by And and Or not working ?
 
Missions not defined in the same folder as the units using them is not working!

I have not used the expression system much so don't know.
 
Can you put them in the core then and have that work on all modules? If you do that, would you be able to put them in the module you want them in AS WELL so that you maintain portability?
 
Back
Top Bottom