A New SDK generic base Info class proposal

primem0ver

Emperor
Joined
Jun 16, 2006
Messages
1,158
Location
Peoria, AZ
This may be something I should post in a general form but for now I think it is most appropriate here since we have a large number of developments underway.

IMPORTANT NOTE: This will be a rather technical discussion mainly for SDK modders.

During my work in on the GeoRealism mod (and in previous work on other mods) I have wondered why Firaxis didn't propose a way of consolidating XML by putting info classes into temporary groups for the purpose of quickly and easily assigning values without the inordinate amount of XML we find in the info files.

For example, my current need in the GeoRealism mod is to associate the odds a vegetation type (and a bedrock/geography type) have to produce a particular bonus. Given the amount of bonuses in this mod, using the traditional Civ XML/Info method this would take a LOT of unnecessary XML since the odds for groups of bonuses are the same. Traditionally I would have to define those odds for each and every bonus. I can't use bonus classes to get the job done since the purpose for bonus classes is significantly different.

What's more is that any info class used to group infos would only need to exist at XML loading time since their purpose is to streamline associating a particular info class (such as bonuses in the example) with a certain piece of data (such as odds in the example) and linking that association to a second info class (such as vegetation types in the above example).

So I am proposing a new generic base class to be used in the SDK's CvInfo.h and CvInfo.cpp files. There will also be an associated enumeration for handling derived types that will also be defined in the CvInfo.h file since there is no need to use it anywhere else.

The CvVolatileInfo class (so named because it is temporary) is an abstract base class that cannot be instantiated since each instance needs to be associated with a specific reference class (which is controlled for using the enumeration). This class will meet the following criteria.

  • Derived classes are associated with a specific reference class (a class derived from CvInfoBase).
  • It associates items in the reference class with a common set of values used by the Info class which makes use of the Specific CvVolatileInfo class (which I will refer to as the "source" class).
  • The reference info class items are grouped in a std::vector<int> called "infoIndexes"
  • The source class/data value pairs are stored in a std::vector<INFO_VECTOR>* called "infoMatrix"
  • Requires the derived class to define the read() function which will allow the use of personalized (derived class specific) XML tags even though these tags will still fill the generic values within the CvVolatileInfo base class.
  • Instances are disposable and will (should be) be removed from memory when all XML has been loaded.

*NOTE: INFO_VECTOR is a struct with two integer fields: iInfoID and iData

The details of the class structure and how it can be used will be kept in the following two posts.

Below is are some examples that show how this class would save coding time, coding space (and therefore loading time), and in the long run modding time (because when you add a new info type it only need be modified in one place rather in multiple lists).


Here is a sample section of a file based on the CvVolatileInfo (keep in mind that the class developer must override the read(...) function which allows for customizing tag names even though they will be read into the same basic structures/variables).

