diff --git a/MaxNifPlugins_Readme.txt b/MaxNifPlugins_Readme.txt
index 902dc78cfc998d967e3d5e31b4c4edac2bff90d8..971f29c0f622152c1ea4a7fe240bc2cc9fcfea42 100644
--- a/MaxNifPlugins_Readme.txt
+++ b/MaxNifPlugins_Readme.txt
@@ -34,11 +34,15 @@
       - Added Vertex Color modifier support
       - Fixed issue with static animation import
       - Fixed issue with skin vertex weight count import
+      - Added support for more material/texture properties
+      - Added support for Civilization IV Shader, if installed
+        o holds much of the material data in nif compatible form
       
     o Exporter
       - Upgraded to Visual Studio 2005
       - Dropped registry support in favor of INI file.
-      - Dropped Official Max6 support because I do not have SDK to compile it with (try the max 7 files).
+      - Dropped Official Max6 support because I do not have Max 6 to compile it
+        o Try editing the MaxNifTools.ini and setting the MaxSDKVersion to 0x17700d00
       - Fixed issue with importing glossiness setting on textures.
       - Fixed issues with export of vertex color. Alpha map is now exported as part of the normal color map.
       - No longer exports meshes associated with bone or biped nodes.
@@ -46,6 +50,10 @@
       - Mass, Restitution(Ellasticity), and Friction now share values with Reactor(Havok)
       - Modified UPB export to actually export the values in the UserPropBuffer not just a fixed list.
       - Added Skin Modifier export
+      - Added support for more material/texture properties
+      - Added support for Civilization IV Shader, if installed
+        o holds much of the material data in nif compatible form
+      - Fixed issue with UV map needing to be flipped
       
     o NifProps Utility
       - Mass, Restitution(Ellasticity), and Friction now share values with Reactor(Havok)
diff --git a/MaxNifTools.ini b/MaxNifTools.ini
index c7b2529df4b160dd7e4ce3bba87ac4db452b4627..74969fd1f1d11fa9352dab75f19d5d87182c6f4a 100644
--- a/MaxNifTools.ini
+++ b/MaxNifTools.ini
@@ -6,7 +6,7 @@
 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;DAoC
+KnownApplications=Oblivion;Morrowind;Civilization 4;Dark Age of Camelot;User
 ; Reparse the Applications (and therefore Texture directory cache) on every import/export
 Reparse=0
 
@@ -24,14 +24,14 @@ GenerateStrips=1
 FurnatureMarkers=1
 ; Use Lights if present. Default:0
 Lights=0
-; Include Hidden Nodes if present. Default:0
-IncludeHidden=0
+; Include Hidden Nodes if present. Default:1
+IncludeHidden=1
 ; Export Collision meshes if present. Default:1
 ExportCollision=1
 ; Export Vertext Colors. Default:1
 VertexColors=1
-; Remap Indices. Default:1
-RemapIndices=1
+; Remap Indices. Default:0
+RemapIndices=0
 ; Texture Prefix if texture not found in AppSettings directory. Default:textures
 TexturePrefix=textures
 ; Add Export additional NiNodes for Meshes. Default: 0
@@ -40,14 +40,14 @@ ExportExtraNodes=0
 ExportSkin=1
 ; Export UserPropBuffer. Default: 0
 UserPropBuffer=0
-; Flatten Node Hierarchy. Default: 0
-FlattenHierarchy=0
-; Remove Unreferenced Bones. Default: 0
-RemoveUnreferencedBones=0
+; Flatten Node Hierarchy. Default: 1
+FlattenHierarchy=1
+; Remove Unreferenced Bones. Default: 1
+RemoveUnreferencedBones=1
 
 [MaxNifImport]
 ; Max SDK Plugin Version (0 - AutoSelect; 0x17700d00 - Max6, 0x1f401100 - Max8)  Default: 0 
-MaxSDKVersion=0x17700d00
+MaxSDKVersion=0
 ; 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
@@ -64,7 +64,7 @@ EnableAutoSmooth=1
 ; AutoSmooth angle. Default: 30
 AutoSmoothAngle=30.0
 ; Remove Double/Illegal faces on meshes on import. Default:1
-RemoveDoubleFaces=1
+RemoveDegenerateFaces=1
 RemoveIllegalFaces=1
 ; EnableSkinSupport attempt to skin the mesh if bones are available. Default:1
 EnableSkinSupport=1
@@ -92,8 +92,6 @@ MaxBoneWidth=0.1
 BoneWidthToLengthRatio=0.01
 ; Force nub to point back to parent at expense of loss of rotation data. Default: 1
 ForceRotation=0
-; Browse for skeleton on import. Default: 1
-BrowseForSkeleton=1
 ; DefaultName for Skeletons (use if in same directory as imported nif)
 DefaultSkeletonName=skeleton.nif
 
@@ -121,6 +119,8 @@ ApplyOverallTransformToSkinAndBones=1
 bhkScaleFactor=7.0
 
 ; [Applications]
+; NiVersion - Version of Nif use by game
+; NiUserVersion - User Version of Nif used by game
 ; 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
@@ -132,6 +132,8 @@ bhkScaleFactor=7.0
 ; GoToSkeletonBindPosition - Morrowind trishape data is not in the correct bind position for import. Default: 1
 
 [Oblivion]
+NiVersion=20.0.0.5
+NiUserVersion=11
 ; Installation Folder
 InstallPath=[HKLM\SOFTWARE\Bethesda Softworks\Oblivion]=@"Installed Path"
 ExtractFolder=E:\Nifs\Oblivion
@@ -148,6 +150,8 @@ TextureSearchPaths=${RootPath}\Textures;${TextureRootPath}\Textures\Characters;$
 GoToSkeletonBindPosition=1
 
 [Morrowind]
+NiVersion=4.0.0.2
+NiUserVersion=0
 InstallPath=[HKLM\SOFTWARE\Bethesda Softworks\Morrowind]=@"Installed Path"
 RootPath=${InstallPath}\Data Files
 ExtractFolder=E:\Nifs\Morrowind\Data Files
@@ -157,7 +161,9 @@ TextureExtensions=.tga;
 TextureSearchPaths=${RootPath}\Textures
 GoToSkeletonBindPosition=1
 
-[Civ4]
+[Civilization 4]
+NiVersion=20.0.0.4
+NiUserVersion=0
 InstallPath=[HKEY_LOCAL_MACHINE\SOFTWARE\Firaxis Games\Sid Meier's Civilization 4]=@"INSTALLDIR"
 RootPath=
 ExtractFolder=C:\Projects\Main\Civilization4\assets
@@ -168,7 +174,9 @@ TextureSearchPaths=
 GoToSkeletonBindPosition=1
 DummyNodeMatches=MD;Bip;Bip??;* NonAccum;Effect*;Sound*;Dummy*
 
-[DAoC]
+[Dark Age of Camelot]
+NiVersion=10.1.0.0
+NiUserVersion=0
 Isles_InstallPath=[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Dark Age of Camelot - Shrouded Isles_is1]=@"InstallLocation"
 RootPath=
 ExtractFolder=
@@ -177,4 +185,8 @@ TextureRootPaths=$(ExtractFolder)
 TextureExtensions=.dds;.bmp;.tga
 TextureSearchPaths=
 GoToSkeletonBindPosition=1
-ApplyOverallTransformToSkinAndBones=0
\ No newline at end of file
+ApplyOverallTransformToSkinAndBones=0
+
+[User]
+NiVersion=20.0.0.5
+NiUserVersion=0
diff --git a/NifCommon/AppSettings.cpp b/NifCommon/AppSettings.cpp
index 59cbb30c72e80851afe5047c31700cc9a02eb381..efb8b9c9ab6cbdde700f327a4554aa36801eab97 100644
--- a/NifCommon/AppSettings.cpp
+++ b/NifCommon/AppSettings.cpp
@@ -2,6 +2,7 @@
 #include <string.h>
 #include <tchar.h>
 #include "AppSettings.h"
+#include "IniSection.h"
 
 AppSettingsMap TheAppSettings;
 
@@ -18,6 +19,7 @@ void AppSettings::Initialize(Interface *gi)
 
       string Applications = GetIniValue<string>("System", "KnownApplications", "", iniName);
       stringlist apps = TokenizeString(Applications.c_str(), ";");
+      apps.push_back(string("User")); // always ensure that user is present
       for (stringlist::iterator appstr=apps.begin(); appstr != apps.end(); ++appstr){
          AppSettings* setting = FindAppSetting(*appstr);
          if (NULL == setting){
@@ -46,6 +48,9 @@ void AppSettings::ReadSettings(string iniFile)
 
    std::swap(Environment, settings);
 
+   NiVersion = GetSetting<string>("NiVersion", "20.0.0.5");
+   NiUserVersion = GetSetting<int>("NiUserVersion", 0);
+
    rootPath = GetSetting<string>("RootPath");
    rootPaths = TokenizeString(GetSetting<string>("RootPaths").c_str(), ";");
    searchPaths = TokenizeString(GetSetting<string>("TextureSearchPaths").c_str(), ";");
@@ -61,6 +66,19 @@ void AppSettings::ReadSettings(string iniFile)
    dummyNodeMatches = TokenizeString(GetSetting<string>("DummyNodeMatches").c_str(), ";");
 }
 
+void AppSettings::WriteSettings(Interface *gi)
+{
+   TCHAR iniName[MAX_PATH];
+   LPCTSTR pluginDir = gi->GetDir(APP_PLUGCFG_DIR);
+   PathCombine(iniName, pluginDir, "MaxNifTools.ini");
+   if (-1 != _taccess(iniName, 0)) 
+   {
+      SetIniValue(Name.c_str(), "NiVersion", NiVersion.c_str(), iniName);
+      SetIniValue(Name.c_str(), "NiUserVersion", FormatString("%d", NiUserVersion).c_str(), iniName);
+   }
+}
+
+
 string AppSettings::FindImage(const string& fname){
    TCHAR buffer[MAX_PATH];
 
diff --git a/NifCommon/AppSettings.h b/NifCommon/AppSettings.h
index 0d7cfecf7549749dc2deef643e59401e4a06cd77..3e009eec0add25fbc42bd39a6795a13506c15810 100644
--- a/NifCommon/AppSettings.h
+++ b/NifCommon/AppSettings.h
@@ -42,9 +42,12 @@ public:
    NameValueCollection imgTable;
    stringlist dummyNodeMatches;
    int applyOverallTransformToSkinAndBones;
+   std::string NiVersion;
+   int NiUserVersion;
 
    static void Initialize(Interface *gi);
    void ReadSettings(std::string iniFile);
+   void WriteSettings(Interface *gi);
    std::string FindImage(const std::string& fname);
 
    // Check whether the given file is a child of the root paths
diff --git a/NifCommon/IniSection.h b/NifCommon/IniSection.h
new file mode 100644
index 0000000000000000000000000000000000000000..e42f6a8ded61cb5cb33612f45f897cde6298b362
--- /dev/null
+++ b/NifCommon/IniSection.h
@@ -0,0 +1,124 @@
+#pragma once
+
+#include <string>
+#include <list>
+enum INIDEFTYPE
+{
+   IDT_STRING,
+   IDT_INT,
+   IDT_FLOAT,
+   IDT_BOOL,
+   IDT_FILENAME,
+   IDT_UNKNOWN,
+};
+
+struct INIDEF
+{
+   INIDEF() : ShortName(NULL), IniName(NULL), MemberAddr(0), Description(NULL), DefaultValue(NULL), ValueSize(0) {
+   }
+
+   ~INIDEF() {
+      if (ValueSize && DefaultValue) {
+         delete DefaultValue;
+         DefaultValue = NULL;
+         ValueSize = 0;
+      }
+   }
+
+   template<typename U>
+   INIDEF(LPCTSTR sName, LPCTSTR iName, const U& member, U default, LPCTSTR desc, INIDEFTYPE type) 
+      : ShortName(sName), IniName(iName), MemberAddr(NULL), Description(NULL), MemberType(type) {
+      SetDefault(default);
+   }
+
+   template<>
+   INIDEF(LPCTSTR sName, LPCTSTR iName, const std::string& member, std::string default, LPCTSTR desc, INIDEFTYPE type) 
+      : ShortName(sName), IniName(iName), MemberAddr((DWORD)&member), Description(NULL) { 
+      MemberType = type==IDT_UNKNOWN?IDT_STRING:type; 
+      SetDefault(default);
+   }
+
+   template<>
+   INIDEF(LPCTSTR sName, LPCTSTR iName, const int& member, int default, LPCTSTR desc, INIDEFTYPE type) 
+      : ShortName(sName), IniName(iName), MemberAddr((DWORD)&member), Description(NULL) { 
+      MemberType = type==IDT_UNKNOWN?IDT_INT:type; 
+      SetDefault(default);
+   }
+
+   template<>
+   INIDEF(LPCTSTR sName, LPCTSTR iName, const float& member, float default, LPCTSTR desc, INIDEFTYPE type) 
+      : ShortName(sName), IniName(iName), MemberAddr((DWORD)&member), Description(NULL) { 
+      MemberType = type==IDT_UNKNOWN?IDT_FLOAT:type; 
+      SetDefault(default);
+   }
+
+   template<>
+   INIDEF(LPCTSTR sName, LPCTSTR iName, const bool& member, bool default, LPCTSTR desc, INIDEFTYPE type) 
+      : ShortName(sName), IniName(iName), MemberAddr((DWORD)&member), Description(NULL) { 
+      MemberType = type==IDT_UNKNOWN?IDT_BOOL:type; 
+      SetDefault(default);
+   }
+
+   template<typename U>
+   void SetDefault(U default) {
+      ValueSize = sizeof(U);
+      DefaultValue = new U(default);
+   }
+
+   template <typename U>
+   const U& GetDefault() const {
+      return *(U*)DefaultValue;
+   }
+
+   LPCTSTR ShortName;
+   LPCTSTR IniName;
+   DWORD MemberAddr;
+   INIDEFTYPE MemberType;
+   LPCTSTR Description;
+   LPVOID DefaultValue;
+   DWORD ValueSize;
+};
+
+#define BEGIN_INI_MAP(name) \
+   virtual void *GetMember(const INIDEF* memptr) const { return (void*)(((char*)this) + memptr->MemberAddr); } \
+   virtual const INIDEF* GetInfDefmap() const { return InternalGetInfDefmap(); } \
+   static INIDEF* InternalGetInfDefmap() { \
+   const name* pThis = 0; \
+   static INIDEF map[] = { \
+
+#define BEGIN_INI_MAP_WITH_BASE(name, base) \
+   virtual void *GetMember(const INIDEF* memptr) const { return (void*)(((char*)this) + memptr->MemberAddr); } \
+   virtual const INIDEF* GetInfDefmap() const { return InternalGetInfDefmap(); } \
+   static INIDEF* InternalGetInfDefmap() { \
+   const name* pThis = 0; \
+   static INIDEF map[] = { \
+
+#define END_INI_MAP() \
+   INIDEF() };\
+   return map;\
+}
+
+#define ADDITEM(sName, iName, member, desc) \
+   INIDEF(sName, iName, pThis->member, desc, IDT_UNKNOWN), \
+
+#define ADDITEMEX(sName, iName, member, type, desc) \
+   INIDEF(sName, iName, pThis->member, desc, type), \
+
+struct IniFileSection
+{
+   virtual LPCTSTR GetName() const = 0;
+   virtual const INIDEF* GetInfDefmap() const = 0;
+   virtual void *GetMember(const INIDEF* memptr) const = 0;
+};
+
+typedef std::list<IniFileSection*>  IniFileSectionList;
+
+inline int GetIniDefSectionSize(IniFileSection *section) {
+   int len = 0;
+
+   for (const INIDEF *inidef = section->GetInfDefmap()
+      ; inidef != NULL && inidef->ShortName
+      ; ++inidef)
+      ++len;
+   return len;
+}
\ No newline at end of file
diff --git a/NifCommon/NifCommon_VC80.vcproj b/NifCommon/NifCommon_VC80.vcproj
index 0f75d8fe4a6085024ed57d10801e1541386f3b1d..d8d7fc716fcd9875706ccd7b194dbcfe9aee1078 100644
--- a/NifCommon/NifCommon_VC80.vcproj
+++ b/NifCommon/NifCommon_VC80.vcproj
@@ -504,6 +504,10 @@
 				RelativePath=".\AppSettings.h"
 				>
 			</File>
+			<File
+				RelativePath=".\IniSection.h"
+				>
+			</File>
 			<File
 				RelativePath=".\NifGui.h"
 				>
@@ -516,6 +520,10 @@
 				RelativePath=".\niutils.h"
 				>
 			</File>
+			<File
+				RelativePath=".\objectParams.h"
+				>
+			</File>
 			<File
 				RelativePath=".\pch.h"
 				>
diff --git a/NifCommon/niutils.cpp b/NifCommon/niutils.cpp
index 3f2190afafdf38b239afd0220d83afe5d2fa0793..f6e0b75f433f7da0f505a7abfbcdcc19574befbc 100644
--- a/NifCommon/niutils.cpp
+++ b/NifCommon/niutils.cpp
@@ -70,12 +70,12 @@ std::string FormatString(const TCHAR* format,...)
 }
 
 // Tokenize a string using strtok and return it as a stringlist
-stringlist TokenizeString(LPCTSTR str, LPCTSTR delims)
+stringlist TokenizeString(LPCTSTR str, LPCTSTR delims, bool trim)
 {
    stringlist values;
    LPTSTR buf = STRDUPA(str);
    for (LPTSTR p = _tcstok(buf, delims); p && *p; p = _tcstok(NULL, delims)){
-      values.push_back(string(p));
+      values.push_back(string((trim) ? Trim(p) : p));
    }
    return values;
 }
@@ -583,6 +583,22 @@ TriObject* GetTriObject(Object *o)
 }
 
 // Get or Create the Skin Modifier
+Modifier *GetOrCreateSkin(INode *node)
+{
+   Modifier *skinMod = GetSkin(node);
+   if (skinMod)
+      return skinMod;   
+   
+   IDerivedObject *dobj = CreateDerivedObject(node->GetObjectRef());
+   //create a skin modifier and add it
+   skinMod = (Modifier*) CreateInstance(OSM_CLASS_ID, SKIN_CLASSID);
+   dobj->SetAFlag(A_LOCK_TARGET);
+   dobj->AddModifier(skinMod);
+   dobj->ClearAFlag(A_LOCK_TARGET);
+   node->SetObjectRef(dobj);
+   return skinMod;
+}
+
 Modifier *GetSkin(INode *node)
 {
    Object* pObj = node->GetObjectRef();
@@ -604,14 +620,65 @@ Modifier *GetSkin(INode *node)
       }
       pObj = pDerObj->GetObjRef();
    }
+   return NULL;
+}
 
-   IDerivedObject *dobj = CreateDerivedObject(node->GetObjectRef());
 
-   //create a skin modifier and add it
-   Modifier *skinMod = (Modifier*) CreateInstance(OSM_CLASS_ID, SKIN_CLASSID);
-   dobj->SetAFlag(A_LOCK_TARGET);
-   dobj->AddModifier(skinMod);
-   dobj->ClearAFlag(A_LOCK_TARGET);
-   node->SetObjectRef(dobj);
-   return skinMod;
-}
+TSTR GetFileVersion(const char *fileName)
+{
+   TSTR retval;
+   char fileVersion[MAX_PATH];
+   if (fileName == NULL)
+   {
+      GetModuleFileName(hInstance, fileVersion, MAX_PATH);
+      fileName = fileVersion;
+   }
+   HMODULE ver = GetModuleHandle("version.dll");
+   if (!ver) ver = LoadLibrary("version.dll");
+   if (ver != NULL)
+   {
+      DWORD (APIENTRY *GetFileVersionInfoSize)(LPCTSTR, LPDWORD) = NULL;
+      BOOL (APIENTRY *GetFileVersionInfo)(LPCTSTR, DWORD, DWORD, LPVOID) = NULL;
+      BOOL (APIENTRY *VerQueryValue)(const LPVOID, LPTSTR, LPVOID *, PUINT) = NULL;
+      *(FARPROC*)&GetFileVersionInfoSize = GetProcAddress(ver, "GetFileVersionInfoSizeA");
+      *(FARPROC*)&GetFileVersionInfo = GetProcAddress(ver, "GetFileVersionInfoA");
+      *(FARPROC*)&VerQueryValue = GetProcAddress(ver, "VerQueryValueA");
+      if (GetFileVersionInfoSize && GetFileVersionInfo && VerQueryValue)
+      {
+         DWORD vLen = 0;
+         DWORD vSize = GetFileVersionInfoSize(fileName,&vLen);
+         if (vSize) 
+         {
+            LPVOID versionInfo = malloc(vSize+1);
+            if (GetFileVersionInfo(fileName,vLen,vSize,versionInfo))
+            {            
+               LPVOID version=NULL;
+               if (VerQueryValue(versionInfo,"\\VarFileInfo\\Translation",&version,(UINT *)&vLen) && vLen==4) 
+               {
+                  DWORD langD = *(DWORD*)version;
+                  sprintf(fileVersion, "\\StringFileInfo\\%02X%02X%02X%02X\\ProductVersion",
+                     (langD & 0xff00)>>8,langD & 0xff,(langD & 0xff000000)>>24, (langD & 0xff0000)>>16);            
+               }
+               else 
+               {
+                  sprintf(fileVersion, "\\StringFileInfo\\%04X04B0\\ProductVersion", GetUserDefaultLangID());
+               }
+               LPCTSTR value = NULL;
+               if (VerQueryValue(versionInfo,fileVersion,&version,(UINT *)&vLen))
+                  value = LPCTSTR(version);
+               else if (VerQueryValue(versionInfo,"\\StringFileInfo\\040904B0\\ProductVersion",&version,(UINT *)&vLen))
+                  value = LPCTSTR(version);
+               if (value != NULL)
+               {
+                  stringlist val = TokenizeString(value, ",", true);
+                  if (val.size() >= 4){
+                     retval = FormatText("%s.%s.%s.%s", val[0].c_str(), val[1].c_str(), val[2].c_str(), val[3].c_str());
+                  }
+               }
+               free(versionInfo);
+            }
+         }
+      }
+   }
+   return retval;
+}
\ No newline at end of file
diff --git a/NifCommon/niutils.h b/NifCommon/niutils.h
index 1a8cf8f0ef58eda64eee8555d53fd0b4ef37c198..11aaec24bd1ff57a61c31053bafeed5381b91740 100644
--- a/NifCommon/niutils.h
+++ b/NifCommon/niutils.h
@@ -121,7 +121,7 @@ struct NumericStringEquivalence
 // Common collections that I use
 typedef std::map<std::string, std::string, ltstr> NameValueCollection;
 typedef std::pair<std::string, std::string> KeyValuePair;
