diff --git a/NIF_Blocks.cpp b/NIF_Blocks.cpp
index ff488e0970cace6378f11c40eb4e08032d0ed7cc..ac863a8fac82b3ee53bcc808442be4b165d1c2fa 100644
--- a/NIF_Blocks.cpp
+++ b/NIF_Blocks.cpp
@@ -44,7 +44,9 @@ POSSIBILITY OF SUCH DAMAGE. */
 extern bool verbose;
 extern unsigned int blocks_in_memory;
 
+#ifdef WIN32
 #define endl "\r\n"
+#endif
 
 extern string current_file;
 
@@ -53,13 +55,10 @@ extern string current_file;
  **********************************************************/
 
 ABlock::ABlock() : _block_num(-1), _ref_count(0) {
-		//Temporary to test reference counting
 		blocks_in_memory++;
 	}
 
 ABlock::~ABlock() {
-	//Temporary to test reference counting
-	//cout << "A block has commited suicide." << endl;
 	blocks_in_memory--;
 
 	// Delete all attributes
diff --git a/NIF_Blocks.h b/NIF_Blocks.h
index 9925204dba7906aa36dd76d6ca6a6e5fb7c494ed..1957d3a9381a543a078417ea4c825c852cad8421 100644
--- a/NIF_Blocks.h
+++ b/NIF_Blocks.h
@@ -54,43 +54,11 @@ typedef pair<LinkMapIt,LinkMapIt> LinkMapRange;
 //--Constants--//
 
 //Non-Public Interface IDs
-//const int BlockInternal = -1;
+
 const int SkinInstInternal = -2;
 const int SkinDataInternal = -3;
-//const int NodeInternal = -4;
-
-
-
-
-//void GetBuiltUpTransform(blk_ref block, Matrix & m/*, blk_ref stop*/);
 
-class IBlockInternal {
-public:
-	IBlockInternal() {}
-	virtual ~IBlockInternal() {}
-
-	//Link Tracking
-	virtual void AddParent( IBlock * parent ) = 0;
-	virtual void RemoveParent( IBlock * match ) = 0;
-	virtual void SetBlockNum( int ) = 0;
-	virtual void SetBlockTypeNum( int n ) = 0;
-	virtual int GetBlockTypeNum() = 0;
-	virtual void FixLinks( const vector<blk_ref> & blocks ) = 0;
-	virtual void AddChild( IBlock * new_child ) = 0;
-	virtual void RemoveChild( IBlock * old_child ) = 0;
-
-	//Cross Link Tracking
-	virtual void RemoveCrossLink( IBlock * block_to_remove ) = 0;
-
-	virtual void IncCrossRef( IBlock * block ) = 0;
-	virtual void DecCrossRef( IBlock * block ) = 0;
-
-	//File I/O
-	virtual void Read( istream& in, unsigned int version ) = 0;
-	virtual void Write( ostream& out, unsigned int version ) const = 0;	
-};
-
-class ABlock : public IBlock/*, public IBlockInternal*/ {
+class ABlock : public IBlock {
 public:
 	ABlock();
 	~ABlock();
@@ -157,6 +125,387 @@ protected:
 	list<IBlock*> _cross_refs;
 };
 
+//--Link Classes--//
+
+class Link {
+public:
+	//Constructor
+	//It is required for a LinkGroup to be aware of the block it is part of
+	Link ( IBlock * owner) : _owner(owner), index(-1) {}
+
+	//Destructor
+	~Link() { KillLink(); }
+
+	void SetIndex( const int new_index ) {
+		//This function is for the initial file read.  It records the index of the block which
+		//will later be resolved to a link once all the blocks have been read
+
+		//If there is already a link, kill it
+		if ( link.is_null() == false ) {
+			KillLink();
+			link.nullify();
+		}
+
+		index = new_index;
+	}
+
+	blk_ref GetLink() { return link; }
+
+
+
+	void SetLink( const blk_ref & new_link ) {
+		if ( link != new_link ) {
+			//Kill previous link
+			KillLink();
+			
+			//Set New Link
+			link = new_link;
+			InitLink();
+		}
+	}
+
+	void Fix( const vector<blk_ref> & blocks ) {
+		//The purpouse of this function is to convert the block index to a link
+		//to the corresponding block.
+
+		//Ensure that there is an index to convert
+		if (index == -1 ) {
+			return;
+		}
+		
+		if ( index < int(blocks.size()) && index >= 0 ) {
+			link = blocks[index];
+			InitLink();
+		}
+	}
+private:
+	IBlock * _owner;
+	blk_ref link;
+	int index;
+	void InitLink() {
+		//Add parent at new link site
+		IBlock * target = link.get_block();
+		if ( target != NULL ) {
+			//Get internal interface
+			((ABlock*)target)->AddParent( _owner );
+		}
+	}
+	void KillLink() {
+		//Remove parent at previous location
+		IBlock * target = link.get_block();
+		if ( target != NULL ) {
+			((ABlock*)target)->RemoveParent( _owner );
+		}
+	}
+};
+
+class LinkGroup {
+public:
+	//Constructor
+	//It is required for a LinkGroup to be aware of the block it is part of
+	LinkGroup(IBlock * owner) : _owner(owner) {}
+
+	//Destructor
+	~LinkGroup() { 
+		//Remove all links
+		ClearLinks();
+	}
+
+	void SetIndices( const list<int> new_indices ) {
+		//This function is for the initial file read.  It records the indices of the blocks which
+		//will later be resolved to links once all the blocks have been read
+
+		//If there are already links, kill them
+		ClearLinks();
+
+		indices = new_indices;
+	}
+
+	list<blk_ref> GetLinks() const { 
+		return links;
+	}
+
+	void AddLink( blk_ref const & block ) {
+		InitLink( block );
+		links.push_back( block );
+	}
+
+	void AddLinks( list<blk_ref> const & new_links ) {
+		//Initiate all of the new links
+		list<blk_ref>::const_iterator it;
+		for (it = new_links.begin(); it != new_links.end(); ++it ) {
+			InitLink( *it );
+			links.push_back( *it );
+		}
+	}
+
+	blk_ref FindLink( string const & block_type ) const {
+		//Find the first link with the requested block type
+		for ( list<blk_ref>::const_iterator it = links.begin(); it != links.end(); ++it ) {
+			if ( (*it)->GetBlockType() == block_type )
+				return blk_ref(*it);
+		}
+
+		//No block was found, so return a null one
+		return blk_ref(-1);
+	}
+
+	void ClearLinks() { 
+		//Kill all the links
+		list<blk_ref>::iterator it;
+		for (it = links.begin(); it != links.end(); ++it ) {
+			KillLink( *it );
+		}
+
+		//Clear the list
+		links.clear();
+	}
+
+	void RemoveLinks( blk_ref const & block ) {
+		//Remove all links that match this block
+		//Kill the links first
+		list<blk_ref>::iterator it;
+		for (it = links.begin(); it != links.end(); ++it ) {
+			if ( *it == block ) {
+				KillLink( *it );
+			}
+		}
+		
+		//Now remove them from the list
+		links.remove( block );
+	}
+
+	void Fix( const vector<blk_ref> & blocks ) {
+		//The purpouse of this function is to convert the block indices to a links
+		//to the corresponding blocks.
+		
+		list<int>::iterator it;
+		for (it = indices.begin(); it != indices.end(); ++it ) {
+			if ( *it < int(blocks.size()) && *it >= 0 ) {
+				blk_ref new_link = blocks[*it];
+				InitLink( new_link );
+				links.push_back( new_link );
+			}
+		}
+
+		//Clear indices
+		indices.clear();
+	}
+
+private:
+	IBlock * _owner;
+	list<blk_ref> links;
+	list<int> indices;
+	void InitLink( const blk_ref & link ) {
+		//Add parent at new link site
+		IBlock * target = link.get_block();
+		if ( target != NULL ) {
+			//Get internal interface
+			((ABlock*)target)->AddParent( _owner );
+		}
+	}
+	void KillLink( const blk_ref & link ) {
+		//Remove parent at previous location
+		IBlock * target = link.get_block();
+		if ( target != NULL ) {
+			((ABlock*)target)->RemoveParent( _owner );
+		}
+	}
+};
+
+//--CrossRef Classes--//
+
+class CrossRef {
+public:
+	//Constructor
+	//It is required for a CrossRef to be aware of the block it is part of
+	CrossRef ( IBlock * owner) : _owner(owner), ref(NULL), index(-1) {}
+
+	//Destructor
+	~CrossRef() { KillRef(); }
+
+	void SetIndex( const int new_index ) {
+		//This function is for the initial file read.  It records the index of the block which
+		//will later be resolved to a reference once all the blocks have been read
+
+		//If there is already a reference, kill it
+		if ( ref != NULL ) {
+			KillRef();
+			ref = NULL;
+		}
+
+		index = new_index;
+	}
+
+	IBlock * GetCrossRef() { return ref; }
+
+	void SetCrossRef( IBlock * new_ref ) {
+		if ( ref != new_ref ) {
+			//Kill previous link
+			KillRef();
+			
+			//Set New Link
+			ref = new_ref;
+			InitRef();
+		}
+	}
+
+	void RemoveCrossLink( IBlock * block_to_remove ) {
+		//This function's purpouse is to inform this CrossRef that the block it is referencing has died
+		//Simply set it to NULL
+		ref = NULL;
+	}
+
+	void Fix( const vector<blk_ref> & blocks ) {
+		//The purpouse of this function is to convert the block index to a reference
+		//to the corresponding block.
+		
+		if (index < int(blocks.size()) && index >= 0 ) {
+			ref = blocks[index].get_block();
+			index = -1;
+			InitRef();
+		}
+	}
+
+private:
+	IBlock * _owner;
+	IBlock * ref;
+	int index;
+	void InitRef() {
+		//Inform target block that it is being cross referenced
+		if ( ref != NULL ) {
+			//Get internal interface
+			((ABlock*)ref)->IncCrossRef( _owner );
+		}
+	}
+	void KillRef() {
+		//Inform target block that it is no longer being cross referenced
+		if ( ref != NULL ) {
+			((ABlock*)ref)->IncCrossRef( _owner );
+		}
+	}
+};
+
+class CrossRefGroup {
+public:
+	//Constructor
+	//It is required for a LinkGroup to be aware of the block it is part of
+	CrossRefGroup(IBlock * owner) : _owner(owner) {}
+
+	//Destructor
+	~CrossRefGroup() { 
+		//Remove all links
+		ClearRefs();
+	}
+
+	void SetIndices( const list<int> new_indices ) {
+		//This function is for the initial file read.  It records the indices of the blocks which
+		//will later be resolved to links once all the blocks have been read
+
+		//If there are already links, kill them
+		ClearRefs();
+
+		indices = new_indices;
+	}
+
+	list<IBlock *> GetRefs() const { 
+		return refs;
+	}
+
+	void AddRef( IBlock * const & new_ref ) {
+		InitRef( new_ref );
+		refs.push_back( new_ref );
+	}
+
+	void AddRefs( list<IBlock *> const & new_refs ) {
+		//Initiate all of the new links
+		list<IBlock *>::const_iterator it;
+		for (it = new_refs.begin(); it != new_refs.end(); ++it ) {
+			InitRef( *it );
+			refs.push_back( *it );
+		}
+	}
+
+	IBlock * FindRef( string const & block_type ) const {
+		//Find the first reference with the requested block type
+		for ( list<IBlock *>::const_iterator it = refs.begin(); it != refs.end(); ++it ) {
+			if ( (*it)->GetBlockType() == block_type )
+				return *it;
+		}
+
+		//No block was found, so return NULL
+		return NULL;
+	}
+
+	void ClearRefs() { 
+		//Kill all the refs
+		list<IBlock *>::iterator it;
+		for (it = refs.begin(); it != refs.end(); ++it ) {
+			KillRef( *it );
+		}
+
+		//Clear the list
+		refs.clear();
+	}
+
+	void RemoveRefs( IBlock * const block ) {
+		//Remove all refs that match this block
+		//Kill the refs first
+		list<IBlock *>::iterator it;
+		for (it = refs.begin(); it != refs.end(); ++it ) {
+			if ( *it == block ) {
+				KillRef( *it );
+			}
+		}
+		
+		//Now remove them from the list
+		refs.remove( block );
+	}
+
+	void Fix( const vector<blk_ref> & blocks ) {
+		//The purpouse of this function is to convert the block indices to a links
+		//to the corresponding blocks.
+		
+		list<int>::iterator it;
+		for (it = indices.begin(); it != indices.end(); ++it ) {
+			if ( *it < int(blocks.size()) && *it >= 0 ) {
+				IBlock * new_ref = blocks[*it].get_block();
+				InitRef( new_ref );
+				refs.push_back( new_ref );
+			}
+		}
+
+		//Clear indices
+		indices.clear();
+	}
+
+	void RemoveCrossLink( IBlock * block_to_remove ) {
+		//This function's purpouse is to inform this CrossRefGroup that one of the blocks
+		//it is referencing has died
+
+		//Remove matching refs
+		RemoveRefs( block_to_remove );
+	}
+
+private:
+	IBlock * _owner;
+	list<IBlock *> refs;
+	list<int> indices;
+	void InitRef( IBlock * ref ) {
+		//Inform target block that it is being cross referenced
+		if ( ref != NULL ) {
+			//Get internal interface
+			((ABlock*)ref)->IncCrossRef( _owner );
+		}
+	}
+	void KillRef( IBlock * ref ) {
+		//Inform target block that it is no longer being cross referenced
+		if ( ref != NULL ) {
+			((ABlock*)ref)->IncCrossRef( _owner );
+		}
+	}
+};
+
 class AControllable : public ABlock {
 public:
 	AControllable();
@@ -165,13 +514,7 @@ public:
 	~AControllable() {}
 };
 
-//class INodeInternal {
-//public:
-//	virtual void IncSkinRef( IBlock * skin_data ) = 0;
-//	virtual void DecSkinRef( IBlock * skin_data ) = 0;
-//};
-
-class ANode : public AControllable, public INode/*, public INodeInternal*/ {
+class ANode : public AControllable, public INode {
 public:
 	ANode();
 	void Init() { 
diff --git a/nif_attrs.h b/nif_attrs.h
index 92304fb6652f0529bc32b81a47993d4a60bb7395..c45f7b5f7864a1a094e1027c7e1550ec4ccc38ae 100644
--- a/nif_attrs.h
+++ b/nif_attrs.h
@@ -105,9 +105,9 @@ protected:
 
 class lnk_ref : public blk_ref {
 public:
-	lnk_ref ( IBlock * owner) : _owner(owner) { /*cout << "Constructor " <<  endl;*/ InitLink(); }
-	lnk_ref( IBlock * owner, int index ) : blk_ref(index), _owner(owner) { /*cout << "Constructor "  << endl;*/ InitLink(); }
-	lnk_ref( IBlock * owner, blk_ref block ) : blk_ref(block), _owner(owner) { /*cout << "Constructor " << endl;*/ InitLink(); }
+	lnk_ref ( IBlock * owner) : _owner(owner) { InitLink(); }
+	lnk_ref( IBlock * owner, int index ) : blk_ref(index), _owner(owner) { InitLink(); }
+	lnk_ref( IBlock * owner, blk_ref block ) : blk_ref(block), _owner(owner) { InitLink(); }
 
 	//Copy Constructors
 	lnk_ref( const lnk_ref & rh ) {
@@ -120,7 +120,7 @@ public:
 		InitLink();
 	}
 	//Destructor
-	~lnk_ref() { /*cout << "Destructor " << endl;*/ KillLink(); /*cin.get();*/}
+	~lnk_ref() { KillLink(); }
 	//Assignment Operator
 	lnk_ref & operator=(const blk_ref & rh ) { 
 		if ( blk_ref(*this)!= rh ) {
diff --git a/niflib.h b/niflib.h
index af0717a5e7ae3174efccaa01ac970cf00475de09..28955d82205b0be95a9da4fe66c29153f99716de 100644
--- a/niflib.h
+++ b/niflib.h
@@ -3224,6 +3224,18 @@ public:
 		else
 			return false;
 	}
+
+	/*!
+	 * Makes this reference a null reference, decrimenting the reference count of the block it was pointing to, if any.
+	 */
+	void nullify() {
+		if ( _block != NULL ) {
+			//Decrement reference count
+			_block->SubtractRef();
+		}
+		_block = NULL;
+		_index = -1;
+	}
 	blk_ref( IBlock * block ) : _index(-1), _block(block) {
 
 		//Increment reference count