Modding Custom Identities
Video Guide
Timestamps:
- 0:34 Dumping data
- 1:29 Making a mod folder
- 2:03 Opening VSCode | File -> Open Folder -> game/Bepinex/plugins/Lethe
- 2:43 Finding and copying a personality .json
- 3:11 Pasting the personality .json into the template personality folder
- 4:13 Removing unnecessary character ids
- 4:36 Brief explanation of all lines of text in the id entry | Timestamps below point to more important explanations
- 4:42 "id"
- 6:09 "appearance"
- 7:56 "defenseSkillIDList"
- 8:18 "rank"
- 8:28 "hp"
- 9:02 "minSpeedList" & "maxSpeedList"
- 10:26 "breakSection"
- 10:41 "resistInfo"
- 10:57 "attributeList" | Explanations end here
- 11:42 Writing localisation for the modded personality | see custom localisation for changing skill or passive locale
- 13:30 Making sure it works in-game
Text Guide
Note: While in casual conversation people will shorten the term "identity" down to ID, this quickly gets very confusing when you work on json numbers since ID numbers are so important.
Thus, I'll be referring to identity as "personalities" in this thread, since that is also the language they are referred to in the games code.
How to Begin
- Go to the
Lethe
folder inside of plugins - Open up your
dumpedData
folder in Visual Studio code - Open up the
limbus_data
folder. - Scroll down a bit until you get to the
personalities
folder. - There should be 12 different json files here, going from file "0" (which is Yi Sang's file) all the way to "11" (which is Gregor's file).
- All of these files are in sinner order. A helpful way of checking this is either in game by going to the drive menu,
or by checking the
characterList
locale file (which we will get to later)
If you have an idea in mind for a personality that you want to work with as a base, you can go into the respective sinners json file and search for them using control F.
While Sinner personalities are not named here, their appearances are still generally accurate enough for you to understand which sinner it's talking about. That, plus personalities are added to the file in release order.
Now, to actually begin to make some changes. Lethe only really looks at the "custom" folders within our config file and ignores the rest (with an exception we'll get to later), so if we want to modify our identity we need to move it into the proper folder.
- First of all, copy and paste your personality file.
- Go and copy and paste the
modtemplate
folder, and paste it into themods
folder. (I'd recommend giving it its own name at this point) - Then go into
custom_limbus_data/personality/
and paste your file in there.
Right now, this means Lethe will overwrite all the vanilla data with the information within our custom personality file.
Now let's go and trim the fat. Delete all the other personalities in our json file except for the one we wish to further work on.
As you can see we are getting an error message. This is because of how json files work.
Every entry into your "list" needs to have a comma ,
at the end of it to signify that this entry ends there and that
you are about to enter a new one.
However, this does not apply to the last entry in a list, as you are essentially telling your json file it needs to go and look for the next entry in the list... when no such thing exists. This generally leads us down to the road of pain and crashes, so we should do our absolute best to avoid dumb formatting errors such as this.
Now that we fixed our stupid formatting problems lets go and look at our personalities file and explain everything in order, shall we? Attached below are three images of every single part of a custom personality (for now)
{
"list": [
{
"id": 10101,
"appearance": "10101_YiSang_BaseAppearance",
"unitKeywordList": [
"BASE_APPEARANCE", "SMALL"
],
"associationList": [ "LIMBUS_COMPANY" ],
"characterId": 1,
"panicType": 9999,
"season": 0,
"defenseSkillIDList": [
1010104
],
"panicSkillOnErosion": 1000104,
"slotWeightConditionList": [
"Default1"
],
"rank": 1,
"hp": {
"defaultStat": 72,
"incrementByLevel": 2.48
},
"defCorrection": -2,
"minSpeedList": [
4,
4,
4,
4
],
"maxSpeedList": [
6,
7,
8,
8
],
"uniqueAttribute": "AZURE",
"mentalConditionInfo": {
"add": [
{
"level": 1,
"conditionIDList": [
{
"conditionID": "OnWinDuelAsParryingCountMultiply10AndPlus20Percent"
},
{
"conditionID": "OnKillEnemyAsLevelRatioMultiply10"
},
{
"conditionID": "OnKillEnemyByOtherAllyAsLevelRatioMultiply5"
}
]
}
],
"min": [
{
"level": 1,
"conditionIDList": [
{
"conditionID": "OnDieAllyAsLevelRatio10"
}
]
}
]
},
"breakSection": {
"sectionList": [
65,
35,
15
]
},
"resistInfo": {
"atkResistList": [
{
"type": "SLASH",
"value": 2
},
{
"type": "PENETRATE",
"value": 0.5
},
{
"type": "HIT",
"value": 1
}
]
},
"attributeList": [
{
"skillId": 1010101,
"number": 3
},
{
"skillId": 1010102,
"number": 2
},
{
"skillId": 1010103,
"number": 1
}
]
}
]
}
-
id
: this is the ID number that identifies a certain personality as being... what it is. If we use the ID number of a vanilla personality we will overwrite it, and if we use a custom ID number we will create a new personality- Note: the ID number of a personality follows the pattern of XYYZZ.
- X here is always 1
- YY here is what sinner this identity belongs to
- ZZ is used to identify what specific identity of this sinner it belongs to.
-
For example, "10301" is the ID number of "LCB Don Quixote" because she is the first Don Quixote ID, while "10304" is the ID number of "N Corp Mittelhammer" Don Quixote because she is the fourth Don Quixote ID.
-
It is always recommended to follow this pattern when making a custom personality, as breaking this pattern will generally lead to unnecessary bugs that we would much rather avoid.
-
Here is an example of a VALID personality ID: "10135", whilst "113492" would be considered "invalid", and as such would break various functions in the game (I.e the identity would be unable to enter the Mirror Dungeon.)
-
appearance
this determines how our personality actually looks like when used in game. Appearance holds the animations as well as the sound effects of a personality.- An appearance can also be changed into being the appearance of an abnormality or enemy, and these appearances can be found by going through the "abnormality-unit" folder or the "enemy" folder
- Note that certainly abnormalities are prone to bugging out (usually ones with multiple parts, such as the King in Binds), so this will always require some experimentation to figure out which properly work (and bothering Zenocara to fix it when it doesn't end up working lmao)
-
unitKeyWordList
andassociationList
this just determines what tags are added to your personality. Generally not that important, except for something like a Blade Lineage or N Corp custom personality -
characterID
this determines what sinner your custom personality belongs to. Important note is that these ID numbers start from 0, so Yi Sang is Sinner Number 1, and Gregor Sinner Number 12. -
panicType
this is just the panic type your sinner has when they reach low morale or panic. For personalities this is generally kept at 9999 (the default Panic for Sinners), but this can be freely changed into other panic types. -
season
generally unimportant as we unlock all personalities by default, but this determines what season your personality was released in. -
defensiveSkillIDList
determines what defensive skill your identity uses. If you put in multiple entries to this list, the game will use only the first entry when you use a defensive skill, but this can be important for niche cases (like a BL Meursault for example). -
panicSkillOnErosion
determines what the empty slots are when you corrode. If you change this, when you corrode your empty slots will instead become the skill you specified. Dumb and generally not that useful, but funny I guess? -
slotWeightConditionList
determines the slot weight of your personality (as in how much AOE is required to hit their slots). Generally forgettable and better kept at the default -
rank
determines whether your personality is a 1 star, 2 star or 3 star. Mostly useless, but still neat.
Now we get to HP. HP is a list with two values in it
defaultStat
is the amount of HP your personality would have assuming they were level 0.incrementByLevel
determines how much a personalities HP scales every time they level up. This value is often far more important than Default HP.defCorrection
is your identities Defense Level. While vanilla limbus likes to keep this at a scale of -5 to 5 this is no hard cap, and this value can be cranked way up if you wish.
Now we get to speed. Speed has two entirely different lists for it, those being minSpeedList
and maxSpeedList
It's important to note that speed is written based off of uptie (or Gacksung), with the first entry in the list being uptie 1, the second being uptie 2, the third uptie 3, etc.
In the private server everything is uptie 4 by default (unless changed in the dashboard), so we should really only be looking at the last entry when modifying speed.
"minSpeedList": [
4,
4,
4,
4
],
"maxSpeedList": [
6,
7,
8,
8
],
mentalConditionInfo
is another list value, and while it might seem complex it really isn't.
The add
section of the list determines all of this identity's factors that increase their SP, while everything in
the min
section determines factors that lower their SP.
Generally you don't really care about these values that much, but the numbers within them can also be easily changed, in case you want to make your personality gain/lose SP faster or whatever.
"mentalConditionInfo": {
"add": [
{
"level": 1,
"conditionIDList": [
{
"conditionID": "OnWinDuelAsParryingCountMultiply10AndPlus20Percent"
},
{
"conditionID": "OnKillEnemyAsLevelRatioMultiply10"
},
{
"conditionID": "OnKillEnemyByOtherAllyAsLevelRatioMultiply5"
}
]
}
],
"min": [
{
"level": 1,
"conditionIDList": [
{
"conditionID": "OnDieAllyAsLevelRatio10"
}
]
}
]
},
breakSection
is another list that determines at what percentages a personalities Stagger Bars are.
In the example image attached, this would be a personality with 3 stagger bars, one at 70%, another at 40%, then another at 20%
- Note: While stagger bars at negative percentages are entirely fair game, stagger bars above 100% don't do anything.
"breakSection": {
"sectionList": [
65,
35,
15
]
},
resistInfo
is another list and is quite self-explanatory, this is how physically weak your personality is to certain
damage types.
- Note: While the UI will happily display damage resistances that go above x2, when viewed in game all damage resistances above x2 will be lowered back down to x2.
So far all of this has been pretty easy to modify, we just change the numbers around, change the ID number and boom we have a fully playable ID (if lacking in any localization).
Now we get to the second to last part of making a custom personality, and probably the biggest part. Skills are
written in attributeList
as seen below, and each have their own ID number.
Every skill is essentially a different "entry" into this list, with an ID number pointing to what skill you need to use, and an "amount" determining how many of them you have.
-
Note 1: Unlike Abnormalities (that all have patterns), sinners have a skill bag with a set amount of each skill in their possession. Changing the "number" value in a skills entry changes how many of said skill you have, and is why you have more Skill 1's than Skill 3's.
-
Note 2: If you want to quickly find a specific skill, go into
limbus_locale
and then "SkillList", and use control F to quickly search for the skill ID you need. -
If you want this skillList to be more readable, I recommend pressing Control + S to save the document (with the format on save option enabled), as this will make the Skill List a lot more readable
-
Note 3: There is no actual limit to the amount of skills you can place on a personality, so if you want to make a personality with 99 skills, you can!
"attributeList": [
{
"skillId": 1010101,
"number": 3
},
{
"skillId": 1010102,
"number": 2
},
{
"skillId": 1010103,
"number": 1
}
]
If you want to know more about Skills (or how to make Custom Skills), I recommend reading the appropriate thread on that.
Additional Note
Something I forgot mention before was unitScriptID
, because it's usually unused, and when used without reason will
something cause weird bugs like soft locks, or preventing your ID from spawning.
I'd recommend that, unless you're making an ID that explicitly requires them (such as a Bloodfiend ID), to just remove the entire field.