Authors: JeNoVaViRuS
This tutorial will show how to add a spell from scratch but we will be using an existing animation (you can use your own one that you created instead). You normally have a cast and a fire animation for a spell and we will only use one but still cover how to implement both. Be aware that you should invest time to create a proper and fitting sfx for your spell or be prepared to have a mediocre one.
All text that is within quotation marks is meant to be literal so it's already existing exactly like this or meant to be like this. The file names sometimes include the sub-folder (in the game folder) at the start of its name so you can easily find them. Always create/have a backup ready of the original files. You should always use ModEngine 2/3 and copy the files into the mod folder.
The spell needs to be created as a usable magic item and as an item (goods) to be found.
Param editor → Magic
Optionally you can set a replacement status type for a stat like INT or FTH.
Then you can set the threshold at which amount it should pick another spell when executing this spell. You add its ID into the replacement Magic ID field below.
This way you can let the spell execute in another way depending on a stat of the player.
Param editor → Bullet
Param editor → AtkParam_PC
Param editor → EquipParamGoods
Text editor → Goods
Text editor → Spells
These are the ID ranges in a000 for magic:
As you can see left hand animation is offset by 2000 and fire animation by 300.
DS Anim Studio:
First download the decompiled versions of “common_define.hks” and “c0000.hks”. You need to edit them and then put them into the “action/script” folder.
In “common_define.hks” you need to add your custom variable e.g. “MAGIC_REQUEST_CUSTOM_SPELL” like this:
MAGIC_REQUEST_CUSTOM_SPELL = 51
“51” is the next free ID. This is also the “refType” ID that you need to set in the “Magic” params.
Also add the variable (as name) to the “AttackMagicIndex” array if it is an attack. This is normally on line 165 right below the “magic request” section.
In “c0000.hks” there is an “ExecMagic” function on line 2207.
Example: After line 2326 which is:
elseif magic_type == 50 then
magic_index = MAGIC_REQUEST_FAN
we add our own entry:
elseif magic_type == 51 then
magic_index = MAGIC_REQUEST_CUSTOM_SPELL
The “magic_type” ID is the “refType” ID. The “magic_index” is an ID that gets applied to “IndexMagicType”.
Warning: “hkxpack-souls” can write out of memory bounds. Backup the original into another folder. Use a Windows VM and a hex editor (e.g. “ImHex”) and after converting it back from .xml to .hkx you need to do a compare between the original and your new version - if they start to differ at a specific point which is NOT your new entries you need to reboot and convert it from .xml to .hkx again until it doesn't appear. Otherwise your savegame and all other players who use the file will not be able to load a savegame like 50% of the time. Doesn't occur on all systems.
Every object has a unique name #XXXX
There are hkobjects for every possible state to cast magic from. Those “hkbManualSelectorGenerator” lists are:
#7921: MagicLaunchLeft_Selector
#8056: MagicLaunchLeftSA_Selector
#8276: MagicFireLeft_Selector
#10638: MagicLaunchLeft_Upper_Selector
#10700: MagicLaunchLeftSA_Upper_Selector
#10797: MagicFireLeft_Upper_Selector
#8447: MagicLaunchRight_Selector
#8585: MagicLaunchRightSA_Selector
#8803: MagicFireRight_Selector
#10866: MagicLaunchRight_Upper_Selector
#10930: MagicLaunchRightSA_Upper_Selector
#11028: MagicFireRight_Upper_Selector
Launch means charging up the spell.
Fire means throwing the spell.
Upper means it only uses the upper body to perform the spell.
Their 'hkparam name=“generators”' variable holds a list of all IDs of the spells (their objects are normally right below). The order of those IDs determines how the game picks the corresponding animation.
So e.g. “refType=4” picks the 5th ID from that list and plays it because the index starts at 0.
Below every “hkbManualSelectorGenerator” you need to create a new “CustomManualSelectorGenerator” and a “hkbClipGenerator”. You only need to do this for the first 3 left/right, you simply refer to the #IDs that you already created within the last 3. The next free name/ID for objects is: #12802
Example:
Now repeat that for each other Selector. There you set other consecutive IDs (they need to be unique).
Optional (split the animation): set a crop time if you have only one animation:
For the “Launch” entries you set:
cropStartAmountLocalTime = 0.0
cropEndAmountLocalTime = <end where your animation uses a windup in seconds e.g. 0.24>
For the “Fire” entries you set:
cropStartAmountLocalTime = <end where your animation uses a windup in seconds e.g. 0.24>
cropEndAmountLocalTime = 0.0
Optional: Instead of splitting an animation you can set the idle anim ID a000_000000 for the “fire” Selectors.
Optional:
playbackSpeed = the speed of your animation in % meaning 1.0 (default) is 100%, so 1.5 is 150%
enforcedDuration = speeds up your animation so that it completes in that amount of time in seconds
startTime = starts the animation AND TAE at this time in % (so 0 - 1 meaning at 1.0 it would complete instantly and at 0.5 it starts in the middle) so this SKIPS tae events that exist before the time it would start