Spoiler :
Code:
<CIV4VBonusGroupInfos>
	<BonusSpawnGroups>
		<BonusSpawnGroup>
			<Type>BIOSPAWNCLASS_QUINE</Type>
			<SourceClass>VegetationInfos</SourceClass>
			<!-- WHEN A BONUS GETS ADDED TO THE MOD... ONLY ONE ENTRY NEEDS TO BE MADE RIGHT HERE (in the appropriate group) -->
			<!-- INSTEAD OF MODIFYING EVERY SINGLE VEGETATION OR BEDROCK THAT PRODUCES THAT BONUS! -->
			<Bonuses>
				<Bonus>BONUS_HORSE</Bonus>
				<Bonus>BONUS_COW</Bonus>
				<Bonus>BONUS_NEW_BONUS</Bonus>
			</Bonuses>
			<SpawnVegetations>
				<SpawnVegetation>
					<Vegetation>VEGETATION_SAVANNAH_GRASS</Vegetation>
					<iOdds>4</iOdds>
				</SpawnVegetation>
				<SpawnVegetation>
					<Vegetation>VEGETATION_SAVANNAH</Vegetation>
					<iOdds>4</iOdds>
				</SpawnVegetation>
				<SpawnVegetation>
					<Vegetation>VEGETATION_ARID_OASIS</Vegetation>
					<iOdds>3</iOdds>
				</SpawnVegetation>
				<SpawnVegetation>
					<Vegetation>VEGETATION_OASIS</Vegetation>
					<iOdds>3</iOdds>
				</SpawnVegetation>
				<SpawnVegetation>
					<Vegetation>VEGETATION_WESTERN_GRASS</Vegetation>
					<iOdds>6</iOdds>
				</SpawnVegetation>
				<SpawnVegetation>
					<Vegetation>VEGETATION_GRASS</Vegetation>
					<iOdds>10</iOdds>
				</SpawnVegetation>
				<SpawnVegetation>
					<Vegetation>VEGETATION_TALLGRASS</Vegetation>
					<iOdds>10</iOdds>
				</SpawnVegetation>
				<SpawnVegetation>
					<Vegetation>VEGETATION_LUSH</Vegetation>
					<iOdds>10</iOdds>
				</SpawnVegetation>
				<SpawnVegetation>
					<Vegetation>VEGETATION_LUSH_GRASS</Vegetation>
					<iOdds>10</iOdds>
				</SpawnVegetation>
				<SpawnVegetation>
					<Vegetation>VEGETATION_PLAINS_DECIDUOUS</Vegetation>
					<iOdds>6</iOdds>
				</SpawnVegetation>
				<SpawnVegetation>
					<Vegetation>VEGETATION_RIVER_DECIDUOUS</Vegetation>
					<iOdds>6</iOdds>
				</SpawnVegetation>
				<SpawnVegetation>
					<Vegetation>VEGETATION_DRY_PLAINS</Vegetation>
					<iOdds>15</iOdds>
				</SpawnVegetation>
				<SpawnVegetation>
					<Vegetation>VEGETATION_GRASS_PLAINS</Vegetation>
					<iOdds>15</iOdds>
				</SpawnVegetation>		 
			</SpawnVegetations>
		</BonusSpawnGroup>
	</BonusSpawnGroups>
</CIV4VBonusGroupInfos>

When the above file is loaded, it will access every vegetation on the "SpawnVegetations" list and make an "spawn odds entry" for each bonus on the "Bonuses" list.

There are two ways the above information could have been coded without the Volatile classes. Either within the CIV4VegetationInfos.xml file or within the CIV4BonusInfos.xml file. Theoretically, this could be done with the Volatile info files as well. One would just have to simply reverse the lists. The first, single depth list would be a list of vegetations and the second a list of bonuses to apply the values too. Please pay attention to the comments in each file because they explain the repetition that would be involved and how the above file avoids that repetition.

1. Here is an example of what one would have to have originally done to the CIV4VegetationInfos.xml file.

Spoiler :
Code:
<CIV4VegetationInfos>
	<VegetationInfos>
		<VegetationInfo>
			<Type>VEGETATION_SAVANNAH_GRASS</Type>
			<Description></Description>
			<Civilopedia></Civilopedia>
			<Help></Help>
			<Button></Button>
			<MapColor>COLOR_BLUE</MapColor>
			<Feature>FEATURE_SWORDGRASS</Feature>
			<Variety>0</Variety>
			<SoilTerrain>TERRAIN_SAVANNAH</SoilTerrain>
			<bInundated>0</bInundated>
			<bRooted>1</bRooted>
			<bRequiresRiver>0</bRequiresRiver>
			<bRequiresGroundwater>0</bRequiresGroundwater>
			<iOverrideOdds>0</iOverrideOdds>
			<iSpawnOdds>20</iSpawnOdds>
			<!-- THE FOLLOWING ENTRIES WOULD NEED TO EXIST IN EVERY VEGETATION ON THAT LIST -->	
			<SpawnsBonuses>
				<SpawnsBonus>
					<Bonus>BONUS_HORSE</Bonus>
					<iOdds>4</iOdds>
				</SpawnsBonus>
				<SpawnsBonus>
					<Bonus>BONUS_COW</Bonus>
					<iOdds>4</iOdds>
				</SpawnsBonus>
			</SpawnsBonuses>
		</VegetationInfo>
	</VegetationInfos>
</CIV4VegetationInfos>

2. Here is how it would need to be without the volatile info class if one used the Bonus Info file:

