The Sims 4 Modern Python Modding: Part 2 — Hello World

June Hanabi
Analytics Vidhya
Published in
10 min readSep 21, 2020

In this part we’re going to create a mod that prints Hello World to the console. This gets you familiar with the process of writing the code and converting it into a mod that can run inside the game. It also familiarizes you with the Sims 4 python library that we decompiled in part 1 and I briefly talked about.

This part assumes you have finished part 1, if not, you need to read through and go through part 1.

The simplest program we can make

Let’s make the overly common “Hello World” program which is only 6 lines. This program will output to the cheat console the words “Hello World” when you type in a command.

The brutal reality of python scripting for Sims 4 mods

Notice a few keywords in the paragraph above — “output”, “cheat console”, “command”. In order to make a mod, you need to know what to make and read the official documentation and notes in the code that EA gives you… Except EA is among very few companies that has decided to not give you any help, notes, documentation, or code for using their modding system so you’re left scavenging through obscure files and code and all you can go on is the names of the files and and to look through complicated obscure contents to try and figure out how it works.

This is important to know because this is the entirety of python script modding for Sims 4. You’re completely on your own, apart from asking around on forums and hoping to get a good answer or answer at all, you don’t have anything to go on and to do the simplest thing could take hours of digging through obscure files and hundreds of lines of code trying to make sense of things.

Finding the pieces to this Hello World mod

Thankfully I can guide you through the initial waters of finding the information you need and bringing together this mod. The first thing we want to do is to allow us to interact with our script through the cheat console so that’s a starting point.

Out of the 3 folders I mentioned in part 1, which do you think would house such code.

  • Could it be base? No, remember base houses hundreds of little tiny instructions similar to writing 4 pages of detail on asking your friend to hand you an apple. Working with the cheat console is probably going to be too large an endeavor for the base folder. Never rule it out though, there’s always the possibility you guessed wrong.
  • Could it be core? Probably not, it houses bigger things but they’re all usually generic and not specifically related to gameplay.
  • Could it be simulation? This would be my first guess. A cheat console is specifically related to the game and simulation houses game-specific code so we should probably look there.

Even better, since we know exactly what we’re looking for. Lets do a search across all the folders and files to save us some time. Poking through the files is great for exploring and getting ideas but in other cases a search can save a lot of time.

So I found something interesting. There’s many cases of what looks to be scattered code that registers cheat codes. Do you see the

