diff --git a/SConstruct b/SConstruct
index 99badebeb60aced072a6288b142a7a2d6f111801..4eafbe945cbb591a55cf727145357298a70bfa8b 100644
--- a/SConstruct
+++ b/SConstruct
@@ -36,13 +36,13 @@ try:
 except KeyError:
     print """
 Error: SWIG not found.
-Please install SWIG, as we need it to create the python wrapper.
+Please install SWIG, it's needed to create the python wrapper.
 You can get it from http://www.swig.org/"""
     if sys.platform == "win32": print "Also don't forget to add the SWIG directory to your %PATH%."
     Exit(1)
 
 # build niflib and python wrapper
-niflib = env.StaticLibrary('niflib', Split('niflib.cpp nif_math.cpp NIF_Blocks.cpp NIF_IO.cpp docsys_extract.cpp'), CPPPATH = '.', CPPFLAGS = cppflags)
+niflib = env.StaticLibrary('niflib', Split('niflib.cpp nif_math.cpp NIF_Blocks.cpp NIF_IO.cpp docsys_extract.cpp kfm.cpp'), CPPPATH = '.', CPPFLAGS = cppflags)
 nifshlib = env.SharedLibrary('_niflib', 'pyniflib.i', LIBS=['niflib'] + python_lib, LIBPATH=['.'] + python_libpath, SWIGFLAGS = '-c++ -python', CPPPATH = ['.'] + python_include, CPPFLAGS = cppflags, SHLIBPREFIX='')
 # makes sure niflib.lib is built before trying to build _niflib.dll
 env.Depends(nifshlib, niflib)
