View Full Version : Creating a new energy shield

01-02-2007, 12:12 PM
Mod note: Some posts from this thread (http://www.lucasforums.com/showthread.php?t=174171) has been copied to the tutorial forum here for easier reference. Please post comments or questions in the original thread. ~M

To make a new shield armband you essentially need to modify 4 standard game files, and create two new files. First, the files you need to modify:

This file is located in the main game folder (where the swkotor.exe or swkotor2.exe file is located). It contains all the standard text that is shown in the game that doesn't come from mods. Make a backup copy of this file first, in case something gets messed up. Then open this file with a TLK file editor (TalkEd for example) and add a new entry to it. As the text of this entry, type in the name of your shield. Then make note of the index number (StrRef) your entry gets added as, you'll need this number soon.

Save your changes to the dialog.tlk. Remember that this file should never be put in the override folder, it should always be in the main game folder.

This 2DA file contains the specifics of a particular type of energy shield. This includes information about how much damage is blocked, what types of damage is blocked, and what visual effects are shown on the one protected by the shield.

If you don't have a copy in your override folder already you can extract one from 2da.bif with KotorTool. Add a new line to this table for your shield. It's easier if you pick the line of a similar shield and copy&paste it at the end and then just modify the values you want to be different. The columns in this file are:
(Row Label) - Just set it to the next number in sequence.

Label - This is not used by the game, just to make the file more easy to understand for humans and allow installers and such to uniquely identify a line. Set this to a unique name for your shield.

visualeffectdef - This column holds a Row Label value from visualeffects.2da, telling the game what "glow" effect to display on the one protected by the shield while it's active.

defaultradius - Unused as far as I can tell. Just set it to -1.

damageflags - This column contains a bit-field of OR-ed together damage constant numbers to tell the game what types of damage will be blocked by the shield. To get the value to put in this column, add together the numbers for the relevant damage types as listed below:

Damage type Constant value
----------------------- --------------
Bludgeoning 1
Piercing 2
Slashing 4
Universal (all) 8
Unstoppable (disruptor) 16
Cold 32
Light side 64
Electrical 128
Fire 256
Dark side 512
Sonic 1024
Ion 2048
Blaster 4096

So, for example, to make a shield that blocks all physical types of damage, you'd put 7 (1 + 2 + 4) in the damageflags column.

vulnerflags - This field works just like the damageflags field, only that the damage types specified here will deal double damage to a shield of this type. This is usually used to make Ion damage drop shields quicker, but you can specify any damage types here.

resistance - Don't know for sure what this does. I suspect it's the maximum amount of damage inflicted by a single hit that will be blocked by the shield, but that's just speculation. All standard shields in the game have this set to 300 so unless you have a reason not to I suggest you do so as well. :)

amount - This specifies the amount of damage the shield will block before it expires.

permanent - This isn't used by any of the standard shields in the game, but I think if it's set to 1 the amount column will be ignored and the shield will continue to block damage until its effect duration expires.

The remaining columns are only used for droid shields that don't use the "skin tight" glow, and will determine how their shield bubble looks. They should all be set to **** for regular armband shields worn by humanoids.

When you've added your new line and set its values, save the modified 2DA file in the override folder. Remember the line number of the new line you added, it will soon be needed.

This file is used to display feedback to a player that they are under the effect of a particular effect. In KotOR this will determine what little icon is shown on the character screen of the character. In TSL it will determine what text is shown on the "Effects" screen of the character. You should add a new line to this file for your shield, so the player will know when their character is protected by it. The columns are:

(Row Label) - Set this to the next number in sequence.

Label - Used to make the file more easily readable by humans, and lines distinguishable by installer and patcher applications, but not used by the game itself. Set it to a unique name for your shield.

iconresref - Set this to the name of a TGA or TPC file (without the .tga or .tpc extension itself) containing the icon to display on the character screen, if this is for KotOR1. In TSL you can probably leave it unset as it is not used by that game.

good - If this is set to 1 the effect will be listed as a beneficial (buff/defense) effect, which you'd want in the case of a shield. If set to 0 it will be listed as a debilitating or otherwise unbeneficial effect (such as poison, stun etc).

description - I don't think this is used by either of the games, so just set it to ****.

priority - This will affect the order in which the icon or name is displayed in the listing. Doesn't really matter what you set it to for anything else, as far as I can tell.

namestrref - This needs to be set to a StrRef of where the name of the effect (in this case the name of your shield) is stored. A StrRef is an index value in the dialog.tlk file. Set this to the StrRef of the dialog.tlk entry you added previously.

This contains definitions for all force powers and activatable items in the game, linking them to the script that does whatever they are meant to do. It's too complicated to describe in detail here, so just find a line for one of the existing shields in the game and copy&paste it at the end. Line 99, the common energy shield, will do nicely. Then change the following columns:

(Row Label) - Set this to the next number in sequence.

label - Set this to a unique name to identify your armband. It's not used by the game, but makes the file easier to read for humans or installer/patcher applications.

name - Set this to the StrRef number of the new entry you added to dialog.tlk above.

impactscript - This should contain the name of your script (without the .NCS extension) that is used to trigger the shield when the armband is used. Make up a new unique name for your script. It can be at most 16 characters long and may only contain characters a-z, numbers 0-9 and underscore _ characters. Remember the name, you'll soon create this file.

That's all you need to change from the original line you copied. Save your modified spells.2da file in your override folder, and remember the line number of the line you just added. This will be used shortly.

Next, the files that needs to be created:

The impact script
Create a new script source file (NSS) and give it the name you set in the impactscript column above. The content of the script could simply look something like this, and will tie together some of the files you just modified:

void main() {
effect eShield = EffectForceShield(999);
eShield = SetEffectIcon(eShield, 999);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eShield, GetSpellTargetObject(), 120.0);

The colored part in the script below are what needs to be modified:
Change the yellow number to the line number in forceshields.2da of the new line you added there.

Change the blue number to the line number in effecticon.2da of the new line you added there.

Change the green number to the duration, in seconds, that the shield will last (unless it will expire by blocking it's maximum amount of damage before then).

Compile your modified NSS file into an NCS file, and put the NCS file in the override folder.

The UTI file
Create a new UTI file for your armband, name it whatever you like and give it a suitable description. Set the Base Item type to Forearm Bands (46), and set the ModelVariation to the number at the end of the ii_frArmBnds_###.tpc (or .tga) texture file you want to use as inventory icon for your armband. The standard ones goes from ii_frArmBnds_001.tpc (1) to ii_frArmBnds_010.tpc (10), but you can add your own textures with your own number in the name, and set the ModelVariation accordingly.

As item property, add an Activate Item property, set the SubType to the line in spells.2da you added earlier, and set the Value to the number of charges per use you want your shield to have, determining how many times your shield item can be used before burning out.

Save the UTI file in the override folder as well, and hopefully everything should work. :)

01-02-2007, 04:06 PM
Let's take Yusanis Shield as a reference:
It has deflect Energy, Electrical 100pts as it's abilities. Now according to your table, the damageflags should be set at 4224 assuming 'Blaster' refers to 'Energy.' The damageflags for Yusanis Shield in the forceshileds.2da, however, is 6208. This has me a bit confused....

I've noticed that the "Lightside" and "Electrical" damage types have switched value between KotOR1 and TSL for some odd reason. The table I posted was for TSL, so if it's for KotOR use 64 for Electrical and 128 for Lightside. Also, in KotOR1 all the standard shields are set to block Ion damage (though the shield takes double damage from it), while this isn't the case for TSL.

Edit - R2-X2 says: "damage types weren't actually switched between the 2 games, and electrical is 128 in K1 just as it is in K2 (and light side 64), the energy shields in K1 simply have a wrong bitflag set, and do not block electrical damage at all."

As for 6208 as damage type, this means for KotOR1 the shield blocks Blaster/Energy (0x1000), Ion (0x0800) and Electrical (0x0040) damage. If you want to see what damage types are set for a shield you can do the math backwards, even though there is an easier way (see below). It's easier to see what you are doing if you convert the values to hexadecimal though, since we are dealing with a bit-field. So the KotOR1 table would be:

Damage type Constant value (in hex) (in Binary)
----------------------- -------------- -------- --------------
Bludgeoning 1 0x0001 0000000000001
Piercing 2 0x0002 0000000000010
Slashing 4 0x0004 0000000000100
Universal (all) 8 0x0008 0000000001000
Unstoppable (disruptor) 16 0x0010 0000000010000
Cold 32 0x0020 0000000100000
Electrical 64 0x0040 0000001000000
Light side 128 0x0080 0000010000000
Fire 256 0x0100 0000100000000
Dark side 512 0x0200 0001000000000
Sonic 1024 0x0400 0010000000000
Ion 2048 0x0800 0100000000000
Blaster 4096 0x1000 1000000000000

Now, 6208 in hexadecimal notation is 0x1840. Check against the table above. We have 0x1000, which is for Blaster/Energy damage, 0x0800 which is for Ion damage, 0x0040 which is for Electrical damage. 0x1000 + 0x0800 + 0x0040 = 0x1840 = 6208.

If you look at the values in binary notation instead it makes even more sense through. Check the table above, now instead of seeing one number, see each digit as a flag/position that can either be turned on (1) or turned off (0). Each position represents a particular type of damage. Essentially you set the position reserved for each damage type to on (1) to make the shield protect against it. The 1 in the table above shows the position representing each type of damage. (Imagine a number of checkboxes lined up next to one another.)

For example, always counting from the right towards the left, position number 7 determines if the shield blocks electrical damage. It is set to 1 to "turn it on", and so the digit there is 1. Cold damage is position number 6, but Yusanis shield does not block Cold, so that position has the value 0. And so on.

So, 6208 is 1100001000000 in binary notation. Here we see that flags number 7 (electrical), 12 (Ion) and 13 (Blaster/Energy) are turned on. Thus Yusani's Shield blocks Energy, Ion and Electrical damage. :)

You can use the Calculator that comes with Windows to convert numbers between different notation if you set it to Advanced/Scientific mode in the menu.

Also, Yusanis Shield also has an expiry when Max damage is taken OR when the seconds expire. Does the example script you posted cover that? You wrote "...Change the green number to the duration, in seconds, that the shield will last (unless it will expire by blocking it's maximum amount of damage before then)."

An EffectForceShield() effect automatically expires whenever the specified amount of damage has been blocked by it. Like with most other effects, you can also apply it with a duration, after which the effect expires if it has not already done so on its own, or been removed by a script by then.

Thus, Yusanis shield will expire either when 100 damage has been blocked, a script calls the ClearAllEffects() function on the character, or when 220 seconds of time has passed, whichever happens first.

You can also apply the shield effect without a duration, by changing the first parameter to the ApplyEffectToObject() function from DURATION_TYPE_TEMPORARY to DURATION_TYPE_PERMANENT and then not specifying any duration number. The shield would then stay on the character either until the specified damage has been blocked, or a script clears effects from the character.

Edit: One other note, the script that you wrote is at the bottom of the k_sup_bands.nss file. Would I be able to just add it there by starting with the 'else if(nIindex == Row Label from Spells.2da)' command instead of of creating a brand new script file?

You should be able to, but I see no reason why you would want to do that. As a rule of thumb you should strive for modifying existing standard game files as little as possible when doing mods. If you can create a new script to handle what your mods needs to be done this makes it a lot easier to make several different mods play nice together.

(Sometimes it's unavoidable to modify the standard scripts, like if you modify the creature AI or random loot system, but whenever you can "outsource" your new mod-related stuff to its own uniquely named files it's preferable, in my opinion.)

01-03-2007, 11:20 AM
3. Using Kotor Tool, added a new line by copy and paste to effecticon.2da and changed the row label, label, and iconresref, saved to override. There was no cloumn for me to change the 'namestrref' like you said in your description, the column just wasn't there.

The namestrref column was added to effecticon.2da in KotOR2:TSL (since it shows a text description of the effect instead of an icon like KotOR1), and does not exist for KotOR1.

7. Using Kotor Tool, tried to modify the .uti by using the Activate Item property, however, the Subtype will not show up. SO, it looks to me like all the changes are made but I cannot get the Activate Item Property/Subtype to access the new subtype I just created.

In KotorTool, check in the Tools Menu --> Options --> Other that the "Look in game's override folder for 2DA files" is checked. If it's not, check it and restart KotorTool and it should recognize your changes.

If it still doesn't work you can open the UTI file with a GFF Editor and change the subtype value in the PropertiesList --> # --> Subtype field for your property.

(Also don't forget to compile the script. The game does not use NSS source code files for anything, only NCS bytecode files.)

01-03-2007, 12:49 PM
The effect Icon isn't showing up. I have made the change in effecticon.2da to the .tga icon in my override. Is their another specific Icon that the game uses for the Effect Icon? I just pointed it to the Icon that displays in the inventory screen. Here's the script:

The KotOR games are usually pretty picky when it comes to image dimensions. I'd recommend that you open another of the effect icons (listed in the effecticon.2da file) and check what dimensions, resolution, TXI and alpha-channel setup that icon has, and make your own icon accordingly. Unless my memory completely fails me the inventory icons are larger than the effect icons displayed on the character record.

Also make sure the name of your icon is a valid ResRef (max 16 characters not counting the file type extension, alphanumerical characters and underscore only).

01-03-2007, 01:19 PM
what are you naming your icon? it must be (safer to) in the ii_frarmbands_xxx format with the xxx being your variation number, defined in your .uti file. If your variation number is only 2 digits.. put a '0' before it.

eg. 2 = 002 / 16 = 016

Also, i can't remember, but try saving it in both 24bit & 32bit. One or the other works.. but I can't remember which is required for icons. Or if you can, simply choose another game icon that would be similar to yours rather than making an entirely new icon. Just make sure to change those number values.

01-03-2007, 02:37 PM
So, I double-checked and counted and it does match. The effecticon.2da line numbers run concurrently up to line 59, then it switches to line 61, the three(3) 63's so it looks like this


I added my line number after the last 63 and labelled it 64.

The line number is the actual counted number, from he top (line 0) down, increasing the count with 1 for each line. It does not have the match the number in the (Row Label) column. KotorTool's 2DA editor does (unfortunately) not display the line number. But you must refer to your new line by line number, not Row Label, in the script.

Often the row label is set to the same as the line number, but in some files this is messed up, and this is one of them. Thus, if you have no other mods adding lines to effecticon.2da, your new line would have line number 62. Thus you would use the number 62 in your impact script.

(The Row Label numbering skips over 56, 58, 60.)

01-03-2007, 02:50 PM
Just out of curiosity, how did you come up with 62? My thinking was 59 = 59, 61 = 60, 63 = 61, the second 63 = 62 and the third 63 = 63, thus making the next line 64.

The Row Label numbering in effecticon.2da for KotOR1 skips over the numbers 56, 58, 60. Just count the lines manually to be sure (or export the 2DA to text and use a text editor with line numbering to make it easier to check :)).

In short, don't blindly trust the Row Label values in 2DA files that are indexed by row number, there is no guarantee that the sequence is unbroken, since the game doesn't actually use those numbers for anything. (Though it's worth keeping in mind that there are a few 2DA files which are indexed by Row Label instead of line number, just to confuse matters further.)