Hello all,
I've run into a bit of a stumbling block and I'm hoping I can get some assistance. I've been inspired to try my hand at some modding (Thank you in advance T7 for the increased blood pressure ;) ) and I've decide to make a Bounty Hunter's item pack, however, I'm running into some issues with the armband shields. What I would like to do is change some of the properties of the armband shields to something unique. The property changes would include things like what the shield deflects, how many points it deflects and the duration etc.
By doing some searching, it seems like I have to script some properties for the new shield. Now, I don't really know how to script, but I figured that if I extracted the script using Kotor Tool, it should be pretty simple to copy and paste what I want, make a couple of changes, and drop the .nss file in the overide, add a new entry to spells.2da, make the appropriate changes to the .uti file and I'm done.
Now I figured out the the script is k_sup_bands.nss as indicated in the spells.2da file. The entries in the k_sup_bands.nss file, however, look like this:
//:: k_sup_bands
/*
This is the generic script to run all
forearm bands in the game
99 Energy Shield Protects against energy weapons. Damage Resistance 5. Up to 50 damage.
100 Sith Energy Shield Protects against energy weapons and sonic attacks. Damage Resistance 5. Up to 50 damage.
101 Arkanian Energy Shield Protects against energy, sonic, cold and fire attacks. Damage Resistance 5. Up to 50 damage.
102 Echani shield Protects against energy weapons. Damage resistance 10. Up to 50 damage.
103 Mandalorian melee Damage Resistance 5. Up to 50 damage.
104 Mandalorian power shield Protects against energy weapons and physical damage. Damage resistance 10. Up to 50 damage.
105 Echani dueling shield Protects against energy weapons. Damage resistance 10. Up to 100 damage.
106 Yusanis’ Modified dueling shield Protects against energy weapons. Damage resistance 15. Up to 100 damage.
107 Proto-type Verpine Energy shield Protects against energy, sonic, cold and fire attacks. Damage Resistance 10. Up to 100 damage.
110 Droid 1 Energy
111 Droid 2 Energy
112 Droid 3 Energy
113 Droid 1 Hazard
114 Droid 2 Hazard
115 Droid 3 Hazard
*/
//:: Created By: Preston Watamaniuk
//:: Copyright (c) 2002 Bioware Corp.
#include "k_inc_debug"
void main()
{
int nIndex = GetSpellId();
int nShield;
int nIcon;
if(nIndex == 99)
{
nShield = SHIELD_ENERGY;
nIcon = 45;
}
else if(nIndex == 100)
{
nShield = SHIELD_ENERGY_SITH;
nIcon = 46;
}
else if(nIndex == 101)
{
nShield = SHIELD_ENERGY_ARKANIAN;
nIcon = 47;
That isn't the whole script file, but all the other entries look like the ones above. Am I missing something? Am I in the wrong file? Is there a different file I should be tring to change? There doesn't seem to be any indicators to change what I would like to change. Is what I'm trying to do even possible?
Any help would be appreciated!
PrimusPilus
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:
dialog.tlk
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.
forceshields.2da
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.
effecticon.2da
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.
spells.2da
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. :)
Hey, thanks for the response! Very detailed and it looks very easy to follow, thank you for that! I guess I should of mentioned that this was for K1 but I see that you included your explanation for both, thanks!
I have a couple of questions if you wouldn't mind...
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....
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)."
It seems the way you wrote it that it's either one or the other but not both. Is there a way to make it so that the charge expires either when Max damage is taken OR when the seconds expire? Maybe I'm just reading it wrong or I'm not understanding.
I appreciate the help, thanks again.
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?
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 can however it is a much better programming and modding choice to keep your files seperate. As it makes merging mods much easier for the end-user. The only time that the core game files as the one you mentioned above should be changed is if you are changing the effects of the items they manage and handle.
Either way you decide to go with the mod make certain to include your source scripts.
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.
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.)
Thanks again for the response, you're instructions are clearly laid out and very easy to follow.
I do have one concern, however. Let me start by explaining what I have done.
1. Using Kotor Tool, loaded up the Dialog editor and added to line 32135 the Text for the Shield. Backed up old Dialog.tlk file and placed new one in the main game folder
2. Using Kotor Tool, added a new line by copy and paste to forceshields.2da and changed the row label, the label and the damageflags, saved to override
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.
4. Using Kotor Tool, added a new line by copy and paste to spells.2da and changed the row label, label, name to 32135 from the dialog.tlk file, and changed the impactscript to my unique script name, saved to override
5. Added the .uti and icon .tga for the item to override
6. Using Kotor Tool, put your script example into a unique script and saved in override (double checked your blue, gree, and yellow changes to ensure they were correct.)
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.
Any help will be appreciated and thanks again for the responses.
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.)
Yup, I'm an idiot ;). Just before you posted I had a look under the options in Kotor Tool and checked 'look for 2da files in override' or whatever it says. Tested in game and it appears to work perfectly. Now I just have to check to ensure that the damage blocks I added actually work.
Thanks again for your assistance and if I may, this should be added to the tutorials section since you did such a fine job of explaining!
Thanks again!
Ok, one more slight concern to report and I probably should of checked this before but I was just happy that the shield activated and worked ;).
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:
void main() {
effect eShield = EffectForceShield(19);
eShield = SetEffectIcon(eShield, 64);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eShield, GetSpellTargetObject(), 180.0);
}
Line 64 is the new line created in effecticon.2da. I also tried it with no space between the comma and 64, still the same result.
As always, help is extremely appreciated!
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).
I'd love to! You don't happen to know where they are located, do you ;) ? In effecticon.2da, the icons that the game points to are ii_frarmbnds_XXX. The only place I can find these files are in Erfs-Texture Packs-swpc_tex_gui.erf-I. This is the file I extracted and modified accordingly. I can't locate any other ii_frrambnds_XXX files using Kotor Tool.
I also tried changing the iconresref to one that the game currently uses instead of my custom .tga and the icon doesn't show up with that either.
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.
Hey again!
Just ran one more test. I changed an existing shield in effecticon.2da to point to the resref of the .tga I created in the override and the shield Icon showed up. So the game does recognize the Icon and it's not a matter of resizing. What it won't do is give me the Icon for my new item.
@ Chainz, the name of the icon is ii_frarmbnds_066
Any thoughts?
only thing i could suggest (other than the tga bits) is to double-check your armband uti to make sure the model variation is set to 66 :giveup:
Are you getting a big white square.. or just nothing at all? Also, are you re-spawning a new instance of your armband when you're testing?
Though you are making .2da changes.. it's always best to spawn a new instance of items after you make changes. Usually not required for skinning, but it still makes for good habit practice since savegame data only stores the first instance of an object created.
@ chainz, yeah the uti matches. The Icon shows up fine in the inventory screen, it's when you activate the shield and the little icon is supposed to show up on the player character screen showing that the pc is under an effect is where it's not showing up. I changed an existing shield icon to point to mine and it shows up there but not with my new item, and yeah, I'm respawning the item every time to get a 'fresh' load. The other way to do it is to re-load KSE and re-add the item that way.
Just ran one more test. I changed an existing shield in effecticon.2da to point to the resref of the .tga I created in the override and the shield Icon showed up.
Seems like the script doesn't use the correct effect icon link. Doublecheck that the number you put in the script for the effect icon matches the line number (which is not necessarily the number in the row label column) in effecticon.2da, counted from the top where the first line is number 0.
How does your line in effecticon.2da look? what values have you put in the different columns?
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, then three(3) 63's so it looks like this
59
61
63
63
63
I added my line number after the last 63 and labelled it 64. The script and the compiled script reflect that. The Icon still does not show up.
The line I added looks like this:
Row label - 64
label - ITEM_ABILITY_FETTS_ARMBAND
iconresref - ii_frarmbnds_066 (I have tried this in caps like the original files in case it was case sensitive, it did not make a difference when I added my icon to an existing shield in the file)
good - 1 (just like an original)
description - **** (just like an original)
priority - 5 (just like an original)
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
59
61
63
63
63
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.)
Well, that works! Thank you very much for your patience and your help(that's to everyone who replied to this thread).
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.
I appreciate all the assistance very much folks, thank you all!
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.)