Hacking Relationships, Part 2Profuse apologies for this being so, so late, but I managed to figure out what I was doing wrong and have prepared part 2 as I promised long ago! The programmers among you will probably find some of this a bit of a bore, or find errors in my reasoning, terminology or methodology. If so, do let me know.
If you've been following up to this point, you should be able to find a creature's historical figure entry in memory. I believe I may have misled you in part 1, as the way the historical figure entries look is different in .34 and I got a bit confused. I'll fix it soon. Anyway, below is what a real historical figure entry looks like:
In this picture, you can see all of Victim A and Victim B's historical figure entries. You'll have to search for these like I explained in part 1, and they may not be consecutive! There are two values I've highlighted, because they're important.
The value highlighted in red is the creature's
Historical Figure ID. This is the value that the game needs to identify a historical figure, and is how it links them together.
The value highlighted in green is part of an STL Vector that stores pointers to
Historical Figure Links. There are actually a few details about this that you might find interesting, but aren't extremely important for what we're doing. I'll go into it anyway for those who care:
An STL Vector is a special type of array that has some code to automatically manage its location in memory as it grows. For our purposes, what we care about are the three pointers that are used to store a vector. You can see these as the three 4-byte values in sequence. The first two pointers point to the beginning of the vector, and the last points to the end. You can tell how many elements are in a vector by subtracting the start from the end and dividingy by the size of the element. In this case, Victim A has two links: subtracting the values gives 8, and each entry is 4-bytes long (the size of a 32-bit pointer).
Anyway, you'll need to follow this pointer to get to the historical figure links. To follow the pointer, you're going to have to juggle the numbers a bit because of endianness. The reason the values are jumbled has to do with the processor's architecture, but that need not detain us at this juncture. All you need to know is that the pointer is stored in reverse in memory. So, while you see:
E0 8E D8 1D
What you really want is:
1D D8 8E E0
Just reverse the order of the bytes (not the characters of the hex values themselves!) and you get the pointer you're looking for. You can follow this pointer by hitting the second button in the hex editor window (circled in red below) and entering the pointer. I recommend opening a second hex editor window for this purpose. Here's an example of what I get by following this pointer:
Highlighted in green are the two pointers to the actual links themselves. Right now, there's no real way to just add new entries, only replace existing ones. By following either of these pointers, you will arrive at the link itself, which looks something like the screen below:
There's only two parts to the link that we care about (there might be more to it, but I haven't deciphered the rest and it doesn't matter anyway). The first part, highlighted in green, is the
Link Type. This is a pointer to... something. I hate to admit that I actually don't know what this points to. Regardless, this is what determines whether you see Deity, Object of Worship, Lover, Spouse, Child, or whatever else in the relationships screen.
The second part, highlighted in red, is the
Historical Figure ID. Remember this? Yep, it's the value from before that we got from the historical figure structure. So, just to fool around, let's try changing that to the value for Victim A's historical figure: 8C 00 00 00 (remember this will be different for you!).
You can see on the left that I changed the old historical figure ID to be that for Victim A: 8C 00 00 00. If you go to the relationships screen for Victim A, you'll see he worships himself! That's not quite what we're aiming for, so let's change that to Victim B. To do that, just change the value to Victim B's historical figure ID. For me, that's: 8D 00 00 00. How convenient! Don't expect it to be so convenient for you though, especially for running games.
Ah, that's more like it. We're just one step away from what we need: changing the type to that of a spouse, not a thing to worship (joke however you will). Unfortunately, I'm stuck at this point at the moment. In existing games, what I've done is look up the value for the type for the type of the relationship I was interested in, where it already existed. That is, if in a game I already had some married dwarves and wanted to marry more, I'd just look up the value for the type for the married dwarves by following the pointers, then go and set it for the dwarves I was interested in.
A word of warning: You can change the
Historical Figure ID while viewing the relationships page. If it's a bad value, nothing goes awry and the game just ignores it. However, changing the
Type while viewing the relationships page will crash the game! Furthermore, changing the
Type to something that's not valid will also promptly crash the game! This is because you're changing pointers, and the game tries to reference it, gets garbage and the OS terminates the program to protect the rest of the running software. Changing it to a good value is fine, but a bad one is a no-no.
Regardless, now that you know 90% of what to do to set what shows up on the relationships page, there's one more piece of the puzzle to actually have dwarves be considered married for the purposes of producing children. This seems to be something most people want to avoid these days, but in case you're interested, you need to set the value of the
Spouse ID in the original creature struct. This is actually much easier to do, but I haven't pinned down the location for .34.x yet, so I'll have to show you how to do this in Part 3!
I know, I'm sorry for being a tease. With what I've given you so far though, you should have some idea of how this stuff is stored in memory and can probably do a bit of exploring yourself.
Part 3 will contain at the very least how to set the Spouse ID, but I also plan to include how to find the type you're looking for. That's something I never did the hard way for .31.25, so it's new ground for me too. As a bonus, I'll show you how to cancel pregnancies, cause a dwarf to give birth immediately, or steal pregnancies from other dwarves!
Part 3 should be up in a few weeks at the rate I'm working on this.
A plugin to do this automatically should follow within the decade.