[Update] This investigation was made on CK2 v2.1.6. The steps below can still be applied to current versions, but memory addresses will be different. For people looking for a quick cheat, here is the Cheat Engine file for the latest CK2 (v2.3.2).
In my earlier post I explained how to alter the ruler designer in Crusader Kings 2 to remove the age restrictions. Many have pointed out that there are mods that already do this or that add new traits that can be picked up to just decrease the age. These discussions led me to think that the only advantage to my method is that, with a bit of extra tweaking, we could enable Iron Mode with achievements even if the ruler designer has been used. I sort of successfully tested this hypothesis and went a step further than that. The result is a pretty impressive. With this simple hack, everyone can now turn on the Ironman mode and have the Steam achievements enabled.
Nota bene, in my last post I did not research for alternatives that could achieve the same thing. I was simply not interested in that. Manipulating the game as I did was almost the entire interest that I had on the subject. The same applies to this post. I do not know and I honestly haven’t searched for alternative methods that allow someone to play with mods (and ruler designer) with achievements enabled.
I will do two things in this post. First, I will show you the quickest steps needed to achieve this in CK2 v2.1.6 by using the same Cheat Engine application. You can use any other memory hacker for this. Lastly, I will detail the steps I took in my investigation to reach to this solution, knowledge that will help you achieve similar things with any other game. Let’s dig in.
Quick steps on how to enable this in CK2 v2.1.6
1. Launch the game with your mods of choice.
2. Launch your memory hacker of choice and open the CKII process.
3. Look at the 4-byte value stored at 0x019F3F90. Copy that value. (This is a memory pointer).
4. Add 0x42 to that value (the memory pointer). The result will be the memory address of a value that tells the game if achievements are disabled or not.
5. Set to 1 the value stored at the memory address calculated in the previous step. If you click the Finish button in the ruler designer, you will have to set this value back to 1. Alternatively, some memory hackers allow you to “freeze” the value, so you only set it once to 1, freeze it, and no longer need to care about it. Or in other words, if the Ironmode button is not a green check mark, this value is zero and needs to be modified back to 1 to get the green check button.
For those of you using Cheat Engine, the program allows you to manually add a pointer directly, simplifying steps 3 to 5 . Simply click on “Add address manually” and select the following things as pictured below:
1. Open the game and Cheat Engine (CE).
2. In CE, go to File -> Open Process and choose CK2game.exe from the list.
3. In CE, go to File -> Open File to open the file you just downloaded. You will now see an entry in the list of addresses, like in the picture below. The description will be “Enable Achievements in Ironman Mode”.
4. For that new entry, double click on its value (under the Value column). It will be either 0 or 1, and you need to set it to 1.
5. For the same entry, click on the check-box in the Active column to have it checked.
6. You can now play your game with achievements enabled. CE should look like this:
This method has a chance to not work with future versions of the game, but that is unlikely since the pointer is stored in a global variable. Nonetheless, the next section explains how to correctly determine the right pointer regardless of the game version.
How did you find this out?
I needed a starting point. It appears that the game has a variable that says if the Ironman mode is selected or not. By simply searching for zeroes and ones after enabling and disabling the Ironman mode back and forth, I found the memory address of that variable. Then I set a memory access breakpoint on it to see which code reads or writes to that variable. By doing this and then toggling the Ironman mode once again, I find where the relevant code interested in this variable is. Surely, the logic on whether to enable or disable achievements has to be somewhere in that code. The steps I took thus far were very similar to the methods described in my previous post about hacking the ruler designer.
Once I had set that access breakpoint it started being hit about every second. It turns out that there is a UI thread running this code again and again, constantly checking if the Ironman mode should be enabled or not, and then updating the button seen on-screen to reflect that choice. Here is where the breakpoint is triggered and how the code looks like.
As you can see from the comments I wrote, if the user wanted to enable Ironman mode, there is an extra check that determines if achievements should be enabled or not. If achievements should be enabled (there’s no game alteration) then “push 01” instruction is executed, otherwise “push 03” instruction is executed. To understand what these are, think of the Ironman mode button as a tri-state checkbox, or a button that has 3 states. These “push”-es that you are seeing are simply updating that button state. Here is the mapping between pushed values and states:
1- Ironman mode enabled, with achievements
2- Ironman mode disabled
3- Ironman mode enabled, without achievements
Now, as a simple exercise, you can modify the “push 03” instruction to “push 02” and notice how the Ironman mode button will never say that achievements are not enabled, even if you are using mods or if you just designed a new ruler. However, this change doesn’t REALLY enable achievements, it just forces that button to look differently. If you start the game, you will not receive any achievement.
But this is more than a good starting point. We can see the function call above (“call 00E71640”) that checks if achievements should be enabled or not. Maybe we can find something in there, some common code or variables that are used in other parts of the game to tell if achievements should really be enabled or not. But before looking at the function, do notice that we can now easily get the address of the variable that tells if achievements should be enabled or not. The code above uses instruction “cmp [eax+42],bl” to test that value, so [eax+42] is the address we want. 0x42 is a static value, but EAX is not. EAX is returned by the function call previously mentioned, the one we’re going to look at right now.
Well, well, well, aren’t we lucky? This function straight away assigns EAX a static address and doesn’t modify it thereafter. “mov eax,[019F3F90]”, this is where the magical number from the previous section comes from. This is obviously a pointer to a global structure used throughout the game, and the global variable that indicates achievements are enabled or not is stored at offset 0x42 in this structure, based on the code we saw in the previous function. At this point, we really got lucky. We do not need to dig through the code anymore to see how and where that value is determined and modified. We can simply set that value ourselves every time it changes, which is not frequently. From my observations, this variable is modified by the game once when the game is launched, when it checks if there are any mods running, and secondly, this value is modified by the game once more whenever we click the “Finish” button in the ruler designer. To alter the game behavior, we simply need to override this value after the game sets it, which is what the “quick steps” section above is describing.
The solution we found is good enough. There may be some other triggers in the game code that will modify this variable throughout the game, but I haven’t found one yet, and it is also unlikely. What I have not tested is using a cheat command, as they are disabled in Ironman mode anyway. If the game would constantly update this value, or not even store it in memory, but simply compute it on demand, then we would have needed to dig a lot more into the code that actually performs these checks. But that’s not the case.
In the future the pointer may change, but since we already found all the relevant functions we need, we can just search for the assembly code in those functions to quickly find them and then look at the new pointer address. From CE this can be done from the Memory Viewer and then clicking on Search -> Find assembly code.
What could be done next? I guess I will be looking into enabling the console in Ironman mode (and still earn achievements when used).
I had started playing Crusader Kings II again and like every other time before it, I always get to the point when I want to mess up with my ruler, i.e. cheat a bit. And by a bit, I mean a whole lot. Nothing short of the most over powered ruler possible is acceptable. Even though the game provides all the in-game cheat commands necessary to achieve this, it is not as easy as one may think. You can easily set the age of any character and change their stats, but their traits need to be added one by one. The list of good and bad traits is a long one, and you have to do a bit of searching for it on the web or by finding the right plain-text file in the game configuration folder that defines these traits (and then making sure you only add the good ones). This is further complicated if you happen to use any of the popular mods for CKII (e.g. Lux Invicta) that more than doubles the list of ruler traits. Furthermore, the cheat command requires you to input the ID of the trait, not its display name in game. For the vanilla game, I think these two values coincide most of the time, but that is certainly not the case for mods. There are plenty of situations where the ID of the trait is either a synonym word for it or worse, a misspelling. So there is no escape, you have to find the configuration files that define the traits for every mod and dig in. There must be a better way!
Well, the game has this wonderful DLC called Ruler Designer that allows you to customize your ruler when setting up your game, which undoubtedly adds more flavor to the game and can be an excellent tool for role playing purposes. I, and many others, do not consider this designer feature a cheating tool. Every stat and trait has an associated “age” cost and your configuration cannot go above the age of 50. This means you cannot go about creating an overpowered ruler as you always have to counter balance buffed up stats and good traits with a set of bad traits to lower the age. While this is fun and great, it doesn’t help me with creating the most OP ruler ever known to man. Not without a little bit of hacking. If we could just somehow get rid of the age cost, creating an OP ruler via the Ruler Designer is so much simpler than using cheat commands and digging through configuration files, because everything you need is on your screen and you can just select what you want. This is how the ruler designer looks like on the attributes panel.
The list of traits clearly displays the age cost. If I were to pick the Genius trait in Figure 2, my age would increase by 30. If I were to pick Genius plus Attractive, I would be 16+30+16=62 years old, 12 years above the maximum 50 so I wouldn’t be able to create that ruler. I would need to pick some bad traits already to decrease the age, and I have only picked up 2 good traits so far!
In these situations I usually use any random memory hacker to open the CKII process, scan the memory for the value that I am looking for and modify it. For example, here I would search for the value 16 which would yield an insane amount of results, then I would narrow the results by modifying a stat or picking up an ability that modifies the age, and then I would search again for the new value from the result list, rinse and repeat until I narrow it down to 1-2 memory addresses. Then I just modify that value to set the age that I want. Sometimes the value you are looking for is not a 4-byte integer, it may be smaller or bigger, a decimal or floating point number (where decimals might be truncated). Sometimes it’s not the wrong data type you’re searching for, but the value itself. For example, age may be computed and stored in months, but a conversion function is used to display it in years.
Unfortunately, it is not that simple here. That value, the age, is never stored in memory (or not persistently; it is computed, displayed, and then forgotten), so searching the memory for it doesn’t yield any result. And even if it were, this scenario is a little more complicated than that as there is a “Finish” button you can see in the screenshots above, which gets grayed out when age goes above 50. Finding and modifying the age may not un-gray that button. This means we have to do a bit of debugging here: search for a starting point, set some breakpoints, disassemble the code and figure out how we can modify stats and traits without changing the age. You can pretty much use any debugger for this, but there are a few simple ones written specifically for game cheating such as T-Search or Cheat Engine. I will be using the latter.
The plan of attack:
- Try to find the variables that change when a stat or trait is modified. Some portion of the code will have to access these variables to then compute the age and enable or disable the “Finish” button.
- Once we find the memory address of such a variable, we can set memory access breakpoint which will show us what code is reading or writing to that memory address. There can be multiple pieces of code that do this for various reasons.
- We will look through each part of code that accesses those variable to understand its purpose, figuring out if it has anything to do with age or the “Finish” button.
- Alter the code so that the age always remains the same, and the “Finish” button is enabled so we can create our ruler.
- Max out the stats and choose every last good trait in that god damn long list to create the most OP ruler known to man.
Actual steps with screenshots:
- Fire up CKII, start a new game and go to the ruler designer on the Attributes tab. Fire up Cheat Engine and open the CKII process.
- In Cheat Engine, search for every 4-byte integer with the value of 6. This will yield a bunch of results. Go back in-game and modify the Diplomacy stat from 6 to 7. Go back to Cheat Engine and continue the search for the new value of 7. This should yield only 1 memory address. (If not, change the value again, search it up, rinse and repeat)
- We found the variable that stores the diplomacy. Double click on it to add in the address list at the bottom of the window, where you right-click on it and select “Find out what accesses this address”. Itwillinform you that it needs to attach a debugger to the process and you must accept. A window will pop up for the results,currently empty. You need to back in-gameandmodify the Diplomacy stat again. The new window will then populate with a list of instruction pointers where the Diplomacyvaluewas accessed.
- Foreach of the results you have a snapshot of the register space at the time and of the stack. If you look closely, the value stored intheEDX registerplus3C (hexadecimal) is the address for the Diplomacy value above. In the result window above, you are seeing the op codes or instructions executed by the processor that involved the [edx+3C] address, in other words, your Diplomacy. The first result is an instructionthatwrites to your Diplomacy variable, it adds whatever was in the EDI register to your Diplomacy. This instruction was obviously executed when I clicked to increase the value of my Diplomacy, so it’s not what we’re looking for. We’re looking for code that just reads the Diplomacy, to see what for. The second instruction in list does that. It reads the Diplomacy value and stores it intheECX register. Let’s disassemble the code to see what is going on there.
- We seethatthe instruction from our resultlistis executed part of a humongous function (you’d have to scroll up and way down to get to the beginning and the end of it). What could it possibly do? So, our instruction is the one highlighted above.TheECX register stores the diplomacy value. The following instruction subtracts 6 from it. Interestingly,theminimum base diplomacy value you can have is 6 (or any other stat). The second instruction after thatmultiplesECX by 1000. Basically,thisa normalization of sort.ECX eventually gets storedinEAX to serve as a parameter for the function call that follows. I dug into this function and this is the one that computes the age. But we’re not really interested in that function now because of the following observation. This piece of code keeps repeating throughout this functionforeach main stat, constantly computing the age for whatever reason. This huge function actually returns the total age computed based on stats and traits. For some reason, when you change a stat once, this function will get called 3 times. I assume once to get the age to display it in the Ruler Designer, once to update the enabled/disabled status of the Finish button, and once for probably updating the avatar (the older you are, the older you look). It is inefficient, but it’s not really a time-consuming / heavy processing type of operation. We could dig into the functionthatdoes the conversion to age so that it always returns 16 (minimum age), or we could just change this function to always return 16 in the end, no matter what it computed along the way. Let’s look how the end of the function looks like.
- The highlighted code is the end of the function. After the first instruction in the highlight, EBX is storing the age after taking into account all the stats and traits selected.
mov eax,[CK2game.exe+B7FE6C] <- this sets EAX to 0x10 (16). That is the minimum age possible.
cmp ebx,eax <- this compares the calculated age with 16
jnge CK2game.SDL_GetNumAudioDrivers+2A564D <- if the calculated age is smaller than 16, this instruction jumps below and the function exits returning age 16.
mov eax, ebx <- if the calculated age is not smaller than 16, this instruction is executed and stores the age in EAX
The rest of the instructions deal with correctly exiting the function and returning the value of EAX, which is either 16 or the calculated age.
- Our solution is for this function to always return 16 no matter what the calculated age. You can invert the “jnge” instruction such that the function return 16 when the calculated age is higher than 16. But this leaves a problem for the scenario where you select a bunch of bad traits that would lower your age below 16. I guess you could use that to create child rulers (untested), but you stillhave the possibility of going below 0 andunderflowing the buffer such that your age is now 2 billion years. We can avoid all that by simply NOP-ing out the instructions in that if-statement (basically deleting the if-statement) such that the function returns right after settingEAX to 16. It looks like this:
We end up with a function that goes over all the stats and traits and computes the value for the age, but it always returns 16 at the end. This function is used by user interface to display the age number, to display your portrait based on age, and to let you click on the Finish button. After the change above, I could do this in my designer and the age remains at 16:
Since this part of the function is unlikely to change with game updates, you can right away just search for those opcodes plus bytes I just NOP-ed out and do it again. I believe Cheat Engine allows you to write a very small and simple LUA script to do that, so next time you fire up the game and cheat engine, you just execute the script and be done with it. Similarly, you can write a small program (a trainer) that does the same thing.
Well, now, back to my game of conquering the Scottish Highlands, driving out the Norse, uniting Scotland and educating the “English” in speaking proper Gaelic 🙂
[UPDATE] To summarize, you can achieve this by following these two steps:
- Launch any memory hacker and open the CKII process
- Search for byte sequence 38D87C0288C3 and replace it with 909090909090