diff --git a/NifImport/AppSettings.cpp b/NifImport/AppSettings.cpp
index e21bb7460befd237af6b5408c4a1012eb09c8a38..6beb806947c59460a0c04e8d3a5fef912c993744 100644
--- a/NifImport/AppSettings.cpp
+++ b/NifImport/AppSettings.cpp
@@ -20,10 +20,10 @@ void AppSettings::Initialize(Interface *gi)
       string Applications = GetIniValue<string>("System", "KnownApplications", "", iniName);
       stringlist apps = TokenizeString(Applications.c_str(), ";");
       for (stringlist::iterator appstr=apps.begin(); appstr != apps.end(); ++appstr){
-         AppSettingsMap::iterator itr = TheAppSettings.find(*appstr);
-         if (itr == TheAppSettings.end()){
-            itr = TheAppSettings.insert(TheAppSettings.end(), AppSettingsMap::value_type(*appstr, AppSettings(*appstr)) );
-            (*itr).second.ReadSettings(iniName);
+         AppSettings* setting = FindAppSetting(*appstr);
+         if (NULL == setting){
+            AppSettingsMap::iterator itr = TheAppSettings.insert(TheAppSettings.end(), AppSettings(*appstr));
+            (*itr).ReadSettings(iniName);
          }
       }
    }
@@ -48,17 +48,14 @@ void AppSettings::ReadSettings(string iniFile)
    std::swap(Environment, settings);
 
    rootPath = GetSetting<string>("RootPath");
-
-   string searchPathString = GetSetting<string>("TextureSearchPaths");
-   searchPaths = TokenizeString(searchPathString.c_str(), ";");
-
-   string extensionString = GetSetting<string>("TextureExtensions");
-   extensions = TokenizeString(extensionString.c_str(), ";");
-
-   string texRootPathString = GetSetting<string>("TextureRootPaths");
-   rootPaths = TokenizeString(texRootPathString.c_str(), ";");
+   rootPaths = TokenizeString(GetSetting<string>("RootPaths").c_str(), ";");
+   searchPaths = TokenizeString(GetSetting<string>("TextureSearchPaths").c_str(), ";");
+   extensions = TokenizeString(GetSetting<string>("TextureExtensions").c_str(), ";");
+   textureRootPaths = TokenizeString(GetSetting<string>("TextureRootPaths").c_str(), ";");
 
    Skeleton = GetSetting<string>("Skeleton");