Spoiler :
Code:
<Civ4BonusInfos xmlns="x-schema:CIV4TerrainSchema.xml">
	<BonusInfos>

		...
		<BonusInfo>
			<Type>BONUS_HORSE</Type>
			<Description>TXT_KEY_BONUS_HORSE</Description>
			...
			<!-- notice that this is nearly the same as the list in the derived BonusGroupInfo file -->
			<!== except that if done here, it needs to be repeated for every single bonus within the list -->
			<!-- i.e. all odds in this section MUST BE REPEATED FOR COW -->
			<SpawnVegetations>
				<SpawnVegetation>
					<Vegetation>VEGETATION_SAVANNAH_GRASS</Vegetation>
					<iOdds>4</iOdds>
				</SpawnVegetation>
				<SpawnVegetation>
					<Vegetation>VEGETATION_SAVANNAH</Vegetation>
					<iOdds>4</iOdds>
				</SpawnVegetation>
				<SpawnVegetation>
					<Vegetation>VEGETATION_ARID_OASIS</Vegetation>
					<iOdds>3</iOdds>
				</SpawnVegetation>
				<SpawnVegetation>
					<Vegetation>VEGETATION_OASIS</Vegetation>
					<iOdds>3</iOdds>
				</SpawnVegetation>
				<SpawnVegetation>
					<Vegetation>VEGETATION_WESTERN_GRASS</Vegetation>
					<iOdds>6</iOdds>
				</SpawnVegetation>
				<SpawnVegetation>
					<Vegetation>VEGETATION_GRASS</Vegetation>
					<iOdds>10</iOdds>
				</SpawnVegetation>
				<SpawnVegetation>
					<Vegetation>VEGETATION_TALLGRASS</Vegetation>
					<iOdds>10</iOdds>
				</SpawnVegetation>
				<SpawnVegetation>
					<Vegetation>VEGETATION_LUSH</Vegetation>
					<iOdds>10</iOdds>
				</SpawnVegetation>
				<SpawnVegetation>
					<Vegetation>VEGETATION_LUSH_GRASS</Vegetation>
					<iOdds>10</iOdds>
				</SpawnVegetation>
				<SpawnVegetation>
					<Vegetation>VEGETATION_PLAINS_DECIDUOUS</Vegetation>
					<iOdds>6</iOdds>
				</SpawnVegetation>
				<SpawnVegetation>
					<Vegetation>VEGETATION_RIVER_DECIDUOUS</Vegetation>
					<iOdds>6</iOdds>
				</SpawnVegetation>
				<SpawnVegetation>
					<Vegetation>VEGETATION_DRY_PLAINS</Vegetation>
					<iOdds>15</iOdds>
				</SpawnVegetation>
				<SpawnVegetation>
					<Vegetation>VEGETATION_GRASS_PLAINS</Vegetation>
					<iOdds>15</iOdds>
				</SpawnVegetation>		 
			</SpawnVegetations>
			...
		</BonusInfo>
	</BonusInfos>
</Civ4BonusInfos>
 
Reserved for future use.
 
Reserved for future use.
 
If I get you correctly then the main purpose of the proposed solution is the grouping of info types (like a group of bonuses or a group of unittypes) for use in different info classes to reference them without listing every single one each time.

How would that look from an XML point of view? Would you have a separate info XML that defines those groups?

Groups defined that way usually have a meaning that might be used for more than one purpose including easier texts in help files. So wouldn't it be better to keep them instead of deleting them after XML reading?

I am not quite sure yet how this will be used in the XML reading code but I guess this will become clearer when you post an example or two.
 
If I get you correctly then the main purpose of the proposed solution is the grouping of info types (like a group of bonuses or a group of unittypes) for use in different info classes to reference them without listing every single one each time.

How would that look from an XML point of view? Would you have a separate info XML that defines those groups?

Groups defined that way usually have a meaning that might be used for more than one purpose including easier texts in help files. So wouldn't it be better to keep them instead of deleting them after XML reading?

I am not quite sure yet how this will be used in the XML reading code but I guess this will become clearer when you post an example or two.

I think what he is proposing amounts to syntactic sugar that essentially lets you '#include' boilerplate section of XML attribution into instances, rather than repeating it. However, I'd also like to see an example set of XML to clarify please...
 
I will put an example in the first post when I have a few moments to create the other two ways to do this.
 
Groups defined that way usually have a meaning that might be used for more than one purpose including easier texts in help files. So wouldn't it be better to keep them instead of deleting them after XML reading

There may be a point to this sometimes... I have thought about something similar myself. That is one of the things I hope to discuss in this thread. But Koshling is also right. It is mainly a way to avoid extremely repetitious XML code and because of the way the GeoRealism engine will work to generate the map, either boiler plate XML or a lot of time consuming (both in creating and in loading) xml will be necessary (especially in C2C with its endless numbers of bonuses). Whether there will be a use for these infos after XML is loaded remains to be seen (and discussed).
 