diff --git a/kfm.cpp b/kfm.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f76a66fbc2fcda90cf9d787aad60eee0cc016c16
--- /dev/null
+++ b/kfm.cpp
@@ -0,0 +1,140 @@
+//--Kfm Functions--//
+
+#include "kfm.h"
+#include "NIF_IO.h"
+
+void KfmEventString::Read( istream & in, unsigned int version ) {
+	unk_int = ReadUInt(in);
+	event = ReadString(in);
+};
+
+void KfmEventString::Write( ostream & out, unsigned int version ) {
+	WriteUInt(unk_int, out);
+	WriteString(event, out);
+};
+
+void KfmEvent::Read( istream & in, uint version ) {
+	id = ReadUInt(in);
+	type = ReadUInt(in);
+	if ( type != 5 ) {
+		unk_float = ReadFloat(in);
+		event_strings.resize(ReadUInt(in));
+		for ( vector<KfmEventString>::iterator it = event_strings.begin(); it != event_strings.end(); it++ ) it->Read(in, version);
+		unk_int3 = ReadUInt(in);
+	};
+};
+
+void KfmAction::Read( istream & in, uint version ) {
+	if ( version <= VER_KFM_1_2_4b ) action_name = ReadString(in);
+	action_filename = ReadString(in);
+	unk_int1 = ReadUInt(in);
+	events.resize(ReadUInt(in));
+	for ( vector<KfmEvent>::iterator it = events.begin(); it != events.end(); it++ ) it->Read(in, version);
+	unk_int2 = ReadUInt(in);
+};
+
+unsigned int Kfm::Read( string const & file_name ) {
+	ifstream in( file_name.c_str(), ifstream::binary );
+	unsigned int version = Read(in);
+	if ( in.eof() )
+		throw runtime_error("End of file reached prematurely. This KFM may be corrupt or improperly supported.");
+	ReadByte( in ); // this should fail, and trigger the in.eof() flag
+	if ( ! in.eof() )
+		throw runtime_error("End of file not reached. This KFM may be corrupt or improperly supported.");
+	return version;
+};
+
+unsigned int Kfm::Read( istream & in ) {
+	//--Read Header--//
+	char header_string[64];
+	in.getline( header_string, 64 );
+	string headerstr(header_string);
+
+	// make sure this is a KFM file
+	if ( headerstr.substr(0, 26) != ";Gamebryo KFM File Version" ) {
+		version = VER_INVALID;
+		return version;
+	};
+
+	// supported versions
+	if ( headerstr == ";Gamebryo KFM File Version 2.0.0.0b" ) version = VER_KFM_2_0_0_0b;
+	else if ( headerstr == ";Gamebryo KFM File Version 1.2.4b" ) version = VER_KFM_1_2_4b;
+	//else if ( headerstr == ";Gamebryo KFM File Version 1.0" ) version = VER_KFM_1_0;
+	//else if ( headerstr == ";Gamebryo KFM File Version 1.0\r" ) version = VER_KFM_1_0; // Windows eol style
+	else {
+		version = VER_UNSUPPORTED;
+		return version;
+	};
+	
+	//--Read remainder--//
+	if (version == VER_KFM_1_0) {
+		// TODO write a parser
+	} else {
+		if (version >= VER_KFM_2_0_0_0b) unk_byte = ReadByte(in);
+		else unk_byte = 1;
+		nif_filename = ReadString(in);
+		master = ReadString(in);
+		unk_int1 = ReadUInt(in);
+		unk_int2 = ReadUInt(in);
+		unk_float1 = ReadFloat(in);
+		unk_float2 = ReadFloat(in);
+		actions.resize(ReadUInt(in));
+		unk_int3 = ReadUInt(in);
+		for ( vector<KfmAction>::iterator it = actions.begin(); it != actions.end(); it++ ) it->Read(in, version);
+	};
+
+	// Retrieve action names
+	if ( version >= VER_KFM_2_0_0_0b ) {
+		string model_name = nif_filename.substr(0, nif_filename.length()-4); // strip .nif extension
+		for ( vector<KfmAction>::iterator it = actions.begin(); it != actions.end(); it++ ) {
+			string action_name = it->action_filename.substr(0, it->action_filename.length()-3); // strip .kf extension
+			if (action_name.find( model_name + "_" ) == 0)
+				action_name = action_name.substr(model_name.length() + 1, string::npos);
+			if (action_name.find( master + "_" ) == 0)
+				action_name = action_name.substr(master.length() + 1, string::npos);
+			it->action_name = action_name;
+		};
+	};
+
+	return version;
+};
+
+/*
+void Kfm::Write( ostream & out, uint version ) {
+	if ( version == VER_KFM_1_0 ) {
+		// handle this case seperately
+		out << ";Gamebryo KFM File Version 1.0" << endl;
+		// TODO write the rest of the data
+	} else {
+		if ( version == VER_KFM_1_2_4b )
+			out.write(";Gamebryo KFM File Version 1.2.4b\n", 34);
+		else if ( version == VER_KFM_2_0_0_0b )
+			out.write(";Gamebryo KFM File Version 2.0.0.0b\n", 37);
+		else throw runtime_error("Cannot write KFM file of this version.");
+	};
+};
+*/
+
+blk_ref Kfm::MergeActions( string const & path ) {
+	// Read NIF file
+	cout << path + '\\' + nif_filename << endl;
+	blk_ref nif = ReadNifTree( path + '\\' + nif_filename);
+	
+	// Read Kf files
+	vector<blk_ref> kf;
+	for ( vector<KfmAction>::iterator it = actions.begin(); it != actions.end(); it++ ) {
+		string action_filename = path + '\\' + it->action_filename;
+		// Check if the file exists.
+		// Probably we should check some other field in the Kfm file to determine this...
+		bool exists = false;
+		fstream fin;
+		fin.open(action_filename.c_str(), ios::in);
+		if( fin.is_open() ) exists = true;
+		fin.close();
+		// Import it, if it exists.
+		if (exists) kf.push_back( ReadNifTree(action_filename) );
+	};
+	
+	// TODO: merge everything into the nif file
+	return nif;
+}
diff --git a/kfm.h b/kfm.h
new file mode 100644
index 0000000000000000000000000000000000000000..6ecbc9bcf21ed9c91f2dad9684d1561d6b710c39
--- /dev/null
+++ b/kfm.h
@@ -0,0 +1,71 @@
+#ifndef _KFM_H
+#define _KFM_H
+
+#include "niflib.h"
+
+using namespace std;
+
+//--KFM File Format--//
+
+//KFM Versions
+const unsigned int VER_KFM_1_0 = 0x01000000; /*!< Kfm Version 1.0 */ 
+const unsigned int VER_KFM_1_2_4b = 0x01020400; /*!< Kfm Version 1.2.4b */ 
+const unsigned int VER_KFM_2_0_0_0b = 0x02000000; /*!< Kfm Version 2.0.0.0b */ 
+
+//KFM Data Structure
+
+struct KfmEventString {
+	unsigned int unk_int;
+	string event;
+
+	KfmEventString() : unk_int(0), event() {};
+	void Read( istream & in, unsigned int version );
+	void Write( ostream & out, unsigned int version );
+};
+
+struct KfmEvent {
+	unsigned int id;
+	unsigned int type;
+	float unk_float;
+	vector<KfmEventString> event_strings;
+	unsigned int unk_int3;
+	
+	KfmEvent() : id(0), type(0), unk_float(0.5f), event_strings(), unk_int3(0) {};
+	void Read( istream & in, unsigned int version );
+	//void Write( ostream & out, unsigned int version );
+};
+
+struct KfmAction {
+	string action_name;
+	string action_filename;
+	unsigned int unk_int1;
+	vector<KfmEvent> events;
+	unsigned int unk_int2;
+
+	void Read( istream & in, unsigned int version );
+	//void Write( ostream & out, unsigned int version );
+};
+
+struct Kfm {
+	unsigned int version;
+	unsigned char unk_byte;
+	string nif_filename;
+	string master;
+	unsigned int unk_int1;
+	unsigned int unk_int2;
+	float unk_float1;
+	float unk_float2;
+	unsigned int unk_int3;
+	vector<KfmAction> actions;
+	
+	// Reads the given file and returns the KFM version.
+	unsigned int Read( string const & file_name ); // returns Kfm version
+	unsigned int Read( istream & in ); // returns Kfm version
+
+	// Reads the NIF file and all KF files referred to in this KFM, and returns the root block of the resulting NIF tree.
+	blk_ref Kfm::MergeActions( string const & path );
+	//void Write( string const & file_name, unsigned int version );
+	//void Write( ostream & out, unsigned int version );
+};
+
+#endif
diff --git a/niflib.cpp b/niflib.cpp
index 8172f8bafb25707c4b5efe26e4cf36e3dc09ebaa..40791650a050a7c47d357180f32f4d58c0dbb35a 100644
--- a/niflib.cpp
+++ b/niflib.cpp
@@ -34,6 +34,7 @@ POSSIBILITY OF SUCH DAMAGE. */
 #include "niflib.h"
 #include "NIF_Blocks.h"
 #include "nif_attrs.h"
