Tools

- Yabber
- FXMLR
- DS Map Studio
- DS Anim Studio / TAE Editor
- Zeditor
- DRB Icon Appender
- DarkScript3
- paint.net
- Notepad++

This tutorial will show how to add a spell from scratch but we will be using the animation and sfx from the special attack of the "Crystal Ring Shield" (you can use your own one that you created instead).
Keep in mind that a special attack is only one animation but normal spells have a separate casting animation and a throwing animation. This is done so the casting animation can be reused but a different throwing animation can be chained.

The files are often mentioned with (.dcx) for the DSR version of those files.
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.

Parts of the game that need to be modified to create a spell

Icon

Go to the game folder «menu» and convert «menu_0.tpf(.dcx)» with yabber. Open the .dds files with "paint.net" where you want to add your icon (default is «Icon30.dds») and save it as BC3 (linear). The icons are ordered as a matrix. Every symbol only has limited space by default convention (80 width and 90 height in PTDE or double of that in remastered). You add your icon to a free space and then use DRB Icon Appender to tell the game at which coordinates you inserted your icon into the whole icon picture. Repack the "menu_0-tpf" folder with yabber.

Open DRB Icon Appender and go to the last ID of the "Icon30" entries. On the bottom right enter the next available ID and add it. Select "Icon30" for your new entry. Now you need to look at the .dds matrix again and determine the correct numbers (double of all of that in remastered):
Left Edge: starting point of the icon from the left going to the right. Always starting at 1 with +82 for each next symbol line (1,83,165,247,329,411,493,575,657,739,821,903)
Top Edge: starting point of the icon from the top going to the bottom. Always starting at 1 with +92 for each next symbol row (1, 93, 185, 277, 369, 461, 553, 645, 737, 829)
Width: always 80 by default convention
Height: always 90 by default convention
Now save it. The tool modifies the "menu.drb(.dcx)" file in the "menu" folder.

Parameters for spell attack and bullet

Bullet for projectiles and
AtkParam_Pc for the attack or SpEffectParam for an spEffect that gets applied to the player or nearby players:

DS Map Studio -> Param Editor

Search the "EquipParamWeapon" category for the "Crystal Ring Shield" and find it's "spAtkcategory" which is "92".

Go to the "Bullet" category and search for "92". You will find the entry with ID "1120". Duplicate this entry to the next ID. Change the "atkId_Bullet" to something else e.g. "4802801".

The "atkId_Bullet" field with "4802800" is the attack ID, go to the "atkParam_PC" category and duplicate it as well and give it the ID from above e.g. "4802801". Now duplicate this entry to the next ID. Set the attack damage, attack type, hit radius and so on as you like.

sfx

The easist way to create a new sfx would be to copy an existing one from another spell and then change colors, size and shape.
In this case we look up the bullet ID from above so "4802800" and see the field "sfxId_Bullet" which is the projectile that is flying after we have cast it. Since this one looks better than the actual casting sfx of the "Crystal Ring Shield" we will use this one.

Go to your games "sfx" folder. General sfx independant from maps are in "FRPG_SfxBnd_CommonEffects.ffxbnd(.dcx)" so unpack it with yabber. The .ffx files are now unpacked to:

sfx\FRPG_SfxBnd_CommonEffects-ffxbnd\Sfx\OutputData\Main\Effect_win32
or
sfx\FRPG_SfxBnd_CommonEffects-ffxbnd-dcx\Sfx\OutputData\Main\Effect_x64

All spell sfx IDs correlate to a file and their numbers are "20000" + sfxId.
Duplicate and rename the file "f0023142.ffx" to a free ID between 20000 and 20100 e.g. "20092" meaning "f0020092.ffx". Casting sfx of a spell can only be within a limited range so keep this number in mind.
Now convert the "f0020092.ffx" with FXMLR. It will create a file called "f0020092.xml". Edit it with Notepad++. At the top change the EffectID="23142" to EffectID="20092". Convert the "f0020092.xml" with FXMLR so you get a working "f0020092.ffx".

Normally you could now do the same for the bullet and impact sfx of your new spell but we can reuse the ones from the special attack which are both in the bullet so sfxId_Bullet is "23142" and sfxId_Hit is "23242". Both of them can have a higher range of IDs than the casting sfx so choose a free range e.g. 20800 - 20900 for all your new ones.