Ok. I added the requested examples to the first post.
 
Ok. I added the requested examples to the first post.
I understand now what you want and would like to suggest a fourth solution:
Instead of having the vegetation information in the bonus group, only have that as a definition of a bonus group: a name, description and a set of bonuses. Then in the vegetation XML you specify the group name when you do the assignment instead of the single bonuses.
It would probably be best to have one info class/XML file that can define any group of IDs that can then be used in supported info classes.
 
I understand now what you want and would like to suggest a fourth solution:
Instead of having the vegetation information in the bonus group, only have that as a definition of a bonus group: a name, description and a set of bonuses. Then in the vegetation XML you specify the group name when you do the assignment instead of the single bonuses.
It would probably be best to have one info class/XML file that can define any group of IDs that can then be used in supported info classes.

This is essentially what I am proposing. The top example is an example of such a file. None of the other entries would need to exist. Not even the group reference you mention. Did I misinterpret what you said?
 
This is essentially what I am proposing. The top example is an example of such a file. None of the other entries would need to exist. Not even the group reference you mention. Did I misinterpret what you said?
I'll give an example of what I mean tomorrow.
 
Ok, here is the example:

One ID grouping XML:
Spoiler :
Code:
<CIV4IDGroupInfos>
	<IDGroups>
		<IDGroup>
			<Type>BIOSPAWNCLASS_QUINE</Type>
			<Description>TXT_KEY_BIOSPAWNCLASS_QUINE</Description>
			<IDs>
				<ID>BONUS_HORSE</ID>
				<ID>BONUS_COW</ID>
				<ID>BONUS_NEW_BONUS</ID>
			</IDs>
		</IDGroup>
	</IDGroups>
</CIV4IDGroupInfos>

The vegetation info would then look like this:
Spoiler :
Code:
<CIV4VegetationInfos>
	<VegetationInfos>
		<VegetationInfo>
			<Type>VEGETATION_SAVANNAH_GRASS</Type>
			<Description></Description>
			<Civilopedia></Civilopedia>
			<Help></Help>
			<Button></Button>
			<MapColor>COLOR_BLUE</MapColor>
			<Feature>FEATURE_SWORDGRASS</Feature>
			<Variety>0</Variety>
			<SoilTerrain>TERRAIN_SAVANNAH</SoilTerrain>
			<bInundated>0</bInundated>
			<bRooted>1</bRooted>
			<bRequiresRiver>0</bRequiresRiver>
			<bRequiresGroundwater>0</bRequiresGroundwater>
			<iOverrideOdds>0</iOverrideOdds>
			<iSpawnOdds>20</iSpawnOdds>
			<SpawnsBonuses>
				<SpawnsBonus>
					<BonusGroup>BIOSPAWNCLASS_QUINE</BonusGroup>
					<iOdds>4</iOdds>
				</SpawnsBonus>
				<SpawnsBonus>
					<Bonus>BONUS_WHATEVER_SINGULAR</Bonus>
					<iOdds>7</iOdds>
				</SpawnsBonus>
			</SpawnsBonuses>
		</VegetationInfo>
	</VegetationInfos>
</CIV4VegetationInfos>

The advantages are that the group info can be used to store groups of any info types, all in one info class and XML file without changes needed. The repetition is gone and you can also use the quine group description in the help text generation. The disadvantage is that the storing and reading of the vegetation info class is slightly more complex but I think that can be packaged into a storage class that handles groups transparently.
 
The advantages are that the group info can be used to store groups of any info types, all in one info class and XML file without changes needed. The repetition is gone and you can also use the quine group description in the help text generation. The disadvantage is that the storing and reading of the vegetation info class is slightly more complex but I think that can be packaged into a storage class that handles groups transparently.

Ok I see your point. But if the groups are not to be persistent, then the other way is better because it does the same thing with the extra bonus of storing all assignment data in a central location without having to sort through each vegetation (as you pointed out). I will think about it.

In the end, however, I never planned and still don't plan on changing the way text works. I don't think reporting groups is necessary. The point is to provide a quick and easily modified way of indexing relationships. The structure of the way the information is stored in the CvVegetationInfos class remains unchanged. I don't want to use more memory or text handling. I just want to simplify coding and loading the xml.
 
Back
Top Bottom