[TUTORIAL] - KotOR Modding Tutorial Series

Recommended Posts

[TUTORIAL] - KotOR Modding Tutorial Series

These tutorials should be enough to get anybody started making levels for the game using the available resources and tutorials / tools etc

IMPORTANT NOTE : A lot of the tools I use are outdated now that Holocron Toolset is out, however I still prefer working with each filetype as I am use to the programs that edit them directly that I use throughout this tutorial.

So if you are using Holocron Toolset or KotOR Level Editor, things will be different, but the general idea should be the same.

I suggest trying out Holocron Toolset if you want an all in one program for editing levels, it does everything KotOR Level Editor does and most of what all the tools I have below do, except perhaps findrefs, dencs, kotor gui editor, walkswitch, anicam, ptheditor and lip synch editor, but it does everything the rest of the programs do and it might even do some of the things from the programs I just mentioned, I am not sure!

Available Source Material & Tools

These are the tools I use for modding the game.


I also use the KotOR Level Editor which requires Unity, but I started modding using many of these tools and tried to make sure I had a tool for working with each and every filetype if possible.


Lots of source material is available as well as many tutorials, some old, some new and very detailed information on the filetypes and the game itself.

.nss scripts for every script I have been able to access from both games are included within the .mod files for my project which can be opened with the latest ERFEdit.exe available via the KotOR Modding Tools Section on the Downloads page of this site. ( NOTE : I will be removing them when the project reaches a final release, but I will make sure to post them somewhere for people to access )


