Im just passing through, cause I still dont have much time,
but try this updated (but utterly untested) version of ent_merge.

It SHOULD by-pass the collision_mode problem.
Click to reveal..
Code:
ENTITY* ent_merge(ENTITY* targ, ENTITY* src)
{	// verify that pointer parameters are valid... otherwise abort.
	if(targ==NULL)	{	return(NULL);	}		//invalid TARGET entity pointer
	if(src ==NULL)	{	return(NULL);	}		//invalid SOURCE entity pointer
	var old_coll_mode=collision_mode;	collision_mode=1;
 	//--------------------------------------------------------------------------------------
	// initialize TARGET entity to a brand new 'empty' mesh
	LPD3DXMESH meshes[3];	(meshes[0])=(meshes[1])=(meshes[2])=NULL;
	short *tbuff;		D3DVERTEX *vbuff;
	if(targ==src)	
	{	D3DXCreateMesh(0x01,0x03,D3DXMESH_MANAGED,pvertexdecl,pd3ddev,&meshes[1]);
		(meshes[1])->LockIndexBuffer (0, (void**)&tbuff);
		tbuff[0]=0;	tbuff[1]=1;	tbuff[2]=2;	(meshes[1])->UnlockIndexBuffer();
		if((meshes[1])!=NULL)	if(((meshes[0])=ent_getmesh(targ,0,0)))
		{	ent_setmesh(targ,(meshes[1]),0,0);  //(meshes[0])->Release();  
			collision_mode=old_coll_mode;	return(targ);	}	}	
 	//--------------------------------------------------------------------------------------
	// merge supplied meshes into a new single mesh, and re-assign/release accordingly
	meshes[0]=ent_getmesh(targ,0,0);		meshes[1]=ent_getmesh(src,0,0);
	D3DXConcatenateMeshes(meshes,0x2,D3DXMESH_MANAGED,0,0,pvertexdecl,pd3ddev,&meshes[2]);
	int t,v, vert_off=ent_status(targ,1), vert_end=vert_off+ent_status(src,1);
	//if((meshes[0])!=NULL)	{	(meshes[0])->Release();					}
	if((meshes[2])!=NULL)	{	ent_setmesh(targ,(meshes[2]),0,0);			}
	else				{	collision_mode=old_coll_mode;	return(NULL);	}
	if(!ent_status(targ,8))	{	ent_setskin(targ,ent_getskin(src,1),1);	}	//if need skin
 	//--------------------------------------------------------------------------------------
	// transform merged-in vertices
	VECTOR tmpV;	D3DVERTEX* vb;		long* ab;	ent_buffers(targ, 0,0, &vb, 0,&ab);
	for(v=vert_off; v<vert_end; v++)
	{	vb[v].nx = vb[v].ny = vb[v].nz = 0;
		vec_mul(vec_set(tmpV, vector(vb[v].x,vb[v].z,vb[v].y)), src.scale_x);
		vec_sub(vec_add(vec_rotate(tmpV, src.pan), src.x), targ.x);
		vb[v].x=tmpV.x;	vb[v].y=tmpV.z;	vb[v].z=tmpV.y;						}
	for(t=0; t<ent_status(targ,4); t++)		{	ab[t] = NULL;						}
 	//--------------------------------------------------------------------------------------
	// re-calculate all normals
	DWORD* p_adjacency  = sys_malloc(ent_status(targ,4)*3*sizeof(DWORD));
	(meshes[2])->GenerateAdjacency(0.001, p_adjacency);	
	D3DXComputeNormals((meshes[2]), p_adjacency); 		sys_free(p_adjacency);
	(meshes[2])->OptimizeInplace(0x03000000, p_adjacency, NULL, NULL, NULL);
 	//--------------------------------------------------------------------------------------
	collision_mode=old_coll_mode;	return(targ);
}




"There is no fate but what WE make." - CEO Cyberdyne Systems Corp.
A8.30.5 Commercial