Menu

Non-mod specific features

Nightinggale

This is a list of features I added to the DLL in Medieval Conquest, which would work in any mod. Overall features listed here has to do with data handing and data storage and as such they are tools for modders rather than ingame features. most if not all of the features mentioned here have been written with performance in mind, meaning they should all be quite fast. Also they contain a number of asserts for quick detection and localization of bugs (such as calling with invalid ID).

If possible, the features mentioned here are written in files of their own, meaning they can be copied into other mods with very little effort.

This is a short summary of major aspects of the features. I plan on full documentation in the header files.

If you are interested in anything, feel free to contact me. In fact it would like be best if you contact me instead of just copying without telling me because this is work in progress. Some of it is well tested and confirmed to work and something might have been added yesterday.

Nightinggale

XML reading

I changed XML reading to read Basic Info ASAP. This serves two purposes.

  1. It reads all the types before any XML files are actually read
  2. GC.getNum*Types() will work right away

1 will reduce or possibly even completely remove the need for readPass2 and readPass3, making XML reading code much easier to handle and easier to read.

2 unlike vanilla, the lengths are available for the constructor in CvPlayer.

The actual XML data is read just prior to opening the main menu. This includes the files vanilla reads after the main menu.

Savegames

Improved upgrade conversion

CvGame saves the type strings for a bunch of XML files. On load, it generates a conversion table for moving from the saved set of types to the current one. This is build into the XML reading code meaning it hooks into the regular read function calls and works based on overloaded calls. No change for the vanilla functions, but reading types like CivicTypes and UnitTypes will automatically trigger this system.

For instance if a UnitTypes is saved as 4, the conversion table can say that this string has now moved to 6 and the read function will read 6.

Shared read and write code

The savegame code now has a function called readWrite(bool bRead, stream), which is called by both read() and write().

It calls readWrite() for each variable, which is simply a wrapper for read and write (uses bRead to pick). This mean it boils down to call the same code as the vanilla read and write functions, but since there is just one function, read and write can't go out of sync. New variables can be added with just a single line.

Just in Time arrays

Called JITarray for short. Originally named as such because it was meant to cache and only allocate if it was actually used. Now with greatly expanded features, the name is no longer that good.

No manual memory management

This is a class, which has a pointer used for an array. Constructor and deconstructor handles assigning NULL and freeing the memory, meaning no adding this as a variable in a class (like CvPlayer or CvUnit) will not need any code in the constructor or deconstructor and it can't leak memory.

It will require a line in reset though, but that will just be a call to the member function reset().

It has two basic functions, which are set() and get(). Just write to it and it will allocate memory if needed and it will free memory if it is no longer needed. If the array is unallocated, it assumes all variables to be the default value (set by constructor, default 0).

More advanced functions, such as add() and even adding JIT arrays with each other or comparing them also exist. isAllocated() is a shortcut to tell if all variables is default, which have been used to skip looping arrays entirely with nice performance boosts as a result.

Length is given in the constructor. It is given as an enum type, which tells which XML file it uses for length (which makes it important to have read the XML basic info prior to calling the constructor of CvPlayer)

XML interface

There is a read function, which is given an XML pointer and a tag and it will read the XML file and fill the array with XML data.
However after this feature has been added, InfoArray showed up and does this way better (see below). JIT arrays can add with an InfoArray as argument, making those two types to some degree interchangeable and they work well together.

Savegames

Buildin read, write and readWrite().

Automated use of type conversion table from CvGame (see Savegames), except it works on array index rather than changing the content of a single variable. However the JIT array will call the regular read/write code for each variable, meaning if it is something like a BuildingTypes or similar, that too will call the conversion code.

Read will assign the default value to anything, not stored in the savegame. This is exploited by write(). It is perfectly happy writing just 10% of the array if it knows the remaining only contains default value. Less data written results in smaller savegame files.

2D JIT array

This is a vector of JIT arrays. The goal is to make it as close to JIT arrays as possible.

2D cache array

Same functionality as 2D JIT array, but it is optimized for having all the memory allocated all the time. Intended for stacking cached values of multiple InfoArrays.

BoolArray

More or less the same as JIT array, except it is written for storing just true or false. This is done in an array of unsigned 32 bit ints, where each is used to store 32 bools. This will reduce memory usage and savegame file size.

InfoArray

This is an array designed to be used in info classes. It reads an array, but it only stores the values present in XML. This mean it works like the vectors in vanilla. However the constructor tells how many variables there are for each index (default 2) and how many of those are text types, which should be converted to ints (default 1).

Regardless of the size, it will read XML data by just using read and a tag to read and it adapts to various XML layouts.

See here for an example: forum link

ModifierContainer

This is a class for applying the effect of multiple modifiers.

It is meant as a replacement of
var *= modifier;
var /= 100;

Instead it adds all the modifiers with .add(modifier).

In the end it uses .get() to get the result. Internally it will calculate in a way to get a consistent result regardless of order of inputs. It will also try to fight int rounding errors. It is also optimized with some shortcuts, such as return 0 if one of the inputs is 0 (no need to multiply and divide a lot) as well as ignore inputs, which are 100.

Modifier cache variables

There are frontends using ModifierContainer, which works well for caching stuff. They are written to be used in CvPlayer and uses InfoArrays as input.

The variables have a ContainerModfier and a cached get() for quick access of the result. They exist as single variable as well as 1D and 2D arrays.


MongoDB Logo MongoDB