Modder's Documentation

Done, finally. Now, AIAndy do you have one of those for the Outcome System? I can't find it. I need to find how to put a cost in gold on a mission so that you can't do the mission if you can't afford it.
I am not sure if I ever wrote one for the outcome system.
The cost tag for an outcome mission is iCost, used within the Action tag and you can also have a PropertyCost.
 
I am not sure if I ever wrote one for the outcome system.
The cost tag for an outcome mission is iCost, used within the Action tag and you can also have a PropertyCost.

Now I am really confused. I have a (diplomatic) mission which can have many outcomes. the mission should only be done if you can afford the cost. So if I put the cost on the action outcomes will the button will be available if the player can't afford any of the outcomes? If so whats to them saying the button does not work?
 
Now I am really confused. I have a (diplomatic) mission which can have many outcomes. the mission should only be done if you can afford the cost. So if I put the cost on the action outcomes will the button will be available if the player can't afford any of the outcomes? If so whats to them saying the button does not work?
Not in the outcomes, you add it directly under the action tag, where the MissionType and bKill is.
An example with PropertyCost from the nomad tech demo:
Code:
				<Action>
					<MissionType>MISSION_NOMAD_DEFENDER</MissionType>
					<bKill>0</bKill>
					<PropertyCost>
					  <Property>
					    <PropertyType>PROPERTY_FRUIT</PropertyType>
					    <iPropertyValue>60</iPropertyValue>
					  </Property>
					  <Property>
					    <PropertyType>PROPERTY_HUNT</PropertyType>
					    <iPropertyValue>40</iPropertyValue>
					  </Property>
					  <Property>
					    <PropertyType>PROPERTY_MATERIAL</PropertyType>
					    <iPropertyValue>100</iPropertyValue>
					  </Property>
					</PropertyCost>
					<ActionOutcomes>
						<Outcome>
							<OutcomeType>OUTCOME_NOMAD_DEFENDER</OutcomeType>
							<iChance>100</iChance>
							<UnitType>UNIT_STONE_THROWER</UnitType>
						</Outcome>
					</ActionOutcomes>
				</Action>
Now instead of PropertyCost and its subtags you use iCost, like this:
Code:
				<Action>
					<MissionType>MISSION_NOMAD_DEFENDER</MissionType>
					<bKill>0</bKill>
					<iCost>100</iCost>
					<ActionOutcomes>
						<Outcome>
							<OutcomeType>OUTCOME_NOMAD_DEFENDER</OutcomeType>
							<iChance>100</iChance>
							<UnitType>UNIT_STONE_THROWER</UnitType>
						</Outcome>
					</ActionOutcomes>
				</Action>
 
Hey quick question. Turns out adding civs to C2C is harder than vanilla :p

Basically just copy and paste a folder from a current civ and change all the appropriate stuff right?

Do I need to touch the schema files at all?
 
You need to use the c2c schema file.

Thank you DH.

Can anyone tell me where I'm suppose to find the art files for culture wonder buildings. I'm trying to figure out how to get to those buttons but I can not seem to find them anywhere. On a related topic, can those buttons be used for new civ buttons?
 
Thank you DH.

Can anyone tell me where I'm suppose to find the art files for culture wonder buildings. I'm trying to figure out how to get to those buttons but I can not seem to find them anywhere. On a related topic, can those buttons be used for new civ buttons?

Some are taken from the core civs such as English or French while others were added later like Aborigine or Inuit. This is why some flags do not match their playable civs. Most of the add-on civ icon/buttons are in the Hydro.FPK under the Embassy folder.

The wonders were suppose to be Embassy buildings like in Age of Empires 3 but changed as the concept evolved. So the name of the folder stayed. Note that they only have button/icons and not things like flags like a playable civ has. Also the culture resource and the culture wonder share the same icon/button.
 
