Tools
- Witchy
- FXMLR
- DS Map Studio
- DS Anim Studio
- 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 Witchy. 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 Witchy.
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.
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 will create the sfx ID "200000092" BUT these casting sfx are entered without the prefix 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"
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. If you want to create a custom one read this.
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 Witchy. 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" + sfxVariationId.
Duplicate and rename the file "f0023142.ffx" to a free ID e.g. "200000092" meaning "f200000092.ffx".
Now convert the "f200000092.ffx" with FXMLR. It will create a file called "f200000092.xml". Edit it with Notepad++. At the top change the EffectID="23142" to EffectID="200000092". Convert the "f200000092.xml" with FXMLR so you get a working "f200000092.ffx".
It is better to chose a range outside of the vanilla ones since you can run out of IDs e.g. 200000000+. 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" (always 100 IDs apart). So your new range for those could be e.g. 300000000+ for bullets and 400000000+ for impacts.
Now edit the Witchy.xml in the unpacked folder and add a new <file></file> tag entry after the last .ffx one for your f200000092.ffx file with a consecutive ID, and then repack the "FRPG_SfxBnd_CommonEffects-ffxbnd" folder with Witchy.
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.
Since only one exists this tutorial uses 1 instead of 2 animations per side. The cast and execute animations are one.
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
A list of event types 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 (copy and paste existing one), change to Type "114", start can be at 0 but it is recommended to use a slight delay (so the character can start to play the animation).
FFXID: 2000000 (last 2 digits are taken from the spells param "sfxVariationId")
DummyPolySource: If it looks up the players DummyPolys (0) or the ones of the weapon in either hand.
DummyPolyID: Where to spawn the sfx (use "Window" -> "Scene Explorer" -> "Helpers" to show possible DummyPolys). This influences the orientation of the sfx.
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
If you want to spawn a different sfx for each side (e.g. orientation related to side) then you can use this way for left side with the .ffx file "f2000100XX.ffx" and for the right side you set the "FFXID" to e.g. "2000200" and create your .ffx file with the ID "f2000200XX.ffx" where XX is the sfxVariationId param field of the spell. The 2 numbers between should be left free in case you want to add additional sfx effects for each side so you could add e.g. "f2000101XX.ffx" at another DummyPoly.
In the execute animation you would use event 115 (it terminates differently) with the same IDs in the fields.
2. Bullet spawn: Add a new event, change to Type "64", start time is the end time of the Type 114 (115 in 2nd animation if it exist but not the case here). This event is normally only one frame long because only one bullet is spawned.
DummyPolyID: Where to spawn the bullet
b: 0 if only one bullet fired, 1 if you spawn more than 1 bullet in an interval
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", start time e.g. at "2.0", end time is until the end of the animation.
ToActivateEarly: "93" determines the early activation of this event meaning the animation finishes earlier
ToJudgeHowEarly: 5 (determines that dex is used to decide the speed)
Parameter1: 1
Parameter2: 0
Unk0C: 0
StateInfo: 0
4. remove "Disable Turning": A Type "0" event with JumpTableID "7" which disables turning during 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", start time "0", end time e.g. "0.5"
JumpTableID: "91" (disables running)
Add an event Type "0", start time is the end time of the one above so "0.5", end time e.g. "1.1"
JumpTableID: "90" (limits player to slow walk)
Add an event Type "0", start time is the end time of the one above so "1.1", end time e.g. "1.8"
JumpTableID: "89" (limits player to standing still)
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", start time at "0" and end time is your preferred time limit. Set the angles as you see fit.
UpwardAngleLimit:
DownwardAngleLimit:
UpwardAngleThreshold:
DownwardAngleThreshold:
Keep in mind that all those changes need to be done for the right hand animation as well.
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)