Using Cheat Engine to give myself gold in Majesty

Using Cheat Engine to give myself gold in Majesty

I currently aspire to create an AI to play the game Majesty: The Fantasy Kingdom Sim.

One important part of building this AI will be allowing it to know what actions it can perform. Almost all meaningful actions in Majesty will consume gold, so knowing how much gold we have in the royal treasury is critical.

I'll be using Cheat Engine to perform this task.

Finding the gold value for a single game

First, let's start a game and see that we have 20000 gold. We can use Cheat Engine to pull up all of the memory addresses that store the value 20000. image.png

Then, we can buy something in the game and have Cheat Engine filter this list to contain only the memory addresses that now have 19600. image.png

In this case, there is only one address, with the value 0x107E5CB8. You can double-click it to preserve the address in Cheat Engine.

One big problem though - this address isn't consistent! Every game of Majesty will store its gold value in a different memory address. Instead of performing this manual scan for every game, it would be great to know ahead of time where the gold value for the game will be located.

Memory offset

You could imagine the gold value for a game being stored in a data structure like this:

class Game {
  bool hasEnded;
  bool isMultiplayer;
  uint32_t questId;
  uint32_t timeElapsed;
  uint32_t currentGold; // <--- this is the value we want
  uint32_t workerCount;
}

The location where Game is stored in memory will change for every game. However, the currentGold location inside of the Game structure will never change - it was compiled with the game's code!

In the above example, if bool has a size of 1 byte, and uint_32 has a size of 4 bytes, the offset for currentGold would be 10 bytes.

Cheat Engine has a method for finding this offset. First, right-click the saved memory address and click "Find out what accesses this address": image.png

Resume the game and make another purchase. Notice the opcode accesses: image.png

In this case, that +10 attached to each operation means we have an offset of 10. This will help us later.

Pointer scanning and pointer mapping

To find out how to get to your friends' house, you want a set of directions. Start at your apartment, turn left onto 90, turn left onto 405, exit and Main street, look for house number 1184.

Similarly, what we want is a set of directions for how to find gold value of a Majesty game. Start at the base of Majesty's address space, move down 10,000 bytes, follow the pointer at that address, move 50 bytes, follow the pointer at that address, etc.

Creating this set of instructions for a memory address is called pointer scanning. We'll try it out now.

Right click on the current gold address and select "Pointer scan for this address" image.png

In the next menu, the only value we need to change is to add the offset we discovered earlier. This tells Cheat Engine "you last step is going to be to move 10 bytes down". image.png

In the results, you'll notice two things. One - the number of results is impossibly high! Two - not all of the results make sense. For example, why would a set of directions start with "AquaSnap.dll"? image.png

We need to pare down this list. Close that dialog. Right click the memory address, and click "generate pointer map". This will save a list of all of the possible routes to our gold address.

Now, go back to the Majesty main menu, and start a new game. Use the process from before to find the current gold value, and generate a pointer map for it. image.png

Now, right click on the new gold address and select "Pointer scan for this address". We'll do the same thing as last time, except:

  • Check "Use saved pointermap", and input the file from the current game's scan
  • Check "Compare results with other saved pointermap(s), input the file from the old game's scan, and make sure to select its address in the dropdown image.png

The result should be a bit more favorable. For me, it was only 189 possible paths: image.png

It worth noting: multiple of these paths could be valid! Similar to how you can take the back roads to get to your friend's house.

What's the best way to my friend's house?

Let's double-click a bunch of the values from this pointer scan that start with "MajestyHD.exe"+.... image.png

Now, let's go back to the main menu in Majesty and start another new game. image.png

Notice how some of the pointers point to the correct gold value (8500) and others don't have the correct path (pointing to garbage memory).

If you continue to start new games and remove the invalid pointers, you will eventually find ones that consistently work. For example: image.png

We've reached our goal! For any arbitrary instance of Majesty, we're now reasonably confident that we can follow this specific path of pointers to reach out current gold value.

Just to be sure, we can give ourselves an unreasonable amount of money by manipulating the value stored at the memory address.

image.png

That should be enough for plenty of guardhouses.

Did you find this article valuable?

Support Scott's development by becoming a sponsor. Any amount is appreciated!