Thank you for clearing that up for me Hydro! Yeah I'm going to do work on the flag decals which may take some time since I'm not that good with graphics stuff. I'm making up some more playable civs for a scenario and obviously they will have buttons. I can send them over to you when I'm done if you want them (the ones that don't already have culture wonder buttons).
 
Thank you for clearing that up for me Hydro! Yeah I'm going to do work on the flag decals which may take some time since I'm not that good with graphics stuff. I'm making up some more playable civs for a scenario and obviously they will have buttons. I can send them over to you when I'm done if you want them (the ones that don't already have culture wonder buttons).

You should ask SO if he already has the civ you want on file. He has so many civs already made but not converted to C2C yet. Save you some time an effort.
 
New Building Costs:

This is a reference for starting points for building and unit costs in the XML. These numbers will ofc be adjusted by gamespeed and other modifiers.

Column Cost
30 80
31 90
32 100
33 105
34 110
35 120
36 130
37 130
38 140
39 150
40 160
41 180
42 190
43 200
44 220
45 230
46 250
47 260
48 280
49 300
50 320
51 350
52 370
53 400
54 420
55 450
56 490
57 520
58 560
59 600
60 640
61 680
62 730
63 780
64 840
65 890
66 960
67 1020
68 1100
69 1150
70 1250
71 1350
72 1450
73 1550
74 1650
75 1750
76 1900
77 2000
78 2150
79 2300
80 2450
81 2650
82 2800
83 3000
84 3250
85 3450
86 3700
87 3950
88 4250
89 4550
90 4850
91 5200
92 5550
93 5950
94 6350
95 6800
96 7300
97 7800
98 8350
99 8900
100 9550
101 9900
102 11000
103 12100
104 12100
105 13200
106 14300
107 15400
108 16500
109 17600
110 18700
111 19800
112 22000
113 23100
114 24200
115 26400
116 28600
117 29700
118 31900
119 34100
120 37400
121 39600
122 41800

This is for normal buildings and units.

NOTE: Do not use these numbers blindly for the Galactic Era or Multi-Maps. That will require more tweaking which I'll get to when we cross that bridge.

  • National Wonders cost 4 times what a normal building would cost for that tech
  • World Wonders cost 8 times what a normal building would cost for that tech
  • Projects cost 12 times what a normal building would cost for that tech
 
This post is to provide modders with an overview of the current support for multi-maps and viewports.

Overview

Firstly a brief recap of the traditional, vanilla Civ IV structure:

Each game state (either from a save, or generated when starting a new game) includes a single map, represented by the CvMap class (CyMap in Python). This class has properties of x and y size, and how the coordinates wrap (so plane, vs torus vs sphere topologically). It also allows you to find the details of any particular plot given its coordinates (returns a CvPlot or CyPlot)

From the perspective of the game engine, over which we have no control, the above model must be what the game engine sees. Hence, to change what gets displayed all we can do is vary the CONTENTS of the single map that is presented to the game engine (i.e. - what's in the plots). To achieve this we introduce a proxy class which presents the same external interface as CvMap, but pulls its data from different places (maybe different underlying maps, maybe different regions of a single map). This proxy is what is known as a viewport (CvViewport) [actually the class hierarchy is more complex than this, but I'll go into fuller detail later]. To switch maps we just change the CvMap the viewport pulls its data from and tell the game engine that all plots are dirty, so it requeries everything. Python does not see the viewport directly, since currently it always operates on the complete map (unlike the game engine it has to process game state, not just passively display things, so it has to see everything). For that reason Python access to the map bypasses the viewport and always accesses the underlying map. There are some exposed functions Python can use however, to determine whether a particular plot is in the current viewport that the game engine is seeing.

This system is most developed to support user-visible viewports as windows into a single larger map, but it's fundamentally exactly the same as viewports onto multiple maps. In current C2C it is always active, even if you have (user level) viewports turned off. In that default case the viewport simply has the same dimensions as the entire map, so the fact that the game engine is interfacing via the viewport has no functional effect.

C2C also supports (to some extent) multiple actual maps. The globals (CvInternalGlobals) holds an array of maps (instead of the single one that vanilla BTS holds). At any time any one of these can be the 'current' map (and for now map index 0 is always current until we add UI and Python to switch). The current map can be switched using cvInternalGlobals::switchMap() to any in the allocated array. Currently, when processing end turn, only the current map will be processed (so in effect the turn only takes place on the current map) - this is one of the things that will have to change (it will need to iterate through all the maps playing the [AI] turn in each).

At game start map 0 is automatically generated. At any other time new maps (with indexes > 0) may be generated by Python calls. Such map generation just creates a new CvMap instance - it does not actually generate its plots at the time. The first time a map switch is made to a new map its plots will be generated. Currently this just uses the default map generator, and there is no control over map script used (this needs to change - see below)

We also inherited (from Lytning's parallel maps prototype) some map-definition XML, though this is essentially unused by C2C. It is accessible via Python. It consists of two files:

CvMapInfo.xml, which defines a set of maps; and
CvMapSwitchInfo.xml which defines mechanisms for switching between maps

Both of these are essentially unused collections of properties. Lytning's intent was to access these from Python, and based on what they contain, to call the other Python APIs that actually manipulate and switch between multimaps, to generate (and use) the necessary resulting maps.

My recommendation is to do away entirely with CvMapSwitchInfo (map switching is better handled as implicit mechanisms in the DLL and UI elements via the Python IMO). I would also repurpose (and enhance) CvMapInfo so that it defines the full set of maps available (including scripts etc.). In effect that means that it predefines a set of types (MapTypes, which is an enum we already have) which are valid indexes to use when calling functions like SetCurrentMap(). The DLL needs to be enhanced to read the appropriate map script (and other properties like size and wrapping) when it needs to generate the map on demand the first time it is switched to (that way we don't take the memory hit until the map is needed). The code that does this (and will need to be enhanced to read CvMapInfo and act accordingly) is in CvMap::afterSwitch().

Detailed reference material

In detail the actual class hierarchy used for maps is as follows:

CvMapInterfaceBase - abstract class that defines the external interface a map needs to provide

CvMap - underlying concrete map - a subclass of CvMapInterfaceBase

CvViewport - a window onto an underlying map - a subclass of CvMapInterafceBase. This has a reference to a CvMap instance which is the udnerlying map - the viewport size may be any size less than or equal to the underlying map size

CvMapExternal - class the game engine links to. This is just a shell that forwards all requests to an associated CvMpInterfaceBase instance, which will be the current viewport on the current map

Python methods are currently exposed on CyMap, and are as follows:

Map type (so this will correspond with the type id in CvMapInfo.xml if we follow my suggestion above - currently it's just an array index in the global map array which is pretty meaningless to Python). If we do this then the setType() method should be removed from the python, since it will only be legitimate to set the type at map creation type.
Code:
	int getType();
	void setType(int iNewType);

Viewports:
Code:
	bool viewportsEnabled();
	int	getViewportWidth();
	int	getViewportHeight();
	int	getMapXFromViewportX(int iX);
	int	getMapYFromViewportY(int iY);
	int	getViewportXFromMapX(int iX);
	int	getViewportYFromMapY(int iY);
	bool isInViewport(int X, int Y);

Viewport manipulation (don't mess with closeAdvsor unless you know what you're doing - it's used to switch back to a normal view after being in the military advisor):
Code:
	void closeAdvisor(int advisorWidth, int iMinimapLeft, int iMinimapRight, int iMinimapTop, int iMinimapBottom);
	void bringIntoView(int iX, int iY, bool bDisplayCityScreen);

Map switching:

Code:
void CyGlobalContext::switchMap(int iMap);
int CyGlobalContext::getNumMapInfos() const;
CvMapInfo* CyGlobalContext::getMapInfo(int iMap) const;
int CyGlobalContext::getNumMapSwitchInfos() const;
CvMapSwitchInfo* CyGlobalContext::getMapSwitchInfo(int iMapSwitch) const;
CyMap* CyGlobalContext::getMapByIndex(int iIndex);
void CyGlobalContext::initializeMap(int iMap);

These are only partially hooked up currently, and if we follow my proposal of getting rid of CvMapSwitchInfo.xml and using CvMapInfo.xml to define all the legitimate maps (MAP_EARTH, MAP_MOON, ...) then getMapByIndex() and getMapSwitchInfo() will disappear. InitializeMap() is also not needed in the Python, since we'll just have the DLL initialize all maps at startup (note - initializing a map is not the same as generating it, which happens on demand when it is first switched to)
 
Top Bottom