Patch 1.87.8193.35 added custom damage types. This tutorial will show you how to add new damage types relatively cleanly into the game.
Note there are still a few limitations around projectile ammo visual effects.
Patch Notes
The patch notes state this which may be useful to reference later:
- Two new 2DA files have been added: damagetypes.2da and damagetypegroups.2da.
- damagetypes.2da: each damage type in the game must have an entry.
- Label is cosmetic, for developer ease only.
- CharSheetStrref refers to the name of the damage type as seen on the character sheet.
- DamageTypeGroup is a row ID into damagetypegroups.2da.
- damagetypes.2da: each damage type in the game must have an entry.
- damagetypegroups.2da: each damage type is associated with a group. A group can be associated with more than one damage type. A group is a way to aggregate multiple damage types into one in the combat log. By default, it is used to aggregate the four physical sources of damage into a group that displays physical damage.
- Label is cosmetic, for developer ease only.
- FeedbackStrref refers to the name of the damage type as seen in the combat log. It uses the CUSTOM0 token to substitute the damage value.
- ColorR/ColorG/ColorB (0-255) drives the color of the damage type.
- Added a row for base damage to iprp_damagetype.2da and damagehitvisual.2da. This row is necessary to line up subsequent rows for custom damage types.
- Rows in damagehitvisual.2da have a 1:1 mapping with rows in damagetypes.2da.
- Rows in iprp_damagetype.2da have an almost 1:1 mapping, just pretend that Subdual and Physical don't exist.
- In other words, row 13 in damagehitvisual.2da will apply to damage type 13 in damagetypes.2da, and row 15 in iprp_damagetype.2da will apply to damage type 13 in damagetypes.2da.
- Added support for customizable weapon glow FX..
- iprp_damagetypes.2da has been extended with a new column, VisualFX.
- VisualFX is a row ID into iprp_visualfx.2da.
- This allows you to remap item property damage types to different visual FX on the weapon.
- Now you can fulfill your desire to make all damage types produce a beautiful golden glow, or you can add weapon glows for one of your custom damage types!
- iprp_damagetypes.2da has been extended with a new column, VisualFX.
Understanding an Existing Damage Type
Existing damage types can now be renamed, and elemental damage types can be repurposed. However the physical damage types are still tied in the engine to weapon damage, and damage reduction, so it is much harder to make changes there (and highly recommended not to).
But let's say we want to check out an existing damage type. Let's use DAMAGE_TYPE_DIVINE. It has these properties:
It is line ID 6 - row 7 - in damagetypes.2da this gives it a value in nwscript of 64. This comes from the 7th position from the right in a bitwise representation of 32bits due to it's row number:
00000000000000000000000001000000 ^ 7th position from the right
Plug it into a calculator gets you out 64: https://www.rapidtables.com/convert/number/binary-to-decimal.html
This is DAMAGE_TYPE_DIVINE:
It has a CharsheetStrref of 58305 which is "Divine Damage".
It uses DamageTypeGroup value of 4. This references damagetypegroups.2da line 4, providing the string reference for feedback and the colour to use for that feedback in text form and floating numbers - in this case TLK line 10460 - "<CUSTOM0> Divine" - and yellow colour R 255 G 255 B 0.
The final 2da file damagehitvisual.2da uses the same ID line as damagetypes.2da - 6 - which points to VFX 289 in visualeffects.2da
For item properties in iprp_damagetype.2da it is line 8 and the TLK string 5155 is used which is just the word "Divine". This is constant IP_CONST_DAMAGETYPE_DIVINE. VisualFX column isn't set for this line (the VFX on any weapon it is applied to).
Note there is no way for divine to have a projectile visual effect. These are still hardcoded to the 5 default ones - acid, cold, electrical, fire and sonic, as per ammunitiontypes.2da
Adding a new Damage Type
Let's say we wanted to add a new damage type "Psychic" for your Mindflaters psionic abilities. This is reasonably easy and follows the above example. You need some 2da changes and 2 TLK strings, and perhaps a new constant for your damage:
First we add a new row to damagetypes.2da adding a new TLK reference and DamageTypeGroup IDs.
2DA V2.0 Label CharsheetStrref DamageTypeGroup 0 Bludgeoning 58345 0 1 Piercing 58341 0 2 Slashing 58344 0 3 Magical 58302 1 4 Acid 58303 2 5 Cold 58304 3 6 Divine 58305 4 7 Electrical 58306 5 8 Fire 58308 6 9 Negative 58309 7 10 Positive 58310 8 11 Sonic 58311 9 12 Base 58301 0 13 Psychic 16877216 10
Secondly we add to damagetypegroups.2da the new line we reference before (10) and new colour (we choose a form of pink - find a RGB colour picker online eg this one) and TLK string in the form of "<CUSTOM0> Psychic":
2DA V2.0 Label FeedbackStrref ColorR ColorG ColorB 0 Physical 5594 **** **** **** 1 Magical 5593 204 119 255 2 Acid 10458 0 102 0 3 Cold 10459 153 255 255 4 Divine 10460 255 255 0 5 Electrical 10461 0 102 255 6 Fire 10462 255 0 0 7 Negative 10463 153 153 153 8 Positive 10464 255 255 255 9 Sonic 10465 255 153 0 10 Psychic 16877217 255 0 255
Thirdly we add to damagehitvisuals.2da, same row ID as damagetypes.2da, in this case we are leaving it blank since we don't have a handy VFX for it but feel free to add one if you wanted:
2DA V2.0 Label VisualEffectID RangedEffectID 0 Bludgeoning **** **** 1 Piercing **** **** 2 Slashing **** **** 3 Magical 76 **** 4 Acid 283 **** 5 Cold 281 **** 6 Divine 289 **** 7 Electrical 282 **** 8 Fire 280 **** 9 Negative 282 **** 10 Positive 289 **** 11 Sonic 284 **** 12 Base **** **** 13 Psychic **** ****
Lastly we add a new constant for our damage type. It is row 14 so using the calculator a 1 with 13 zeroes after gives us 8192 - which we can double check in nwscript since DAMAGE_TYPE_CUSTOM1 should match it - and it does!
const int DAMAGE_TYPE_PSYCHIC = 8192;
Then we can test it, for instance with this simple script you can run on yourself using the script window. There is no custom TLK used it sets the strings using TLK overrides for now - you'll need to add them to your TLK file for the toolset to recognise it properly however!
const int DAMAGE_TYPE_PSYCHIC = 8192; void main() { SetTlkOverride(16877216, "Psychic Damage"); SetTlkOverride(16877217, "<CUSTOM0> Psychic"); effect eDamage = EffectDamage(5, DAMAGE_TYPE_PSYCHIC); ApplyEffectToObject(DURATION_TYPE_INSTANT, eDamage, OBJECT_SELF); }
See the results in game:
Now you have a custom damage type!
Damage Type on Item Properties
This is pretty simple - you need another TLK string and line in iprp_damagetype.2da and off this you can generate a custom constant for nwscript purposes. The TLK String should be just the sole word "Psychic".
2DA V2.0 Name Label Cost VisualFX 0 1031 Bludgeoning 1.25 **** 1 1032 Piercing 1.25 **** 2 1033 Slashing 1.25 **** 3 **** Subdual **** **** 4 **** Physical **** **** 5 62487 Magical 0.35 **** 6 1027 Acid 0.35 0 7 1029 Cold 0.4 1 8 5155 Divine 0.4 **** 9 1030 Electrical 0.45 2 10 1028 Fire 0.5 3 11 5158 Negative 0.5 **** 12 5159 Positive 0.5 **** 13 2202 Sonic 0.5 4 14 **** Base **** **** 15 16877218 Psychic 0.5 ****
We can add a new constant for this item property damage type following the others:
const int IP_CONST_DAMAGETYPE_PSYCHIC = 15;
Remember fix up your custom TLK file and you can add item properties too, a script for testing:
const int IP_CONST_DAMAGETYPE_PSYCHIC = 15; void main() { SetTlkOverride(16877216, "Psychic Damage"); SetTlkOverride(16877217, "<CUSTOM0> Psychic"); SetTlkOverride(16877218, "Psychic"); object oItem = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, OBJECT_SELF); if(GetIsObjectValid(oItem)) { itemproperty ipAddDamage = ItemPropertyDamageBonus(IP_CONST_DAMAGETYPE_PSYCHIC, IP_CONST_DAMAGEBONUS_1d6); AddItemProperty(DURATION_TYPE_TEMPORARY, ipAddDamage, oItem, 60.0); } }
You can also generate damage resistance properties and the like as well.
Congratulations hopefully you now know how to add up to 19 custom damage types to your game!
Some suggestions from threads online:
- Damage - Basic untyped or typeless damage not usually resistible by anything. Bioware tended to use Magical for this, which works fine for most spells but doesn't look good for other cases.
- Fatigue Damage - Again not usually resistible, caused by not resting
- Sanctified and Vile Damage - from the Book of Vile Darkness, special rules for it
- Force Damage - Used for some spells (Bioware basically uses "Magical" for these cases, but "Force" sounds so much cooler!)
- Poison Damage - Some monsters who do "poison damage" not just ability score damage may use this
- Falling Damage - splat!
- Sacred, Profane, Axiomatic and Anarchic Damage - are for good, evil, law and chaos damage respectively - although the latter two might not exist usually it's fun to think about (while divine is basically "untyped but named" so shouldn't be resisted).
Example Material
Now that is all completed you now have a new damage type! You could add custom (or existing) VFX references as needed, or leave it to just be a spell effect and applying a suitably good impact VFX might be enough.
Any problems? You can download this guides files as a zip to play around: Tutorial_Psychic_Damage.zip