-typedef std::list<std::string> stringlist;
+typedef std::vector<std::string> stringlist;
 
 extern int wildcmp(const TCHAR *wild, const TCHAR *string);
 extern int wildcmpi(const TCHAR *wild, const TCHAR *string);
@@ -209,7 +209,7 @@ inline void SetIniValue<TSTR>(LPCTSTR Section, LPCTSTR Setting, TSTR value, LPCT
 extern TSTR FormatText(const TCHAR* format,...);
 extern std::string FormatString(const TCHAR* format,...);
 
-extern stringlist TokenizeString(LPCTSTR str, LPCTSTR delims);
+extern stringlist TokenizeString(LPCTSTR str, LPCTSTR delims, bool trim=false);
 extern string GetIndirectValue(LPCSTR path);
 extern NameValueCollection ReadIniSection(LPCTSTR Section, LPCTSTR iniFileName );
 extern string ExpandQualifiers(const string& src, const NameValueCollection& map);
@@ -271,6 +271,9 @@ static inline Color TOCOLOR(const Niflib::Color3& c3) {
    return Color(c3.r, c3.g, c3.b);
 }
 
+static inline Niflib::Color3 TOCOLOR3(const Color& c3) {
+   return Niflib::Color3(c3.r, c3.g, c3.b);
+}
 
 static inline Point3 TOPOINT3(const Niflib::Vector3& v){
    return Point3(v.x, v.y, v.z);
@@ -334,7 +337,10 @@ inline Niflib::Ref<U> SelectFirstObjectOfType( list<Niflib::Ref<T> > const & obj
 TSTR PrintMatrix3(Matrix3& m);
 TSTR PrintMatrix44(Niflib::Matrix44& m);
 
+extern Modifier *GetOrCreateSkin(INode *node);
 extern Modifier *GetSkin(INode *node);
 extern TriObject* GetTriObject(Object *o);
 
+extern TSTR GetFileVersion(const char *fileName);
+
 #endif // _NIUTILS_H_
\ No newline at end of file
diff --git a/NifCommon/objectParams.h b/NifCommon/objectParams.h
index 23a45f424dc7db9d93716af5ca3aeacb2c484102..9773e3e0b076371a4e3ad44955e921b8c77061c1 100644
--- a/NifCommon/objectParams.h
+++ b/NifCommon/objectParams.h
@@ -32,7 +32,7 @@ inline Value* make_maxscript_value(const Color& rgb);
 inline Value* make_maxscript_value(LPCTSTR str);
 inline Value* make_maxscript_value(ReferenceTarget* rtarg);
 
-#if VERSION_3DSMAX <= ((MAX_RELEASE_R7<<16)+(15<<8)+0)
+#if VERSION_3DSMAX <= ((7000<<16)+(15<<8)+0) // Version 7
 inline void clear_error_source_data() {}
 #endif
 
@@ -317,7 +317,8 @@ inline float ConvertMAXScriptToC<float>::cvt(Value* val)
 
 inline Color ConvertMAXScriptToC<Color>::cvt(Value* val)
 {
-	return val->to_point3();
+	Point3 pt3 = val->to_point3();
+   return Color(pt3.x/255.0f, pt3.y/255.0f, pt3.z/255.0f);
 }
 
 inline LPTSTR ConvertMAXScriptToC<LPTSTR>::cvt(Value* val)
diff --git a/NifExport/Coll.cpp b/NifExport/Coll.cpp
index 20a7ab684917a195939e1c69a6b42673f6649f0e..5c8f30f7e431ca774d9f85efc7971a4ae2cef901 100755
--- a/NifExport/Coll.cpp
+++ b/NifExport/Coll.cpp
@@ -252,6 +252,9 @@ Exporter::Result Exporter::exportCollision(NiNodeRef &parent, INode *node)
 	// marked as collision?
 	bool coll = npIsCollision(node);
 
+   bool local = !mFlattenHierarchy;
+   NiNodeRef nodeParent = mFlattenHierarchy ? mNiRoot : parent;
+
 	NiNodeRef newParent;
 	if (coll)
 	{
@@ -275,7 +278,7 @@ Exporter::Result Exporter::exportCollision(NiNodeRef &parent, INode *node)
 		body->SetRotation(q);
 		body->SetTranslation(Vector3(trans.x/7, trans.y/7, trans.z/7));
 */
-		newParent = makeNode(parent, node);
+		newParent = nodeParent; // always have collision one level up?
 
 		bhkSphereRepShapeRef shape = makeCollisionShape(node);
 		bhkRigidBodyRef body = makeCollisionBody(node);
@@ -283,18 +286,17 @@ Exporter::Result Exporter::exportCollision(NiNodeRef &parent, INode *node)
 
 		bhkCollisionObjectRef co = DynamicCast<bhkCollisionObject>(CreateBlock("bhkCollisionObject"));
 		co->SetBody(DynamicCast<NiObject>(body));
+      
 		co->SetParent(newParent);
 
 		// link
 		newParent->SetCollisionObject(DynamicCast<NiCollisionObject>(co));
 
-	} else
-	if (isCollisionGroup(node))
-	{
-		newParent = makeNode(parent, node);
-	} else
-		newParent = parent;
-
+	} else if (isCollisionGroup(node) && !mFlattenHierarchy) {
+		newParent = makeNode(nodeParent, node);
+   } else {
+		newParent = nodeParent;
+   }
 	for (int i=0; i<node->NumberOfChildren(); i++) 
 	{
 		Result result = exportCollision(newParent, node->GetChildNode(i));
@@ -315,13 +317,13 @@ bhkRigidBodyRef Exporter::makeCollisionBody(INode *node)
 
    // Handle compatibility
    npGetProp(node, NP_HVK_MASS_OLD, mass, NP_DEFAULT_HVK_EMPTY);
-   if (mass != NP_DEFAULT_HVK_EMPTY)
+   if (mass == NP_DEFAULT_HVK_EMPTY)
       npGetProp(node, NP_HVK_MASS, mass, NP_DEFAULT_HVK_MASS);
    npGetProp(node, NP_HVK_FRICTION_OLD, frict, NP_DEFAULT_HVK_EMPTY);
-   if (frict != NP_DEFAULT_HVK_EMPTY)
+   if (frict == NP_DEFAULT_HVK_EMPTY)
       npGetProp(node, NP_HVK_FRICTION, frict, NP_DEFAULT_HVK_FRICTION);
    npGetProp(node, NP_HVK_RESTITUTION_OLD, resti, NP_DEFAULT_HVK_EMPTY);
-   if (resti != NP_DEFAULT_HVK_EMPTY)
+   if (resti == NP_DEFAULT_HVK_EMPTY)
       npGetProp(node, NP_HVK_RESTITUTION, resti, NP_DEFAULT_HVK_RESTITUTION);
 
 	npGetProp(node, NP_HVK_LAYER, lyr, NP_DEFAULT_HVK_LAYER);
@@ -336,7 +338,7 @@ bhkRigidBodyRef Exporter::makeCollisionBody(INode *node)
 	npGetProp(node, NP_HVK_CENTER, center);
 
 	// setup body
-	bhkRigidBodyRef body = DynamicCast<bhkRigidBody>(CreateBlock("bhkRigidBody"));
+	bhkRigidBodyRef body = DynamicCast<bhkRigidBody>(CreateBlock("bhkRigidBodyT"));
 
 	body->SetLayer(lyr);
 	body->SetLayerCopy(lyr);
@@ -351,6 +353,8 @@ bhkRigidBodyRef Exporter::makeCollisionBody(INode *node)
 	body->SetMaxAngularVelocity(maxangvel);
 	body->SetPenetrationDepth(pendepth);
 	body->SetCenter(center);
+   QuaternionXYZW q; q.x = q.y = q.z = 0; q.w = 1.0f;
+   body->SetRotation(q);
 
 	return body;
 }
@@ -490,7 +494,6 @@ bhkSphereRepShapeRef Exporter::makeTriStripsShape(INode *node)
 	shape->SetUnknownInts1(unknownInts1);
 */
 
-   ASSERT(!"TODO: Need to support this");
 /* Still not handled
 	vector<uint> unknownInts2;
 	unknownInts2.resize(1);
diff --git a/NifExport/Config.cpp b/NifExport/Config.cpp
index 5c4937cadb20e65d8f923e8f922cad1db6c0e984..f9ab7303a6158bd3d9ec593149f5a5ae719c2d76 100755
--- a/NifExport/Config.cpp
+++ b/NifExport/Config.cpp
@@ -57,6 +57,13 @@ void Exporter::writeConfig(Interface *i)
       SetIniValue(NifExportSection, "TexturePrefix", mTexPrefix, iniName);
       SetIniValue(NifExportSection, "ExportCollision", mExportCollision, iniName);
       SetIniValue(NifExportSection, "RemapIndices", mRemapIndices, iniName);
+
+      SetIniValue(NifExportSection, "ExportExtraNodes", mExportExtraNodes, iniName);
+      SetIniValue(NifExportSection, "ExportSkin", mExportSkin, iniName);
+      SetIniValue(NifExportSection, "UserPropBuffer", mUserPropBuffer, iniName);
+      SetIniValue(NifExportSection, "FlattenHierarchy", mFlattenHierarchy, iniName);
+      SetIniValue(NifExportSection, "RemoveUnreferencedBones", mRemoveUnreferencedBones, iniName);
+      SetIniValue(NifExportSection, "SortNodesToEnd", mSortNodesToEnd, iniName);
    }
 }
 
diff --git a/NifExport/Exporter.cpp b/NifExport/Exporter.cpp
index a38bfe331892fd4a3c5d67ff83de4f2c477aad17..57c2e09580ae43c7895d49697712751cdccb90be 100755
--- a/NifExport/Exporter.cpp
+++ b/NifExport/Exporter.cpp
@@ -20,6 +20,9 @@ bool Exporter::mUserPropBuffer=false;
 bool Exporter::mFlattenHierarchy=false;
 bool Exporter::mRemoveUnreferencedBones=false;
 bool Exporter::mSortNodesToEnd=false;
+string Exporter::mGameName = "User";
+string Exporter::mNifVersion = "20.0.0.5";
+int Exporter::mNifUserVersion = 0;
 
 Exporter::Exporter(Interface *i, AppSettings *appSettings)
    : mI(i), mAppSettings(appSettings)
@@ -28,11 +31,21 @@ Exporter::Exporter(Interface *i, AppSettings *appSettings)
 
 Exporter::Result Exporter::doExport(NiNodeRef &root, INode *node)
 {
+   //root->SetName("Scene Root");
+
 	BSXFlagsRef bsx = CreateNiObject<BSXFlags>();
 	bsx->SetName("BSX");
 	bsx->SetFlags(0x00000002);
    root->AddExtraData(DynamicCast<NiExtraData>(bsx));
-   exportUPB(root, node);
+   bool ok = exportUPB(root, node);
+
+   if (!ok && Exporter::mExportCollision)
+   {
+      NiStringExtraDataRef strings = DynamicCast<NiStringExtraData>(CreateBlock("NiStringExtraData"));	
+      strings->SetName("UPB");
+      strings->SetData("Ellasticity = 0.300000\r\nFriction = 0.300000\r\nUnyielding = 0\r\nProxy_Geometry = <None>\r\nUse_Display_Proxy = 0\r\nDisplay_Children = 1\r\nDisable_Collisions = 0\r\nInactive = 0\r\nDisplay_Proxy = <None>\r\nMass = 0.000000\r\nSimulation_Geometry = 2\r\nCollision_Groups = 589825\r\n");
+      root->AddExtraData(DynamicCast<NiExtraData>(strings));
+   }
 
 	mNiRoot = root;
 	
diff --git a/NifExport/Exporter.h b/NifExport/Exporter.h
index a931c1be48718980b30b77c6e6906be033f09872..e73a5a4a163ca4774b1babc677131467ef4e2f54 100755
--- a/NifExport/Exporter.h
+++ b/NifExport/Exporter.h
@@ -5,6 +5,7 @@ using namespace Niflib;
 
 class BitmapTex;
 class AppSettings;
+class StdMat2;
 
 class Exporter
 {
@@ -49,6 +50,9 @@ public:
    static bool          mFlattenHierarchy;
    static bool          mRemoveUnreferencedBones;
    static bool          mSortNodesToEnd;
+   static string        mGameName;
+   static string        mNifVersion;
+   static int           mNifUserVersion;
 
 	Exporter(Interface *i, AppSettings *appSettings);
 
@@ -108,7 +112,8 @@ private:
 	void					nodeTransform(QuaternionXYZW &rot, Vector3 &trans, INode *node, TimeValue t, bool local=true);
 	Point3					getVertexNormal(Mesh* mesh, int faceNo, RVertex* rv);
 	bool					equal(const Vector3 &a, const Point3 &b, float thresh);
-	BitmapTex				*getTexture(Mtl *mtl);
+   BitmapTex				*getTexture(Mtl *mtl);
+   BitmapTex				*getTexture(Mtl *mtl, int i);
 	void					getTextureMatrix(Matrix3 &mat, Mtl *mtl);
    NiNodeRef				makeNode(NiNodeRef &parent, INode *maxNode, bool local=true);
    NiNodeRef				getNode(const string& name);
@@ -138,8 +143,10 @@ private:
 	/* texture & material */
 	// creates NiTexturingProperty + NiSourceTexture
 	void					makeTexture(NiAVObjectRef &parent, Mtl *mtl);
+   bool              makeTextureDesc(BitmapTex *bmTex, Niflib::TexDesc &td);
 	// creates a NiMaterialProperty
 	void					makeMaterial(NiAVObjectRef &parent, Mtl *mtl);
+   bool              exportCiv4Shader(NiAVObjectRef parent, Mtl* mtl);
 
 	/* havok & collision */
 	int						addVertex(vector<Vector3> &verts, vector<Vector3> &vnorms, const Point3 &pt, const Point3 &norm);
diff --git a/NifExport/Mesh.cpp b/NifExport/Mesh.cpp
index 2ec3cb8d42e6eafd40293523d2efb49b427ccf48..8c29ba46a93b61d848085215432dfa9294880620 100755
--- a/NifExport/Mesh.cpp
+++ b/NifExport/Mesh.cpp
@@ -251,7 +251,6 @@ NiTriBasedGeomRef Exporter::makeMesh(NiNodeRef &parent, Mtl *mtl, FaceGroup &grp
 
 	NiAVObjectRef av(DynamicCast<NiAVObject>(shape));
 	makeMaterial(av, mtl);
-	makeTexture(av, mtl);
 
 	parent->AddChild(DynamicCast<NiAVObject>(shape));
 
@@ -265,8 +264,10 @@ int Exporter::addVertex(FaceGroup &grp, int face, int vi, Mesh *mesh, const Matr
 	Point3 norm = getVertexNormal(mesh, face, mesh->getRVertPtr(vidx));
 
 	Point3 uv;
-	if (mesh->tVerts && mesh->tvFace)
+   if (mesh->tVerts && mesh->tvFace) {
 		uv = mesh->tVerts[ mesh->tvFace[ face ].t[ vi ]] * texm;
+      uv.y += 1.0f;
+   }
 
    Color4 col(1.0f, 1.0f, 1.0f);
    if (mVertexColors && !vertColors.empty()){
@@ -282,7 +283,7 @@ int Exporter::addVertex(FaceGroup &grp, int face, int vi, Mesh *mesh, const Matr
 		if (equal(grp.verts[i], pt, mWeldThresh) &&
 			equal(grp.vnorms[i], norm, 0))
 		{
-			if (mesh->tvFace && (grp.uvs[i].u!=uv.x || grp.uvs[i].v!=uv.y))
+			if (mesh->tVerts && mesh->tvFace && (grp.uvs[i].u!=uv.x || grp.uvs[i].v!=uv.y))
 				continue;
 
 			if (mVertexColors && !vertColors.empty() &&
diff --git a/NifExport/MtlTex.cpp b/NifExport/MtlTex.cpp
index a18a2b2886d785a9a1fa328f7be4c8f4cef14808..75b4089cd2050e44187e0961f0ab882b4a14ba92 100755
--- a/NifExport/MtlTex.cpp
+++ b/NifExport/MtlTex.cpp
@@ -1,20 +1,76 @@
 #include "pch.h"
 #include "stdmat.h"
+#include "shaders.h"
 #include "AppSettings.h"
+#include "obj/NiWireframeProperty.h"
+#include "obj/NiAlphaProperty.h"
+#include "obj/NiStencilProperty.h"
+#include "obj/NiShadeProperty.h"
+#include "obj/NiVertexColorProperty.h"
+#include "obj/NiDitherProperty.h"
+#include "obj/NiSpecularProperty.h"
 
 void Exporter::makeTexture(NiAVObjectRef &parent, Mtl *mtl)
 {
-	BitmapTex *bmTex = getTexture(mtl);
-
+   BitmapTex *bmTex = getTexture(mtl);
 	if (!bmTex)
-		return;
+      return;
 
-	NiTexturingPropertyRef texProp(DynamicCast<NiTexturingProperty>(CreateBlock("NiTexturingProperty")));
+	NiTexturingPropertyRef texProp = CreateNiObject<NiTexturingProperty>();
 	texProp->SetApplyMode(APPLY_MODULATE);
 	texProp->SetTextureCount(7);
 
 	TexDesc td;
-	td.source = DynamicCast<NiSourceTexture>(CreateBlock("NiSourceTexture"));
+   if (makeTextureDesc(bmTex, td))
+	   texProp->SetTexture(BASE_MAP, td);
+
+	NiPropertyRef prop = DynamicCast<NiProperty>(texProp);
+	parent->AddProperty(prop);
+}
+
+bool Exporter::makeTextureDesc(BitmapTex *bmTex, TexDesc& td)
+{
+   td.source = CreateNiObject<NiSourceTexture>();
+
+   // Filtering
+   switch (bmTex->GetFilterType())
+   {
+   case FILTER_PYR:  td.filterMode = FILTER_TRILERP; break;
+   case FILTER_SAT:  td.filterMode = FILTER_BILERP; break;
+   case FILTER_NADA: td.filterMode = FILTER_NEAREST; break;
+   }
+
+   td.clampMode = TexClampMode();  
+   switch (bmTex->GetTextureTiling())
+   {
+   case 3: td.clampMode = WRAP_S_WRAP_T; break;
+   case 1: td.clampMode = WRAP_S_CLAMP_T; break;
+   case 2: td.clampMode = CLAMP_S_WRAP_T; break;
+   case 0: td.clampMode = CLAMP_S_CLAMP_T; break;
+   }
+
+   if (UVGen *uvGen = bmTex->GetTheUVGen()){
+      if (RefTargetHandle ref = uvGen->GetReference(0)){
+         TexCoord trans, tiling;
+         float wangle;
+         bool ok = true;
+         if(ok) ok &= getMAXScriptValue(ref, "U_Offset", 0, trans.u);
+         if(ok) ok &= getMAXScriptValue(ref, "V_Offset", 0, trans.v);
+         if(ok) ok &= getMAXScriptValue(ref, "U_Tiling", 0, tiling.u);
+         if(ok) ok &= getMAXScriptValue(ref, "V_Tiling", 0, tiling.v);
+         if(ok) ok &= getMAXScriptValue(ref, "W_Angle", 0, wangle);
+         if (ok) {
+            if (trans.u != 0.0f || trans.v != 0.0f || tiling.u != 1.0f || tiling.v != 1.0f || wangle != 0.0f) {
+               td.hasTextureTransform = true;
+               td.translation = trans;
+               td.tiling = tiling;
+               td.wRotation = TORAD(wangle);
+               td.transformType_ = 1;
+               td.centerOffset = TexCoord(0.5, 0.5);
+            }
+         }
+      }
+   }
 
    // Get file name and check if it matches the "app" settings in the ini file
    TSTR mapPath;
@@ -31,23 +87,25 @@ void Exporter::makeTexture(NiAVObjectRef &parent, Mtl *mtl)
    {
       TSTR p, f;
       SplitPathFile(mapPath, &p, &f);
-	   TSTR newPath;
-	   if (mTexPrefix != "")
-		   newPath = TSTR(mTexPrefix.c_str()) + _T("\\") + f;
-	   else
-		   newPath = f;
-   	
+      TSTR newPath;
+      if (mTexPrefix != "")
+         newPath = TSTR(mTexPrefix.c_str()) + _T("\\") + f;
+      else
+         newPath = f;
+
       NiObjectRef unk_link(NULL);
-	   td.source->SetExternalTexture(newPath.data(), unk_link);
+      td.source->SetExternalTexture(newPath.data(), unk_link);
    }
-	texProp->SetTexture(BASE_MAP, td);
-
-	NiPropertyRef prop = DynamicCast<NiProperty>(texProp);
-	parent->AddProperty(prop);
+   return true;
 }
 
 void Exporter::makeMaterial(NiAVObjectRef &parent, Mtl *mtl)
 {
+   // Fill-in using the Civ4 Shader if available
+   bool done = exportCiv4Shader(parent, mtl);
+   if (done)
+      return;
+
 	string name;
 	NiMaterialPropertyRef mtlProp(DynamicCast<NiMaterialProperty>(CreateBlock("NiMaterialProperty")));
 	if (mtl)
@@ -74,6 +132,29 @@ void Exporter::makeMaterial(NiAVObjectRef &parent, Mtl *mtl)
       {
          StdMat2 * smtl = (StdMat2*)mtl;
          mtlProp->SetTransparency(smtl->GetOpacity(0));
+
+         if (smtl->SupportsShaders()) {
+            if (Shader *s = smtl->GetShader()) {
+               if (smtl->GetWire()){
+                  NiWireframePropertyRef wireProp = CreateNiObject<NiWireframeProperty>();
+                  wireProp->SetFlags(1);
+                  parent->AddProperty(wireProp);
+               }
+               if (smtl->GetTwoSided()){
+                  NiStencilPropertyRef stencil = CreateNiObject<NiStencilProperty>();
+                  stencil->SetStencilFunction(4);
+                  stencil->SetStencilEnabled(false);
+                  stencil->SetPassAction(3);
+                  stencil->SetDrawMode(3);
+                  parent->AddProperty(stencil);
+               }
+               if (smtl->IsFaceted()) {
+                  NiShadePropertyRef shade = CreateNiObject<NiShadeProperty>();
+                  shade->SetFlags(0);
+                  parent->AddProperty(shade);
+               }
+            }
+         }
       }
 	} else
 	{
@@ -90,6 +171,8 @@ void Exporter::makeMaterial(NiAVObjectRef &parent, Mtl *mtl)
 
 	NiPropertyRef prop = DynamicCast<NiProperty>(mtlProp);
 	parent->AddProperty(prop);
+
+   makeTexture(parent, mtl);
 }
 
 
@@ -133,6 +216,21 @@ BitmapTex *Exporter::getTexture(Mtl *mtl)
 	return bmTex;
 }
 
+BitmapTex *Exporter::getTexture(Mtl *mtl, int i)
+{
+   if (mtl) {
+      int texMaps = mtl->NumSubTexmaps();
+      if (i < texMaps) {
+         if (Texmap *texMap = mtl->GetSubTexmap(i)) {
+            if (texMap->ClassID() == Class_ID(BMTEX_CLASS_ID, 0)) {
+               return (BitmapTex*)texMap;
+            }
+         }
+      }
+   }
+   return NULL;
+}
+
 void Exporter::getTextureMatrix(Matrix3 &mat, Mtl *mtl)
 {
 	BitmapTex *tex = getTexture(mtl);
@@ -141,3 +239,207 @@ void Exporter::getTextureMatrix(Matrix3 &mat, Mtl *mtl)
 	else
 		mat.IdentityMatrix();
 }
+
+
+bool Exporter::exportCiv4Shader(NiAVObjectRef parent, Mtl* mtl)
+{
+   if (!mtl) 
+      return false;
+
+   RefTargetHandle ref = mtl->GetReference(2/*shader*/);
+   if (!ref)
+      return false;
+
+   TSTR shaderByName;
+   if(mtl->ClassID() == Class_ID(DMTL_CLASS_ID, 0) )
+   {
+      StdMat2 * smtl = (StdMat2*)mtl;
+      if (smtl->SupportsShaders()) {
+         if (Shader *s = smtl->GetShader()) {
+            s->GetClassName(shaderByName);
+         }
+      }
+   }
+   if (shaderByName != TSTR("CivilizationIV Shader"))
+         return false;
+
+   //if (Shader *s = mtl->GetShader()) {
+   //   TSTR className;
+   //   s->GetClassName(className);
+   //   if (className != TSTR("CivilizationIV Shader"))
+   //      return false;
+
+   Color ambient = Color(0.0f,0.0f,0.0f), diffuse = Color(0.0f,0.0f,0.0f), specular = Color(0.0f,0.0f,0.0f), emittance = Color(0.0f,0.0f,0.0f);
+   float shininess = 0.0f, alpha = 0.0f, Magnitude = 0.0f, LumaScale = 0.0f, LumaOffset = 0.0f;
+   int TestRef = 0, srcBlend = 0, destBlend = 0, TestMode = 0;
+   bool AlphaTestEnable = false;
+   int ApplyMode = 0, SrcVertexMode = 0, LightingMode = 0;
+   bool VertexColorsEnable = false, SpecularEnable = false, NoSorter = false, Dither = false;
+   int alphaMode = 0, BaseTextureExport=0, DarkTextureExport=0, DetailTextureExport=0;
+   int Decal1TextureExport=0, Decal2TextureExport=0, GlossTextureExport=0, GlowTextureExport=0;
+   LPTSTR CustomShader = NULL;
+   int ShaderViewerTechnique=0, ShaderExportTechnique=0;
+   bool UseNormalMaps = false;
+   int NormalMapTechnique=0;
+
+   bool ok = true;
+   
+   if(ok) ok &= getMAXScriptValue(ref, "ambient", 0, ambient );
+   if(ok) ok &= getMAXScriptValue(ref, "diffuse", 0, diffuse );
+   if(ok) ok &= getMAXScriptValue(ref, "specular", 0, specular );
+   if(ok) ok &= getMAXScriptValue(ref, "emittance", 0, emittance );
+   if(ok) ok &= getMAXScriptValue(ref, "shininess", 0, shininess );
+   if(ok) ok &= getMAXScriptValue(ref, "alpha", 0, alpha );
+   if(ok) ok &= getMAXScriptValue(ref, "Bump_Map_Magnitude", 0, Magnitude);
+   if(ok) ok &= getMAXScriptValue(ref, "Bump_Map_Luma_Scale", 0, LumaScale);
+   if(ok) ok &= getMAXScriptValue(ref, "Bump_Map_Luma_offset", 0, LumaOffset);
+   if(ok) ok &= getMAXScriptValue(ref, "TestRef", 0, TestRef );
+   if(ok) ok &= getMAXScriptValue(ref, "AlphaTestEnable", 0, AlphaTestEnable );
+   if(ok) ok &= getMAXScriptValue(ref, "Vertex_Color_Enable", 0, VertexColorsEnable);
+   if(ok) ok &= getMAXScriptValue(ref, "SpecularEnable", 0, SpecularEnable);
+   if(ok) ok &= getMAXScriptValue(ref, "NoSorter", 0, NoSorter);
+   if(ok) ok &= getMAXScriptValue(ref, "Dither", 0, Dither );
+   if(ok) ok &= getMAXScriptValue(ref, "UseNormalMaps", 0, UseNormalMaps );
+   if(ok) ok &= getMAXScriptValue(ref, "srcBlend", 0, srcBlend);
+   if(ok) ok &= getMAXScriptValue(ref, "destBlend", 0, destBlend);
+   if(ok) ok &= getMAXScriptValue(ref, "TestMode", 0, TestMode );
+   if(ok) ok &= getMAXScriptValue(ref, "ApplyMode", 0, ApplyMode);
+   if(ok) ok &= getMAXScriptValue(ref, "SourceVertexMode", 0, SrcVertexMode);
+   if(ok) ok &= getMAXScriptValue(ref, "LightingMode", 0, LightingMode);
+   if(ok) ok &= getMAXScriptValue(ref, "alphaMode", 0, alphaMode);
+   if(ok) ok &= getMAXScriptValue(ref, "BaseTextureExport", 0, BaseTextureExport);
+   if(ok) ok &= getMAXScriptValue(ref, "DarkTextureExport", 0, DarkTextureExport);
+   if(ok) ok &= getMAXScriptValue(ref, "DetailTextureExport", 0, DetailTextureExport);
+   if(ok) ok &= getMAXScriptValue(ref, "Decal1TextureExport", 0, Decal1TextureExport);
+   if(ok) ok &= getMAXScriptValue(ref, "Decal2TextureExport", 0, Decal2TextureExport);
+   if(ok) ok &= getMAXScriptValue(ref, "GlossTextureExport", 0, GlossTextureExport);
+   if(ok) ok &= getMAXScriptValue(ref, "GlowTextureExport", 0, GlowTextureExport);
+   if(ok) ok &= getMAXScriptValue(ref, "CustomShader", 0, CustomShader );
+   if(ok) ok &= getMAXScriptValue(ref, "ShaderViewerTechnique", 0, ShaderViewerTechnique);
+   if(ok) ok &= getMAXScriptValue(ref, "ShaderExportTechnique", 0, ShaderExportTechnique);
+   if(ok) ok &= getMAXScriptValue(ref, "NormalMapTechnique", 0, NormalMapTechnique );
+   
+   if (ok) // civ4 shader
+   {
+      NiMaterialPropertyRef mtlProp = CreateNiObject<NiMaterialProperty>();
+      parent->AddProperty(mtlProp);
+
+      mtlProp->SetName((char*)mtl->GetName());
+      mtlProp->SetAmbientColor(TOCOLOR3(ambient));
+      mtlProp->SetDiffuseColor(TOCOLOR3(diffuse));
+      mtlProp->SetSpecularColor(TOCOLOR3(specular));
+      mtlProp->SetEmissiveColor(TOCOLOR3(emittance));
+      mtlProp->SetGlossiness(shininess);
+      mtlProp->SetTransparency(alpha/100.0f);
+      if(mtl->ClassID() == Class_ID(DMTL_CLASS_ID, 0) )
+      {
+         StdMat2 * smtl = (StdMat2*)mtl;
+         if (smtl->SupportsShaders()) {
+            if (Shader *s = smtl->GetShader()) {
+               if (smtl->GetWire()){
+                  NiWireframePropertyRef wireProp = CreateNiObject<NiWireframeProperty>();
+                  wireProp->SetFlags(1);
+                  parent->AddProperty(wireProp);
+               }
+               if (smtl->GetTwoSided()){
+                  NiStencilPropertyRef stencil = CreateNiObject<NiStencilProperty>();
+                  stencil->SetStencilFunction(4);
+                  stencil->SetStencilEnabled(false);
+                  stencil->SetPassAction(3);
+                  stencil->SetDrawMode(3);
+                  parent->AddProperty(stencil);
+               }
+               if (smtl->IsFaceted()) {
+                  NiShadePropertyRef shade = CreateNiObject<NiShadeProperty>();
+                  shade->SetFlags(0);
+                  parent->AddProperty(shade);
+               }
+            }
+         }
+      }
+      if (VertexColorsEnable && (SrcVertexMode != 2 || LightingMode != 1)) {
+         NiVertexColorPropertyRef vertexColor = CreateNiObject<NiVertexColorProperty>();
+         parent->AddProperty(vertexColor);
+         vertexColor->SetVertexMode(VertMode(SrcVertexMode));
+         vertexColor->SetLightingMode(LightMode(LightingMode));
+         vertexColor->SetFlags(LightingMode + (SrcVertexMode << 3));
+      }
+      if (SpecularEnable) {
+         NiSpecularPropertyRef prop = CreateNiObject<NiSpecularProperty>();
+         parent->AddProperty(prop);
+         prop->SetFlags(1);
+
+      }
+      if (Dither) {
+         NiDitherPropertyRef prop = CreateNiObject<NiDitherProperty>();
+         parent->AddProperty(prop);
+         prop->SetFlags(1);
+      }
+      if (alphaMode != 0 || AlphaTestEnable) {
+         // always add alpha ???
+         NiAlphaPropertyRef alphaProp = CreateNiObject<NiAlphaProperty>();
+         parent->AddProperty(alphaProp);
+         alphaProp->SetAlphaBlend(true);
+         if (alphaMode == 0) { // automatic
+            alphaProp->SetSourceBlendMode(NiAlphaProperty::BlendMode(srcBlend));
+            alphaProp->SetDestBlendMode(NiAlphaProperty::BlendMode(destBlend));
+         } else if (alphaMode == 1) { // None
+            alphaProp->SetAlphaBlend(false);
+            alphaProp->SetSourceBlendMode(NiAlphaProperty::BM_SRC_ALPHA);
+            alphaProp->SetDestBlendMode(NiAlphaProperty::BM_ONE_MINUS_SRC_ALPHA);
+         } else if (alphaMode == 2) { // Standard
+            alphaProp->SetSourceBlendMode(NiAlphaProperty::BM_SRC_ALPHA);
+            alphaProp->SetDestBlendMode(NiAlphaProperty::BM_ONE_MINUS_SRC_ALPHA);
+         } else if (alphaMode == 3) { // Additive
+            alphaProp->SetSourceBlendMode(NiAlphaProperty::BM_ONE);
+            alphaProp->SetDestBlendMode(NiAlphaProperty::BM_ONE);
+         } else if (alphaMode == 4) { // Multiplicative
+            alphaProp->SetSourceBlendMode(NiAlphaProperty::BM_ZERO);
+            alphaProp->SetDestBlendMode(NiAlphaProperty::BM_SRC_COLOR);
+         } else { // Advanced
+            alphaProp->SetSourceBlendMode(NiAlphaProperty::BlendMode(srcBlend));
+            alphaProp->SetDestBlendMode(NiAlphaProperty::BlendMode(destBlend));
+         }
+         alphaProp->SetTestMode(NiAlphaProperty::TestMode(TestMode));
+         alphaProp->SetAlphaSort(!NoSorter);
+         alphaProp->SetAlphaTestThreshold(TestRef);
+         alphaProp->SetAlphaTest(AlphaTestEnable);
+      }
+
+      int ntex = mtl->NumSubTexmaps();
+      if (ntex > 0)
+      {
+         ntex = min(ntex, 7);
+         TexType texmap[] = {BASE_MAP, DARK_MAP, DETAIL_MAP, DECAL_0_MAP, BUMP_MAP, GLOSS_MAP, GLOW_MAP, DECAL_1_MAP};
+         NiTexturingPropertyRef texProp = CreateNiObject<NiTexturingProperty>();       
+         texProp->SetApplyMode(Niflib::ApplyMode(ApplyMode));
+         texProp->SetTextureCount(7);
+         for (int i = 0; i < ntex; ++i) {
+
+            BitmapTex *bmTex = getTexture(mtl, i);
+            if (!bmTex)
+               continue;
+
+            TexDesc td;
+            if (makeTextureDesc(bmTex, td)) {
+               TexType textype = texmap[i];
+               texProp->SetTexture(textype, td);
+               if (textype == BUMP_MAP) {
+                  td.source->SetPixelLayout(PIX_LAY_BUMPMAP);
+                  texProp->SetLumaOffset(LumaOffset);
+                  texProp->SetLumaScale(LumaScale);
+
+                  Matrix22 m2;
+                  m2[0][0] = m2[1][1] = Magnitude;
+                  m2[0][1] = m2[1][0] = 0.0f;
+                  texProp->SetBumpMapMatrix(m2);
+               }
+            }
+         }
+
+         parent->AddProperty(texProp);
+      }
+      return true;
+   }
+   return false;
+}
diff --git a/NifExport/NifExport.cpp b/NifExport/NifExport.cpp
index 4095a3ab849228e0a551f44405b8f0545c0f0d1a..26051600b07b974c6498c8782ea47f01f4ff7e15 100755
--- a/NifExport/NifExport.cpp
+++ b/NifExport/NifExport.cpp
@@ -66,6 +66,16 @@ BOOL CALLBACK NifExportOptionsDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARA
 	{
 		case WM_INITDIALOG:
 			{
+            // Append file version to dialog
+            TSTR fileVersion = GetFileVersion(NULL);
+            if (!fileVersion.isNull()) {
+               char buffer[256];
+               GetWindowText(hWnd, buffer, _countof(buffer));
+               _tcscat(buffer, TEXT(" "));
+               _tcscat(buffer, fileVersion);
+               SetWindowText(hWnd, buffer);
+            }
+
 				imp = (NifExport *)lParam;
 				CenterWindow(hWnd,GetParent(hWnd));
 				CheckDlgButton(hWnd, IDC_CHK_STRIPS, Exporter::mTriStrips);
@@ -75,7 +85,23 @@ BOOL CALLBACK NifExportOptionsDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARA
 				CheckDlgButton(hWnd, IDC_CHK_VCOLORS, Exporter::mVertexColors);
 				SetDlgItemText(hWnd, IDC_ED_TEXPREFIX, Exporter::mTexPrefix.c_str());
 				CheckDlgButton(hWnd, IDC_CHK_COLL, Exporter::mExportCollision);
-				CheckDlgButton(hWnd, IDC_CHK_REMAP, Exporter::mRemapIndices);
+            CheckDlgButton(hWnd, IDC_CHK_REMAP, Exporter::mRemapIndices);
+
+            CheckDlgButton(hWnd, IDC_CHK_EXTRA, Exporter::mExportExtraNodes);
+            CheckDlgButton(hWnd, IDC_CHK_SKIN, Exporter::mExportSkin);
+            CheckDlgButton(hWnd, IDC_CHK_UPB, Exporter::mUserPropBuffer);
+            CheckDlgButton(hWnd, IDC_CHK_HIER, Exporter::mFlattenHierarchy);
+            CheckDlgButton(hWnd, IDC_CHK_REM_BONES, Exporter::mRemoveUnreferencedBones);
+            CheckDlgButton(hWnd, IDC_CHK_SORTNODES, Exporter::mSortNodesToEnd);
+
+            string selection = Exporter::mGameName;
+            string version = Exporter::mNifVersion;
+            string userVer = FormatString("%d", Exporter::mNifUserVersion);
+            for (AppSettingsMap::iterator itr = TheAppSettings.begin(), end = TheAppSettings.end(); itr != end; ++itr)
+               SendDlgItemMessage(hWnd, IDC_CB_GAME, CB_ADDSTRING, 0, LPARAM(itr->Name.c_str()));
+            SendDlgItemMessage(hWnd, IDC_CB_GAME, CB_SELECTSTRING, WPARAM(-1), LPARAM(selection.c_str()));
+            SendDlgItemMessage(hWnd, IDC_CB_VERSION, WM_SETTEXT, 0, LPARAM(version.c_str()));
+            SendDlgItemMessage(hWnd, IDC_CB_USER_VERSION, WM_SETTEXT, 0, LPARAM(userVer.c_str()));
 
 				TSTR tmp;
 				tmp.printf("%.4f", Exporter::mWeldThresh);
@@ -92,11 +118,23 @@ BOOL CALLBACK NifExportOptionsDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARA
 		case WM_COMMAND:
 			if (HIWORD(wParam) == BN_CLICKED)
 			{
-				char tmp[MAX_PATH];
+				char tmp[MAX_PATH], *end;
 				bool close = false;
 				switch (LOWORD(wParam))
 				{
 					case IDOK:
+                  // Validity Check
+                  GetDlgItemText(hWnd, IDC_CB_VERSION, tmp, MAX_PATH);
+                  if (tmp[0] != 0)
+                  {
+                     int nifVersion = GetVersion(tmp);
+                     if (!IsVersionSupported(nifVersion))
+                     {
+                        MessageBox(hWnd, FormatString("Version '%s' is not a supported version.", tmp).c_str(), "NifExport", MB_OK|MB_ICONSTOP);
+                        return FALSE;
+                     }
+                  }
+
 						Exporter::mTriStrips = IsDlgButtonChecked(hWnd, IDC_CHK_STRIPS);
 						Exporter::mExportHidden = IsDlgButtonChecked(hWnd, IDC_CHK_HIDDEN);
 						Exporter::mExportFurn = IsDlgButtonChecked(hWnd, IDC_CHK_FURN);
@@ -104,6 +142,13 @@ BOOL CALLBACK NifExportOptionsDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARA
 						Exporter::mVertexColors = IsDlgButtonChecked(hWnd, IDC_CHK_VCOLORS);
 						Exporter::mExportCollision = IsDlgButtonChecked(hWnd, IDC_CHK_COLL);
 						Exporter::mRemapIndices = IsDlgButtonChecked(hWnd, IDC_CHK_REMAP);
+
+                  Exporter::mExportExtraNodes = IsDlgButtonChecked(hWnd, IDC_CHK_EXTRA);
+                  Exporter::mExportSkin = IsDlgButtonChecked(hWnd, IDC_CHK_SKIN);
+                  Exporter::mUserPropBuffer = IsDlgButtonChecked(hWnd, IDC_CHK_UPB);
+                  Exporter::mFlattenHierarchy = IsDlgButtonChecked(hWnd, IDC_CHK_HIER);
+                  Exporter::mRemoveUnreferencedBones = IsDlgButtonChecked(hWnd, IDC_CHK_REM_BONES);
+                  Exporter::mSortNodesToEnd = IsDlgButtonChecked(hWnd, IDC_CHK_SORTNODES);
 							
 						GetDlgItemText(hWnd, IDC_ED_TEXPREFIX, tmp, MAX_PATH);
 						Exporter::mTexPrefix = tmp;
@@ -111,6 +156,16 @@ BOOL CALLBACK NifExportOptionsDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARA
 						GetDlgItemText(hWnd, IDC_ED_WELDTHRESH, tmp, MAX_PATH);
 						Exporter::mWeldThresh = atof(tmp);
 
+                  GetDlgItemText(hWnd, IDC_CB_GAME, tmp, MAX_PATH);
+                  if (AppSettings *appSettings = FindAppSetting(tmp))
+                  {
+                     Exporter::mGameName = appSettings->Name;
+                     GetDlgItemText(hWnd, IDC_CB_VERSION, tmp, MAX_PATH);
+                     Exporter::mNifVersion = tmp;
+                     GetDlgItemText(hWnd, IDC_CB_USER_VERSION, tmp, MAX_PATH);
+                     Exporter::mNifUserVersion = strtol(tmp, &end, 0);
+                  }
+
 						EndDialog(hWnd, imp->mDlgResult=IDOK);
 						close = true;
 						break;
@@ -124,8 +179,7 @@ BOOL CALLBACK NifExportOptionsDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARA
 				if (close)
 					SendMessage(hWnd, WM_CLOSE, 0, 0);
 			}
-
-			if (HIWORD(wParam) == STN_CLICKED)
+         else if (HIWORD(wParam) == STN_CLICKED)
 			{
 				if (LOWORD(wParam) == IDC_LBL_LINK)
 				{
@@ -133,7 +187,21 @@ BOOL CALLBACK NifExportOptionsDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARA
 						         NULL, NULL, SW_SHOWDEFAULT);
 				}
 			}
-
+         else if (HIWORD(wParam) == CBN_SELCHANGE)
+         {
+            if (LOWORD(wParam) == IDC_CB_GAME)
+            {
+               char tmp[MAX_PATH];
+               GetDlgItemText(hWnd, IDC_CB_GAME, tmp, MAX_PATH);
+               if (AppSettings *appSettings = FindAppSetting(tmp))
+               {
+                  string version = appSettings->NiVersion;
+                  string userVer = FormatString("%d", appSettings->NiUserVersion);
+                  SendDlgItemMessage(hWnd, IDC_CB_VERSION, WM_SETTEXT, 0, LPARAM(version.c_str()));
+                  SendDlgItemMessage(hWnd, IDC_CB_USER_VERSION, WM_SETTEXT, 0, LPARAM(userVer.c_str()));
+               }
+            }
+         }
 			break;
 	}
 	return FALSE;
@@ -243,12 +311,15 @@ int	NifExport::DoExport(const TCHAR *name, ExpInterface *ei, Interface *i, BOOL
          appSettings = FindAppSetting(curapp);
       }
    }
-   if (appSettings == NULL && !TheAppSettings.empty()){
+   if (appSettings == NULL && !TheAppSettings.empty())
       appSettings = &TheAppSettings.front();
-   }
 
 	if(!suppressPrompts)
 	{
+      Exporter::mGameName = appSettings->Name;
+      Exporter::mNifVersion = appSettings->NiVersion;
+      Exporter::mNifUserVersion = appSettings->NiUserVersion;
+
 		if (DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_PANEL), GetActiveWindow(), NifExportOptionsDlgProc, (LPARAM)this) != IDOK)
 			return true;
 
@@ -256,10 +327,28 @@ int	NifExport::DoExport(const TCHAR *name, ExpInterface *ei, Interface *i, BOOL
 		Exporter::writeConfig(i);
 		// write config to root node
 		Exporter::writeConfig(i->GetRootNode());
+
+      // Update the current app version
+      appSettings = FindAppSetting(Exporter::mGameName);
+      if (appSettings == NULL && !TheAppSettings.empty())
+         appSettings = &TheAppSettings.front();
+      appSettings->NiVersion = Exporter::mNifVersion;
+      appSettings->NiUserVersion = Exporter::mNifUserVersion;
+      appSettings->WriteSettings(i);
 	}
 
 	try
 	{
+      int nifVersion = VER_20_0_0_5;
+      int nifUserVer = Exporter::mNifUserVersion;
+
+      if (!Exporter::mNifVersion.empty())
+      {
+         nifVersion = GetVersion(Exporter::mNifVersion);
+         if (!IsVersionSupported(nifVersion))
+            throw exception(FormatString("Version '%s' is not a supported version.").c_str());
+      }
+
 		Exporter::mSelectedOnly = (options&SCENE_EXPORT_SELECTED) != 0;
 		Exporter exp(i, appSettings);
 		
@@ -269,7 +358,7 @@ int	NifExport::DoExport(const TCHAR *name, ExpInterface *ei, Interface *i, BOOL
 		if (result!=Exporter::Ok)
 			throw exception("Unknown error.");
 
-		WriteNifTree(name, NiObjectRef(root), VER_20_0_0_5, 11);
+		WriteNifTree(name, NiObjectRef(root), nifVersion, nifUserVer);
 	}
 
 	catch (exception &e)
diff --git a/NifExport/NifExport.rc b/NifExport/NifExport.rc
index 038667854b98a6945469e8acfb823773be7c6033..efbb97acbaf89c7f9b54e300fcb1fe00dbc39d73 100755
--- a/NifExport/NifExport.rc
+++ b/NifExport/NifExport.rc
@@ -13,7 +13,7 @@
 #undef APSTUDIO_READONLY_SYMBOLS
 
 /////////////////////////////////////////////////////////////////////////////
-// Deutsch (Deutschland) resources
+// German (Germany) resources
 
 #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU)
 #ifdef _WIN32
@@ -35,12 +35,12 @@ END
 
 #endif    // APSTUDIO_INVOKED
 
-#endif    // Deutsch (Deutschland) resources
+#endif    // German (Germany) resources
 /////////////////////////////////////////////////////////////////////////////
 
 
 /////////////////////////////////////////////////////////////////////////////
-// Englisch (USA) resources
+// English (U.S.) resources
 
 #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
 #ifdef _WIN32
@@ -73,48 +73,43 @@ END
 // Dialog
 //
 
-IDD_PANEL DIALOGEX 0, 0, 200, 137
-STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | 
-    WS_SYSMENU
+IDD_PANEL DIALOGEX 0, 0, 207, 187
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
 EXSTYLE WS_EX_TOOLWINDOW
 CAPTION "Export Nif"
 FONT 8, "MS Sans Serif", 0, 0, 0x1
 BEGIN
-    CONTROL         "",IDC_EDIT,"CustEdit",NOT WS_VISIBLE | WS_TABSTOP,148,8,
-                    35,10
-    CONTROL         "",IDC_SPIN,"SpinnerControl",NOT WS_VISIBLE,186,7,7,10
-    PUSHBUTTON      "&Export",IDOK,5,115,34,14
-    PUSHBUTTON      "&Cancel",IDCANCEL,45,115,33,14
-    CONTROL         "Include &Hidden",IDC_CHK_HIDDEN,"Button",
-                    BS_AUTOCHECKBOX | WS_TABSTOP,80,5,64,10
-    CONTROL         "Generate &Strips",IDC_CHK_STRIPS,"Button",
-                    BS_AUTOCHECKBOX | WS_TABSTOP,5,5,65,10
-    CONTROL         "Furniture &Markers",IDC_CHK_FURN,"Button",
-                    BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,5,15,71,10
-    EDITTEXT        IDC_ED_TEXPREFIX,5,60,190,12,ES_AUTOHSCROLL
-    LTEXT           "Texture &Prefix",IDC_STATIC,5,50,44,8
-    CONTROL         "&Lights",IDC_CHK_LIGHTS,"Button",BS_AUTOCHECKBOX | 
-                    WS_DISABLED | WS_TABSTOP,5,25,35,10
-    EDITTEXT        IDC_ED_WELDTHRESH,163,22,35,12,ES_AUTOHSCROLL | NOT 
-                    WS_VISIBLE | WS_DISABLED
-    LTEXT           "Auto-&Weld",IDC_LBL_WELDTHRESH,160,30,34,8,NOT 
-                    WS_VISIBLE | WS_DISABLED
-    CONTROL         "Export Co&llision",IDC_CHK_COLL,"Button",
-                    BS_AUTOCHECKBOX | WS_TABSTOP,80,15,68,10
-    CONTROL         "&Vertex Colors",IDC_CHK_VCOLORS,"Button",
-                    BS_AUTOCHECKBOX | WS_TABSTOP,80,25,68,10
-    LTEXT           "http://niftools.sourceforge.net",IDC_LBL_LINK,98,114,95,
-                    14,SS_NOTIFY | SS_CENTERIMAGE
-    CONTROL         "&Remap Indices",IDC_CHK_REMAP,"Button",BS_AUTOCHECKBOX | 
-                    WS_TABSTOP,80,35,68,10
-    COMBOBOX        IDC_CB_GAME,5,90,105,70,CBS_DROPDOWN | CBS_SORT | 
-                    WS_DISABLED | WS_VSCROLL | WS_TABSTOP
-    LTEXT           "Game",IDC_STATIC,5,79,66,8,WS_DISABLED
-    EDITTEXT        IDC_CB_VERSION,115,90,45,12,ES_AUTOHSCROLL | WS_DISABLED
-    LTEXT           "Version",IDC_STATIC,115,79,39,8,WS_DISABLED
-    EDITTEXT        IDC_CB_USER_VERSION,165,90,30,12,ES_AUTOHSCROLL | 
-                    WS_DISABLED
-    LTEXT           "User",IDC_STATIC,165,79,25,8,WS_DISABLED
+    GROUPBOX        "Export:",IDC_STATIC,7,7,81,97
+    CONTROL         "&Hidden Nodes",IDC_CHK_HIDDEN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,17,67,10
+    CONTROL         "Co&llision",IDC_CHK_COLL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,29,67,10
+    CONTROL         "&Vertex Colors",IDC_CHK_VCOLORS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,41,67,10
+    CONTROL         "Skin Modifier",IDC_CHK_SKIN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,53,67,10
+    CONTROL         "&Animation",IDC_CHK_ANIMATION,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_DISABLED | WS_TABSTOP,14,65,67,10
+    CONTROL         "Furniture &Markers",IDC_CHK_FURN,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_DISABLED | WS_TABSTOP,14,77,67,10
+    CONTROL         "&Lights",IDC_CHK_LIGHTS,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_DISABLED | WS_TABSTOP,14,89,67,10
+    GROUPBOX        "Behaviors:",IDC_STATIC,94,6,101,97
+    CONTROL         "Generate &Strips",IDC_CHK_STRIPS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,17,88,10
+    CONTROL         "&Remap Indices",IDC_CHK_REMAP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,29,88,10
+    CONTROL         "Extra Nodes on Mesh",IDC_CHK_EXTRA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,41,88,11
+    CONTROL         "Add User Prop Buffer",IDC_CHK_UPB,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,53,88,11
+    CONTROL         "Flatten Hierarchy",IDC_CHK_HIER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,65,88,10
+    CONTROL         "Remove Extra Bones",IDC_CHK_REM_BONES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,77,88,10
+    CONTROL         "Sort Nodes",IDC_CHK_SORTNODES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,89,88,10
+    CONTROL         "",IDC_SPIN,"SpinnerControl",NOT WS_VISIBLE,193,7,7,10
+    CONTROL         "",IDC_EDIT,"CustEdit",NOT WS_VISIBLE | WS_TABSTOP,194,18,6,10
+    EDITTEXT        IDC_ED_WELDTHRESH,189,30,11,12,ES_AUTOHSCROLL | NOT WS_VISIBLE | WS_DISABLED
+    LTEXT           "Auto-&Weld",IDC_LBL_WELDTHRESH,192,42,8,8,NOT WS_VISIBLE | WS_DISABLED
+    LTEXT           "Default Texture &Prefix:",IDC_STATIC,7,111,71,8
+    EDITTEXT        IDC_ED_TEXPREFIX,7,122,190,12,ES_AUTOHSCROLL
+    LTEXT           "Game",IDC_STATIC,7,138,66,8
+    COMBOBOX        IDC_CB_GAME,7,149,105,70,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+    LTEXT           "Version",IDC_STATIC,117,138,39,8
+    EDITTEXT        IDC_CB_VERSION,117,149,45,12,ES_AUTOHSCROLL
+    LTEXT           "User",IDC_STATIC,167,138,25,8
+    EDITTEXT        IDC_CB_USER_VERSION,167,149,30,12,ES_AUTOHSCROLL
+    DEFPUSHBUTTON   "&Export",IDOK,5,166,34,14
+    PUSHBUTTON      "&Cancel",IDCANCEL,45,166,33,14
+    LTEXT           "http://niftools.sourceforge.net",IDC_LBL_LINK,105,166,95,14,SS_NOTIFY | SS_CENTERIMAGE
 END
 
 
@@ -129,14 +124,53 @@ BEGIN
     IDD_PANEL, DIALOG
     BEGIN
         LEFTMARGIN, 7
-        RIGHTMARGIN, 193
+        RIGHTMARGIN, 200
         TOPMARGIN, 7
-        BOTTOMMARGIN, 130
+        BOTTOMMARGIN, 180
     END
 END
 #endif    // APSTUDIO_INVOKED
 
 
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 0,2,0,0
+ PRODUCTVERSION 0,2,0,0
+ FILEFLAGSMASK 0x37L
+#ifdef _DEBUG
+ FILEFLAGS 0x21L
+#else
+ FILEFLAGS 0x20L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040904b0"
+        BEGIN
+            VALUE "FileDescription", "3ds Max Nif Exporter"
+            VALUE "FileVersion", "0, 2, 0, 0"
+            VALUE "InternalName", "NifExport.dle"
+            VALUE "LegalCopyright", "Copyright (c) 2006, NIF File Format Library and Tools\r\nAll rights reserved."
+            VALUE "OriginalFilename", "NifExport.dle"
+            VALUE "ProductName", "3ds Max Nif Exporter"
+            VALUE "ProductVersion", "0, 2, 0, 0"
+            VALUE "SpecialBuild", "Alpha"
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x409, 1200
+    END
+END
+
+
 /////////////////////////////////////////////////////////////////////////////
 //
 // String Table
@@ -149,7 +183,7 @@ BEGIN
     IDS_SPIN                "Spin"
 END
 
-#endif    // Englisch (USA) resources
+#endif    // English (U.S.) resources
 /////////////////////////////////////////////////////////////////////////////
 
 
diff --git a/NifExport/NifExport_VC80.vcproj b/NifExport/NifExport_VC80.vcproj
index fc8e25e2ef0100924b32526d640dbcbc0fd0b6c3..dda568d17180c761d47f363dfe57d6d4527b6597 100644
--- a/NifExport/NifExport_VC80.vcproj
+++ b/NifExport/NifExport_VC80.vcproj
@@ -47,7 +47,7 @@
 			/>
 			<Tool
 				Name="VCCLCompilerTool"
-				AdditionalOptions="/LD /FI&quot;$(ProjectDir)pch.h&quot;"
+				AdditionalOptions="/LD /FI&quot;$(ProjectDir)pch.h&quot; /Zm200"
 				Optimization="2"
 				InlineFunctionExpansion="2"
 				EnableIntrinsicFunctions="true"
@@ -153,7 +153,7 @@
 			/>
 			<Tool
 				Name="VCCLCompilerTool"
-				AdditionalOptions="/LD /FI&quot;$(ProjectDir)pch.h&quot;"
+				AdditionalOptions="/LD /FI&quot;$(ProjectDir)pch.h&quot; /Zm200"
 				Optimization="0"
 				AdditionalIncludeDirectories="C:\3dsmax8\maxsdk\include;..\..\niflib;..\NifCommon"
 				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS"
@@ -250,7 +250,7 @@
 			/>
 			<Tool
 				Name="VCCLCompilerTool"
-				AdditionalOptions="/LD /FI&quot;$(ProjectDir)pch.h&quot;"
+				AdditionalOptions="/LD /FI&quot;$(ProjectDir)pch.h&quot; /Zm200"
 				Optimization="0"
 				AdditionalIncludeDirectories="C:\3dsmax6\maxsdk\include;..\..\niflib;..\NifCommon"
 				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS"
@@ -349,7 +349,7 @@
 			/>
 			<Tool
 				Name="VCCLCompilerTool"
-				AdditionalOptions="/LD /FI&quot;$(ProjectDir)pch.h&quot;"
+				AdditionalOptions="/LD /FI&quot;$(ProjectDir)pch.h&quot; /Zm200"
 				Optimization="2"
 				InlineFunctionExpansion="2"
 				EnableIntrinsicFunctions="true"
@@ -457,7 +457,7 @@
 			/>
 			<Tool
 				Name="VCCLCompilerTool"
-				AdditionalOptions="/LD /FI&quot;$(ProjectDir)pch.h&quot;"
+				AdditionalOptions="/LD /FI&quot;$(ProjectDir)pch.h&quot; /Zm200"
 				Optimization="2"
 				InlineFunctionExpansion="2"
 				EnableIntrinsicFunctions="true"
@@ -563,7 +563,7 @@
 			/>
 			<Tool
 				Name="VCCLCompilerTool"
-				AdditionalOptions="/LD /FI&quot;$(ProjectDir)pch.h&quot;"
+				AdditionalOptions="/LD /FI&quot;$(ProjectDir)pch.h&quot; /Zm200"
 				Optimization="0"
 				AdditionalIncludeDirectories="C:\3dsmax7\maxsdk\include;..\..\niflib;..\NifCommon"
 				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS"
diff --git a/NifExport/Util.cpp b/NifExport/Util.cpp
index c714c707df901670b79a70dac5346865aa847a5a..b310bc015a17b53053b298b36814ec532b75af0f 100755
--- a/NifExport/Util.cpp
+++ b/NifExport/Util.cpp
@@ -234,12 +234,16 @@ struct SortNodeEquivalence
       if (!rhs) return true;
       string ltype = lhs->GetType().GetTypeName();
       string rtype = rhs->GetType().GetTypeName();
-      if (ltype == "NiNode")
+      if (ltype == rtype)
          return false;
-      if (rtype == "NiNode")
+      if (ltype == "bhkCollisionObject")
          return true;
-      if (ltype == rtype)
+      if (rtype == "bhkCollisionObject")
          return false;
+      if (ltype == "NiNode")
+         return false;
+      else if (rtype == "NiNode")
+         return true;
       return (ltype < rtype); 
    }
 };
diff --git a/NifExport/pch.h b/NifExport/pch.h
index f916d528ae7da3d1bd7ed4442a1375f2fd4d4012..34cf26caf18153a7d51953332c74dc6c67357e3f 100755
--- a/NifExport/pch.h
+++ b/NifExport/pch.h
@@ -13,7 +13,8 @@
 #include "istdplug.h"
 #include "iparamb2.h"
 #include "iparamm2.h"
-
+#include "objectParams.h"
+#undef ALPHA_NONE
 
 // niflib/Ref.h' header guard caused havok!
 // near & far 
diff --git a/NifExport/resource.h b/NifExport/resource.h
index 520d8a8052002445c114aa5546795d1ea3692752..26b12888647b45a91583ef8ae799de1149d1f1fe 100755
--- a/NifExport/resource.h
+++ b/NifExport/resource.h
@@ -25,6 +25,14 @@
 #define IDC_CB_VERSION                  1015
 #define IDC_CB_VERSION2                 1016
 #define IDC_CB_USER_VERSION             1016
+#define IDC_CHK_SKIN                    1017
+#define IDC_CHK_ANIMATION               1018
+#define IDC_CHK_EXTRA                   1019
+#define IDC_CHK_UPB                     1020
+#define IDC_CHK_HIER                    1021
+#define IDC_CHK_REM_BONES               1022
+#define IDC_CHECK7                      1023
+#define IDC_CHK_SORTNODES               1023
 #define IDC_COLOR                       1456
 #define IDC_EDIT                        1490
 #define IDC_SPIN                        1496
@@ -35,7 +43,7 @@
 #ifndef APSTUDIO_READONLY_SYMBOLS
 #define _APS_NEXT_RESOURCE_VALUE        102
 #define _APS_NEXT_COMMAND_VALUE         40001
-#define _APS_NEXT_CONTROL_VALUE         1016
+#define _APS_NEXT_CONTROL_VALUE         1024
 #define _APS_NEXT_SYMED_VALUE           101
 #endif
 #endif
diff --git a/NifImport/ImportMeshAndSkin.cpp b/NifImport/ImportMeshAndSkin.cpp
index 4cfdc3f3d44b7c48092a1a4ede2cab63b641f06b..846be2687dc88896d2d2161a540ec8225c4d3883 100644
--- a/NifImport/ImportMeshAndSkin.cpp
+++ b/NifImport/ImportMeshAndSkin.cpp
@@ -365,7 +365,7 @@ bool NifImporter::ImportSkin(ImpNode *node, NiTriBasedGeomRef triGeom)
    vector<NiNodeRef> nifBones = nifSkin->GetBones();
 
    //create a skin modifier and add it
-   Modifier *skinMod = GetSkin(tnode);
+   Modifier *skinMod = GetOrCreateSkin(tnode);
    TriObject *triObject = GetTriObject(tnode->GetObjectRef());
    Mesh& m = triObject->GetMesh();
 
diff --git a/NifImport/ImportMtlAndTex.cpp b/NifImport/ImportMtlAndTex.cpp
index 838ba000029d2ca73d96ce6bbee2c7d3eea97b22..d99faf6936efe4d0f56ba01d830f333bc45f030f 100644
--- a/NifImport/ImportMtlAndTex.cpp
+++ b/NifImport/ImportMtlAndTex.cpp
@@ -16,6 +16,10 @@ HISTORY:
 #include "obj/NiWireframeProperty.h"
 #include "obj/NiAlphaProperty.h"
 #include "obj/NiStencilProperty.h"
+#include "obj/NiShadeProperty.h"
+#include "obj/NiVertexColorProperty.h"
+#include "obj/NiDitherProperty.h"
+#include "obj/NiSpecularProperty.h"
 #include "objectParams.h"
 using namespace Niflib;
 
@@ -26,10 +30,50 @@ Texmap* NifImporter::CreateTexture(TexDesc& desc)
       string filename = texSrc->GetExternalFileName();
       if (bmpMgr->CanImport(filename.c_str())){
          BitmapTex *bmpTex = NewDefaultBitmapTex();
-         bmpTex->SetName(texSrc->GetName().c_str());
+         string name = texSrc->GetName();
+         if (name.empty()) {
+            TCHAR buffer[MAX_PATH];
+            _tcscpy(buffer, PathFindFileName(filename.c_str()));
+            PathRemoveExtension(buffer);
+            name = buffer;
+         }         
+         bmpTex->SetName(name.c_str());
          bmpTex->SetMapName(const_cast<TCHAR*>(FindImage(filename).c_str()));
          bmpTex->SetAlphaAsMono(TRUE);
-         bmpTex->SetAlphaSource(ALPHA_NONE);
+         bmpTex->SetAlphaSource(ALPHA_DEFAULT);
+
+         switch (desc.filterMode)
+         {
+         case FILTER_TRILERP: bmpTex->SetFilterType(FILTER_PYR); break;
+         case FILTER_BILERP:  bmpTex->SetFilterType(FILTER_SAT); break;
+         case FILTER_NEAREST: bmpTex->SetFilterType(FILTER_NADA); break;
+         }
+
+         if (UVGen *uvGen = bmpTex->GetTheUVGen()){
+
+            switch (desc.clampMode)
+            {
+            case WRAP_S_WRAP_T : uvGen->SetTextureTiling(3); break;
+            case WRAP_S_CLAMP_T: uvGen->SetTextureTiling(1); break;
+            case CLAMP_S_WRAP_T: uvGen->SetTextureTiling(2); break;
+            case CLAMP_S_CLAMP_T:uvGen->SetTextureTiling(0); break;
+            }
+
+            if (desc.hasTextureTransform) {
+               if (RefTargetHandle ref = uvGen->GetReference(0)){
+                  TexCoord trans = desc.translation;
+                  TexCoord tiling = desc.tiling;
+                  float wangle = TODEG(desc.wRotation);
+
+                  setMAXScriptValue(ref, "U_Offset", 0, trans.u);
+                  setMAXScriptValue(ref, "V_Offset", 0, trans.v);
+                  setMAXScriptValue(ref, "U_Tiling", 0, tiling.u);
+                  setMAXScriptValue(ref, "V_Tiling", 0, tiling.v);
+                  setMAXScriptValue(ref, "W_Angle", 0, wangle);
+               }
+            }
+         }
+
          return bmpTex;
       }
    }
@@ -45,6 +89,7 @@ bool NifImporter::ImportMaterialAndTextures(ImpNode *node, NiAVObjectRef avObjec
    NiWireframePropertyRef wireRef = SelectFirstObjectOfType<NiWireframeProperty>(props);
    NiAlphaPropertyRef alphaRef = SelectFirstObjectOfType<NiAlphaProperty>(props);
    NiStencilPropertyRef stencilRef = SelectFirstObjectOfType<NiStencilProperty>(props);
+   NiShadePropertyRef shadeRef = SelectFirstObjectOfType<NiShadeProperty>(props);
 
    bool hasTexture = (texRef && matRef);
    if (matRef != NULL){
@@ -52,6 +97,13 @@ bool NifImporter::ImportMaterialAndTextures(ImpNode *node, NiAVObjectRef avObjec
       m->SetName(matRef->GetName().c_str());
       if (showTextures)
          m->SetMtlFlag(MTL_DISPLAY_ENABLE_FLAGS, TRUE);
+
+      // try the civ4 shader first then default back to normal shaders
+      if (ImportCiv4Shader(node, avObject, m)) {
+         gi->GetMaterialLibrary().Add(m);
+         node->GetINode()->SetMtl(m);
+         return true;
+		}
       m->SetAmbient(TOCOLOR(matRef->GetAmbientColor()),0);
       m->SetDiffuse(TOCOLOR(matRef->GetDiffuseColor()),0);
       m->SetSpecular(TOCOLOR(matRef->GetSpecularColor()),0);
@@ -64,19 +116,24 @@ bool NifImporter::ImportMaterialAndTextures(ImpNode *node, NiAVObjectRef avObjec
       m->SetShininess(matRef->GetGlossiness()/100.0,0);
       m->SetOpacity(matRef->GetTransparency(),0);
 
-      bool hasShaderAttributes = (wireRef != NULL) || (stencilRef != NULL);
+      bool hasShaderAttributes = (wireRef != NULL) || (stencilRef != NULL) || (shadeRef != NULL);
       if (m->SupportsShaders() && hasShaderAttributes) {
          if (Shader *s = m->GetShader()) {
             if (wireRef != NULL && (wireRef->GetFlags() & 1)) {
                BOOL value = TRUE;
-               setMAXScriptValue(s->GetReference(0), "wire", 0, value);
+               m->SetWire(value);
             }
             if (stencilRef != NULL) {
-
+               if (stencilRef->GetDrawMode() == 3 /*DRAW_BOTH*/) {
+                  BOOL value = TRUE;
+                  m->SetTwoSided(value);
+               }
+            }
+            if (shadeRef != NULL && shadeRef->GetFlags() & 1) {
+               m->SetFaceted(TRUE);
             }
          }
       }
-      
 
       if (NULL != texRef)
       {
@@ -115,12 +172,150 @@ bool NifImporter::ImportMaterialAndTextures(ImpNode *node, NiAVObjectRef avObjec
    return hasTexture;
 }
 
+bool NifImporter::ImportCiv4Shader(ImpNode *node, NiAVObjectRef avObject, StdMat2 *mtl)
+{
+   if (!useCiv4Shader || !mtl || !mtl->SupportsShaders()) 
+      return false;
+
+   Class_ID civ4Shader(0x670a77d0,0x23ab5c7f);
+   if (!mtl->SwitchShader(civ4Shader))
+      return false;
+
+   TSTR shaderByName;
+   if (Shader *s = mtl->GetShader())
+      s->GetClassName(shaderByName);
+   if (shaderByName != TSTR("CivilizationIV Shader"))
+      return false;
+
+   RefTargetHandle ref = mtl->GetReference(2/*shader*/);
+   if (!ref)
+      return false;
+
+   vector<NiPropertyRef> props = avObject->GetProperties();
+
+   if (NiMaterialPropertyRef matRef = SelectFirstObjectOfType<NiMaterialProperty>(props)){
+      Color ambient = TOCOLOR(matRef->GetAmbientColor());
+      Color diffuse = TOCOLOR(matRef->GetDiffuseColor());
+      Color specular = TOCOLOR(matRef->GetSpecularColor());
+      Color emittance = TOCOLOR(matRef->GetEmissiveColor());
+      float shininess = matRef->GetGlossiness();
+      float alpha = matRef->GetTransparency() * 100.0f;
+
+      mtl->SetShinStr(0.0,0);
+      mtl->SetShininess(shininess/100.0,0);
+      mtl->SetOpacity(alpha*100.0f,0);
+
+      setMAXScriptValue(ref, "ambient", 0, ambient );
+      setMAXScriptValue(ref, "diffuse", 0, diffuse );
+      setMAXScriptValue(ref, "specular", 0, specular );
+      setMAXScriptValue(ref, "emittance", 0, emittance );
+      setMAXScriptValue(ref, "shininess", 0, shininess );
+      setMAXScriptValue(ref, "alpha", 0, alpha );
+   }
+   if (NiShadePropertyRef shadeRef = SelectFirstObjectOfType<NiShadeProperty>(props)) {
+      if (shadeRef->GetFlags() & 1){
+         mtl->SetFaceted(TRUE);
+      }
+   }
+   if (NiWireframePropertyRef wireRef = SelectFirstObjectOfType<NiWireframeProperty>(props)) {
+      if (wireRef->GetFlags() & 1){
+         mtl->SetWire(TRUE);
+      }
+   }
+   if (NiStencilPropertyRef stencilRef = SelectFirstObjectOfType<NiStencilProperty>(props)) {
+      mtl->SetTwoSided(TRUE);
+   }
+   bool Dither = false;
+   bool SpecularEnable = false;
+   if (NiDitherPropertyRef ditherRef = SelectFirstObjectOfType<NiDitherProperty>(props)) {
+      Dither = (ditherRef->GetFlags() & 1) ? true : false;
+   }
+   if (NiSpecularPropertyRef specRef = SelectFirstObjectOfType<NiSpecularProperty>(props)) {
+      SpecularEnable = (specRef->GetFlags() & 1) ? true : false;
+   }
+   setMAXScriptValue(ref, "Dither", 0, Dither );
+   setMAXScriptValue(ref, "SpecularEnable", 0, SpecularEnable);
+
+   if (NiVertexColorPropertyRef vertexColor = SelectFirstObjectOfType<NiVertexColorProperty>(props)) {
+      int SrcVertexMode = vertexColor->GetVertexMode();
+      int LightingMode = vertexColor->GetLightingMode();
+      bool VertexColorsEnable = true;
+      setMAXScriptValue(ref, "Vertex_Color_Enable", 0, VertexColorsEnable);
+      setMAXScriptValue(ref, "SourceVertexMode", 0, SrcVertexMode);
+      setMAXScriptValue(ref, "LightingMode", 0, LightingMode);
+   } else {
+      bool VertexColorsEnable = false;
+      setMAXScriptValue(ref, "Vertex_Color_Enable", 0, VertexColorsEnable);
+   }
+   if (NiAlphaPropertyRef alphaRef = SelectFirstObjectOfType<NiAlphaProperty>(props)) {
+      int TestRef = alphaRef->GetAlphaTestThreshold();
+      int srcBlend = alphaRef->GetSourceBlendMode(); 
+      int destBlend = alphaRef->GetDestBlendMode();
+      int TestMode = alphaRef->GetTestMode();
+      bool AlphaTestEnable = alphaRef->GetAlphaTest();     
+      bool NoSorter = !alphaRef->GetAlphaSort();
+      bool alphaBlend = alphaRef->GetAlphaBlend();
+      int alphaMode = 1;
+
+      if (!alphaBlend) {
+         alphaMode = 1; // none
+      } else if (srcBlend == NiAlphaProperty::BM_SRC_ALPHA && destBlend == NiAlphaProperty::BM_ONE_MINUS_SRC_ALPHA) {
+         alphaMode = 0; // standard or automatic?
+      } else if (srcBlend == NiAlphaProperty::BM_ONE && destBlend == NiAlphaProperty::BM_ONE) {
+         alphaMode = 3;
+      } else if (srcBlend == NiAlphaProperty::BM_ZERO && destBlend == NiAlphaProperty::BM_SRC_COLOR) {
+         alphaMode = 4;
+      } else {
+         alphaMode = 5;
+      }
+      setMAXScriptValue(ref, "AlphaTestEnable", 0, AlphaTestEnable );
+      setMAXScriptValue(ref, "alphaMode", 0, alphaMode);
+      setMAXScriptValue(ref, "srcBlend", 0, srcBlend);
+      setMAXScriptValue(ref, "destBlend", 0, destBlend);
+      setMAXScriptValue(ref, "NoSorter", 0, NoSorter);
+      setMAXScriptValue(ref, "TestRef", 0, TestRef );
+      setMAXScriptValue(ref, "TestMode", 0, TestMode );
+   }
+   if (NiTexturingPropertyRef texRef = SelectFirstObjectOfType<NiTexturingProperty>(props)) {
+      Matrix22 m2 = texRef->GetBumpMapMatrix();
+      float Magnitude = (m2[0][0] + m2[1][1]) / 2.0f;
+      float LumaScale = texRef->GetLumaScale();
+      float LumaOffset = texRef->GetLumaOffset();
+      int ApplyMode = texRef->GetApplyMode();
+
+      setMAXScriptValue(ref, "Bump_Map_Magnitude", 0, Magnitude);
+      setMAXScriptValue(ref, "Bump_Map_Luma_Scale", 0, LumaScale);
+      setMAXScriptValue(ref, "Bump_Map_Luma_offset", 0, LumaOffset);
+      setMAXScriptValue(ref, "ApplyMode", 0, ApplyMode);
+
+      int ntex = mtl->NumSubTexmaps();
+      if (ntex > 0)
+      {
+         ntex = min(ntex, 7);
+         TexType texmap[] = {BASE_MAP, DARK_MAP, DETAIL_MAP, DECAL_0_MAP, BUMP_MAP, GLOSS_MAP, GLOW_MAP, DECAL_1_MAP};
+         NiTexturingPropertyRef texProp = CreateNiObject<NiTexturingProperty>();       
+         texProp->SetApplyMode(Niflib::ApplyMode(ApplyMode));
+         texProp->SetTextureCount(7);
+         for (int i = 0; i < ntex; ++i) {
+            TexType textype = texmap[i];
+            if (texRef->HasTexture(textype)){
+               if (Texmap* tex = CreateTexture(texRef->GetTexture(textype))) {
+                  mtl->SetSubTexmap(i, tex);
+               }
+            }
+         }
+      }
+   }
+   return true;
+}
+
+
 string NifImporter::FindImage(const string& name)
 {
    TCHAR buffer[MAX_PATH];
 
    // Simply check for fully qualified path
-   if (PathIsRoot(name.c_str())) {
+   if (!PathIsRelative(name.c_str())) {
       if (-1 != _taccess(name.c_str(), 0))
          return string(buffer);
    } 
@@ -138,4 +333,6 @@ string NifImporter::FindImage(const string& name)
       return appSettings->FindImage(name);
    }
    return name;
-}
\ No newline at end of file
+}
+
+
diff --git a/NifImport/ImportSkeleton.cpp b/NifImport/ImportSkeleton.cpp
index 885d9307f21f757fe5c7491ac6dfe76bc6b1a99a..dfc2eb05d1b15c09de9ba895eba9f855fe68f60b 100644
--- a/NifImport/ImportSkeleton.cpp
+++ b/NifImport/ImportSkeleton.cpp
@@ -611,10 +611,7 @@ void NifImporter::ImportBones(NiNodeRef node, bool recurse)
          else if (bone = CreateBone(name, p, pp, zAxis))
          {
             PosRotScaleNode(bone, p, q, scale, prs);
-            if (isDummy)
-               bone->Hide(TRUE);
-            else
-               bone->Hide(node->GetHidden() ? TRUE : FALSE);
+            bone->Hide(node->GetHidden() ? TRUE : FALSE);
          }
          if (bone)
          {
diff --git a/NifImport/MaxNifImport.cpp b/NifImport/MaxNifImport.cpp
index 40f861f38063688af2cf9bd8ba990616856fe2b2..9af93ff400107ef8195ed814b3fea1e1beb4d565 100644
--- a/NifImport/MaxNifImport.cpp
+++ b/NifImport/MaxNifImport.cpp
@@ -64,44 +64,6 @@ class MaxNifImportClassDesc : public ClassDesc2 {
 static MaxNifImportClassDesc MaxNifImportDesc;
 ClassDesc2* GetMaxNifImportDesc() { return &MaxNifImportDesc; }
 
-BOOL CALLBACK MaxNifImportOptionsDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam) {
-	static NifImporter *imp = NULL;
-
-	switch(message) {
-		case WM_INITDIALOG:
-         {
-			   imp = (NifImporter *)lParam;
-			   CenterWindow(hWnd,GetParent(hWnd));
-
-            char buffer[33] = {0};
-            sprintf(buffer, "%f", imp->bipedHeight);
-            SetWindowText(GetDlgItem(hWnd, IDC_EDITHEIGHT), buffer);
-         }
-			return TRUE;
-
-		case WM_CLOSE:
-         {
-            char buffer[33] = {0}, *end = NULL;
-            GetWindowText(GetDlgItem(hWnd, IDC_EDITHEIGHT), buffer, 33);
-            imp->bipedHeight = strtod(buffer, &end);
-			   EndDialog(hWnd, 0);
-         }
-			return TRUE;
-
-      case WM_COMMAND : 
-         {
-            switch (wParam)
-            {
-            case IDCLOSE :
-               SendMessage(hWnd, WM_CLOSE, 0, 0);
-               return TRUE;
-            }
-         }
-         break;
-	}
-	return FALSE;
-}
-
 
 //--- MaxNifImport -------------------------------------------------------
 MaxNifImport::MaxNifImport()
diff --git a/NifImport/MaxNifImport.rc b/NifImport/MaxNifImport.rc
index 06f8df207660ee5a1dc89b7a577eabb935420ed5..639490ea76e49e9d2968c9cae8afa0afcb4b3166 100644
--- a/NifImport/MaxNifImport.rc
+++ b/NifImport/MaxNifImport.rc
@@ -26,14 +26,34 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
 // Dialog
 //
 
-IDD_PANEL DIALOGEX 0, 0, 142, 59
+IDD_PANEL DIALOGEX 0, 0, 206, 158
 STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
 EXSTYLE WS_EX_TOOLWINDOW
+CAPTION "Import Nif"
 FONT 8, "MS Sans Serif", 0, 0, 0x1
 BEGIN
-    EDITTEXT        IDC_EDITHEIGHT,68,15,62,14,ES_AUTOHSCROLL
-    LTEXT           "&Height:",IDC_STATIC,16,18,49,8
-    PUSHBUTTON      "&Close",IDCLOSE,44,38,50,14
+    GROUPBOX        "Import:",IDC_STATIC,7,6,81,81
+    CONTROL         "&Skeleton",IDC_CHK_BONES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,16,67,10
+    CONTROL         "Skin Modifier",IDC_CHK_SKIN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,27,67,10
+    CONTROL         "&Vertex Colors",IDC_CHK_VCOLORS,"Button",BS_AUTO3STATE | WS_TABSTOP,14,38,67,10
+    CONTROL         "Co&llision",IDC_CHK_COLL,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,14,62,67,10
+    CONTROL         "&Animation",IDC_CHK_ANIMATION,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,50,67,10
+    CONTROL         "Furniture &Markers",IDC_CHK_FURN,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,14,73,67,10
+    GROUPBOX        "Behaviors:",IDC_STATIC,94,6,101,81
+    CONTROL         "Flip UV",IDC_CHK_FLIP_UV,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,16,88,10
+    CONTROL         "&Render Textures in View",IDC_CHK_SHOW_TEX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,27,88,10
+    CONTROL         "&Auto Smooth Mesh",IDC_CHK_AUTOSMOOTH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,38,88,11
+    CONTROL         "Remove Illegal Faces",IDC_CHK_ILLEGAL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,50,88,11
+    CONTROL         "Remove Unused Bones",IDC_CHK_REM_BONES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,62,88,10
+    CONTROL         "&Use Biped",IDC_CHK_BIPED,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,102,73,87,10
+    LTEXT           "Skeleton:",IDC_STC_SKELETON,7,107,31,8
+    EDITTEXT        IDC_ED_SKELETON,7,119,171,12,ES_AUTOHSCROLL
+    PUSHBUTTON      "...",IDC_BTN_BROWSE,180,119,19,13
+    LTEXT           "Game:",IDC_STATIC,7,93,31,8
+    COMBOBOX        IDC_CB_GAME,47,91,131,70,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+    DEFPUSHBUTTON   "&Import",IDOK,5,137,34,14
+    PUSHBUTTON      "&Cancel",IDCANCEL,45,137,33,14
+    LTEXT           "http://niftools.sourceforge.net",IDC_LBL_LINK,93,137,95,14,SS_NOTIFY | SS_CENTERIMAGE
 END
 
 
@@ -48,9 +68,9 @@ BEGIN
     IDD_PANEL, DIALOG
     BEGIN
         LEFTMARGIN, 7
-        RIGHTMARGIN, 135
+        RIGHTMARGIN, 199
         TOPMARGIN, 7
-        BOTTOMMARGIN, 52
+        BOTTOMMARGIN, 151
     END
 END
 #endif    // APSTUDIO_INVOKED
@@ -88,8 +108,8 @@ END
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 0,1,6,8
- PRODUCTVERSION 0,1,6,0
+ FILEVERSION 0,2,0,0
+ PRODUCTVERSION 0,2,0,0
  FILEFLAGSMASK 0x37L
 #ifdef _DEBUG
  FILEFLAGS 0x21L
@@ -105,12 +125,12 @@ BEGIN
         BLOCK "040904b0"
         BEGIN
             VALUE "FileDescription", "3ds Max Nif Importer"
-            VALUE "FileVersion", "0, 1, 6, 8"
+            VALUE "FileVersion", "0, 2, 0, 0"
             VALUE "InternalName", "MaxNifImport.dli"
             VALUE "LegalCopyright", "Copyright (c) 2006, NIF File Format Library and Tools\r\nAll rights reserved."
             VALUE "OriginalFilename", "MaxNifImport.dli"
             VALUE "ProductName", "3ds Max Nif Importer"
-            VALUE "ProductVersion", "0, 1, 6, 0"
+            VALUE "ProductVersion", "0, 2, 0, 0"
             VALUE "SpecialBuild", "Alpha"
         END
     END
diff --git a/NifImport/MaxNifImport_VC80.vcproj b/NifImport/MaxNifImport_VC80.vcproj
index d05d46e9cfaefeadbf4298674f94c3230d2a2f02..245bcbb797a644a6ca549347aeed5ab49ebc701a 100644
--- a/NifImport/MaxNifImport_VC80.vcproj
+++ b/NifImport/MaxNifImport_VC80.vcproj
@@ -695,10 +695,6 @@
 				RelativePath=".\KFImporter.h"
 				>
 			</File>
-			<File
-				RelativePath=".\objectParams.h"
-				>
-			</File>
 			<File
 				RelativePath=".\resource.h"
 				>
@@ -788,6 +784,10 @@
 				RelativePath=".\MaxNifImport.h"
 				>
 			</File>
+			<File
+				RelativePath=".\NifDialog.cpp"
+				>
+			</File>
 			<File
 				RelativePath=".\NIFImport.cpp"
 				>
diff --git a/NifImport/NIFImport.cpp b/NifImport/NIFImport.cpp
index b8f9dc9f34800d879348115b1076b5c9f19c17b2..c728fed2ccba49f28f21c5dc739b2101a96a0a2a 100644
--- a/NifImport/NIFImport.cpp
+++ b/NifImport/NIFImport.cpp
@@ -72,7 +72,7 @@ void NifImporter::Initialize()
 
       hasSkeleton = HasSkeleton();
       isBiped = IsBiped();
-      skeleton = (appSettings != NULL) ? appSettings->Skeleton : "";
+      skeleton = GetSkeleton(appSettings);
       importSkeleton = (appSettings != NULL) ? appSettings->useSkeleton : false;
       importSkeleton &= hasSkeleton;
 
@@ -89,6 +89,22 @@ void NifImporter::Initialize()
    }
 }
 
+string NifImporter::GetSkeleton(AppSettings *appSettings)
+{
+   string skeleton = (appSettings != NULL) ? appSettings->Skeleton : "";
+   // 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;
+   }
+   return skeleton;
+}
+
 void NifImporter::LoadIniSettings()
 {
    TCHAR iniName[MAX_PATH];
@@ -127,6 +143,7 @@ void NifImporter::LoadIniSettings()
    enableSkinSupport = GetIniValue(NifImportSection, "EnableSkinSupport", true);
    enableCollision = GetIniValue(NifImportSection, "EnableCollision", true);
    vertexColorMode = GetIniValue<int>(NifImportSection, "VertexColorMode", 1);
+   useCiv4Shader = GetIniValue(NifImportSection, "UseCiv4Shader", true);
 
    // Biped
    importBones = GetIniValue(BipedImportSection, "ImportBones", true);
@@ -154,7 +171,10 @@ void NifImporter::LoadIniSettings()
 
    // Collision
    bhkScaleFactor = GetIniValue<float>(CollisionSection, "bhkScaleFactor", 7.0f);
-
+   ApplyAppSettings();
+}
+void NifImporter::ApplyAppSettings()
+{
    goToSkeletonBindPosition = false;
    // Override specific settings
    if (appSettings) {
@@ -170,14 +190,22 @@ void NifImporter::LoadIniSettings()
 
 void NifImporter::SaveIniSettings()
 {
-   //SetIniValue(NifImportSection, "UseBiped", useBiped);
-   //SetIniValue<string>(NifImportSection, "Skeleton", skeleton);
-   //SetIniValue<string>(NifImportSection, "SkeletonCheck", skeletonCheck);
-
-   //SetIniValue<float>(BipedImportSection, "BipedHeight", bipedHeight);
-   //SetIniValue<float>(BipedImportSection, "BipedAngle", bipedAngle);
-   //SetIniValue<float>(BipedImportSection, "BipedAnkleAttach", bipedAnkleAttach);
-   //SetIniValue(BipedImportSection, "BipedTrianglePelvis", bipedTrianglePelvis);
+   SetIniValue(NifImportSection, "UseBiped", useBiped);
+   SetIniValue(NifImportSection, "EnableSkinSupport", enableSkinSupport);
+   SetIniValue(NifImportSection, "VertexColorMode", vertexColorMode);
+   SetIniValue(NifImportSection, "EnableCollision", enableCollision);
+   //SetIniValue(NifImportSection, "EnableFurniture", enableAnimations);
+
+   SetIniValue(NifImportSection, "FlipUVTextures", flipUVTextures);
+   SetIniValue(NifImportSection, "ShowTextures", showTextures);
+   SetIniValue(NifImportSection, "EnableAutoSmooth", enableAutoSmooth);
+   SetIniValue(NifImportSection, "RemoveIllegalFaces", removeIllegalFaces);
+   SetIniValue(NifImportSection, "RemoveDegenerateFaces", removeDegenerateFaces);
+
+   SetIniValue(BipedImportSection, "ImportBones", importBones);
+   SetIniValue(BipedImportSection, "RemoveUnusedImportedBones", removeUnusedImportedBones);
+
+   SetIniValue(AnimImportSection, "EnableAnimations", enableAnimations);
 }
 
 INode *NifImporter::GetNode(Niflib::NiNodeRef node)
@@ -190,39 +218,48 @@ INode *NifImporter::GetNode(Niflib::NiNodeRef node)
 bool NifImporter::DoImport()
 {
    bool ok = true;
+   if (!suppressPrompts)
+   {
+      if (!ShowDialog())
+         return true;
+
+      ApplyAppSettings();
+      SaveIniSettings();
+   }
+
    vector<string> importedBones;
    if (!isBiped && importSkeleton && importBones)
    {
-      if (browseForSkeleton)
-      {
-         TCHAR filter[64], *pfilter=filter;
-         pfilter = _tcscpy(filter, shortDescription.c_str());
-         pfilter = _tcscat(pfilter, " (*.NIF)");
-         pfilter += strlen(pfilter);
-         *pfilter++ = '\0';
-         _tcscpy(pfilter, "*.NIF");
-         pfilter += strlen(pfilter);
-         *pfilter++ = '\0';
-         *pfilter++ = '\0';
-
-         TCHAR filename[MAX_PATH];
-         GetFullPathName(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;
-         importSkeleton = GetOpenFileName(&ofn) ? true : false;
-         if (importSkeleton) {
-            skeleton = filename;
-         }
-      }
+      //if (browseForSkeleton)
+      //{
+      //   TCHAR filter[64], *pfilter=filter;
+      //   pfilter = _tcscpy(filter, shortDescription.c_str());
+      //   pfilter = _tcscat(pfilter, " (*.NIF)");
+      //   pfilter += strlen(pfilter);
+      //   *pfilter++ = '\0';
+      //   _tcscpy(pfilter, "*.NIF");
+      //   pfilter += strlen(pfilter);
+      //   *pfilter++ = '\0';
+      //   *pfilter++ = '\0';
+
+      //   TCHAR filename[MAX_PATH];
+      //   GetFullPathName(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;
+      //   importSkeleton = GetOpenFileName(&ofn) ? true : false;
+      //   if (importSkeleton) {
+      //      skeleton = filename;
+      //   }
+      //}
       if (importSkeleton && !skeleton.empty()) {
          NifImporter skelImport(skeleton.c_str(), i, gi, suppressPrompts);
          if (skelImport.isValid())
@@ -233,7 +270,7 @@ bool NifImporter::DoImport()
             // Disable undesirable skeleton items
             skelImport.enableCollision = false;
             skelImport.enableAnimations = false;
-
+            skelImport.suppressPrompts = true;
             skelImport.DoImport();
             if (!skelImport.useBiped && removeUnusedImportedBones)
                importedBones = GetNamesOfNodes(skelImport.nodes);
diff --git a/NifImport/NIFImporter.h b/NifImport/NIFImporter.h
index c15cbf1d72103962de741a3174e6e1ba589f41d5..4f61b1d82f2bc0349ad6b62726e813cd483b4488 100644
--- a/NifImport/NIFImporter.h
+++ b/NifImport/NIFImporter.h
@@ -15,8 +15,10 @@ HISTORY:
 #define __NIFIMPORTER_H__
 
 #include "BaseImporter.h"
+#include "IniSection.h"
+
 // NIF Importer
-class NifImporter : public BaseImporter
+class NifImporter : public BaseImporter//, public IniFileSection
 {
 public:
    // Ini settings
@@ -30,6 +32,7 @@ public:
    bool goToSkeletonBindPosition;
    bool enableCollision;
    int vertexColorMode;
+   bool useCiv4Shader;
 
    // Biped/Bones related settings
    bool importBones;
@@ -77,6 +80,8 @@ public:
    void LoadIniSettings();
    void SaveIniSettings();
 
+   void ApplyAppSettings();
+
    bool HasSkeleton();
    bool IsBiped();
    void ImportBones(vector<Niflib::NiNodeRef>& bones);
@@ -92,6 +97,7 @@ public:
    bool ImportMesh(Niflib::NiTriShapeRef triShape);
    bool ImportMesh(Niflib::NiTriStripsRef triStrips);
    bool ImportMaterialAndTextures(ImpNode *node, Niflib::NiAVObjectRef avObject);
+   bool ImportCiv4Shader(ImpNode *node, Niflib::NiAVObjectRef avObject, StdMat2 *m);
    bool ImportTransform(ImpNode *node, Niflib::NiAVObjectRef avObject);
    bool ImportMesh(ImpNode *node, TriObject *o, Niflib::NiTriBasedGeomRef triGeom, Niflib::NiTriBasedGeomDataRef triGeomData, vector<Niflib::Triangle>& tris);
    bool ImportVertexColor(ImpNode *node, TriObject *o, Niflib::NiTriBasedGeomRef triGeom, Niflib::NiTriBasedGeomDataRef triGeomData, vector<Niflib::Triangle>& tris);
@@ -105,7 +111,9 @@ public:
    bool ImportCollision(Niflib::NiNodeRef node);
 
    INode *GetNode(Niflib::NiNodeRef node);
+   string GetSkeleton(AppSettings *appSettings);
 
+   bool ShowDialog();
    virtual bool DoImport();
 
    // Animation Helpers
diff --git a/NifImport/NifDialog.cpp b/NifImport/NifDialog.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8294625a2e5578e8ab2ce43dd57d907bd55e5d19
--- /dev/null
+++ b/NifImport/NifDialog.cpp
@@ -0,0 +1,187 @@
+/**********************************************************************
+*<
+FILE: ImporterCore.cpp
+
+DESCRIPTION:	Core Import helper routines
+
+CREATED BY: tazpn (Theo)
+
+HISTORY: 
+
+*>	Copyright (c) 2006, All Rights Reserved.
+**********************************************************************/
+#include "stdafx.h"
+#include "MaxNifImport.h"
+#include "resource.h"
+#include "shellapi.h"
+
+using namespace Niflib;
+
+BOOL CALLBACK MaxNifImportOptionsDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam) {
+   static NifImporter *imp = NULL;
+   static DWORD dlgRes = IDCANCEL; 
+
+   switch(message) {
+      case WM_INITDIALOG:
+         {
+            dlgRes = IDCANCEL;
+
+            // Append file version to dialog
+            TSTR version = GetFileVersion(NULL);
+            if (!version.isNull()) {
+               char buffer[256];
+               GetWindowText(hWnd, buffer, _countof(buffer));
+               _tcscat(buffer, TEXT(" "));
+               _tcscat(buffer, version);
+               SetWindowText(hWnd, buffer);
+            }
+
+            imp = (NifImporter *)lParam;
+            CenterWindow(hWnd,GetParent(hWnd));
+
+            CheckDlgButton(hWnd, IDC_CHK_BONES, imp->importBones);
+            CheckDlgButton(hWnd, IDC_CHK_SKIN, imp->enableSkinSupport);
+            CheckDlgButton(hWnd, IDC_CHK_VCOLORS, imp->vertexColorMode);
+            CheckDlgButton(hWnd, IDC_CHK_COLL, imp->enableCollision);
+            CheckDlgButton(hWnd, IDC_CHK_ANIMATION, imp->enableAnimations);
+            //CheckDlgButton(hWnd, IDC_CHK_FURN, imp->);
+
+            CheckDlgButton(hWnd, IDC_CHK_FLIP_UV, imp->flipUVTextures);
+            CheckDlgButton(hWnd, IDC_CHK_SHOW_TEX, imp->showTextures);
+            CheckDlgButton(hWnd, IDC_CHK_AUTOSMOOTH, imp->enableAutoSmooth);
+            CheckDlgButton(hWnd, IDC_CHK_ILLEGAL, imp->removeIllegalFaces);
+            CheckDlgButton(hWnd, IDC_CHK_REM_BONES, imp->removeUnusedImportedBones);
+            CheckDlgButton(hWnd, IDC_CHK_BIPED, imp->useBiped);
+            
+            string selection = (imp->appSettings) ? imp->appSettings->Name : "User";
+            for (AppSettingsMap::iterator itr = TheAppSettings.begin(), end = TheAppSettings.end(); itr != end; ++itr)
+               SendDlgItemMessage(hWnd, IDC_CB_GAME, CB_ADDSTRING, 0, LPARAM(itr->Name.c_str()));
+            SendDlgItemMessage(hWnd, IDC_CB_GAME, CB_SELECTSTRING, WPARAM(-1), LPARAM(selection.c_str()));
+
+            SHAutoComplete(GetDlgItem(hWnd, IDC_ED_SKELETON), SHACF_FILESYSTEM);
+            if (imp->HasSkeleton() && imp->appSettings && imp->importSkeleton) {
+               SetDlgItemText(hWnd, IDC_ED_SKELETON, imp->skeleton.c_str());
+            } else {
+               EnableWindow(GetDlgItem(hWnd, IDC_STC_SKELETON), FALSE);
+               EnableWindow(GetDlgItem(hWnd, IDC_ED_SKELETON), FALSE);
+               EnableWindow(GetDlgItem(hWnd, IDC_BTN_BROWSE), FALSE);
+               EnableWindow(GetDlgItem(hWnd, IDC_CHK_BIPED), FALSE);
+               EnableWindow(GetDlgItem(hWnd, IDC_CHK_REM_BONES), FALSE);
+            }
+         }
+         return TRUE;
+
+      case WM_CLOSE:
+         {
+            EndDialog(hWnd, dlgRes);
+         }
+         return TRUE;
+
+      case WM_COMMAND : 
+         {
+            if (HIWORD(wParam) == BN_CLICKED)
+            {
+               char tmp[MAX_PATH];
+               switch (LOWORD(wParam))
+               {
+               case IDOK:
+
+                  imp->importBones = IsDlgButtonChecked(hWnd, IDC_CHK_BONES) ? true : false;
+                  imp->enableSkinSupport = IsDlgButtonChecked(hWnd, IDC_CHK_SKIN) ? true : false;
+                  imp->vertexColorMode = (int)IsDlgButtonChecked(hWnd, IDC_CHK_VCOLORS);
+                  imp->enableCollision = IsDlgButtonChecked(hWnd, IDC_CHK_COLL) ? true : false;
+                  imp->enableAnimations = IsDlgButtonChecked(hWnd, IDC_CHK_ANIMATION) ? true : false;
+                  //IsDlgButtonChecked(hWnd, IDC_CHK_FURN, imp->);
+
+                  imp->flipUVTextures = IsDlgButtonChecked(hWnd, IDC_CHK_FLIP_UV) ? true : false;
+                  imp->showTextures = IsDlgButtonChecked(hWnd, IDC_CHK_SHOW_TEX) ? true : false;
+                  imp->enableAutoSmooth = IsDlgButtonChecked(hWnd, IDC_CHK_AUTOSMOOTH) ? true : false;
+                  imp->removeDegenerateFaces =
+                  imp->removeIllegalFaces = IsDlgButtonChecked(hWnd, IDC_CHK_ILLEGAL) ? true : false;
+                  imp->removeUnusedImportedBones = IsDlgButtonChecked(hWnd, IDC_CHK_REM_BONES) ? true : false;
+                  imp->useBiped = IsDlgButtonChecked(hWnd, IDC_CHK_BIPED) ? true : false;
+
+                  GetDlgItemText(hWnd, IDC_CB_GAME, tmp, MAX_PATH);
+                  if (AppSettings *appSettings = FindAppSetting(tmp)) {
+                     imp->appSettings = appSettings;
+                  }
+                  
+                  GetDlgItemText(hWnd, IDC_ED_SKELETON, tmp, MAX_PATH);
+                  imp->skeleton = tmp;
+
+                  EndDialog(hWnd, dlgRes=IDOK);
+                  return TRUE;
+
+               case IDCANCEL:
+                  EndDialog(hWnd, dlgRes=IDCANCEL);
+                  return TRUE;
+
+               case IDC_BTN_BROWSE:
+                  {
+                     TCHAR filter[64], *pfilter=filter;
+                     pfilter = _tcscpy(filter, shortDescription.c_str());
+                     pfilter = _tcscat(pfilter, " (*.NIF)");
+                     pfilter += strlen(pfilter);
+                     *pfilter++ = '\0';
+                     _tcscpy(pfilter, "*.NIF");
+                     pfilter += strlen(pfilter);
+                     *pfilter++ = '\0';
+                     *pfilter++ = '\0';
+
+                     GetDlgItemText(hWnd, IDC_ED_SKELETON, tmp, MAX_PATH);
+                     GetLongPathName(tmp, tmp, _countof(tmp));
+
+                     OPENFILENAME ofn;
+                     memset(&ofn, 0, sizeof(ofn));
+                     ofn.lStructSize = sizeof(ofn);
+                     ofn.hwndOwner = imp->gi->GetMAXHWnd();
+                     ofn.lpstrFilter = filter;
+                     ofn.lpstrFile = tmp;
+                     ofn.nMaxFile = _countof(tmp);
+                     ofn.lpstrTitle = TEXT("Browse for Skeleton NIF...");
+                     ofn.lpstrDefExt = TEXT("NIF");
+                     ofn.Flags = OFN_HIDEREADONLY|OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_NOCHANGEDIR|OFN_PATHMUSTEXIST;
+                     if (GetOpenFileName(&ofn)) {
+                        SetDlgItemText(hWnd, IDC_ED_SKELETON, tmp);
+                     }
+                  }
+                  break;
+               }
+            }
+            else if (HIWORD(wParam) == STN_CLICKED)
+            {
+               if (LOWORD(wParam) == IDC_LBL_LINK)
+               {
+                  ShellExecute(hWnd, "open", "http://niftools.sourceforge.net",
+                     NULL, NULL, SW_SHOWDEFAULT);
+               }
+            }
+            else if (HIWORD(wParam) == CBN_SELCHANGE)
+            {
+               if (LOWORD(wParam) == IDC_CB_GAME)
+               {
+                  char tmp[MAX_PATH];
+                  GetDlgItemText(hWnd, IDC_CB_GAME, tmp, MAX_PATH);
+                  if (AppSettings *appSettings = FindAppSetting(tmp))
+                  {
+                     string skeleton = imp->GetSkeleton(appSettings);
+                     BOOL enable = imp->HasSkeleton() ? TRUE : FALSE;
+                     if (enable) {
+                        SetDlgItemText(hWnd, IDC_ED_SKELETON, skeleton.c_str());
+                     }
+                     EnableWindow(GetDlgItem(hWnd, IDC_STC_SKELETON), enable);
+                     EnableWindow(GetDlgItem(hWnd, IDC_ED_SKELETON), enable);
+                     EnableWindow(GetDlgItem(hWnd, IDC_BTN_BROWSE), enable);
+                  }
+               }
+            }
+         }
+         break;
+   }
+   return FALSE;
+}
+
+bool NifImporter::ShowDialog()
+{
+   return (IDOK == DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_PANEL), GetActiveWindow(), MaxNifImportOptionsDlgProc, (LPARAM)this));
+}
\ No newline at end of file
diff --git a/NifImport/objectParams.h b/NifImport/objectParams.h
deleted file mode 100644
index 23a45f424dc7db9d93716af5ca3aeacb2c484102..0000000000000000000000000000000000000000
--- a/NifImport/objectParams.h
+++ /dev/null
@@ -1,339 +0,0 @@
-/*===========================================================================*\
- | 
- |  FILE:	objectParams.h
- |			Skeleton project and code for a Utility
- |			3D Studio MAX R3.0
- | 
- |  AUTH:   Cleve Ard
- |			Render Group
- |			Copyright(c) Discreet 2000
- |
- |  HIST:	Started 9-8-00
- | 
-\*===========================================================================*/
-
-#ifndef _OBJECTPARAMS_H_
-#define _OBJECTPARAMS_H_
-
-#include "maxscrpt/maxscrpt.h"
-#include "maxscrpt/Numbers.h"
-#include "maxscrpt/Name.h"
-#include "maxscrpt/ColorVal.h"
-#include "maxscrpt/MAXObj.h"
-#include "assert1.h"
-
-template <class T>
-class ConvertMAXScriptToC;
-inline Value* make_maxscript_value(bool v);
-inline Value* make_maxscript_value(int v);
-inline Value* make_maxscript_value(float v);
-inline Value* make_maxscript_value(COLORREF rgb);
-inline Value* make_maxscript_value(const Color& rgb);
-inline Value* make_maxscript_value(LPCTSTR str);
-inline Value* make_maxscript_value(ReferenceTarget* rtarg);
-
-#if VERSION_3DSMAX <= ((MAX_RELEASE_R7<<16)+(15<<8)+0)
-inline void clear_error_source_data() {}
-#endif
-
-// Not all of the paramters for materials and shaders
-// are published in the interfaces. ObjectParams class
-// is used to access the properties of objects the same
-// way the scriptor does, so you can get to properties.
-
-// Set the array parameter named name to the value at time t.
-template<class T>
-bool setMAXScriptValue(ReferenceTarget* obj, LPTSTR name, TimeValue t, T value, int tabIndex)
-{
-	bool rval = false;					// Return false if fails
-	assert(obj != NULL);
-	init_thread_locals();
-	push_alloc_frame();
-	two_value_locals(prop, result);		// Keep two local variables
-	save_current_frames();
-	trace_back_active = FALSE;
-
-	try {
-		// Get the name of the parameter and then retrieve
-		// the array holding the value we want to set.
-		vl.prop = Name::intern(name);
-		vl.result = MAXWrapper::get_property(obj, vl.prop, NULL);
-
-		// Make sure it is the right type.
-		if (vl.result != NULL && vl.result->tag == class_tag(MAXPB2ArrayParam)) {
-			// OK. Now we make sure the tabIndex is within the array bounds.
-			MAXPB2ArrayParam* array = static_cast<MAXPB2ArrayParam*>(vl.result);
-			if (array->pblock != NULL && array->pdef != NULL
-					&& tabIndex >= 0 && tabIndex < array->pblock->Count(array->pdef->ID)) {
-				// Set the value in the array.
-				array->pblock->SetValue(array->pdef->ID, 0, value, tabIndex);
-				rval = true;		// Succeeded
-			}
-		}
-	} catch ( ... ) {
-		// Failed.
-		clear_error_source_data();
-		restore_current_frames();
-		MAXScript_signals = 0;
-		if (progress_bar_up)
-			MAXScript_interface->ProgressEnd(), progress_bar_up = FALSE;
-	}
-	pop_value_locals();
-	pop_alloc_frame();
-	return rval;
-}
-
-// Set the parameter. Cannot be an array entry
-template<class T>
-bool setMAXScriptValue(ReferenceTarget* obj, LPTSTR name, TimeValue t, T& value)
-{
-	bool rval = false;					// return false if fails
-	assert(obj != NULL);
-	init_thread_locals();
-	push_alloc_frame();
-	two_value_locals(prop, val);			// Keep two local variables
-	save_current_frames();
-	trace_back_active = FALSE;
-
-	try {
-		// Get the name and value to set
-		vl.prop = Name::intern(name);
-		vl.val = make_maxscript_value(value);
-
-		// Set the value.
-		Value* val = MAXWrapper::set_property(obj, vl.prop, vl.val);
-		if (val != NULL)
-			rval = true;				// Succeeded
-	} catch ( ... ) {
-		// Failed.
-		clear_error_source_data();
-		restore_current_frames();
-		MAXScript_signals = 0;
-		if (progress_bar_up)
-			MAXScript_interface->ProgressEnd(), progress_bar_up = FALSE;
-	}
-	pop_value_locals();
-	pop_alloc_frame();
-	return rval;
-}
-
-// Get the parameter from an array
-template<class T>
-bool getMAXScriptValue(ReferenceTarget* obj, LPTSTR name, TimeValue t, T& value, int tabIndex)
-{
-	bool rval = false;					// Return false if fails
-	assert(obj != NULL);
-	init_thread_locals();
-	push_alloc_frame();
-	two_value_locals(prop, result);		// Keep two local variables
-	save_current_frames();
-	trace_back_active = FALSE;
-
-	try {
-		// Get the name and the array holding the roperty.
-		vl.prop = Name::intern(name);
-		vl.result = MAXWrapper::get_property(obj, vl.prop, NULL);
-
-		// Make sure it is they right type.
-		if (vl.result != NULL && is_tab_param(vl.result)) {
-			// OK. Now we make sure the tabIndex is within the array bounds.
-			MAXPB2ArrayParam* array = static_cast<MAXPB2ArrayParam*>(vl.result);
-			if (array->pblock != NULL && array->pdef != NULL
-					&& tabIndex >= 0 && tabIndex < array->pblock->Count(array->pdef->ID)) {
-				// Good. Get the value
-				array->pblock->GetValue(array->pdef->ID, 0, value, Interval(0,0), tabIndex);
-				rval = true;			// Succeeded
-			}
-		}
-	} catch ( ... ) {
-		// Failed.
-		clear_error_source_data();
-		restore_current_frames();
-		MAXScript_signals = 0;
-		if (progress_bar_up)
-			MAXScript_interface->ProgressEnd(), progress_bar_up = FALSE;
-	}
-	pop_value_locals();
-	pop_alloc_frame();
-	return rval;
-}
-
-// Get the parameter
-template<class T>
-bool getMAXScriptValue(ReferenceTarget* obj, LPTSTR name, TimeValue t, T& value)
-{
-	bool rval = false;				// Return false if fails
-	assert(obj != NULL);
-	init_thread_locals();
-	push_alloc_frame();
-	two_value_locals(prop, result);	// Keep two local varaibles
-	save_current_frames();
-	trace_back_active = FALSE;
-
-	try {
-		// Get the name and the parameter value
-		vl.prop = Name::intern(name);
-		vl.result = MAXWrapper::get_property(obj, vl.prop, NULL);
-
-		// Make sure it is valid.
-		if (vl.result != NULL && vl.result != &undefined && vl.result != &unsupplied) {
-			// Convert to C++ type.
-			value = ConvertMAXScriptToC<T>::cvt(vl.result);
-			rval = true;				// Succeeded
-		}
-	} catch ( ... ) {
-		clear_error_source_data();
-		restore_current_frames();
-		MAXScript_signals = 0;
-		if (progress_bar_up)
-			MAXScript_interface->ProgressEnd(), progress_bar_up = FALSE;
-	}
-	pop_value_locals();
-	pop_alloc_frame();
-	return rval;
-}
-
-// Get the parameter controller
-inline Control* getMAXScriptController(ReferenceTarget* obj, LPTSTR name, ParamDimension*& dim)
-{
-	Control* rval = NULL;
-	assert(obj != NULL);
-	init_thread_locals();
-	push_alloc_frame();
-	one_value_local(prop);			// Keep one local varaibles
-	save_current_frames();
-	trace_back_active = FALSE;
-
-	try {
-		// Get the name and the parameter value
-		vl.prop = Name::intern(name);
-		rval = MAXWrapper::get_max_prop_controller(obj, vl.prop, &dim);
-	} catch ( ... ) {
-		clear_error_source_data();
-		restore_current_frames();
-		MAXScript_signals = 0;
-		if (progress_bar_up)
-			MAXScript_interface->ProgressEnd(), progress_bar_up = FALSE;
-	}
-	pop_value_locals();
-	pop_alloc_frame();
-	return rval;
-}
-
-// Set the parameter controller
-inline bool setMAXScriptController(ReferenceTarget* obj, LPTSTR name, Control* control, ParamDimension* dim)
-{
-	bool rval = false;
-	assert(obj != NULL);
-	init_thread_locals();
-	push_alloc_frame();
-	two_value_locals(prop, maxControl);			// Keep two local varaibles
-	save_current_frames();
-	trace_back_active = FALSE;
-
-	try {
-		// Get the name and the parameter value
-		vl.prop = Name::intern(name);
-		vl.maxControl = MAXControl::intern(control, dim);
-		rval = MAXWrapper::set_max_prop_controller(obj, vl.prop,
-			static_cast<MAXControl*>(vl.maxControl)) != 0;
-	} catch ( ... ) {
-		clear_error_source_data();
-		restore_current_frames();
-		MAXScript_signals = 0;
-		if (progress_bar_up)
-			MAXScript_interface->ProgressEnd(), progress_bar_up = FALSE;
-	}
-	pop_value_locals();
-	pop_alloc_frame();
-	return rval;
-}
-
-// These helpers are used to convert C++ values to
-// their MAXScript value. Maxscript uses different
-// methods to handle the conversion, and these helpers
-// allow the conversion to be templated. You may need
-// to add more converter, if you need to access other
-// parameter types.
-inline Value* make_maxscript_value(bool v)
-{
-	return_protected(v ? &true_value : &false_value);
-}
-
-inline Value* make_maxscript_value(int v)
-{
-	return_protected(Integer::intern(v));
-}
-
-inline Value* make_maxscript_value(float v)
-{
-	return_protected(Float::intern(v));
-}
-
-inline Value* make_maxscript_value(COLORREF rgb)
-{
-	return new ColorValue(rgb);
-}
-
-inline Value* make_maxscript_value(const Color& rgb)
-{
-	return new ColorValue(rgb);
-}
-
-inline Value* make_maxscript_value(LPCTSTR str)
-{
-	return Name::intern(const_cast<LPTSTR>(str));
-}
-
-inline Value* make_maxscript_value(ReferenceTarget* rtarg)
-{
-	return MAXClass::make_wrapper_for(rtarg);
-}
-
-// These helpers convert MAXScript values to C++ values.
-// MAXScript uses different methods for this conversion,
-// and these helpers template the conversion. You will
-// need to add more converters if you need more types.
-template <class T>
-class ConvertMAXScriptToC {
-public:
-	static T cvt(Value* val);
-};
-
-inline bool ConvertMAXScriptToC<bool>::cvt(Value* val)
-{
-	return val->to_bool() != 0;
-}
-
-inline int ConvertMAXScriptToC<int>::cvt(Value* val)
-{
-	return val->to_int();
-}
-
-inline float ConvertMAXScriptToC<float>::cvt(Value* val)
-{
-	return val->to_float();
-}
-
-inline Color ConvertMAXScriptToC<Color>::cvt(Value* val)
-{
-	return val->to_point3();
-}
-
-inline LPTSTR ConvertMAXScriptToC<LPTSTR>::cvt(Value* val)
-{
-	return val->to_string();
-}
-
-inline Texmap* ConvertMAXScriptToC<Texmap*>::cvt(Value* val)
-{
-	return val->to_texmap();
-}
-
-inline ReferenceTarget* ConvertMAXScriptToC<ReferenceTarget*>::cvt(Value* val)
-{
-	return val->to_reftarg();
-}
-
-
-#endif
diff --git a/NifImport/resource.h b/NifImport/resource.h
index 01805df3283da03790417e21430b878414cedeee..6c53f318b4a80ce8b73781b4ea2812d7eeee552d 100644
--- a/NifImport/resource.h
+++ b/NifImport/resource.h
@@ -12,9 +12,25 @@
 #define IDC_DOSTUFF                     1000
 #define IDC_EDITHEIGHT                  1001
 #define IDC_BUTTON1                     1002
-#define IDC_COLOR                       1456
-#define IDC_EDIT                        1490
-#define IDC_SPIN                        1496
+#define IDC_BTN_BROWSE                  1002
+#define IDC_CHK_BONES                   1003
+#define IDC_CHK_FLIP_UV                 1004
+#define IDC_CHK_FURN                    1005
+#define IDC_ED_SKELETON                 1006
+#define IDC_CHK_BIPED                   1007
+#define IDC_CHK_COLL                    1010
+#define IDC_LBL_LINK                    1011
+#define IDC_CHK_VCOLORS                 1012
+#define IDC_CHK_SHOW_TEX                1013
+#define IDC_CB_GAME                     1014
+#define IDC_CB_USER_VERSION             1016
+#define IDC_CHK_SKIN                    1017
+#define IDC_CHK_ANIMATION               1018
+#define IDC_CHK_AUTOSMOOTH              1019
+#define IDC_CHK_ILLEGAL                 1020
+#define IDC_STC_SKELETON                1021
+#define IDC_CHK_REM_BONES               1022
+
 
 // Next default values for new objects
 // 
diff --git a/NifPlugins_VC80.sln b/NifPlugins_VC80.sln
index b3f90853ccc8912e9620aae0909175f068ad49ea..b1ec78f894fd30a15c84de112a25e85b2b426018 100644
--- a/NifPlugins_VC80.sln
+++ b/NifPlugins_VC80.sln
@@ -30,6 +30,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
 	ProjectSection(SolutionItems) = preProject
 		MaxNifPlugins_Readme.txt = MaxNifPlugins_Readme.txt
 		MaxNifTools.ini = MaxNifTools.ini
+		..\docsys\nif.xml = ..\docsys\nif.xml
 		NifPlugins_Development_Readme.txt = NifPlugins_Development_Readme.txt
 	EndProjectSection
 EndProject