Custom Save File (from Paradox Interactive) vs XML Save File

So I have been playing Crusader Kings 2 (and a slew of other Paradox Interactive games). I really like how moddable it is and I want to emulate it. Both the openness and the gameplay.

I’m trying to decide what format to use for my save files. I’ve never used XML. But using an open format (well-documented, well-tested, human readable, existing third-party scripts) appeals to me.

I’m conscious that Paradox went a different way for CK2 (and the EU series). I’m wondering if it’s because there are major limits to XML for their purposes. I’ve seen lots of threads debating the merits of XML, but none that really tells me if CK2 would be any less achievable using XML.

Their save games can be 50+ megabytes each. It’s possible they’d be even more massive with XML.

For reference, here’s a segment of their save file, with some discussion.

It starts with a character code (554036=…)

554036=
		{
			birth_name="Lambert"
			birth_date="1164.3.30"
			father=543529
			mother=544709
			spouse=557616
			dynasty=678

Seems straight forward. The character gets a name, a birth date, and link to other character codes to establish family members. (And a dynasty code to establish their family “team” number.)

That should be pretty doable, right?

Moving on…

			fertility=0.600
			health=5.500
			prestige=1390.451
			score=13612.258
			piety=1114.511

The game keeps track of some float values in pretty predictable ways. Also pretty doable in XML, I should think.

			attributes=
			{
9 4 3 10 7 			}

This part is interesting. Every character has 5 RPG-style attributes. Instead of having to type out “94”, CK2 just lists the 5 attributes in order, which is admittedly more convenient.

This isn’t how you would conventionally use XML to maximize readability. But could you just have a list of codes in an entry anyway?

traits=
			{
5 120 65 82 77 86 83 94 			}

This one is even more interesting. Traits are all unique, represented by codes. (“65” means they’re a scholar. “77” means they’re greedy.) Each trait gives a corresponding set of bonuses (e.g. +2 strength, +4 intelligence), which are gathered by looking it up

THIS I have no idea if XML can handle. Can we just list a bunch of tags to add to a player, and have it look up what those tags do in some other XML file?

			religion="catholic"
			culture="norman"
			graphical_culture="swedish"

These ones are also neat because these tags have specific meanings. But I figure if we can look up a numerical trait in some XML file, we could look up a string in some XML file. (“catholic” gives you X/Y/Z bonuses…)

job_chancellor=yes
				job_marshal=no
				job_treasurer=no
				job_spymaster=no
				job_spiritual=no

Keeps track of jobs as booleans. Seems straight forward.

But tracking all of a player’s units is where things get complicated…

army=
				{
					id=
					{
						id=67683
						type=41
					}
					name="Army of Bishop Hamelin"
					previous=805
					sub_unit=
					{
						id=
						{
							id=40244
							type=42
						}
						title="---"
						home=337
						morale=1.000
						type=2
						owner=554036
						date="1209.5.20"
						retinue_type="RETTYPE_CUL_FRANK_NOR_GER"
						troops=
						{
							light_cavalry=
							{
								200 200 
							}
							knights=
							{
								300 300 
							}
						}
					}
					sub_unit=
					{
						id=
						{
							id=73553
							type=42
						}
						title="---"
						home=337
						morale=1.000
						type=2
						owner=554036
						date="1209.5.20"
						retinue_type="RETTYPE_CUL_FRANK_NOR_GER"
						troops=
						{
							light_cavalry=
							{
								200 200 
							}
							knights=
							{
								300 300 
							}
						}
					}
					sub_unit=
					{

...

I’ll spare you the detail. It’s a save file so they have to keep track of the location of EVERY unit in the game. (Which they store within each character’s data to establish ownership.) I’m honestly not sure if XML could handle this.

At what point does tracking a bunch of units (with their individual locations and attributes) become too much of a pain in XML? Dozens? Hundreds? Thousands?

			claim=
			{
				title="b_burgelarab"
				pressed=yes
				weak=no
			}
			claim=
			{
				title="c_medelpad"
				pressed=no
				weak=yes
			}

Claims are unique to the gameplay and tell you whether the player has the “right” to attack a territory. I guess this goes back to other questions, where you might have an entry in your XML for claims, but it can expand or shrink depending on how many claims you have, AND keep track of certain attributes for each claim.

			known_plots=
			{
570451 559215 546975 			}

“Plots” are also unique to the gameplay, telling you who is plotting to kill/overthrow someone. Each plot gets a unique code, referring to a later part of the save game file with more details (which characters are in on a plot, who the plot is against). Basically, another set of codes to look up, and cross reference with entries later in the save game file.

			flags=
			{
				feast_dancers=1200.12.3
				money_from_the_pope=1205.12.7
				gossip=1204.2.26
				gossip_taken=1204.2.26
				epic_tournament=1207.3.30
				tournament_has_ended=1207.8.6
			}

These flags track events that are active. Events have a string (like “epic_tournament” or “gossip”), and if you look them up in another file, they’re pretty elaborate. Sequences of events with triggers and multiple choice options. I’m curious about this too, but this is getting beyond the scope of a simple save-state discussion.

ally=
				{
					id=573793
					value=321
				}
				ally=
				{
					id=574022
					value=175
	
				enemy=
				{
					id=568834
					value=368
				}
				enemy=
				{
					id=542054
					value=110
				}

Keeps tracks of allies and enemies, with some additional modifiers (probably for AI purposes).

I only posted the save data for one character. If you read passed all the other characters, the save file also keeps tracks of active plots (and the characters involved), active wars (and the characters involved AND the quantity of losses), and other things you would want to be able to re-load in a strategy game.

I know this post is long and convoluted. I really need someone experienced with save files (or XML) to tell me what’s achievable.

Thanks in advance.

It depends on how ‘readable’ you want the save file I guess.
Anythings possible. XML serialization is great and fairly customizable to setup how you want things serialized.

In short, if you setup your player class properly to serialize to XML how you want it to it will ‘just work’.
Then it’s a case of calling something like —

using System.Xml.Serialization;

...


PlayerClass myPlayer;

// To save..
XmlSerializer serializer = new XMLSerializer(typeof(PlayerClass));
using(FileStream file = new FileStream(yourSaveFileHere, FileMode.OpenOrCreate, FileAccess.ReadWrite)) {
    serializer.Serialize(file, myPlayer);
}

// To load..
XmlSerializer deserializer = new XMLSerializer(typeof(PlayerClass));
using(FileStream file = new FileStream(yourSaveFileHere, FileMode.Open, FileAccess.Read)) {
    myPlayer = (PlayerClass)deserializer.Deserialize(file);
}
// If your player class is setup something like this for eg:

class Player 
{
    string name = "Wizard";
    List<string> itemsHolding;
    int health;
    [XmlIgnore]Texture2D uiIcon;
}


// You'll get something like this.. 
// Results could be slightly different but you get the idea :)

<Player>
    <name>Wizard</name>
    <Items>
        // Items will be serialized here differently depending on types.
        // I've just used a list of strings for demo but it can be your own item class, etc.
        <string>Wand</string>
        <string>Potion</string>
    </Items>
    <health>87</health>
</Player>

When you load it up/deserialize the file, all your values will be assigned and ready to go. It really is as simple as that once you’ve got it serializing how you like. MSDN lists all the attributes you can customize properties with, like [XmlIgnore], [XmlAttribute], etc. As for file size, that’s going to be dependant on the amount of data you need to store and more of a personal call if it’s acceptable I think :slight_smile:

Hope that gets you started :slight_smile: