Adding character creator options
How to add a custom option to the character creator.
Last updated
How to add a custom option to the character creator.
Last updated
Published: Aug 8 2024 by Last documented edit: Aug 8 2024 by
This guide will show you how to add your own custom selector to the character creator (CC), the character appearance menu specifically but this knowledge can be reused... hopefully.
The guide is a little longer, but that's because I tried to explain my findings, the coding doesn't take too long. Also the guide is "progressive" and each step "upgrades" the custom selector.
This guide was written by a newbie. It may contain incorrect information and/or bad practices. If you know how to improve this guide, feel free to edit it.
Some understanding of RedScript, this isn't a beginner guide (kinda).
You should already know what you want to do with the option.
Codeware - some structs are unavailable without it
As is the common case with RedScript, we need to hook into something to run our code.
I went for the characterCreationBodyMorphMenu
class, which manages the character appearance menu. Since I want my option to be on top but bellow the gender/voice selection, I will run my code in the CreateVoiceOverSwitcher
method. You could also hook into InitializeList
method (which calls my chosen method) and run your code before (to add on top of the list) or after (to add on the bottom) the wrapped method.
So let's prepare our hook, here is mine:
The method CreateVoiceOverSwitcher
is only called when creating character in new game! If you want your option to be visible in mirror/Ripperdoc hook into the other mentioned method or use Appearance Change Unlocker!
Let's use the hook to add our selector! We simply need to spawn another Selector
widget. Update your wrapped method to look something like this:
You can also spawn the ColorPicker
if you want selector with thumbnails. That requires more set-up and is outside the scope of this guide.
That was easy, right? Now we have this:
Great isn't it? Well... yeah, but it's the default one and doesn't do anything. Let's change it.
To tell the inkWidget what to show, we need to construct a few data structures.
But before that we need something that will stay alive and keep our data in the memory (because inkWidget won't, it only keeps a weak reference).
So let's go with a ScriptableSystem
. Simply make a class that extends it (give it a better name, something to do with your mod). Let's also make the attribute that will hold our data.
Now let's construct our stuff. I chose to make a dedicated method for it, so we can call it once we need it. All of string HAVE to be a translation key, you can add custom ones with ArchiveXL. I'm gonna use some random vanilla strings, please don't judge me. Let's add the method to our class (you can name it however you want):
You may not like the way we create the options here but DO NOT call new gameuiSwitcherOption("...")
!! The struct is incomplete in RedScript and it is not possible to construct it properly. Use the method shown above, maybe in a loop.
That's a bit more code, but I commented it for you. You will probably want to customize it anyway. Remember, this method is inside the class we made before!
Now we need to call that method and to do that we need to obtain an instance of our Scriptable.
Go back to your hook from Step 1 and add this code to the method (this code will be different if you use ScritableService
instead of System):
Update the CName and the cast to match your module and class names. With this we can call our method and option the option data:
This option has to be given to the inkWidget's controller which we can do the following way:
And there we go, your hook method should now look something like this (the line order might differ):
Much better, right? Now what?
Now we want to know what the user choice! You can do this by registering a callback on the inkWidget's controller. I chose to add the callback to my ScriptableSystem.
I'm gonna store the choice in a persistent attribute which will be store in the player's save and we can retrieve it later.
Let's go to our System and let's add our persistent attribute to the top (preferably) of the class:
We're storing an index of the option the user chose. By default it's a zero (unsigned). Also add the following method to the class. We will use it as callback, so mark it as such (cb
).
It will receive the selector widget that was changed. From that we get it's controller and from that we get the currently selected index.
To make the callback work, we have to register it when creating the widget, so go back to your hook one last time. We already have our System reference so the following is all we need to add to end of the method:
You can, again, name the method whatever you want, just remember to change the second CName in the last line.
One last thing remaining is remembering what the user selected last time. We already have the persistent
attribute which is automagically saved, we just have to use it now.
Go to your option data creation method and add a line to the option creation part to look like this:
With this new line the selector will remember what you've selected last time! Incredible!
You can see the whole code from this guide here: https://gist.github.com/Zhincore/9799a02f55a716283982dcb26e1c9a07
And with that we're done with the guide, the rest is up to you!
You can also use Codeware's ScriptableService
if you want to be independent of save. See the RedScript wiki for a comparison: .
Now we have this (again, ignore my choice of strings):