+#include "kfm.h"
 #include <exception>
 #include <stdexcept>
 using namespace std;
@@ -601,13 +602,20 @@ list<blk_ref> SearchAllNifTree( blk_ref const & root_block, string block_name )
 //	return result;
 //};
 
-// Split off XNif & XKf Files given a pointer to the root block of the full Nif file tree.
-void SplitNifTree( blk_ref const & root_block, blk_ref & xnif_root, blk_ref & xkf_root, int game ) {
+/*!
+ * Helper function to split off animation from a nif tree. If no animation groups are defined, then both xnif_root and xkf_root will be null blocks.
+ * \param root_block The root block of the full tree.
+ * \param xnif_root The root block of the tree without animation.
+ * \param xkf_root The root block of the animation tree.
+ * \param kfm The KFM structure (if required by style).
+ * \param kf_type What type of keyframe tree to write (Morrowind style, DAoC style, ...).
+ */
+void SplitNifTree( blk_ref const & root_block, blk_ref & xnif_root, blk_ref & xkf_root, Kfm & kfm, int kf_type ) {
 	// Do we have animation groups (a NiTextKeyExtraData block)?
 	// If so, create XNif and XKf trees.
 	blk_ref txtkey_block = SearchNifTree( root_block, "NiTextKeyExtraData" );
 	if ( txtkey_block.is_null() == false ) {
-		if ( game == GAME_MW ) {
+		if ( kf_type == KF_MW ) {
 			// Construct the XNif file...
 			// We are lazy. (TODO: clone & remove keyframe controllers & keyframe data)
 			xnif_root = root_block;
@@ -684,11 +692,44 @@ void SplitNifTree( blk_ref const & root_block, blk_ref & xnif_root, blk_ref & xk
 	};
 }
 
-// Split an animation tree into multiple animation trees (one per animation group) and a kfm block.
-void SplitKfTree( blk_ref const & root_block, Kfm & kfm, vector<blk_ref> & kf ) {
+/*!
+ * Helper function to split an animation tree into multiple animation trees (one per animation group) and a kfm block.
+ * \param root_block The root block of the full tree.
+ * \param kf Vector of root blocks of the new animation trees.
+ */
+void SplitKfTree( blk_ref const & root_block, vector<blk_ref> & kf ) {
 	throw runtime_error("Not yet implemented.");
 };
 
+void WriteFileGroup( string const & file_name, blk_ref const & root_block, unsigned int version, unsigned int export_files, unsigned int kf_type ) {
+	// Get base filename.
+	uint file_name_slash = uint(file_name.rfind("\\") + 1);
+	string file_name_path = file_name.substr(0, file_name_slash);
+	string file_name_base = file_name.substr(file_name_slash, file_name.length());
+	uint file_name_dot = uint(file_name_base.rfind("."));
+	file_name_base = file_name_base.substr(0, file_name_dot);
+	
+	// Deal with the simple case first
+	if ( export_files == EXPORT_NIF )
+		WriteNifTree( file_name_path + file_name_base + ".nif", root_block, version ); // simply export the NIF file!
+	// Now consider all other cases
+	else if ( kf_type == KF_MW ) {
+		if ( export_files == EXPORT_NIF_KF ) {
+			// for Morrowind we must also write the full NIF file
+			WriteNifTree( file_name_path + file_name_base + ".nif", root_block, version ); // simply export the NIF file!
+			blk_ref xnif_root;
+			blk_ref xkf_root;
+			Kfm kfm; // dummy
+			SplitNifTree( root_block, xnif_root, xkf_root, kfm, KF_MW );
+			WriteNifTree( file_name_path + "x" + file_name_base + ".nif", xnif_root, version ); // simply export the NIF file!
+			WriteNifTree( file_name_path + "x" + file_name_base + ".kf", xkf_root, version ); // simply export the NIF file!
+		} else
+			throw runtime_error("Invalid export option.");
+	} else
+		throw runtime_error("Not yet implemented.");
+};
+
+
 //Returns the total number of blocks in memory
 unsigned int BlocksInMemory() {
 	return blocks_in_memory;
@@ -1033,141 +1074,3 @@ IPosData * QueryPosData ( blk_ref & block ) {
 IPosData const * QueryPosData ( blk_ref const & block ) {
 	return (IPosData const *)block->QueryInterface( ID_POS_DATA );
 }
-
-//--Kfm Functions--//
-
-void KfmEventString::Read( istream & in, unsigned int version ) {
-	unk_int = ReadUInt(in);
-	event = ReadString(in);
-};
-
-void KfmEventString::Write( ostream & out, unsigned int version ) {
-	WriteUInt(unk_int, out);
-	WriteString(event, out);
-};
-
-void KfmEvent::Read( istream & in, uint version ) {
-	id = ReadUInt(in);
-	type = ReadUInt(in);
-	if ( type != 5 ) {
-		unk_float = ReadFloat(in);
-		event_strings.resize(ReadUInt(in));
-		for ( vector<KfmEventString>::iterator it = event_strings.begin(); it != event_strings.end(); it++ ) it->Read(in, version);
-		unk_int3 = ReadUInt(in);
-	};
-};
-
-void KfmAction::Read( istream & in, uint version ) {
-	if ( version <= VER_KFM_1_2_4b ) action_name = ReadString(in);
-	action_filename = ReadString(in);
-	unk_int1 = ReadUInt(in);
-	events.resize(ReadUInt(in));
-	for ( vector<KfmEvent>::iterator it = events.begin(); it != events.end(); it++ ) it->Read(in, version);
-	unk_int2 = ReadUInt(in);
-};
-
-unsigned int Kfm::Read( string const & file_name ) {
-	ifstream in( file_name.c_str(), ifstream::binary );
-	unsigned int version = Read(in);
-	if ( in.eof() )
-		throw runtime_error("End of file reached prematurely. This KFM may be corrupt or improperly supported.");
-	ReadByte( in ); // this should fail, and trigger the in.eof() flag
-	if ( ! in.eof() )
-		throw runtime_error("End of file not reached. This KFM may be corrupt or improperly supported.");
-	return version;
-};
-
-unsigned int Kfm::Read( istream & in ) {
-	//--Read Header--//
-	char header_string[64];
-	in.getline( header_string, 64 );
-	string headerstr(header_string);
-
-	// make sure this is a KFM file
-	if ( headerstr.substr(0, 26) != ";Gamebryo KFM File Version" ) {
-		version = VER_INVALID;
-		return version;
-	};
-
-	// supported versions
-	if ( headerstr == ";Gamebryo KFM File Version 2.0.0.0b" ) version = VER_KFM_2_0_0_0b;
-	else if ( headerstr == ";Gamebryo KFM File Version 1.2.4b" ) version = VER_KFM_1_2_4b;
-	//else if ( headerstr == ";Gamebryo KFM File Version 1.0" ) version = VER_KFM_1_0;
-	//else if ( headerstr == ";Gamebryo KFM File Version 1.0\r" ) version = VER_KFM_1_0; // Windows eol style
-	else {
-		version = VER_UNSUPPORTED;
-		return version;
-	};
-	
-	//--Read remainder--//
-	if (version == VER_KFM_1_0) {
-		// TODO write a parser
-	} else {
-		if (version >= VER_KFM_2_0_0_0b) unk_byte = ReadByte(in);
-		else unk_byte = 1;
-		nif_filename = ReadString(in);
-		master = ReadString(in);
-		unk_int1 = ReadUInt(in);
-		unk_int2 = ReadUInt(in);
-		unk_float1 = ReadFloat(in);
-		unk_float2 = ReadFloat(in);
-		actions.resize(ReadUInt(in));
-		unk_int3 = ReadUInt(in);
-		for ( vector<KfmAction>::iterator it = actions.begin(); it != actions.end(); it++ ) it->Read(in, version);
-	};
-
-	// Retrieve action names
-	if ( version >= VER_KFM_2_0_0_0b ) {
-		string model_name = nif_filename.substr(0, nif_filename.length()-4); // strip .nif extension
-		for ( vector<KfmAction>::iterator it = actions.begin(); it != actions.end(); it++ ) {
-			string action_name = it->action_filename.substr(0, it->action_filename.length()-3); // strip .kf extension
-			if (action_name.find( model_name + "_" ) == 0)
-				action_name = action_name.substr(model_name.length() + 1, string::npos);
-			if (action_name.find( master + "_" ) == 0)
-				action_name = action_name.substr(master.length() + 1, string::npos);
-			it->action_name = action_name;
-		};
-	};
-
-	return version;
-};
-
-/*
-void Kfm::Write( ostream & out, uint version ) {
-	if ( version == VER_KFM_1_0 ) {
-		// handle this case seperately
-		out << ";Gamebryo KFM File Version 1.0" << endl;
-		// TODO write the rest of the data
-	} else {
-		if ( version == VER_KFM_1_2_4b )
-			out.write(";Gamebryo KFM File Version 1.2.4b\n", 34);
-		else if ( version == VER_KFM_2_0_0_0b )
-			out.write(";Gamebryo KFM File Version 2.0.0.0b\n", 37);
-		else throw runtime_error("Cannot write KFM file of this version.");
-	};
-};
-*/
-
-blk_ref Kfm::MergeActions( string const & path ) {
-	// Read NIF file
-	cout << path + '\\' + nif_filename << endl;
-	blk_ref nif = ReadNifTree( path + '\\' + nif_filename);
-	
-	// Read Kf files
-	vector<blk_ref> kf;
-	for ( vector<KfmAction>::iterator it = actions.begin(); it != actions.end(); it++ ) {
-		string action_filename = path + '\\' + it->action_filename;
-		// Check if the file exists.
-		// Probably we should check some other field in the Kfm file to determine this...
-		bool exists = false;
-		fstream fin;
-		fin.open(action_filename.c_str(), ios::in);
-		if( fin.is_open() ) exists = true;
-		fin.close();
-		// Import it, if it exists.
-		if (exists) kf.push_back( ReadNifTree(action_filename) );
-	};
-	
-	// TODO: merge everything into the nif file
-	return nif;
-}
diff --git a/niflib.h b/niflib.h
index d82aeb884dd7e6d8ef4a567cf4b952f435543223..97e1f1648b5613979b98014c991829f33d2e67fd 100644
--- a/niflib.h
+++ b/niflib.h
@@ -79,7 +79,6 @@ struct SkinWeight;
 struct ControllerLink;
 struct TexDesc;
 struct LODRange;
-struct Kfm;
 
 //--Constants--//
 
@@ -161,10 +160,16 @@ const unsigned int VER_UNSUPPORTED = 0xFFFFFFFF; /*!< Unsupported Nif Version */
 const unsigned int VER_INVALID     = 0xFFFFFFFE; /*!< Not a Nif file */
 
 // Keyframe trees are game dependent, so here we define a few games.
-const int GAME_MW = 0; // keyframe files: NiSequenceStreamHelper header, .kf extension
-const int GAME_DAOC = 1; // keyframe files: NiNode header, .kfa extension
-const int GAME_ZOO2 = 2; // (keyframe files not supported)
-const int GAME_CIV4 = 3; // keyframe files: NiControllerSequence header, .kf extension
+const unsigned int KF_MW = 0; // keyframe files: NiSequenceStreamHelper header, .kf extension
+const unsigned int KF_DAOC = 1; // keyframe files: NiNode header, .kfa extension
+const unsigned int KF_CIV4 = 2; // keyframe files: NiControllerSequence header, .kf extension
+
+// Export options.
+const unsigned int EXPORT_NIF = 0; // NIF
+const unsigned int EXPORT_NIF_KF = 1; // NIF + single KF + KFM
+const unsigned int EXPORT_NIF_KF_MULTI = 2; // NIF + multiple KF + KFM
+const unsigned int EXPORT_KF = 3; // single KF
+const unsigned int EXPORT_KF_MULTI = 4; // multiple KF
 
 /*! Lists the basic texture types availiable from the ITexturingProperty interface*/
 enum TexType {
@@ -344,21 +349,14 @@ void WriteNifTree( string const & file_name, blk_ref const & root_block, unsigne
 void WriteNifTree( ostream & stream, blk_ref const & root_block, unsigned int version );
 
 /*!
- * Split off animation from a nif tree. If no animation groups are defined, then both xnif_root and xkf_root will be null blocks.
- * \param root_block The root block of the full tree.
- * \param xnif_root The root block of the tree without animation.
- * \param xkf_root The root block of the animation tree.
- * \param game The game; determines what type of keyframe tree to write.
- */
-void SplitNifTree( blk_ref const & root_block, blk_ref & xnif_root, blk_ref & xkf_root, int game );
-
-/*!
- * Split an animation tree into multiple animation trees (one per animation group) and a kfm block.
- * \param root_block The root block of the full tree.
- * \param kfm The root block of the tree without animation.
- * \param kf Vector of root blocks of the new animation trees.
+ * Writes a bunch of files given a base file name, and a pointer to the root block of the Nif file tree.
+ * \param file_name The desired file name for the base NIF file. This name serves as the basis for the names of any Kf files and Kfm files as well.  The path is relative to the working directory unless a full path is specified.
+ * \param root_block The root block to start from when writing out the NIF file.
+ * \param version The version of the NIF format to use when writing a file.
+ * \param export_files What files to write: NIF, NIF + KF + KFM, NIF + KF's + KFM, KF only, KF's only
+ * \param kf_type The KF type (Morrowind style, DAoC style, CivIV style, ...)
  */
-void SplitKfTree( blk_ref const & root_block, Kfm & kfm, vector<blk_ref> & kf ); // I don't know whether we will be needing a game parameter here... so far we will only use this for CIV4.
+void WriteFileGroup( string const & file_name, blk_ref const & root_block, unsigned int version, unsigned int export_files, unsigned int kf_type );
 
 /*!
  * Merges two Nif trees into one.  For standard Nif files, any blocks with the same name are merged.  For Kf files, blocks are attatched to those that match the name specified in the KF root block.  The data stored in a NIF file varies from version to version.  Usually you are safe with the default option (the highest availiable version) but you may need to use an earlier version if you need to clone an obsolete piece of information.
@@ -3377,124 +3375,6 @@ struct TexDesc {
 	float unknownFloat2; /*!< An unknown floating point value that exists from version 10.1.0.0 on. */ 
 };
 
-//--KFM File Format--//
-
-//KFM Versions
-const unsigned int VER_KFM_1_0 = 0x01000000; /*!< Kfm Version 1.0 */ 
-const unsigned int VER_KFM_1_2_4b = 0x01020400; /*!< Kfm Version 1.2.4b */ 
-const unsigned int VER_KFM_2_0_0_0b = 0x02000000; /*!< Kfm Version 2.0.0.0b */ 
-
-//KFM Data Structure
-
-struct KfmEventString {
-	unsigned int unk_int;
-	string event;
-
-	KfmEventString() : unk_int(0), event() {};
-	void Read( istream & in, unsigned int version );
-	void Write( ostream & out, unsigned int version );
-};
-
-struct KfmEvent {
-	unsigned int id;
-	unsigned int type;
-	float unk_float;
-	vector<KfmEventString> event_strings;
-	unsigned int unk_int3;
-	
-	KfmEvent() : id(0), type(0), unk_float(0.5f), event_strings(), unk_int3(0) {};
-	void Read( istream & in, unsigned int version );
-	//void Write( ostream & out, unsigned int version );
-};
-
-struct KfmAction {
-	string action_name;
-	string action_filename;
-	unsigned int unk_int1;
-	vector<KfmEvent> events;
-	unsigned int unk_int2;
-
-	void Read( istream & in, unsigned int version );
-	//void Write( ostream & out, unsigned int version );
-};
-
-struct Kfm {
-	unsigned int version;
-	unsigned char unk_byte;
-	string nif_filename;
-	string master;
-	unsigned int unk_int1;
-	unsigned int unk_int2;
-	float unk_float1;
-	float unk_float2;
-	unsigned int unk_int3;
-	vector<KfmAction> actions;
-	
-	/*!
-	 * Reads the given file and returns the KFM version.
-	 * \param file_name The input file name.
-	 * \return The KFM version of the file, in hexadecimal format. If the file is not a KFM file, it returns VER_INVALID. If it is a KFM file, but its version is not supported by the library, it returns VER_UNSUPPORTED.
-	 * 
-	 * <b>Example:</b> 
-	 * \code
-	 * Kfm kfm;
-	 * unsigned int ver = kfm.Read( "test_in.kfm" );
-	 * if ( ver == VER_UNSUPPORTED ) cout << "unsupported" << endl;
-	 * else if ( ver == VER_INVALID ) cout << "invalid" << endl;
-	 * else cout << "Describes keyframes for NIF file " << kfm.nif_filename << "." << endl;
-	 *
-	 * \endcode
-	 * 
-	 * <b>In Python:</b>
-	 * \code
-	 * kfm = Kfm()
-	 * ver = kfm.Read( "test_in.kfm" )
-	 * if ( ver == VER_UNSUPPORTED ):
-	 *     print "unsupported"
-	 * elif ( ver == VER_INVALID ):
-	 *     print "invalid"
-	 * else:
-	 *     print "Describes keyframes for NIF file %s."%kfm.nif_filename
-	 * \endcode
-	 */
-	unsigned int Read( string const & file_name ); // returns Kfm version
-	unsigned int Read( istream & in ); // returns Kfm version
-
-	/*!
-	 * Reads the NIF file and all KF files referred to in this KFM, and returns the root block of the resulting NIF tree.
-	 * \param path The file path; usually, this should be the directory where the KFM file was read from.
-	 * \return The root block of the NIF tree.
-	 * 
-	 * <b>Example:</b> 
-	 * \code
-	 * Kfm kfm;
-	 * unsigned int ver = kfm.Read( "test_in.kfm" );
-	 * if ( ver == VER_UNSUPPORTED ) cout << "unsupported" << endl;
-	 * else if ( ver == VER_INVALID ) cout << "invalid" << endl;
-	 * else {
-	 *   blk_ref root = kfm.MergeActions(".");
-	 *   cout << root << endl;
-	 * };
-	 *
-	 * \endcode
-	 * 
-	 * <b>In Python:</b>
-	 * \code
-	 * kfm = Kfm()
-	 * ver = kfm.Read( "test_in.kfm" )
-	 * if ( ver == VER_UNSUPPORTED ):
-	 *     print "unsupported"
-	 * elif ( ver == VER_INVALID ):
-	 *     print "invalid"
-	 * else:
-	 *     print kfm.MergeActions(".")
-	 * \endcode
-	 */
-	blk_ref Kfm::MergeActions( string const & path );
-	//void Write( string const & file_name, unsigned int version );
-	//void Write( ostream & out, unsigned int version );
-};
-
 //--USER GUIDE DOCUMENTATION--//
 
 /*! \mainpage Niflib Documentation
diff --git a/pyniflib.i b/pyniflib.i
index 40ff6b046f0fed1595c1d4b3dbcee0a38b457404..0657706a98dd4581306fc2d9639a5b0c6e654b0e 100644
--- a/pyniflib.i
+++ b/pyniflib.i
@@ -99,9 +99,6 @@ struct Key {
 %template(vector_Key_Color4) std::vector< Key<Color4> >;
 %template(Key_string) Key<std::string>;
 %template(vector_Key_string) std::vector< Key<std::string> >;
-%template(vector_KfmAction) std::vector<KfmAction>;
-%template(vector_KfmEvent) std::vector<KfmEvent>;
-%template(vector_KfmEventString) std::vector<KfmEventString>;
 
 %ignore Float2::operator[](int n);
 %ignore Float2::operator[](int n) const;