+   useSkeleton = GetSetting<bool>("UseSkeleton", useSkeleton);
+   goToSkeletonBindPosition = GetSetting<bool>("GoToSkeletonBindPosition", goToSkeletonBindPosition);
 }
 
 string AppSettings::FindImage(const string& fname){
@@ -71,7 +68,7 @@ string AppSettings::FindImage(const string& fname){
    }
 
    // Test if its relative and in one of the specified root paths
-   for (stringlist::iterator itr = rootPaths.begin(), end = rootPaths.end(); itr != end; ++itr ){
+   for (stringlist::iterator itr = textureRootPaths.begin(), end = textureRootPaths.end(); itr != end; ++itr ){
       PathCombine(buffer, itr->c_str(), fname.c_str());
       if (-1 != _taccess(buffer, 0)){
          return string(buffer);
@@ -100,3 +97,24 @@ string AppSettings::FindImage(const string& fname){
    return fname;
 }
 
+
+// Check whether the given file is a child of the root paths
+bool AppSettings::IsFileInRootPaths(const std::string& fname)
+{
+   TCHAR root[MAX_PATH];
+   TCHAR file[MAX_PATH];
+   GetFullPathName(fname.c_str(), _countof(file), file, NULL);
+   PathMakePretty(file);
+
+   for (stringlist::iterator itr = rootPaths.begin(), end = rootPaths.end(); itr != end; ++itr ){
+      GetFullPathName((*itr).c_str(), _countof(root), root, NULL);
+      PathAddBackslash(root);
+      PathMakePretty(root);
+      if (-1 != _taccess(root,0)) {
+         int len = _tcslen(root);
+         if (0 == _tcsncmp(root, file, len))
+            return true;
+      }
+   }
+   return false;
+}
diff --git a/NifImport/AppSettings.h b/NifImport/AppSettings.h
index ebfb17da52cd87bfae8002d30d15ebcbe92519dc..588cf97698b0f385766c20d97193533629110199 100644
--- a/NifImport/AppSettings.h
+++ b/NifImport/AppSettings.h
@@ -19,15 +19,23 @@ HISTORY:
 class AppSettings
 {
 public:
-   AppSettings(const std::string& name) : Name(name), parsedImages(false) {}
+   AppSettings(const std::string& name) 
+      : Name(name)
+      , parsedImages(false) 
+      , useSkeleton(false)
+      , goToSkeletonBindPosition(true)
+   {}
 
    std::string Name;
    std::string rootPath;
    bool parsedImages;
    stringlist searchPaths;
+   stringlist textureRootPaths;
    stringlist rootPaths;
    stringlist extensions;
    std::string Skeleton;
+   bool useSkeleton;
+   bool goToSkeletonBindPosition;
    NameValueCollection Environment;
    NameValueCollection imgTable;
 
@@ -35,6 +43,9 @@ public:
    void ReadSettings(std::string iniFile);
    std::string FindImage(const std::string& fname);
 
+   // Check whether the given file is a child of the root paths
+   bool IsFileInRootPaths(const std::string& fname);
+
    template<typename T>
    inline T GetSetting(std::string setting){
       T v;
@@ -73,10 +84,32 @@ public:
    }
 };
 
-typedef std::map<std::string, AppSettings, ltstr> AppSettingsMap;
+typedef std::list<AppSettings> AppSettingsMap;
+
+struct AppSettingsNameEquivalence : public ltstr
+{
+   bool operator()(const AppSettings& n1, const AppSettings& n2) const { 
+      return ltstr::operator()(n1.Name, n2.Name);
+   }
+   bool operator()(const string& n1, const AppSettings& n2) const { 
+      return ltstr::operator()(n1, n2.Name);
+   }
+   bool operator()(const AppSettings& n1, const string& n2) const { 
+      return ltstr::operator()(n1.Name, n2);
+   }
+};
 
 // The Global Map
 //  Global so that I dont have to parse the texture directories on every import
 extern AppSettingsMap TheAppSettings;
 
+inline AppSettings* FindAppSetting(const std::string& name){
+   AppSettingsNameEquivalence equiv;
+   for (AppSettingsMap::iterator itr=TheAppSettings.begin(), end = TheAppSettings.end(); itr != end; ++itr){
+      if (!equiv(*itr, name) && !equiv(name, *itr))
+         return &(*itr);
+   }
+   return NULL;
+}
+
 #endif //_APPSETTINGS_H_
\ No newline at end of file
diff --git a/NifImport/MaxNifImport.cpp b/NifImport/MaxNifImport.cpp
index 503f24a1a5bb6c7b31e893991ea53f8cef753268..1bbe69a94bea89fe2193dfb391348d44b4c5df07 100644
--- a/NifImport/MaxNifImport.cpp
+++ b/NifImport/MaxNifImport.cpp
@@ -94,6 +94,7 @@ public:
    float autoSmoothAngle;
    bool flipUVTextures;
    bool enableSkinSupport;
+   bool goToSkeletonBindPosition;
 
    // Biped/Bones related settings
    string skeleton;
@@ -108,6 +109,8 @@ public:
    bool isBiped;
    bool removeUnusedImportedBones;
    bool forceRotation;
+   bool browseForSkeleton;
+   string defaultSkeletonName;
 
    float minBoneWidth;
    float maxBoneWidth;
@@ -124,12 +127,33 @@ public:
       if (p) *p = 0;
       path = buffer;
 
-      blocks = ReadNifList( name );
-      nodes = DynamicCast<NiNode>(blocks);
+      // Load ini settings
       iniFileValid = false;
+      LoadIniSettings();
 
-      if (isValid()) {
-         LoadIniSettings();
+      // load file
+      blocks = ReadNifList( name );
+      nodes = DynamicCast<NiNode>(blocks);
+      if (goToSkeletonBindPosition)
+         GoToSkeletonBindPosition(nodes);
+
+      // Apply post processing checks after reading blocks
+      if (isValid()){
+         hasSkeleton = HasSkeleton();
+         isBiped = IsBiped();
+         skeleton = (appSettings != NULL) ? appSettings->Skeleton : "";
+         importSkeleton &= hasSkeleton;
+
+         // Guess that the skeleton is the same one in the current directory
+         if (importSkeleton && !defaultSkeletonName.empty()) {
+            TCHAR buffer[MAX_PATH];
+            GetFullPathName(name.c_str(), _countof(buffer), buffer, NULL);
+            PathRemoveFileSpec(buffer);
+            PathAddBackslash(buffer);
+            PathAppend(buffer, defaultSkeletonName.c_str());
+            if (-1 != _taccess(buffer, 0))
+               skeleton = buffer;
+         }
       }
    }
    bool isValid() const { return (0 != blocks.size()); }
@@ -398,17 +422,49 @@ int MaxNifImport::DoImport(const TCHAR *filename,ImpInterface *i, Interface *gi,
       else
       {
          vector<string> importedBones;
-         if (importer.importSkeleton && !importer.skeleton.empty())
+         if (importer.importSkeleton)
          {
-            NifImporter skelImport(importer.skeleton.c_str(), i, gi, suppressPrompts);
-            if (skelImport.isValid())
+            if (importer.browseForSkeleton)
             {
-               if (skelImport.useBiped){
-                  skelImport.ImportBipeds(skelImport.nodes);
-               } else {
-                  skelImport.ImportBones(DynamicCast<NiNode>(skelImport.nodes[0]->GetChildren()));
-                  if (importer.removeUnusedImportedBones){
-                     importedBones = GetNamesOfNodes(skelImport.nodes);
+               TCHAR filter[64], *pfilter=filter;
+               pfilter = _tcscpy(filter, this->ShortDesc());
+               pfilter = _tcscat(pfilter, " (*.NIF)");
+               pfilter += strlen(pfilter);
+               *pfilter++ = '\0';
+               _tcscpy(pfilter, "*.NIF");
+               pfilter += strlen(pfilter);
+               *pfilter++ = '\0';
+               *pfilter++ = '\0';
+
+               TCHAR filename[MAX_PATH];
+               GetFullPathName(importer.skeleton.c_str(), _countof(filename), filename, NULL);
+
+               OPENFILENAME ofn;
+               memset(&ofn, 0, sizeof(ofn));
+               ofn.lStructSize = sizeof(ofn);
+               ofn.hwndOwner = gi->GetMAXHWnd();
+               ofn.lpstrFilter = filter;
+               ofn.lpstrFile = filename;
+               ofn.nMaxFile = _countof(filename);
+               ofn.lpstrTitle = TEXT("Browse for Skeleton NIF...");
+               ofn.lpstrDefExt = TEXT("NIF");
+               ofn.Flags = OFN_HIDEREADONLY|OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_NOCHANGEDIR|OFN_PATHMUSTEXIST;
+               importer.importSkeleton = GetOpenFileName(&ofn) ? true : false;
+               if (importer.importSkeleton) {
+                  importer.skeleton = filename;
+               }
+            }
+            if (importer.importSkeleton && !importer.skeleton.empty()) {
+               NifImporter skelImport(importer.skeleton.c_str(), i, gi, suppressPrompts);
+               if (skelImport.isValid())
+               {
+                  if (skelImport.useBiped){
+                     skelImport.ImportBipeds(skelImport.nodes);
+                  } else {
+                     skelImport.ImportBones(DynamicCast<NiNode>(skelImport.nodes[0]->GetChildren()));
+                     if (importer.removeUnusedImportedBones){
+                        importedBones = GetNamesOfNodes(skelImport.nodes);
+                     }
                   }
                }
             }
@@ -417,7 +473,8 @@ int MaxNifImport::DoImport(const TCHAR *filename,ImpInterface *i, Interface *gi,
 
             importer.ImportBones(DynamicCast<NiNode>(importer.nodes[0]->GetChildren()));
             ok = importer.ImportMeshes(importer.nodes[0]);
-            if (importer.removeUnusedImportedBones){
+
+            if (importer.importSkeleton && importer.removeUnusedImportedBones){
                vector<string> importedNodes = GetNamesOfNodes(importer.nodes);
                sort(importedBones.begin(), importedBones.end());
                sort(importedNodes.begin(), importedNodes.end());
@@ -460,9 +517,20 @@ void NifImporter::LoadIniSettings()
    this->iniFileName = iniName;
    iniFileValid = (-1 != _access(iniName, 0));
 
-   string curapp = GetIniValue<string>(NifImportSection, "CurrentApp", "");
-   AppSettingsMap::iterator itr = TheAppSettings.find(curapp);
-   appSettings = (itr != TheAppSettings.end()) ? &(*itr).second : NULL;
+   // Locate which application to use. If Auto, find first app where this file appears in the root path list
+   appSettings = NULL;
+   string curapp = GetIniValue<string>(NifImportSection, "CurrentApp", "AUTO");
+   if (0 == _tcsicmp(curapp.c_str(), "AUTO")) {
+      // Scan Root paths
+      for (AppSettingsMap::iterator itr = TheAppSettings.begin(), end = TheAppSettings.end(); itr != end; ++itr){
+         if ((*itr).IsFileInRootPaths(this->name)) {
+            appSettings = &(*itr);
+            break;
+         }
+      }
+   } else {
+      appSettings = FindAppSetting(curapp);
+   }
 
    useBiped = GetIniValue<bool>(NifImportSection, "UseBiped", false);
    skeletonCheck = GetIniValue<string>(NifImportSection, "SkeletonCheck", "Bip*");
@@ -475,21 +543,20 @@ void NifImporter::LoadIniSettings()
    flipUVTextures = GetIniValue<bool>(NifImportSection, "FlipUVTextures", true);
    enableSkinSupport = GetIniValue<bool>(NifImportSection, "EnableSkinSupport", true);
 
-   skeleton = (appSettings != NULL) ? appSettings->Skeleton : "";
-
    bipedHeight = GetIniValue<float>(BipedImportSection, "BipedHeight", 131.90f);
    bipedAngle = GetIniValue<float>(BipedImportSection, "BipedAngle", 90.0f);
    bipedAnkleAttach = GetIniValue<float>(BipedImportSection, "BipedAnkleAttach", 0.2f);
    bipedTrianglePelvis = GetIniValue<bool>(BipedImportSection, "BipedTrianglePelvis", false);
    removeUnusedImportedBones = GetIniValue<bool>(BipedImportSection, "RemoveUnusedImportedBones", false);
-   forceRotation = GetIniValue<bool>(BipedImportSection, "ForceRotation", false);
+   forceRotation = GetIniValue<bool>(BipedImportSection, "ForceRotation", true);
+   browseForSkeleton = GetIniValue<bool>(BipedImportSection, "BrowseForSkeleton", true);
+   defaultSkeletonName = GetIniValue<string>(BipedImportSection, "DefaultSkeletonName", "Skeleton.Nif");
 
    minBoneWidth = GetIniValue<float>(BipedImportSection, "MinBoneWidth", 0.5f);
    maxBoneWidth = GetIniValue<float>(BipedImportSection, "MaxBoneWidth", 3.0f);
    boneWidthToLengthRatio = GetIniValue<float>(BipedImportSection, "BoneWidthToLengthRatio", 0.25f);
 
-   importSkeleton = hasSkeleton = HasSkeleton();
-   isBiped = IsBiped();
+   goToSkeletonBindPosition = (appSettings ? appSettings->goToSkeletonBindPosition : false);
 }
 
 void NifImporter::SaveIniSettings()
@@ -773,6 +840,7 @@ INode *NifImporter::CreateBone(const string& name, Point3 startPos, Point3 endPo
          }
          return result.n;
       }
+      fpBones->ReleaseInterface();
    }
    return NULL;
 }
@@ -797,6 +865,32 @@ void NifImporter::ImportBones(NiNodeRef node)
       Point3 p = im.GetTrans();
       Quat q(im);
       q.Normalize();
+      Vector3 ppos;
+      Point3 zAxis(0,1,0);
+      if (!children.empty()) {
+         for (vector<NiNodeRef>::iterator itr=children.begin(), end = children.end(); itr != end; ++itr) {
+            Matrix44 cwt = (*itr)->GetWorldTransform();
+            Vector3 cpos; Matrix33 crot; float cscale;
+            cwt.Decompose(cpos, crot, cscale);
+            ppos += cpos;
+         }
+         ppos /= children.size();
+      }
+      else if (parent)
+      {
+         Matrix44 pwt = parent->GetWorldTransform();
+         Matrix33 prot; float pscale;
+         pwt.Decompose(ppos, prot, pscale);
+         if (forceRotation)
+            prs = prsPos;
+      }
+      else
+      {
+         if (forceRotation)
+            prs = prsPos;
+      }
+      Point3 pp(ppos.x, ppos.y, ppos.z);
+
       INode *bone = gi->GetINodeByName(name.c_str());
       if (bone)
       {
@@ -810,31 +904,6 @@ void NifImporter::ImportBones(NiNodeRef node)
       }
       else
       {
-         Vector3 ppos;
-         Point3 zAxis(0,1,0);
-         if (!children.empty()) {
-            for (vector<NiNodeRef>::iterator itr=children.begin(), end = children.end(); itr != end; ++itr) {
-               Matrix44 cwt = (*itr)->GetWorldTransform();
-               Vector3 cpos; Matrix33 crot; float cscale;
-               cwt.Decompose(cpos, crot, cscale);
-               ppos += cpos;
-            }
-            ppos /= children.size();
-         }
-         else if (parent)
-         {
-            Matrix44 pwt = parent->GetWorldTransform();
-            Matrix33 prot; float pscale;
-            pwt.Decompose(ppos, prot, pscale);
-            if (forceRotation)
-               prs = prsPos;
-         }
-         else
-         {
-            if (forceRotation)
-               prs = prsPos;
-         }
-         Point3 pp(ppos.x, ppos.y, ppos.z);
          if (bone = CreateBone(name, p, pp, zAxis))
          {
             PositionAndRotateNode(bone, p, q, prs);
@@ -968,16 +1037,7 @@ bool NifImporter::ImportMaterialAndTextures(ImpNode *node, NiAVObjectRef avObjec
 
 bool NifImporter::ImportTransform(ImpNode *node, NiAVObjectRef avObject)
 {
-   Matrix44 wt = avObject->GetWorldTransform();
-
-   Vector3 pos; Matrix33 rot; float scale;
-   wt.Decompose(pos, rot, scale);
-   Point3 p(pos.x, pos.y, pos.z);
-
-   Matrix3 m(rot.rows[0].data, rot.rows[1].data, rot.rows[2].data, Point3(0,0,0));
-   m.Invert();
-   m.SetTrans(p);
-   node->SetTransform(0,m);   
+   node->SetTransform(0,TOMATRIX3(avObject->GetWorldTransform()));   
    return true;
 }
 
@@ -1173,54 +1233,55 @@ bool NifImporter::ImportSkin(ImpNode *node, NiTriBasedGeomRef triGeom)
    Mesh& m = triObject->GetMesh();
 
    //get the skin interface
-   ISkin *skin = (ISkin *) skinMod->GetInterface(I_SKIN);
-   ISkinImportData* iskinImport = (ISkinImportData*) skinMod->GetInterface(I_SKINIMPORTDATA);
-
-   // Create Bone List
-   Tab<INode*> bones;
-   int i=0;
-   for (vector<NiNodeRef>::iterator itr = nifBones.begin(), end = nifBones.end(); itr != end; ++itr, ++i){
-      string name = (*itr)->GetName();
-      INode *boneRef = gi->GetINodeByName(name.c_str());
-      bones.Append(1, &boneRef);
-      iskinImport->AddBoneEx(boneRef, TRUE);
-
-      // Set Bone Transform
-      //Matrix3 tm = boneRef->GetObjectTM(0);
-      //Matrix3 m = TOMATRIX3(data->GetBoneTransform(i));
-      //iskinImport->SetBoneTm(boneRef, tm, m);
-   }
-   ObjectState os = tnode->EvalWorldState(0);
-
-   // Need to trigger ModifyObject in BonesDefMod prior to adding vertices or nothing is added
-   GetCOREInterface()->ForceCompleteRedraw();
-
-   // Need to get a list of bones and weights for each vertex.
-   vector<VertexHolder> vertexHolders;
-   vertexHolders.resize(m.numVerts);
-   for (int i=0, n=data->GetBoneCount();i<n; ++i){
-      if (INode *boneRef = bones[i]){
-         vector<SkinWeight> weights = data->GetBoneWeights(i);
-         for (vector<SkinWeight>::iterator itr=weights.begin(), end=weights.end(); itr != end; ++itr){
-            VertexHolder& h = vertexHolders[itr->index];
-            h.vertIndex = itr->index;
-            ++h.count;
-            h.weights.Append(1, &itr->weight);
-            h.boneNodeList.Append(1, &boneRef);
+   if (ISkin *skin = (ISkin *) skinMod->GetInterface(I_SKIN)){
+      ISkinImportData* iskinImport = (ISkinImportData*) skinMod->GetInterface(I_SKINIMPORTDATA);
+
+      // Create Bone List
+      Tab<INode*> bones;
+      int i=0;
+      for (vector<NiNodeRef>::iterator itr = nifBones.begin(), end = nifBones.end(); itr != end; ++itr, ++i){
+         string name = (*itr)->GetName();
+         INode *boneRef = gi->GetINodeByName(name.c_str());
+         bones.Append(1, &boneRef);
+         iskinImport->AddBoneEx(boneRef, TRUE);
+
+         // Set Bone Transform
+         //Matrix3 tm = boneRef->GetObjectTM(0);
+         //Matrix3 m = TOMATRIX3(data->GetBoneTransform(i));
+         //iskinImport->SetBoneTm(boneRef, tm, m);
+      }
+      ObjectState os = tnode->EvalWorldState(0);
+
+      // Need to trigger ModifyObject in BonesDefMod prior to adding vertices or nothing is added
+      GetCOREInterface()->ForceCompleteRedraw();
+
+      // Need to get a list of bones and weights for each vertex.
+      vector<VertexHolder> vertexHolders;
+      vertexHolders.resize(m.numVerts);
+      for (int i=0, n=data->GetBoneCount();i<n; ++i){
+         if (INode *boneRef = bones[i]){
+            vector<SkinWeight> weights = data->GetBoneWeights(i);
+            for (vector<SkinWeight>::iterator itr=weights.begin(), end=weights.end(); itr != end; ++itr){
+               VertexHolder& h = vertexHolders[itr->index];
+               h.vertIndex = itr->index;
+               ++h.count;
+               h.weights.Append(1, &itr->weight);
+               h.boneNodeList.Append(1, &boneRef);
+            }
          }
       }
-   }
 
-   // Assign the weights 
-   for (vector<VertexHolder>::iterator itr=vertexHolders.begin(), end=vertexHolders.end(); itr != end; ++itr){
-      VertexHolder& h = (*itr);
-      if (h.count){
-         float sum = 0.0f;
-         for (int i=0; i<h.count; ++i)
-            sum += h.weights[i];
-         ASSERT(fabs(sum-1.0) < 0.001);
-         BOOL add = iskinImport->AddWeights(tnode, h.vertIndex, h.boneNodeList, h.weights);
-         add = add;
+      // Assign the weights 
+      for (vector<VertexHolder>::iterator itr=vertexHolders.begin(), end=vertexHolders.end(); itr != end; ++itr){
+         VertexHolder& h = (*itr);
+         if (h.count){
+            float sum = 0.0f;
+            for (int i=0; i<h.count; ++i)
+               sum += h.weights[i];
+            ASSERT(fabs(sum-1.0) < 0.001);
+            BOOL add = iskinImport->AddWeights(tnode, h.vertIndex, h.boneNodeList, h.weights);
+            add = add;
+         }
       }
    }
    return ok;
diff --git a/NifImport/MaxNifImport.vcproj b/NifImport/MaxNifImport.vcproj
index c118c76f3f8dec98d9f32a0c47754c77a75465fb..c942c2910854273c1f37cfc9cc90e503b456f6bd 100644
--- a/NifImport/MaxNifImport.vcproj
+++ b/NifImport/MaxNifImport.vcproj
@@ -22,6 +22,7 @@
 			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
 			UseOfMFC="0"
 			ATLMinimizesCRunTimeLibraryUsage="false"
+			WholeProgramOptimization="0"
 			>
 			<Tool
 				Name="VCPreBuildEventTool"
@@ -112,7 +113,7 @@
 			/>
 			<Tool
 				Name="VCPostBuildEventTool"
-				CommandLine="if exist &quot;C:\3dsmax8\plugcfg&quot; (&#x0D;&#x0A;if not exist &quot;C:\3dsmax8\plugcfg\MaxNifTools.ini&quot; (&#x0D;&#x0A;copy &quot;$(ProjectDir)MaxNifTools.ini&quot; &quot;C:\3dsmax8\plugcfg\MaxNifTools.ini&quot;&#x0D;&#x0A;)&#x0D;&#x0A;)&#x0D;&#x0A;"
+				CommandLine="if exist &quot;C:\3dsmax8\plugcfg&quot; (&#x0D;&#x0A;   if not exist &quot;C:\3dsmax8\plugcfg\MaxNifTools.ini&quot; (&#x0D;&#x0A;      copy &quot;$(ProjectDir)MaxNifTools.ini&quot; &quot;C:\3dsmax8\plugcfg\MaxNifTools.ini&quot;&#x0D;&#x0A;   )&#x0D;&#x0A;)&#x0D;&#x0A;if exist &quot;C:\3dsmax8&quot; (&#x0D;&#x0A;    xcopy /D /Y /I &quot;$(ProjectDir)MaxNifImport_Readme.txt&quot; &quot;C:\3dsmax8\&quot;&#x0D;&#x0A;)&#x0D;&#x0A;"
 			/>
 		</Configuration>
 		<Configuration
@@ -214,7 +215,7 @@
 			/>
 			<Tool
 				Name="VCPostBuildEventTool"
-				CommandLine="if exist &quot;C:\3dsmax8\plugcfg&quot; (&#x0D;&#x0A;if not exist &quot;C:\3dsmax8\plugcfg\MaxNifTools.ini&quot; (&#x0D;&#x0A;copy &quot;$(ProjectDir)MaxNifTools.ini&quot; &quot;C:\3dsmax8\plugcfg\MaxNifTools.ini&quot;&#x0D;&#x0A;)&#x0D;&#x0A;)&#x0D;&#x0A;"
+				CommandLine="if exist &quot;C:\3dsmax8\plugcfg&quot; (&#x0D;&#x0A;   if not exist &quot;C:\3dsmax8\plugcfg\MaxNifTools.ini&quot; (&#x0D;&#x0A;      copy &quot;$(ProjectDir)MaxNifTools.ini&quot; &quot;C:\3dsmax8\plugcfg\MaxNifTools.ini&quot;&#x0D;&#x0A;   )&#x0D;&#x0A;)&#x0D;&#x0A;if exist &quot;C:\3dsmax8&quot; (&#x0D;&#x0A;    xcopy /D /Y /I &quot;$(ProjectDir)MaxNifImport_Readme.txt&quot; &quot;C:\3dsmax8\&quot;&#x0D;&#x0A;)&#x0D;&#x0A;"
 			/>
 		</Configuration>
 	</Configurations>
diff --git a/NifImport/MaxNifImport_Readme.txt b/NifImport/MaxNifImport_Readme.txt
index 6026a04538ca9ba5059cdd9b358bc6bfda71cb06..329f250c4370367032c4b49df7bb5f8f4a318261 100644
--- a/NifImport/MaxNifImport_Readme.txt
+++ b/NifImport/MaxNifImport_Readme.txt
@@ -9,20 +9,37 @@ It uses the NIF File Format Library and Tools library.
 
 See the plugin INI file for advanced configuration.
 
+=========================
+REQUIREMENTS
+=========================
+3ds Max 8
+
 =========================
 INSTALL
 =========================
 Extract file to 3dsmax8 installation directory.
 
-Edit the MaxNifTools.ini file to adjust paths and other settings.
+Its highly recommended that you edit the MaxNifTools.ini file to adjust paths 
+and other settings to you machine.
 
-=========================
-REQUIREMENTS
-=========================
-3ds Max 8
+Most importantly:
+1. Remove irrelevant applications from the KnownApplications list
+
+2. Fix the RootPaths, TexturePaths and TextureSearchPaths in the Applications for your machine.
+
+   - The ini file has a substitution mechanism to make it easier to just change one location
+     and refer to that path in other areas.
+   
+   - RootPaths is used to determine if the imported nif is in one of those directories
+     if so it assumes the nif is from that app and uses those settings for import.
+     
+   - TexturePaths is used to test if the relative path in the nif is relative to that directory.
+   
+   - TextureSearchPaths will be recursively scanned for file names that match the extensions
+     (this can be time consuming so keep it to only relevant directories to you).
 
 =========================
-UNINSTALLING
+UNINSTALL
 =========================
 Delete the installed files from 3dsmax directory. See the list below in the 
 Installed Files section.
@@ -36,7 +53,7 @@ v 0.1
 =========================
 KNOWN ISSUES
 =========================
-None
+o Bipeds do not import correctly.  Bones are doing better at the moment.
 
 =========================
 INSTALLED FILES
diff --git a/NifImport/MaxNifTools.ini b/NifImport/MaxNifTools.ini
index fb8ea1b472061a89b3f4bc039640a4942543cc4a..3726d4fea38b67a9fbd1f96c1d73616b807135d8 100644
--- a/NifImport/MaxNifTools.ini
+++ b/NifImport/MaxNifTools.ini
@@ -4,17 +4,16 @@
 [System]
 ; ShortDescription used in the 
 ShortDescription=Netimmerse/Gamebryo
-
 ; KnownApplications - Used to indicate which sections in the ini file point 
 ;    to "Applications" which have their own settings in a section below.
 KnownApplications=Oblivion;Morrowind;Civ4
-
 ; Reparse the Applications (and therefore Texture directory cache) on every import/export
 Reparse=0
 
 [MaxNifImport]
-; Current Application to get setting/directory information from.  Should match KnownApps above
-CurrentApp=Oblivion
+; Current Application to get setting/directory information from.  Should match KnownApps above or Auto.
+;   Auto will check the import file against the known root paths use that app if a directory match is found.
+CurrentApp=Auto
 ; Wildcard to use on all NiNodes to test whether a biped may be used. Default: Bip*
 SkeletonCheck=Bip*
 ; Use Bones or Biped.  Biped is broken right now so use bones or nothing.  Default: 0
@@ -48,42 +47,56 @@ RemoveUnusedImportedBones=1
 MinBoneWidth=0.5
 MaxBoneWidth=3
 BoneWidthToLengthRatio=0.25
-; Force nub to point back to parent at expense of loss of rotation. Default: 1
+; Force nub to point back to parent at expense of loss of rotation data. Default: 1
 ForceRotation=1
+; Browse for skeleton on import. Default: 1
+BrowseForSkeleton=1
+; DefaultName for Skeletons (use if in same directory as imported nif)
+DefaultSkeletonName=skeleton.nif
 
-
-;; [Applications]
-; TextureRootPaths - Semicolon separated list of base directories to look for files
+; [Applications]
+; RootPaths - Semicolon separated list of base directories to use when determining which app the imported file is from
+;
+; TextureRootPaths - Semicolon separated list of base directories to look for texturefiles
 ; TextureExtensions - Extensions to scan for when using TextureSearchPaths
 ; TextureSeachPaths - Semicolon separated list of directories to look recursively for files in
+;
+; UseSkeleton - Whether to use skeleton. Default: 0
 ; Skeleton - Default Skeleton to use when importing oblivion meshes
+; GoToSkeletonBindPosition - Morrowind trishape data is not in the correct bind position for import. Default: 1
 
 [Oblivion]
 ; Installation Folder
 InstallPath=[HKLM\SOFTWARE\Bethesda Softworks\Oblivion]=@"Installed Path"
-RootPath=${InstallPath}\Data
 ExtractFolder=E:\Nifs\Oblivion
+
+RootPath=${InstallPath}\Data
 MeshRootPath=${ExtractFolder}\Oblivion - Meshes
 TextureRootPath=${ExtractFolder}\Oblivion - Textures - Compressed
-
+UseSkeleton=1
 Skeleton=${MeshRootPath}\meshes\characters\_male\skeleton.nif
+RootPaths=${RootPath};${MeshRootPath};${TextureRootPath}
 TextureRootPaths=${RootPath};${TextureRootPath}
 TextureExtensions=.dds;
 TextureSearchPaths=${RootPath}\Textures;${TextureRootPath}\Textures\Characters;${TextureRootPath}\Textures\Armor
+GoToSkeletonBindPosition=0
 
 [Morrowind]
 InstallPath=[HKLM\SOFTWARE\Bethesda Softworks\Morrowind]=@"Installed Path"
 RootPath=${InstallPath}\Data Files
 ExtractFolder=E:\Nifs\Morrowind\Data Files
+RootPaths=${RootPath};${ExtractFolder}
 TextureRootPaths=${RootPath}\Textures;${ExtractFolder}\Textures
 TextureExtensions=.tga;
 TextureSearchPaths=${RootPath}\Textures
+GoToSkeletonBindPosition=1
 
 [Civ4]
 InstallPath=[HKEY_LOCAL_MACHINE\SOFTWARE\Firaxis Games\Sid Meier's Civilization 4]=@"INSTALLDIR"
 RootPath=
 ExtractFolder=C:\Projects\Main\Civilization4\assets
+RootPaths=${ExtractFolder};${InstallPath}\Assets;${InstallPath}\Mods;%USERPROFILE%\My Documents\My Games\Civilization 4\CustomAssets;%USERPROFILE%\My Documents\My Games\Civilization 4\Mods
 TextureRootPaths=$(ExtractFolder)\art\shared\
 TextureExtensions=.dds;.bmp
 TextureSearchPaths=
-
+GoToSkeletonBindPosition=0
\ No newline at end of file
diff --git a/NifImport/niutils.cpp b/NifImport/niutils.cpp
index 1a494b12c77d03aa4fb4a35abb70de2a63eb52ec..52353b86788966fb6ce912f9235861623cbce087 100644
--- a/NifImport/niutils.cpp
+++ b/NifImport/niutils.cpp
@@ -106,6 +106,7 @@ NameValueCollection ReadIniSection(LPCTSTR Section, LPCTSTR iniFileName )
 
 // Expand Qualifiers in string using a ${Name} syntax.  Name will be looked up in the
 //    NameValueCollection and expand in place.  Missing names will expand to empty.
+//    - Please dont give self-referential strings
 string ExpandQualifiers(const string& src, const NameValueCollection& map)
 {
    string value;
@@ -125,7 +126,7 @@ string ExpandQualifiers(const string& src, const NameValueCollection& map)
                   string key = src.substr(i+1, term-i-1);
                   NameValueCollection::const_iterator kvp = map.find(key);
                   if (kvp != map.end()) {
-                     value.append(kvp->second);
+                     value.append(ExpandQualifiers(kvp->second, map));
                   } 
                   i = term;
                }
@@ -137,7 +138,7 @@ string ExpandQualifiers(const string& src, const NameValueCollection& map)
                   string key = src.substr(i+1, term-i-1);
                   NameValueCollection::const_iterator kvp = map.find(key);
                   if (kvp != map.end()) {
-                     value.append(kvp->second);
+                     value.append(ExpandQualifiers(kvp->second, map));
                   } 
                   i = term;
                }
@@ -513,3 +514,15 @@ void FindImages(NameValueCollection& images, const string& rootPath, const strin
       }
    }
 }
+
+
+void GoToSkeletonBindPosition(vector<NiNodeRef>& blocks)
+{
+   //Send all skeleton roots to bind position
+   for (uint i = 0; i < blocks.size(); ++i) {
+   	NiNodeRef node = blocks[i];
+   	if ( node != NULL && node->IsSkeletonRoot() ) {
+   		node->GoToSkeletonBindPosition();
+   	}
+   }
+}
\ No newline at end of file
diff --git a/NifImport/niutils.h b/NifImport/niutils.h
index 6e2f12bda5c59f560fdf1ee0b82e0caaf6532626..2458ee3c5f5d1ae3992d9a650b4c254d03f6c752 100644
--- a/NifImport/niutils.h
+++ b/NifImport/niutils.h
@@ -208,6 +208,7 @@ extern Niflib::NiNodeRef FindNodeByName( const vector<Niflib::NiNodeRef>& blocks
 extern std::vector<Niflib::NiNodeRef> SelectNodesByName( const vector<Niflib::NiNodeRef>& blocks, LPCTSTR match);
 extern int CountNodesByName( const vector<Niflib::NiNodeRef>& blocks, LPCTSTR match );
 extern std::vector<std::string> GetNamesOfNodes( const vector<Niflib::NiNodeRef>& blocks );
+extern void GoToSkeletonBindPosition(std::vector<Niflib::NiNodeRef>& blocks);
 
 // Simple conversion helpers
 static inline float TODEG(float x) { return x * 180.0f / PI; }