If there are not then I have either not included them for some reason and will do in future as soon as I notice or I have not been able to decompile them using DeNCS.jar and nwnnsscomp.exe. ( I think below is an example of the only scripts that I haven't included .nss counterparts for and they can easily be decompiled using the following tutorial anyway, I believe the .nss scripts for them exist in another level and I chose not to put them into multiple levels, either way I have them in my source scripts folder )


Some scripts from KotOR1 require the files to be trimmed of some excess bytes, there is some information on it around here somewhere and I will post a link to it when I next find it, the scripts in question are some of those from Tatooine, Manaan, Kashyyyk and the Unknown World.

Actually Decompiling Scripts


In order to decompile scripts you are going to need DeNCS and nwnnsscomp.exe which can be obtained via the downloads section of this site amongst the modding tools section.


Then you can open the javascript runtime file which will launch the decompiler.


From here as an example I am using ERFEdit to open a level from my project, which also contains the .nss scripts for every script which people are free to use to learn from and make their own mods with.


Using ERFEdit or another method obtain the script you wish to decompile.


Once you have done so, drag and drop it into the DeNCS window.


Once you have dropped it into the programs window it will look like the image below.


From here you can right click and select "View Decompiled Code" or you can the options to set the default directory to save the files to and then select File and Save As appropriately.


If you view the decompiled code you can take a look and check out the script before you decide to save it, you can also decompile multiple scripts at a time as well as save them all at once.

The log at the bottom of the window will notify you of any failed attempts at decompiling scripts, it will always give a warning about a partial issue recompiling the script.


Hopefully that helps and will help anybody figuring out how to decompile scripts for the game.

Feel free to use any of the source scripts available in any part of my project to learn from or create new mods with and please give credit appropriately if and where necessary.


KotOR2 Expanded Galaxy

Thor110/Expanded-Galaxy-Main: Expanded Galaxy Main (

KotOR1 in TSL Expanded Galaxy

Thor110/Expanded-Galaxy-Port: Expanded Galaxy Port (

Brotherhood of Shadow : Solomon's Revenge in TSL Expanded Galaxy

Thor110/Expanded-Galaxy-Hood: Expanded Galaxy Hood (


PLEASE do not redistribute the entire project anywhere without my express permission, but feel free to learn from the source material to make as many modifications to the game as you wish.

If you wish to work on the project or contribute by offering or allowing your mod to be included with the project feel free to contact me on here or elsewhere.


In future I might go beyond these basic scripting tutorials and add other types of tutorials such as texturing and modelling that are focused around KotOR2 TSL or working with others towards making a comprehensive KotOR modding guide.

Most material I write will be aimed at KotOR 2 TSL, though alot of the structure of the game is very similar between them both if not almost identical.


For now here are some really basic written tutorials for getting setup with Blender and modding for KotOR or just messing around with the models from the game.

I will continue to work on these providing screenshots and more as necessary.

Blender Tutorial 00 - Getting Blender Setup


Getting Setup

I suggest using Blender 2.92 and the latest version of the kotorblender plugin.

Blender 2.92 ( 3D Modelling Software )

kotorblender ( \addons\kotorblender\plugin-files )

This plugin is used for blender and needs to be placed in C:\Users\your-user-name-here\AppData\Roaming\Blender Foundation\Blender\2.92\scripts\addons

NWN Model Viewer

This can load all the models for quick / easy viewing provided you have the .mdl, .mdx & .tga files associated with the model in the folder.

Folder full of Assets

Getting set up with a folder full of assets takes but a moment and a bit of space.

Use KotOR Tool to extract the following archives. ( models.bif, textures.bif, lightmaps.bif, swpc_tex_gui.erf & swpc_tex_tpa.erf )


Then convert these using the batch tool from MDLEdit ( make sure it is set to the correct mode for whichever game you are converting files for, I have shown extracting K2 files above, but the process is almost identical for K1 )


After having converted them to ASCII and having converted all of the textures from .tpc to .tga you should have no problem getting them loaded up into Blender 2.92 using the kotorblender plugin.

The following is a description of how I converted the textures from .tpc to .tga

I used xoreos tools and the tpc2tga.bat that is available somewhere on the DeadlyStream Forums.

Basically download xoreos tools and get the above mentioned batch file ( tpc2tga.bat ) and or find a similar method to convert all of the .tpc files to .tga files, you can then delete the remaining .tpc files, if you put them back into the game you might require the .txi data which will have to be extracted separately, they exist within the .tpc files, but not the .tga files.

Below is a link to the relevant topic and solution mentioned by DarthParametric

From here it should be as simple as turning on the kotorblender and importing a model.


Provided you put the files in the correct location you will be able to tick the box in the preferences menu.


From here you will be able to import an ASCII model and the associated textures.


I imported 3dgui.mdl


From here it should be fairly straightforward to learn from all the existing in-game models from both games as examples to work from regarding how to structure assets.

Assets are generally listed throughout the various 2DA files associated with the game.

Blender Tutorial 01 - Asset Editing ( INCOMPLETE TUTORIAL )


In general I suggest learning to model in Blender from YouTube tutorial or other online resources, then using what you can to learn from the existing models of the game and make whatever you want using them as an example to work from.


Opening and editing a level, character or asset from within the game.

In order to do this you will need to first use KotOR Tool to extract all of the models and textures to a directory on your computer.

The textures need to be in .tga format, which unfortunately means extracting them one at a time, or using some of the tools around to convert them all at once from .tpc to .tga

You will also need to extract the lightmaps to that same directory if you are planning on working with the levels and the layout or .lyt files if you are planning to load an entire level at once into Blender.

I also use the NWNModelViewer to quickly view the various models throughout the game using a directory full of it's binary file format models.

You will then need to use MDLEdit to convert the model you want to an ASCII file format model. ( Or batch convert to convert lots of models at once )

From here you should easily be able to open any asset from within the game via .mdl or .lyt

Once you have modelled what you wanted and used click + shift drag to place it within the heirarchy of the asset

You will then be able to select the asset and it's entire heirarchy and export it to .mdl

Blender Tutorial 02 - Creating A Placeable


In order to create a placeable I suggest importing a placeable to use as your template to work with.

keeping the "lookathook" and using click + shift and drag to place your model within the correct heirarchy for the model.

modelling the walkmesh area to match and moving the lookathook to where you want the player to be able to click on the placeable object.


I kept the existing walkmesh ( PLC_*_pwk  ) and renamed it to match the placeable I was making.

Moved the lookathook to where I wanted it to be or where I want it to be for now.

And selected then the object I had pasted over from the Ebon Hawk and held shift on the keyboard to add it to the heirarchy of the main object "PLC_baoplace"

from here you will need to click on the placeable and make sure that the entire heirarchy is selected and export it to .mdl format ( ASCII )

then use MDLEdit to convert it back to binary.


and add it to the placeables.2da in order to be able to place it somewhere in a level.


Blender Tutorial 03 - Character Editing


As with all the above tutorials I suggest getting a folder full of all the models ( .mdl, .mdx, .wok, .pwk, .tga, .lyt ) as well as the .mdl.ascii files made by MDLEdit in order to quickly load any model you want into Blender and be able to edit it or alter it as necessary.

From here editing any asset within the game shouldn't be too difficult as well as making new assets provided you are able to make use of existing materials, tutorials, resources and the tools available in order to achieve your goal.

Sorry these tutorials are not very in-depth or detailed, I will work on them more in the future.

For now getting assets loaded into Blender is often peoples first trouble step.

As soon as I find the relevant links I will post about how to use Xoreos tools and the tpc2tga.bat file to convert all the textures for easily loading them up.


When converting a character model make sure to have the relevant supermodel in the same folder as the model being converted.

The supermodel can also be seen if you highlight or click on the header section of the model in MDLEdit at the bottom of the program. As shown for this the Supermodel is NULL meaning there isn't one.


Hopefully this will help anybody get characters or other assets loaded into Blender for whatever they need them for.

Outdated Tutorials & Intro


Download Downloads for my KotOR Modding Tutorial Series are available on the ModDB page.
NOTE : I was writing / organising the tutorials differently when I started the document versions and so they are a little outdated / incomplete in comparison to what is here, but I still have plans to go back and cover some of the topics I planned to in the documents. ( DOWNLOADABLE VERSION IS OUTDATED FOR NOW )

Update Please let me know how you get on with these tutorials, if you have any problems or suggestions for how I could improve anything even grammar / formatting I would really appreciate it, I hope to construct a tutorial series that covers modding of both the Expanded Galaxy Project and both KotOR games from basic modifications to Total Conversion Modifications set in the Old Republic Era of the Star Wars Universe, anything beyond this would require more work on your part, I believe it would be possible to make some interesting stories using the Odyssey engine for Point & Click type games or RPGs in general, but I believe it is better suited towards the Star Wars Universe, more specifically the Old Republic Era due to the abundance of content available in both games, but it could also be re-purposed for other Star Wars Stories from any time.

I will be posting my tutorials on ModDB as well, here is my first link which is a rough tutorial and overview of the future tutorials I have planned, both mods pages on ModDB will also have files to go alongside each mod and help streamline the process of creating levels for both games in the KotOR series and for the Expanded Galaxy Project.

Individually written and quite specific tutorials, mostly scripts and guidance towards achieving specific goals or tasks.

01 - [TUTORIAL] - Creating a Module for TSL using a KotOR Map!

The first tutorial should be a great guide for porting a level from the first game into the second game as well as that it shouldn't be too difficult to work out how to do it the other way around from there on out!


Previous This tutorial has been updated and I have released it as an .odt series on KotOR modding I am starting to write, I am going to be writing a lot more tutorials throughout the process of creating my mods, documenting the entire process and writing a tutorial for each individual element of the game that I learn to modify, change or add to in order to help others create great content for both of the KotOR games and the Expanded Galaxy Project.

Tools Required

Kotor Tool
K-GFF Editor
Bulk Rename Utility ( or Patience )

A copy of K1 & K2 ( Steam, GoG or original 4 CD version )

This tutorial will cover how to port the first module of the Endar Spire from K1 into K2, but the steps are very much the same for any module in the game. ( Open Spoilers to reveal images and instructions )

Layout Files - First open Kotor Tool, make sure your game directories are set, then open up BIF's>layouts.bif & extract "m01aa.lyt".


Extract "m01aa.lyt" to the override directory for your module"


The Lightmaps


Extract "lightmaps.bif" ( not numbered, the first one ) to a folder, delete everything in the folder except m01aa, so click the first m01ab file and scroll to the bottom, then hold shift and click the last file to make this easier.Screenshot_5.png

Model Files


Then extract the entire "models.bif" directory ( this will save you a lot of time ) and delete everything except m01aa ( .mdl, .mdx and .wok files )Screenshot_6.png

Module File Contents


Then open RIM's>Modules> and extract end_m01aa.rim & end_m01aa_s.rim directories.Screenshot_1.pngScreenshot_2.png

MDLEdit - Converting Map Files!


Open MDLEdit, set it to KOTOR1 mode, then batch > convert > to ascii, all of the models for m01aa.

Make sure to set the mode for K1 before converting to ascii and then set the mode back to K2 when converting to binary.

When it is complete, set the program to KOTOR2 mode, then batch > convert > to binary all the ascii files you just converted ( arrange by type to easily select the ascii files )

You will also need to extract the relevant texture pack you wish to use.

Texture Packs, Loading Screen & Minimap.


Extract "swpc_text_tpa" ( these are the high resolution textures )

"tpb" & "tpc" are medium and low resolution versions of the same textures.

if you want to individually single out which .tpc files you need for the module you are welcome to do so.

At some point I will also write a short / easy and quick way to get just the .tga's necessary for an individual module.Screenshot_3.png
Loading Screen


I have just extracted the three texture packs ( lightmaps, gui and tpa ) in their entirety in order to save singling out which files go to which modules because it is easier for the moment and suits the purpose of my project.

Use K-GFF Editor to remove any references to scripts in the .are, .git and .ifo files. Change the Name String Reference to -1, right click and Add String, change this string to "Endar Spire - Above Taris" ( but you do not have to remove the entries for this module to work )


Use K-GFF Editor to remove these references.

Use Kotor Tool, click the ERF button, save the modules as "end_m01aa.mod"(make sure to include the .mod extension) set the dropdown to MOD and select add files, then add the .are, .ifo, .git, .pth and .utd files.


Use the ERF button and build the module.

Make sure to delete the original maps and ascii conversions, as well as to rename all of the files using patience or I suggest Bulk Rename Utility and remove every reference of "-mdledit-mdledit" from the .mdl, .mdx and .wok files. ( you may also want the .dwk & .pwk files )

After creating the module copy it to your Modules folder and copy the rest of the files over to the override folder, you can then use the warp cheat to access the level "warp end_m01aa"

This is just a rough write up of the tutorial I have just converted this module again from scratch at the same time and will do it again taking screenshots and rewriting this short tutorial.~
Download Link
You will need 7zip to extract the contents.

Currently the stars and lasers / anything going on outside does not appear, if you wish to fix this just extract the missing contents from the texture packs.

K1 & K2 You should also be able to use this tutorial to make a module for both KotOR games as well as my Expanded Galaxy Mod, I will also update it so that completely custom areas can be made using parts already in the game allowing for much more diverse level creation.

Note It seems the process is the same for porting TSLmodules to KotOR, but for the moment I am unable to port the outside areas of Telos, Dxun or Dantooine due to foliage being spread across the map due to Vector Calculations being off during the conversion process. ( Noting that you need to be in K2 mode using MDLEdit when converting to ASCII then K1 mode when converting back to binary, exactly the same process I used for KotOR to TSL works in reverse )


These are the current results, very similar to Telos Restoration Zone and Dantooine.



These are some useful links that I have found around that might guide you towards making mods for the game.

Useful Links for learning to mod TSL & KotOR


Links that I have found helpful

My most recent attempts have lead me to this tutorial - Adding Planets To Galaxy Map in TSL
I have also used this tutorial to name the module - Naming a custom module
This tutorial helped me add loading screens to my modules - Custom Loadscreens
Thanks to this next tutorial I was able to add custom music to my module - Adding Custom Music to KOTOR
This tutorial I have not used yet but looks really well made and is for adding custom doors - Door Modelling Tutorial
A long series of video tutorials for modelling a new area - Modelling an new area!
some of the tutorials link to downloads for the actual tutorial itself, luckily some if not most of the mediafire links are still active, you just have to edit out the wayback machine portion of the url after following the link.

I have also come across these tutorials on youtube which others might find handy and I am noting down here for reference / credit to any tutorials that have helped me along my way.
New Area in KotOR Part 1/3 - I haven't used any of these videos yet but they cover information I might need.
Modules Part 1 Overview - The uploader of this video also has lot's of other kotor related modding videos that look and sound useful.
KotOR 1 & 2 Animated Texture Tutorial - This tutorial will definitely be helpful for making modifications to the game.
Using an example set by Effix in the Mod Requests section I have made a little more progress and managed to load the map correctly by including the .mdx, .wok and .lyt files.

More links!

A detailed page about TXI file parameters.
A detailed page about .uti files for items.
A detailed post about .nss source scripts.
A detailed post about .dlg dialogue files.
All pages available on the website from the above four links.

Useful Tutorials & Information From DeadlyStream ( There are quite a few in the Tutorials Section worth reading )


In the following post in this topic are many more tutorials that I am working on to guide people through the process of making mods for KotOR.

Edited by Thor110
  • Like 4
  • Light Side Points 1

Share this post

Link to post
Share on other sites

02 - [TUTORIAL] - Creating a Merchant - TSL



In order to add a merchant, you will need to first add a character to whatever module you want and create a .dlg (Dialog) file which is used by the .utc (Character) you will then need to add any relevant lines of dialog for your character to speak.


Make sure to name the dialog file in the Conversation section of the utc file.


From there you will need to link it to a script using a line of dialog.

The following is an example of the script you will need to use to launch the merchants inventory window.

void main()
  object oStore = GetObjectByTag("merchant_file"); // this is the .utm file listing your merchants inventory
  	oStore = CreateObject(OBJECT_TYPE_STORE, "merchant_file", GetLocation(OBJECT_SELF));
  	DelayCommand(0.5, OpenStore(oStore, GetPCSpeaker()));

this script then needs to be compiled using the KotOR Scripting Tool. ( Make sure to set it to KotOR 2 Mode )

It will open the .utm (Merchant) file which contains a list of the items which are available for purchase.


Another example is to use global variables as conditions to determine what stock your merchant has available.

The next example is a script I am using for the Yavin Orbital Station, it determines which merchant script to load dependant on how many Jedi Masters the Exile has already encountered during their playthrough. ( Between 0 & 4 )

void main()
  if((GetGlobalNumber("000_Jedi_Found") == 0))
    object oStore = GetObjectByTag("thor0");
    if (!GetIsObjectValid(oStore))
    oStore = CreateObject(OBJECT_TYPE_STORE, "thor0", GetLocation(OBJECT_SELF));
    if (GetIsObjectValid(oStore))
    DelayCommand(0.5, OpenStore(oStore, GetPCSpeaker()));
  else if((GetGlobalNumber("000_Jedi_Found") == 1))
    object oStore = GetObjectByTag("thor1");
    if (!GetIsObjectValid(oStore))
    oStore = CreateObject(OBJECT_TYPE_STORE, "thor1", GetLocation(OBJECT_SELF));
    if (GetIsObjectValid(oStore))
    DelayCommand(0.5, OpenStore(oStore, GetPCSpeaker()));
  else if((GetGlobalNumber("000_Jedi_Found") == 2))
    object oStore = GetObjectByTag("thor2");
    if (!GetIsObjectValid(oStore))
    oStore = CreateObject(OBJECT_TYPE_STORE, "thor2", GetLocation(OBJECT_SELF));
    if (GetIsObjectValid(oStore))
    DelayCommand(0.5, OpenStore(oStore, GetPCSpeaker()));
  else if((GetGlobalNumber("000_Jedi_Found") == 3))
    object oStore = GetObjectByTag("thor3");
    if (!GetIsObjectValid(oStore))
    oStore = CreateObject(OBJECT_TYPE_STORE, "thor3", GetLocation(OBJECT_SELF));
    if (GetIsObjectValid(oStore))
    DelayCommand(0.5, OpenStore(oStore, GetPCSpeaker()));
  else if((GetGlobalNumber("000_Jedi_Found") == 4))
    object oStore = GetObjectByTag("thor4");
    if (!GetIsObjectValid(oStore))
    oStore = CreateObject(OBJECT_TYPE_STORE, "thor4", GetLocation(OBJECT_SELF));
    if (GetIsObjectValid(oStore))
    DelayCommand(0.5, OpenStore(oStore, GetPCSpeaker()));

This script is used in the same way as the previous script which has only one merchant file but it will require 5 merchant scripts.


Using the source script from the games files “a_playpazaak” you can also start a game of pazaak using the same process.

The following script will open a door on the map when you interact with a placeable, it could also be used in a dialog if you wish.

void main()
  object oDoor = GetObjectByTag("yav50_airlock");

In this example the placeable “yav_panel50x.utp” which is an invisible placeable loads the above script “yav_panel05” in the OnUsed section which can be found using the KGFF editor on a “.utp” (Placeable) file, the script then opens the door called “yav50_airlock”.

Another useful property to note is the Static property of the doors, which can be used to determine whether or not the door can be selected by the player.

03 - [ADDITIONAL] - Using ERFEdit


ERFEdit is useful for extracting the contents of other module files, this can be handy to look up an example from another level.

In order to make use of the following three examples, you will want to use ERFEdit to extract the contents of the module, you will also need DLGEdit & K-GFF Editor, extract the files and examine them to hopefully save others time from searching through the Characters, Placeables and Alien Voice Overs.

You can also just spawn in each module and look around, each character or placeable will have their number references as their name.

Characters 0-700 approx

Placeables 0-400 approx

Dialog 0-42

With all of these testing rooms I have still had the main three mods I am planning to provide compatibility for ( TSLRCM, M478EP & Jedi Temple ( Coruscant ) Mods ) installed to the game, so if you do not some of their appearances may be missing.

04 - [ADDITIONAL] - Picking an NPC to place in your level - TSL


I was dreading finding a specific NPC to place around any of the levels I am working on so I drafted up these test levels with every NPC from TSL in them.

Using these modules you should have no trouble picking an NPC and identifying what number entry they are in the appearance.2da file.

Testing Rooms.7z









I hope this will be useful for others, I haven't made full use of it yet, but I can now roam around and pick out which NPC's I would like to place and not have to worry about finding their entry number, as well as having the ability to view nearly all of them at once.

05 - [ADDITIONAL] - Picking Placeables to fill your level with - TSL


I decided to do the same thing for placeables, so that I could not only look through them all at once but hopefully find it easier to populate the levels I am working on with placeables and NPC's.

Testing Placeable Rooms.7z









06 - [ADDITIONAL] - Picking Alien Voice Over Dialog for your level - TSL


In the same style as the placeables and characters, but contains one character per alien in the "alienvo.2da" file and a dialog entry for each type of voice over they can use, excluding null entries.

Alien VO Dialog Testing Room.7z

The Rakata & I think a few others don't have voice files even though the 2da file states that they do, I will go through these at some point.






07 - [ADDITIONAL] - Placement & Rotation


The bearing of a placeable is it's rotation, characters have an X orientation and a Y orientation which also pertains to their rotation.

The below co-ordinates are what I am using for making a placeable rotate to face any of the cardinal directions.

I have seen that sometimes people over rotate from these numbers until they get to the right position, for example to face East can also be 4.5 approximately, but I have found the below values to be the best, if someone knows better please let me know.

I generally use KotOR Toolset to locate an item in an existing module and record its co-ordinates then I edit its co-ordinates using K-GFF Editor, from there I tend to test the level over and over again until I get the placement just right.





I realise they are using Radians or Pi, so this can be positive or negative accordingly, Pi itself is *3.14159265359 ( so that might be a more accurate value to use ) though I haven't used that just yet, but it will be such a minute change in rotation that it would be practically impossible to notice anyway.

But I have noticed some things in the game over rotate to get to the correct position, so I thought this might be worth noting for other users, I used other objects in game to determine North & South and went from there.


I also found the below example which is probably a lot more detailed, quoted from Lucas Forums by e-varmint


The "bearing" measurements for doors
and placeables in the .git file use radians instead of degrees. 

Degrees Radians
15= 0.261799388
30= 0.523598776
45= 0.785398163
60= 1.047197551
75= 1.308996939
90= 1.570796327
105= 1.832595715
120= 2.094395102
135= 2.35619449
150= 2.617993878
165= 2.879793266
180= 3.141592654
195= 3.403392041
210= 3.665191429
225= 3.926990817
240= 4.188790205
255= 4.450589593
270= 4.71238898
285= 4.974188368
300= 5.235987756
315= 5.497787144
330= 5.759586532
345= 6.021385919

by e-varmint


08 - [TUTORIAL] - Waypoint Markers


Below is the documentation left within the blueprint waypoint files within the game, when I have actually placed some myself and am more familiar with the process I will try to write a step by step for it as well.

"This is the default waypoint you may place to set a patrol path for a creature or NPC.
1. Create the creature and either use its current Tag or fill in a new one.
2. Place or make sure the WalkWayPoints() is within the body of the On Spawn script for the creature.
3. Place a series of waypoints along the route you wish the creature to walk.
4. Select all of the newly created waypoints and right click. Choose the Create Set option. ( The set will be defined by their numbers )
5. The waypoint set will have a set name of "WP_" + NPC Tag. Thus if an NPC with the Tag "Guard" will have a waypoint set called "WP_Guard". Note that Tags are case sensitive."

Bullet Point #1 Create your creature. ( .utc file which will be spawned using the .git file for the module )
Bullet Point #2 refers to what will be needed in the script. ( Example Scripts Below )
Bullet Point #3 Place your waypoints. ( placing the .utw files along a specified path using the .git file of the module )
Bullet Point #4 will be referring to the software they would have been using during development.
Bullet Point #5 refers to naming the waypoint files. ( "WP_Guard_01.utc" etc )

I have three script examples so far for NPC's walking, but I haven't used any of them yet so cannot confirm they work until I start populating the areas I am working with.

Continue Walking Waypoints - "walk_continue.nss"


#include "k_inc_generic"
#include "k_inc_debug"
#include "k_inc_treas_k2"

void main() {
    // Force them to continue walking waypoints. onEndDialog

Walk Around Randomly - "walk_random.nss"


void main() {
  // onHeartbeat

Walk Waypoints On Spawn - "walk_spawn.nss"


#include "k_inc_generic"
#include "k_inc_debug"
#include "k_inc_treas_k2"

void main()


09 - [TUTORIAL] - Scripting Basics


I will not cover much scripting, but when I am finished with the project all the source will be made available.

You will need KotOR Scripting Tool & possibly DeNCS if you plan to use it ( it can be helpful to get examples from other scripts already in the game to see how they handle certain events and to get an idea of the common operators, functions and the syntax )

The script is saved as a .nss file and then compiled into a .ncs file, I use KotOR Scripting Tool but I think KotOR Tools Text Editor can also compile scripts.

Remotely Opening A Door


void main()
    object oDoor = GetObjectByTag("yav50_airlock");

The above script is called by an invisible placeable in front of the computer screens on the Yavin Orbital Station and the script itself is referenced in the OnUsed section of the associated .utp file, it is also getting the relevant door by its tag which is declared in the relevant doors .utd file.

That's a very basic script, you can also scroll through the KotOR Scripting Tool to see all the available commands on the right hand side, I will be posting basic scripts in this section and hopefully they might be useful for others.

Upon typing the command there is also a description shown in the bottom window of the program.

If you have trouble compiling a script, make sure that "nwscript.nss" is located in the games override folder, also check that the tool is set to KotOR 1 or KotOR 2 accordingly, another possible problem is your relevant registry entry which can either be added back in manually, or just run the "swupdate.exe" and it will update the registry entry ( I had this problem as I was using two seperate installs of KotOR 2 for testing )

10 - [EXAMPLE SCRIPT] - Spawning NPC's on Enter


Below is an example of an on Enter script spawning four NPC's via their utc file packaged with the .module but not placed in the levels git file.

In order to do this you will also need to add a waypoint to the git file to point to where to spawn your NPC.

This code can be used to spawn NPC's dependant on a Global Variable, it is also checking if the leader of the group already exists ( I should check if they all exist, but this works for the moment )


void main() {
  if(GetGlobalNumber("SLE_FIREBLOODS") == 1)
    if (!GetIsObjectValid(GetObjectByTag("rodian2", 0))) {
      CreateObject(1, "rodian2", GetLocation(GetObjectByTag("wp_rodian2", 0)), 0);
      CreateObject(1, "rodian1", GetLocation(GetObjectByTag("wp_rodian1", 0)), 0);
      CreateObject(1, "rodian3", GetLocation(GetObjectByTag("wp_rodian3", 0)), 0);
      CreateObject(1, "rodian4", GetLocation(GetObjectByTag("wp_rodian4", 0)), 0);

Hopefully this short example helps.

11 - [EXAMPLE SCRIPT] - Making NPC's Hostile!


The below code changes the above spawned NPC's to being hostile and changes the Global Number for the Variable storing the state of that questline / encounter.


void main() {
  object oRodian2 = GetObjectByTag("rodian2", 0);
  object oRodian1 = GetObjectByTag("rodian1", 0);
  object oRodian3 = GetObjectByTag("rodian3", 0);
  object oRodian4 = GetObjectByTag("rodian4", 0);
  ChangeToStandardFaction(oRodian2, 1);
  AssignCommand(oRodian2, ActionAttack(GetFirstPC(), 0));
  ChangeToStandardFaction(oRodian1, 1);
  AssignCommand(oRodian1, ActionAttack(GetFirstPC(), 0));
  ChangeToStandardFaction(oRodian3, 1);
  AssignCommand(oRodian3, ActionAttack(GetFirstPC(), 0));
  ChangeToStandardFaction(oRodian4, 1);
  AssignCommand(oRodian4, ActionAttack(GetFirstPC(), 0));
  SetGlobalNumber("SLE_FIREBLOODS", 2);


12 - [EXAMPLE SCRIPT] - Trigger talking to an NPC!


The below code requires a trigger to be placed in the level, on entering the trigger this script will fire.

It starts a conversation with the lead Rodian from the above examples.


void main() {
  if(GetGlobalNumber("SLE_FIREBLOODS") == 1)
    object oEntering = GetEnteringObject();
    if ((!GetIsPartyLeader(oEntering))) {
    object oRodian2 = GetObjectByTag("rodian2", 0);
    AssignCommand(oRodian2, ActionStartConversation(oEntering, "fireblood", 0, 0, 0, "", "", "", "", "", "", 0, 0xFFFFFFFF, 0xFFFFFFFF, 0));
    DestroyObject(OBJECT_SELF, 0.0, 0, 0.0, 0);


13 - [EXAMPLE SCRIPT] - Make an NPC walk randomly


This script is assigned to the heartbeat function of the utc file for the NPC.


void main() {
  // onHeartbeat


14 - [EXAMPLE SCRIPT] - Place a dead NPC


This script needs to be set in the spawn function for the NPC in the relevant .utc file.


void main() {
    effect efDeath = EffectDeath(0, 0, 1);
    ApplyEffectToObject(2, efDeath, OBJECT_SELF, 0.0);


15 - [EXAMPLE SCRIPT] - Starting Conditional


This script is an example of a starting conditional that can be used to check what module the player is in, this could be used for companion dialogs to check you are in a specific area in order to engage in a certain dialog option.


int StartingConditional()
    if ( ( GetModuleName() == "end_m01aa") ||
         ( GetModuleName() == "end_m01ab") ||
         ( GetModuleName() == "tar_m11ab")) {
    return TRUE;
  return FALSE;

The example I have provided checks if it is any of the three named modules, if so it returns TRUE to the DLG, if not it returns FALSE.

It can be modified to check as many modules as required, I included three as an example to either cut down or expand upon.

16 - [TUTORIAL] - Companion Vendor


I recently came up with an idea for a "Droid Companion Vendor" which will sell droids to the player to replace any lost or missed companions throughout the game.


Also given that it demonstrates control of the party / companions, I thought I would work this into a tutorial.

When I have completed the level / vendor itself, I will come back here to write a tutorial, provide the files and give examples on how this could be used to create a Total Conversion


There are a total of 50-55 Droid Types, the plan is to have either all or a select set of the best droids as options.


Maybe even spawning the droid next to the Vendor so that you can see them before buying them, or housing them in a store house with the droids you can purchase on display in the area.


From here you will be able to purchase a new companion for any slot in the game.


for anybody interested here is the code for the conditional script I wrote to check if a specific players companion slot is free.


#include "k_inc_debug"

int StartingConditional()
    int nComp = GetScriptParameter( 1 );
    if ((IsAvailableCreature(nComp)) == FALSE)
        return TRUE;
    return FALSE;

Here is a slightly different version that checks all companion slots at once.


#include "k_inc_debug"

int StartingConditional()
    if ((GetNPCSelectability(9)) == -1)
        return TRUE;
    else if ((GetNPCSelectability(8)) == -1)
        return TRUE;
    else if ((GetNPCSelectability(7)) == -1)
        return TRUE;
    else if ((GetNPCSelectability(6)) == -1)
        return TRUE;
    else if ((GetNPCSelectability(5)) == -1)
        return TRUE;
    else if ((GetNPCSelectability(4)) == -1)
        return TRUE;
    else if ((GetNPCSelectability(3)) == -1)
        return TRUE;
    else if ((GetNPCSelectability(2)) == -1)
        return TRUE;
    else if ((GetNPCSelectability(1)) == -1)
        return TRUE;
    else if ((GetNPCSelectability(0)) == -1)
        return TRUE;
    return FALSE;

here is the code I use to preview the droid, spawning them at the location of the vendor.


void main() {
  string nDroid = GetScriptStringParameter();
  CreateObject(1, nDroid, GetLocation(GetObjectByTag("blackmarket", 0)), 0);

this code is then used to destroy them, if you don't purchase them.


void main() {
  string nDroid = GetScriptStringParameter();
  DelayCommand(0.1, DestroyObject(GetObjectByTag(nDroid), 0.0, 1, 0.0));

and here is the code I used to make them join the party.


void main() {
  string nDroid = GetScriptStringParameter();
  if ((IsAvailableCreature(9)) == FALSE) {
    AddAvailableNPCByTemplate(9, nDroid);
        ShowPartySelectionGUI("k_pend_reset", 9, 0xFFFFFFFF);
    else if ((IsAvailableCreature(8)) == FALSE) {
    AddAvailableNPCByTemplate(8, nDroid);
        DelayCommand(0.1, ShowPartySelectionGUI("k_pend_reset", 8, 0xFFFFFFFF));
    else if ((IsAvailableCreature(7)) == FALSE) {
    AddAvailableNPCByTemplate(7, nDroid);
        DelayCommand(0.1, ShowPartySelectionGUI("k_pend_reset", 7, 0xFFFFFFFF));
    else if ((IsAvailableCreature(6)) == FALSE) {
        AddAvailableNPCByTemplate(6, nDroid);
        DelayCommand(0.1, ShowPartySelectionGUI("k_pend_reset", 6, 0xFFFFFFFF));
    else if ((IsAvailableCreature(5)) == FALSE) {
        AddAvailableNPCByTemplate(5, nDroid);
        DelayCommand(0.1, ShowPartySelectionGUI("k_pend_reset", 5, 0xFFFFFFFF));
    else if ((IsAvailableCreature(4)) == FALSE) {
        AddAvailableNPCByTemplate(4, nDroid);
        DelayCommand(0.1, ShowPartySelectionGUI("k_pend_reset", 4, 0xFFFFFFFF));
    else if ((IsAvailableCreature(3)) == FALSE) {
        AddAvailableNPCByTemplate(3, nDroid);
        DelayCommand(0.1, ShowPartySelectionGUI("k_pend_reset", 3, 0xFFFFFFFF));
    else if ((IsAvailableCreature(2)) == FALSE) {
        AddAvailableNPCByTemplate(2, nDroid);
        DelayCommand(0.1, ShowPartySelectionGUI("k_pend_reset", 2, 0xFFFFFFFF));
    else if ((IsAvailableCreature(1)) == FALSE) {
        AddAvailableNPCByTemplate(1, nDroid);
        DelayCommand(0.1, ShowPartySelectionGUI("k_pend_reset", 1, 0xFFFFFFFF));
    else if ((IsAvailableCreature(0)) == FALSE) {
        AddAvailableNPCByTemplate(0, nDroid);
        DelayCommand(0.1, ShowPartySelectionGUI("k_pend_reset", 0, 0xFFFFFFFF));

This checks if the companion is available, it then adds the NPC to the party and shows the selection screen making sure that the correct slot is selected.

For now this is a very roughly written idea for a tutorial, but I have created the level and when it is finished I will upload it here as a tutorial for people to make use of.

I plan to continue to expand upon this idea and fill the level with scripts and examples provided here for people to pull apart and make use of.

Fow now there is a bug that means if you buy the same droid twice, they remain there because it tries to destroy the NPC in your Party, instead of the one being previewed, this is a side-effect of the fact I wanted to try and have all 55 available droids in the game as options, but it seems without using a global variable the best way to do this will be to individually select each droid for the list. ( there might still be a better way, I have yet to try again )


Feel free to learn from this example, the idea itself I plan to use and release as either a stand-alone mod or as a part of the Expanded Galaxy Project.

17 - [TUTORIAL] - Upgradeable Items


Below is a list of the UpgradeLevel numbers that can be used in .uti files that I found posted by another user on DeadlyStream, I thought I would link through to it and repost it here.

In order to make an item upgradeable the below entry needs editing in the associated .uti file to be in line with the numbers below by item type.


Robes (Knight & Master)        1
Armored Robes (Zal Shey)    2
Light Armors            2
Medium Armors            3
Heavy Armors            4

Regular  (Non-Powered)        1
Vibro Weapons (Powered)        2
Lightsabers  (All Types)    3

Blasters (Scope Only)        1
Blasters (Scope,Chamber)    2
Blasters (All Upgrades)        3


Below is a link to the source from which I found this information.

Source :

18 - [ADDITIONAL] - Door Gallery


A recent request by another modder to make a similar room to my other testing rooms that displayed the available doors in the game.


Doors are all numbered appropriately according to their 2da entry in genericdoors.2da to make them easier to find. They also autoclose after being opened if you are far enough away ( same script as jekk jekk tarr tunnels )

Door Gallery.7z

19 - [ADDITIONAL] - Main Menu Details


In-case anybody ever want's to modify the main menu for a Total Conversion or general mod, you can use the following details to help you do so and the following line of code in a script to change the relevant variable.


Keep in mind for total conversions and big mods that this variable exists by default in globalcat.2da as do some other variables that you might need to keep.

The most recently loaded save determines which menu is shown on the main menu while in-game and I think it might be the auto-save when starting the game up, the number variable "GBL_MAIN_SITH_LORD" sets which is shown.

1 = mainmenu01.mdl = Darth Sion
2 = mainmenu03.mdl = Darth Nihilus
3 = mainmenu04.mdl = Kreia
4 = mainmenu05.mdl = Player

The player can also be changed to other appearances in the main menu using disguises or when the player character is set to something else such as when playing as Bao-Dur's Remote on Malachor V.

At some point in future I might work on a script that can change the players appearance based on another variable using either disguises or changing the active character under a fade-in / fade-out so that the number of main menus can be almost infinitely expanded or at least to the limit of number values.

This could then be spoofed so that any appearance could be shown on the menu, for example it could show the last NPC you spoke to.

However I am not sure how efficient this would be under a save/load fade-in/fade-out cover. But it's an interesting thought or idea none-the-less.

99 - [REQUESTS] - Submit a tutorial idea!


If you have ideas for a tutorial feel free to message me and let me know.

For a while now I have been considering creating a playground of sorts across a few maps and filling it with a combination of all possible interactions in the game, from animations, to dialog and the various alien responses so that people could play through them, seeing everything in action and use it to better pick out the pieces of code, voiceover, items, placeables, doors or characters that they might need to use in their modification of the game.


For now I have set up the Shuttle as an example Starship with access to the galaxy map, but there is a lot more work to be done before I release whatever this is.

Very much like the testing rooms I have created that feature all the doors and characters in the game.

I will continue to provide examples that I think might be useful to people, these are all for TSL so far.

I hope these tutorials and any others I write will help people continue to make mods for KotOR 1 & 2.

These tutorials are getting shorter and less detailed, I may or may not go back and re-write them at some point but if anyone struggles with anything feel free to message me and let me know what I haven't covered very well.


Feel free to join the Discord for my project if you need help with anything related to KotOR modding and I will do my best to assist.


Base Game Scripts & How To Use Them


I am considering working on an index for the base game scripts and how they all function so that people can more easily use them in dialog files without having to constantly look up how they work, what parameters need to be passed along to the script and other such details.

For now here is one such example that I discussed with another user recently.

a_hitman.nss/.ncs - is used to turn an NPC hostile, if they are already hostile it will turn them insane.


//:: FileName a_hostile
//:: Created By: Kevin Saunders
//:: Created On: 07/20/04
//:: Object with Tag = ScriptStringParameter becomes hostile.
//  Modified: Tony Evans 9/9/04  (Added nInst parameter)
//  Modified: Tony Evans 9/15/04 (Added OBJECT_SELF default and nSane param)

void main()

    string sCritter = GetScriptStringParameter();
    int nInst = GetScriptParameter(1);
    int nSane = GetScriptParameter(2);

    object oTarg;

    if (sCritter == "") oTarg = OBJECT_SELF;
    else oTarg = GetObjectByTag(sCritter, nInst);

    if (!nSane) ChangeToStandardFaction(oTarg,STANDARD_FACTION_HOSTILE_1);
    else ChangeToStandardFaction(oTarg,STANDARD_FACTION_INSANE);


The above image shows how you would use this in a dialog file, example is from the Entertainment Promenade on Nar Shaddaa.

KotOR Modding - Crash Course

This 2 hour stream covers the basics of KotOR modding and some of the programs involved, I also regularly stream development of my mod project on Twitch/YouTube.

Not all of this covers KotOR modding, there is about 10-20 minutes during the first hour where I get distracted and the second hour of it is mostly me playing games.


By the basics, I mean the very basics. An overview of the programs and filetypes associated with KotOR as well as the structure of level files.

These are the testing rooms but for K1 the room is lacking a texture but I find this just makes it easier to look through the characters.

If anything in any of my short tutorials isn't clear or you don't understand for some reason then let me know and I will do what I can to help.



Comparing Level Contents

Let's say you have two levels and you need to compare the differences of the contents.

Extract everything from the original level to a folder called "level-a" and the modified folder to "level-b"

Run the following batch script inside the "level-a" folder.


Then delete or move the .bat file and move "file-list.txt" that it just created outside of the folder.


You can also use this script to check that all the files exist.


You will have to move the file-list.txt and this script inside the folder to run the script.


Now run this script at the same location as "file-list.txt" to run a file check against the contents of both folders.


Hopefully this might help someone, where I recently had to transfer all of my changes from manual installs to a TSLPatcher changes.ini file, I found this process helped speed the process up a little bit.


From here, you should know which files differ and you can then use ChangeEdit.exe that comes with TSLPatcher in order to generate the differences between GFF files.


Compiling Scripts

If you have made it this far into the tutorial, you should already be familiar with compiling scripts, however for large projects you might need to recompile a lot of scripts at once, so here is a batch script that I used to do it.


Simply edit the script so that it points to the location of nwnnsscomp.exe for you and then you will be able to put the script into any folder that you need to compile a lot of scripts in and use it to do it all at once.


If the scripts don't work for you, you might need to edit them and read them a bit in order to understand them and then to make sure that you have all of the right files in the right places.



Edited by Thor110
Compiling Scripts
  • Like 7
  • Thanks 1

Share this post

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.