Now edit the yabber.xml and add a new <file></file> tag entry after the last .ffx one for your f0020092.ffx file with a consecutive ID, and then repack the "FRPG_SfxBnd_CommonEffects-ffxbnd" folder with yabber.

Parameters for spell magic and attunement

DS Map Studio -> Param Editor

Magic for basic spell information:
Duplicate a spell that already has the same magic type and is a projectile already e.g. "5520" which is the Sunlight Spear and give your entry a new ID e.g. "5530". It's recommended you pick an ID between 3000 and 5910, which is the vanilla range of IDs. This tutorial will be referring to this ID as the "Spell ID" for convenience.

"sortId" determines at which position in a list the spell is shown relative to other spells.
"refId" is the bullet ID from above so "4802801".
"iconId" is the Icon entry ID we added above.
"maxQuantity" are the spells charges.
"sfxVariationId" is the sfx casting ID from above. We created the sfx ID "20092" BUT these casting sfx are entered without 20000 so this field needs to be "92".
"slotLength" are the attunement slots used by the spell.
"ezStateBehaviour" is the type of magic: "0"=sorcery,"1"=miracle,"2"=pyromancy
"refCategory" is either 1=bullet or 2=spEffect
"spEffectCategory" determines from which other effects this spell is affected. Meaning a ring that boosts sorcery damage can only do that for this spell if the correct type is set. 3=sorcery and pyromancy,4=miracle
"refType" is the animation and state that gets used to cast the spell. We can set this to a new one meaning 27 or higher. "7" is unused but exists. All others are in use from 0 to 26 so we choose "27".

EquipParamGoods for spell item information:
"magicId" should be the Spell ID e.g. "5530".
"goodsType" should be "5"
"iconId" is the ID we added in the "Icon" section.
"sortId" determines at which position the good is shown relative to other goods.

EquipMtrlSetParam for attunement:
Field "materialId01" should be the Spell ID.
"itemNum01" should be "1"

ShopLineupParam for attunement:
The ID should be within the 10000-10099 range, as this is the range defined in Bonfire talkESD shop ranges (this can be modified if you want a higher range).
"mtrlId" should be the Spell ID.
"shopType" should be "2"
"equipType" should be "4"

Text

DS Map Studio -> Text Editor:
The category "goods" hold the spell title, summary and description of the item that you can pick up, buy or get as a reward.
The category "spells" hold the spell title, summary and description of the item that you own and can attune.
You need to add a new ID for both which needs to be the same as the Spell ID e.g. "5530".

Event Script

EMEVD is used to make the attunement menu appear at bonfires only after you own a spell. The common event script has an event "719" that holds all lines separated with the logical "or" operators "||". So you need to add your line e.g.

"|| PlayerHasItem(ItemType.Goods, 5530)"

Create animation

Use DS Anim Studio -> open the "chr\c0000.anibnd(.dcx)" file.

The special attack animations are in: aYYY_XXXX

YYY = "spAtkcategory" param from above
XXXX can be:

3300 = right hand
4300 = both hands
5000 = left hand

So for this example it is "a92". We only need either left and right or both hand since spells are only either cast with one hand or both but never are all 3 variations used with a spell.

Default animation IDs for spells are all in a00_62XX - a00_65XX. 62XX (left hand) - 63XX (right hand) are casting animations. 64XX (left hand) - 65XX (right hand) are executing animations.

Now go to the aYYY e.g. "a92" section and find your animations.
1. Go to the last left hand casting animation ID in a00 which is "6226" and click on it
2. Go to "Edit" -> "Duplicate Animation"
3. Select this new animation and go to "Edit" -> "Edit current Animation properties"
4. Change the Name to "6227" and ID to "a00_6227.hkxwin" then click "Apply & Save Changes"
5. Go to "Edit" -> "Import from Animation ID…"
6. Enter "a92_5000" and press Enter

Repeat this for the right hand with the animation ID "6327" (always +100 steps used in Animation IDs from left to right hand) and the special attack animation "a92_3300".
After that save the animations file (Ctrl+S).

Edit the new animations

