diff --git a/NIF_Blocks.cpp b/NIF_Blocks.cpp
index 98cd3b12ed6479898288fbaa76d76e4666a9237b..007b8fe8b5ce30ab1918009ce1db73fa036f6675 100644
--- a/NIF_Blocks.cpp
+++ b/NIF_Blocks.cpp
@@ -3764,54 +3764,115 @@ NiControllerSequence::~NiControllerSequence() {
 	}
 }
 
-//void NiControllerSequence::SetFirstTargetName( string new_name ) {
-//	_first_child.first = new_name;
-//}
-//
-//void NiControllerSequence::SetFirstController( blk_ref new_link ) {
-//	//Check for identical values
-//	if ( new_link == _first_child.second )
-//		return;
-//	
-//	//Remove old child
-//	if ( _first_child.second.is_null() == false ) {
-//		RemoveChild( _first_child.second.get_block() );
-//	}
-//
-//	//Set new value
-//	_first_child.second = new_link;
-//
-//	//Add new child
-//	if ( _first_child.second.is_null() == false ) {
-//		AddChild( _first_child.second.get_block() );
-//	}
-//}
-//
-//void NiControllerSequence::AddController( string new_name, blk_ref new_link ) {
-//	//Make sure the link isn't null
-//	if ( new_link.is_null() == true ) {
-//		throw runtime_error("Attempted to add a null link to NiControllerSequence block.");
-//	}
-//	
-//	_children.push_back( pair<string,blk_ref>(new_name, new_link) );
-//
-//	//Add new child
-//	AddChild( new_link.get_block() );
-//}
-//
-//void NiControllerSequence::ClearControllers() {
-//
-//	SetFirstTargetName( "" );
-//	SetFirstController( blk_ref(-1) );
-//
-//	//Cycle through all controllers, removing them as parents from the blocks they refer to
-//	for (uint i = 0; i < _children.size(); ++i ) {
-//		RemoveChild( _children[i].second.get_block() );
-//	}
-//
-//	//Clear list
-//	_children.clear();
-//}
+void NiControllerSequence::SetTextKey( string new_name, blk_ref new_link ) {
+	//Set new name
+	txt_key_name = new_name;
+	
+	//Check for identical block values
+	if ( new_link == txt_key_blk )
+		return;
+	
+	//Remove old child
+	if ( txt_key_blk.is_null() == false ) {
+		RemoveChild( txt_key_blk.get_block() );
+	}
+
+	//Set new value
+	txt_key_blk = new_link;
+
+	//Add new child
+	if ( txt_key_blk.is_null() == false ) {
+		AddChild( txt_key_blk.get_block() );
+	}
+}
+
+void NiControllerSequence::AddKfChild( string new_name, blk_ref new_link, string controller_type = "" ) {
+	//Make sure the link isn't null
+	if ( new_link.is_null() == true ) {
+		throw runtime_error("Attempted to add a null link to NiControllerSequence block.");
+	}
+
+	KfChild kc;
+
+	kc.block = new_link;
+
+	//Check for a string palette
+	blk_ref str_pal = GetAttr("String Palette")->asLink();
+	if ( str_pal.is_null() == true ) {
+		//No string palette, store name internally
+		kc.name = new_name;
+	} else {
+		//String palette exists - store name and controller type there
+
+		//Make sure they didn't give us empty strings
+		if ( new_name.size() == 0 || controller_type.size() == 0 ) {
+			throw runtime_error( "You cannot use empty name or controller type strings when using a string palette.");
+		}
+
+		//Get palette
+		string pal = str_pal->GetAttr("Palette")->asString();
+
+		//--Search for copies of the text we want to add--//
+
+		//Search for the name string
+		int offset = (int)pal.find( new_name );
+		if ( offset == -1 ) {
+			//String not found, append it
+			kc.name_offset = (uint)pal.size();
+			pal.append( new_name + '\0' );
+		} else {
+			//String found, use existing offset
+			kc.name_offset = offset;
+		}
+
+		//Search for the controller type string
+		offset = (int)pal.find( controller_type );
+		if ( offset == -1 ) {
+			//String not found, append it
+			kc.controller_offset = (uint)pal.size();
+			pal.append( controller_type + '\0' );
+		} else {
+			//String found, use existing offset
+			kc.controller_offset = offset;
+		}
+
+		//Store the palette back to the string pal block
+		str_pal->GetAttr("Palette")->Set( pal );
+	}
+	
+	children.push_back( kc );
+
+	//Add new child
+	AddChild( kc.block.get_block() );
+	
+	//This should be impossible now, but don't want to forget it later
+	if ( kc.unk_link.is_null() != true ) {
+		AddChild( kc.unk_link.get_block() );
+	}
+}
+
+void NiControllerSequence::ClearKfChildren() {
+
+	//Cycle through all Kf Children, removing them as parents from the blocks they refer to
+	for (uint i = 0; i < children.size(); ++i ) {
+		if ( children[i].block.is_null() != true ) {
+			RemoveChild( children[i].block.get_block() );
+		}
+		if ( children[i].unk_link.is_null() != true ) {
+			RemoveChild( children[i].unk_link.get_block() );
+		}
+	}
+
+	//Clear list
+	children.clear();
+
+	//Check for a string palette
+	blk_ref str_pal = GetAttr("String Palette")->asLink();
+	if ( str_pal.is_null() == false ) {
+		//There's a string palette, so clear it out
+		str_pal->GetAttr("Palette")->Set( "" );
+	}
+}
 
 /***********************************************************
  * NiFloatData methods
diff --git a/NIF_Blocks.h b/NIF_Blocks.h
index d0fc5b408842a4b43c8d239598a41de33f3d2b62..821d0c86dd8c6ee744a3bd44bfa0bcd028a6c069 100644
--- a/NIF_Blocks.h
+++ b/NIF_Blocks.h
@@ -2153,9 +2153,9 @@ public:
 	}
 
 	//IControllerSequence Functions
-	/*void SetTextKey( string new_name, blk_ref new_link );
-	void AddKfChild( string new_name, string controller_type, blk_ref new_link );
-	void ClearKfChildren();*/
+	void SetTextKey( string new_name, blk_ref new_link );
+	void AddKfChild( string new_name, blk_ref new_link, string controller_type);
+	void ClearKfChildren();
 private:
 
 	struct KfChild {
diff --git a/niflib.h b/niflib.h
index 31bcf042038642584d802f0f94a8f71eab3ea840..e1d2b6381293cb0a10294af11a6c9c109640ed62 100644
--- a/niflib.h
+++ b/niflib.h
@@ -2444,10 +2444,10 @@ public:
 class IControllerSequence {
 public:
 	IControllerSequence() {}
-	/*virtual ~IControllerSequence () {}
+	virtual ~IControllerSequence () {}
 	virtual void SetTextKey( string new_name, blk_ref new_link ) = 0;
-	virtual void AddKfChild( string new_name, string controller_type, blk_ref new_link ) = 0;
-	virtual void ClearKfChildren() = 0;*/
+	virtual void AddKfChild( string new_name, blk_ref new_link, string controller_type = "" ) = 0;
+	virtual void ClearKfChildren() = 0;
 };
 
 /*! An advanced interface for the IPalette block which contains a color palette for internally stored paletized textures.