@ sims4.commands.Command(‘…’, …

This is littered throughout the Sims 4 code base and clearly this is how you register a cheat code. This is exciting then because the initial step to what we want to do then seems very easy and not as complicated as I might have imagined it’d be.

Let’s follow the sims4.commands.Command back to it’s original file. That will be where we need to be or at least a good starting point.

So this took an interesting turn of events. When we were guessing above we had ruled out “core” but it was actually under “core”. Although I don’t know the details and it may be impossible to know, a theory is that “base” is loaded first followed by “core” and then “simulation”. If that’s the case it’d make sense “cheat capability” would be in “core” because “simulation” would depend on it. It’s just a guess.

More importantly this is why if you’re looking for something specific, always search for it. This saved us from looking into the wrong folder.

So, in this file we see what we came here for

def Command(*aliases, command_type=CommandType.DebugOnly, …

we have aliases which is the cheat name and what we type into the cheat console, command type which we can speculate what that might be, it just takes a lot of looking around to figure this stuff out.

To speed things up a bit I’m going to share what I’ve learned from looking this over and by reading what others have posted.

Bringing this all-together

import sims4.commands

@sims4.commands.Command('hellow', command_type=sims4.commands.CommandType.Live)
def sayhello(_connection=None):
output = sims4.commands.CheatOutput(_connection)
output('Hello World')

Lets step through it

import sims4.commands

This imports the file that we discovered above allowing us to register a new command.

@sims4.commands.Command('hellow', command_type=sims4.commands.CommandType.Live)
def sayhello(_connection=None):

This says “Register a command called ‘hellow’ that runs the code below”. We also say this command is of type “Live” (You can find the different command types at the top of the file). I’m not entirely sure the details but I believe this means it can be run when you’re on a lot in live mode and without the need for testingcheats to be on. I would need to investigate the code further for answers.

_connection=None When a player enters the cheat code, the game runs your code for that cheat code. It passes any extra information the player typed after that along with a number. _connection is that number. It’s not important to know what the number is but it is important to have that number so it can be used to write text to the cheat console which is exactly what we’re about to do below.

We default _connection to None and as you may know None isn’t a number, so why do we do this? Because we want your mod to crash if a number isn’t given? Why? Because if a number isn’t given then something somewhere is really wrong. There should always be a number there so even if we made up a number instead of None, your mod is still going to crash anyways because a valid number was never given. If it crashes because _connection was None rather than a made up number then when you look at the crash report you can see exactly what happened, or more specifically, what didn’t happen. It gives you an idea on where to start for debugging. _connection should always be a number every time your cheat is called.

output = sims4.commands.CheatOutput(_connection)

We want to print a message on the Cheat Console and after digging on the same file we can see there’s a way to do that with a code called CheatOutput. Calling that returns a function we can call to do exactly that.

output('Hello World')

And finally we arrive at our goal and print “Hello World” to the console.

How do you figure all that out?

Well, it’s not easy and most of that is to blame on the way EA is handling it’s modding platform. As I said above, you either ask around in the community and/or dig through the library code you decompiled. Eventually you may or may not come to an answer.

Don’t rush yourself though or take on a project too large. Start small and take baby steps. This is seriously complicated and large, your entering a huge codebase with no documentation or code comments to go on and little information online. Taking on a task too large will just overwhelm you.

How do we get this into the game?

This is surprisingly simple and yet there’s so little information about this online.

I wrote a tutorial about it here but essentially you can do one of the two options:

  • Compile your python files using version 3.7 and package the py and pyc files together in a zip folder, example, Mods/HelloWorld.zip . You can also rename zip to ts4script as it’s the same thing and most players expect to see a ts4script file Mods/HelloWorld.ts4script
  • Or create a mods folder under Mods and within that a Scripts folder that you can place your py files in for testing like so Mods/HelloWorld/Scripts/main.py

As stated above, all of it is explained in the link above. Lets choose to compile it though and we’ll keep it a zip file because this isn’t actually being published so it’ll save us a step.

How do you compile it?

  1. Run py_compile <mod name>.py. Since I’m not using the Windows path I use C:\python37\python.exe -m py_compile <mod name>.py. Make sure you’re using Python 3.7 as mentioned above.
  2. After running it, python compiles it to a pyc file located inside of __pycache__.

3. Copy out the compiled file inside of __pycache__. It should end with cpython-37.pyc make sure it does end with that.

4. You can rename it and remove the cpython-37 part though and delete the folder although it may be quicker to leave it there as it’s not hurting anything.

5. Zip up both the py and pyc files

6. Now just copy it to the mods folder of your game, as mentioned above you can rename the zip to ts4script but it just adds an extra step and is unnecessary in development.

7. Boot the game, enter a sims lot in live mode, and test it out (accidentally typed it in twice for the snapshot lol, ignore the duplicate line as it wasn’t a fault of programming.)

Additional tips:

  1. Don’t check the game settings to see if your mod is listed under there as a means to see if your mod is correctly made. You could put an empty zip file in there named EmptyMod.zip and it will show up in the game as EmptyMod and look perfectly valid even though it has no files inside of it so it can’t possibly be correct or valid.

2. Your mod may only work when playing a lot with a family on it, trying to test the mod on the town/city screen to make it quicker to test may not work and that could be the reason, not always the fault of your mod.

3. There’s no debugging, and testing is a pain. If there’s an error with the mod which happens all the time in development you’re only option is to log it in the cheat console. If that doesn’t work then you’re left figuring things out as to why. There’s no debugging that I know of and every time you want to test a change you have to exit the game, recompile, re-zip, re-place in the game, and re-start the game all over also re-entering a sims lot. It’s a big pain but it’s part of the process. You can certainly automate things with scripts to a point but it’s still a big pain.

EDIT: There is now Debugging that’s been discovered by Sigma1202 and they posted a video here. I automated it in my boilerplate template if you’re using it and posted a tutorial about it here. The only known way to do this is through PyCharm Pro which costs money, unfortunately. In all other cases we don’t have a way to debug the mod outside of PyCharm Pro.

End of part 2

I know these are super simple but this is all fairly complicated and you need to take it slowly to make sure you understand everything.

We’re done with all the essentials, play around with what you know so far, goof off as that’s the best way to learn. Explorer the files, read through the code, just experiment with random ideas that come to mind. Reading what anybody writes on the internet can greatly help you but you’re the only person who can go from tutorials to independence and confidence in modding.

I suggest to setup a workflow

I really suggest to setup a workflow now, we’re going to enter other tutorials in this series so it may be inconvenient to keep using PowerShell and such. If your interested in my project template now would be a better time to use it since you know the basics of how to do things yourself. The project template works with any editor, not just PyCharm and contains many scripts to make thing much easier and more streamlined.

The tutorial about it is here.

If you’re not interested in my project template, then I recommend you use someone elses or design your own just to keep things simple, straight forward, and easy.

Onto the next part?

Be sure to visit the next part, part 3, which teaches you how to replace existing code completely. A simple but useful skill that can really broaden your modding capabilities.

--

--

June Hanabi
Analytics Vidhya

I just love creating art, taking photographs, programming, and teaching new skills to people.