Now you could continue to use DS Anim Studio but TAE Editor gives a better overview of the events during the animation. To use it unpack the "chr\c0000.anibnd(.dcx)" file with yabber. Then open the a00.tae with the TAE Editor. On the left side you search and click on the new ID "6227" from above.
You can also create the Types in TAE, simply leave the parameters at 0, repack with Yabber, open it in DS Anim Studio and change the "special" parameters (e.g. sfx attach points).

A list of those types of events and their parameters can be found here: TAE Events

Now you need to refine the events of the animation. It needs to work properly just like other spells in the game.

1. Cast sfx spawn: Add a new event, change to Type "114", ParamCount 3, start time can be 0 but it is recommended to use a slight delay (so the character can start to play the animation) e.g. "0.06666667", end time is your cast end time (mostly needs testing so the sfx doesn't stay too long). This one should be edited later in DS Anim Studio because of the visualized DummyPolyID.
parameter#1/s32 FFXID: 200 (last 2 digits are taken from the spells param sfxVariationId)
parameter#2/s32 DummyPolyID: can be left at 0 and be modified in DS Anim Studio.
parameter#3/s32 SlotID: ID determines which virtual slot the sfx takes up so if another spell is cast where the sfx uses the same slot then it gets replaced. -1 = sorcery weapon buff, 0 = nothing/normal cast, 2 = undead rapport, miracle weapon buff

Note: If you want to make a different sfx for each side (e.g. orientation related to side) then you can use this way for one side with the .ffx file "f00200XX.ffx" and for the other side you set the "FFXID" to e.g. 208 and create your .ffx file with the ID "f00208XX.ffx" where XX is the sfxVariationId param field of the spell.

2. Bullet sfx spawn: Add a new event, change to Type "64", ParamCount 2, start time is the end time of the Type 114 that already exists so "1.666667", the end time is the start time + 0.03 so "1.699997".
parameter#1: "0" = no bullet, "1" = from right arm, "2" = from body, "3" = from left arm, 7 = floor (heal), 8 = middle of body, 120 = right hand + weapon, 132 = in front of the palm (combustion)
parameter#2: almost always "0" ("1" is used in AOEs, fire whip, fire surge)

3. Cast speed: Now the animation is comparably long and spells are often influenced and shortened the more dex a character has.
Add a new event, change to Type "300", ParamCount 4, start time e.g. "2.0", end time is the longest time existing in the animation so "3.966667".
parameter#1 is "327773" ("93" in DS Anim Studio) determines the early activation of this event meaning the animation finishes earlier
parameter#2: "1065353216" ("5" in DS Anim Studio) determines that dex is used to decide the speed
parameter#3: "1"
parameter#4: "0"

4. remove "Disable Turning": A Type "0" event with parameter#1 of "7" disables turning during the animation.
You can simply set the parameter#1 to "0" and set the parameter#2 instead to "7" to remind yourself that you simply disabled this event to do nothing. It's recommended to never just delete it.
You can also only edit the time so it only freezes the character at the end of the animation.

5. Movement during the animation: To balance this spell the player shouldn't be able to run around while casting the spell. We will limit the movement more the longer the animation continues.

Add an event Type "0", ParamCount 3, start time "0", end time e.g. "0.5"
parameter#1: "91" (disables running)
parameter#2: "0"
parameter#3: "-1"

Add an event Type "0", ParamCount 3, start time is the end time of the one above so "0.5", end time e.g. "1.1"
parameter#1: "90" (limits player to slow walk)
parameter#2: "0"
parameter#3: "-1"

Add an event Type "0", ParamCount 3, start time is the end time of the one above so "1.1", end time e.g. "1.8"
parameter#1: "89" (limits player to standing still)
parameter#2: "0"
parameter#3: "-1"

6. Set vertical torso aim: We can limit or extend the amount of the upper body movement when aiming.
Add a new event, change it to Type "232", ParamCount 1, start time is "0" and end time is your preferred time limit.
Edit it later in "DS Anim Studio" to set the angles in degrees. There is:
- UpwardAngleLimit
- DownwardAngleLimit
- UpwardAngleThreshold
- DownwardAngleThreshold

Keep in mind that all those changes need to be done for the right hand animation as well.
Atfer you are done, save it and repack the "c0000-anibnd-dcx" folder with yabber before you open it with "DS Anim Studio" to edit the rest.

Add animation state:

Use Zeditor and open the "chr\c0000.esd" file.

1. Go to StateGroup "1" (these are the active states the player enters)
2. Choose a casting animation e.g. from the lightning spear (147), duplicate it (default exist up to 276 so your new one would be state 277)
3. Change the primary Conditions new target state "148" to "0"
4. edit the state enter command (you want to use your own new animations instead):

ChangeUpperBodyAnim((6218 + ((IsRightHandMagic() * 100))), 5, 0.1, 0, 2);
to
ChangeUpperBodyAnim((6227 + ((IsRightHandMagic() * 100))), 5, 0.1, 0, 2);

The function "IsRightHandMagic()" is either true so "1" or false so "0". This means in case of left hand cast the value is "6227" and in case of right hand cast the value is "6327". This is why left and right hand IDs are always 100 away from each other.

Now as covered in the beginning you only have one state and one casting + executing animation.
You could also export the animations, split it into 2, then re-import, create 4 instead of 2 animations and 2 states just like all spells have it.

Now save your changes.

Make your new state usable:

Use Zeditor and open the "chr\c0000.esd" file.

1. Go to StateGroup "1" and into State "0" (idle standing state)
2. Find the group with the magic casting animations (transfers to state: 132,0,157,175,177 etc.) and condition:
(((SetREG3(IsAtkRequest(3)) || SetREG4(IsAtkRequest(2)))) && (SetREG5(IsMagicUseMenuOpened()) == 0))
3. Select one e.g. "173" and click "Deep Clone CND" (replicates to all other states with the exact group name)
4. You can now rename your new condition to something descriptive
5. Change the "Target State" to your new state from above e.g. 277
6. On the top right select "Condition"
7. There is a part that e.g. says "GetMagicAnimType() == 20". This 20 is the "Animation Type" you entered in the spell param "refType". Replace the 20 with your own ID e.g. "27" from above.
8. There is also another group with the magic casting animations and different condition:
(((SetREG6(IsChainAtkRequest(3)) || SetREG7(IsChainAtkRequest(2)))) && (GetREG5() == 0))
9. again click on e.g. "173" and click "Deep Clone CND", rename, set target state and change the "GetMagicAnimType" condition.

Now repeat this for the following States (there is only one magic group in these other states and the condition is listed here as well):
1: (((SetREG4(IsChainAtkRequest(3)) || SetREG5(IsChainAtkRequest(2)))) && (SetREG6(IsMagicUseMenuOpened()) == 0))
19: (((SetREG7(IsChainAtkRequest(3)) || IsChainAtkRequest(2))) && (IsMagicUseMenuOpened() == 0))
32: ((AbortIfFalse((IsChainAtkRequest(3) || IsChainAtkRequest(2)))) && (IsMagicUseMenuOpened() == 0))
45: (((SetREG3(IsChainAtkRequest(3)) || SetREG4(IsChainAtkRequest(2)))) && (SetREG5(IsMagicUseMenuOpened()) == 0))
77: ((AbortIfFalse((IsAtkRequest(3) || IsAtkRequest(2)))) && (IsMagicUseMenuOpened() == 0))
77: ((AbortIfFalse((IsChainAtkRequest(3) || IsChainAtkRequest(2)))) && (IsMagicUseMenuOpened() == 0))
83: (((SetREG5(IsChainAtkRequest(3)) || SetREG6(IsChainAtkRequest(2)))) && (SetREG7(IsMagicUseMenuOpened()) == 0))

Now save your changes.

Insert into the world:

Insert into the world:
Your spell now exists theoretically but needs to be available in the world.
3 options:
- place the item in the world so it can be picked up (go to "Maps" -> "Parts: Objects" -> duplicate an "o0500_00XX" entry, go to "Events: Treasure" -> duplicate the last entry, set your new object from the step before as the "Treausre Object", set the item lot ID - create an item lot that refers to a "good", check or uncheck "is in chest" and "is hidden" depending if you are placing it in a chest or just let it lie around)
- let an npc sell the item (Look at the shop IDs, Go to "Params"-> "Shops" and add / duplicate an entry within the range, change the values accordingly)
- make the spell available as a dialogue or covenant reward (ESD tutorial)