示例#1
0
void CAI_Space::validate			(const u32 level_id) const
{
	VERIFY					(level_graph().header().vertex_count() == cross_table().header().level_vertex_count());
	for (GameGraph::_GRAPH_ID i=0, n = game_graph().header().vertex_count(); i<n; ++i)
		if ((level_id == game_graph().vertex(i)->level_id()) && 
			(!level_graph().valid_vertex_id(game_graph().vertex(i)->level_vertex_id()) ||
			(cross_table().vertex(game_graph().vertex(i)->level_vertex_id()).game_vertex_id() != i) ||
			!level_graph().inside(game_graph().vertex(i)->level_vertex_id(),game_graph().vertex(i)->level_point()))) {
			Msg				("! Graph doesn't correspond to the cross table");
			R_ASSERT2		(false,"Graph doesn't correspond to the cross table");
		}

//	Msg						("death graph point id : %d",cross_table().vertex(455236).game_vertex_id());

	for (u32 i=0, n=game_graph().header().vertex_count(); i<n; ++i) {
		if (level_id != game_graph().vertex(i)->level_id())
			continue;

		CGameGraph::const_spawn_iterator	I, E;
		game_graph().begin_spawn			(i,I,E);
//		Msg									("vertex [%d] has %d death points",i,game_graph().vertex(i)->death_point_count());
		for ( ; I != E; ++I) {
			VERIFY							(cross_table().vertex((*I).level_vertex_id()).game_vertex_id() == i);
		}
	}
	

//	Msg						("* Graph corresponds to the cross table");
}
示例#2
0
void CGameGraphBuilder::save_cross_table	(const float &start, const float &amount)
{
	Progress							(start);

	Msg									("Saving cross table");

//	CTimer								timer;
//	timer.Start							();

	CMemoryWriter						tMemoryStream;
	CGameLevelCrossTable::CHeader		tCrossTableHeader;
	
	tCrossTableHeader.dwVersion			= XRAI_CURRENT_VERSION;
	tCrossTableHeader.dwNodeCount		= level_graph().header().vertex_count();
	tCrossTableHeader.dwGraphPointCount = graph().header().vertex_count();
	tCrossTableHeader.m_level_guid		= level_graph().header().guid();
	tCrossTableHeader.m_game_guid		= m_graph_guid;
	
	tMemoryStream.open_chunk			(CROSS_TABLE_CHUNK_VERSION);
	tMemoryStream.w						(&tCrossTableHeader,sizeof(tCrossTableHeader));
	tMemoryStream.close_chunk			();
	
	tMemoryStream.open_chunk			(CROSS_TABLE_CHUNK_DATA);

	for (int i=0, n=level_graph().header().vertex_count(); i<n; i++) {
		CGameLevelCrossTable::CCell	tCrossTableCell;
		tCrossTableCell.tGraphIndex = (GameGraph::_GRAPH_ID)m_results[i];
		VERIFY						(graph().header().vertex_count() > tCrossTableCell.tGraphIndex);
		tCrossTableCell.fDistance	= float(m_distances[tCrossTableCell.tGraphIndex][i])*level_graph().header().cell_size();
		tMemoryStream.w				(&tCrossTableCell,sizeof(tCrossTableCell));
	}

	tMemoryStream.close_chunk();
	
//	Msg						("CT:SAVE : %f",timer.GetElapsed_sec());
//	Msg						("Flushing cross table");

#ifdef PRIQUEL
	tMemoryStream.save_to	(m_cross_table_name);
#else // PRIQUEL
	string_path				file_name;
	strconcat				(sizeof(file_name), file_name,*m_level_name,CROSS_TABLE_NAME_RAW);
	tMemoryStream.save_to	(file_name);
#endif // PRIQUEL
//	Msg						("CT:SAVE : %f",timer.GetElapsed_sec());

//	Msg						("Freiing cross table resources");

	m_marks.clear			();
	m_mark_stack.clear		();
	m_distances.clear		();
	m_current_fringe.clear	();
	m_next_fringe.clear		();

//	Msg						("CT:SAVE : %f",timer.GetElapsed_sec());
	Progress				(start + amount);
}
示例#3
0
void CGameGraphBuilder::build_graph			(const float &start, const float &amount)
{
	Progress				(start);

	Msg						("Building graph");

	CTimer					timer;
	timer.Start				();

	m_graph_engine			= xr_new<CGraphEngine>(level_graph().header().vertex_count());
	Progress				(start + 0.000000f*amount + amount*0.067204f);
//	Msg						("BG : %f",timer.GetElapsed_sec());

	generate_edges			(start + 0.067204f*amount, amount*0.922647f);
//	Msg						("BG : %f",timer.GetElapsed_sec());

	xr_delete				(m_graph_engine);
	Progress				(start + 0.989851f*amount + amount*0.002150f);
//	Msg						("BG : %f",timer.GetElapsed_sec());

	connectivity_check		(start + 0.992001f*amount, amount*0.000030f);
//	Msg						("BG : %f",timer.GetElapsed_sec());
	optimize_graph			(start + 0.992031f*amount, amount*0.000454f);
//	Msg						("BG : %f",timer.GetElapsed_sec());
	save_graph				(start + 0.992485f*amount, amount*0.007515f);
//	Msg						("BG : %f",timer.GetElapsed_sec());

	Progress				(start + amount);
}
示例#4
0
void CLevelSpawnConstructor::correct_level_changers				()
{
	LEVEL_CHANGER_STORAGE::const_iterator	I = m_level_changers.begin();
	LEVEL_CHANGER_STORAGE::const_iterator	E = m_level_changers.end();
	for ( ; I != E; ++I) {
		Fvector				position = (*I)->o_Position;
		position.y			+= y_shift_correction;
		(*I)->m_tNodeID		= level_graph().vertex(u32(-1),position);
		VERIFY				(level_graph().valid_vertex_id((*I)->m_tNodeID));

		u32					dwBest = cross_table().vertex((*I)->m_tNodeID).game_vertex_id();
		VERIFY				(game_graph().vertex(dwBest)->level_id() == m_level.id());
		(*I)->m_tGraphID	= (GameGraph::_GRAPH_ID)dwBest;

		(*I)->m_fDistance	= cross_table().vertex((*I)->m_tNodeID).distance();
	}
}
示例#5
0
void CGameGraphBuilder::fill_neighbours		(const u32 &game_vertex_id)
{
	m_marks.assign						(level_graph().header().vertex_count(),false);
	m_current_fringe.clear				();

	u32									level_vertex_id = graph().vertex(game_vertex_id)->data().level_vertex_id();

	CLevelGraph::const_iterator			I, E;
	m_mark_stack.reserve				(8192);
	m_mark_stack.push_back				(level_vertex_id);

	for ( ; !m_mark_stack.empty(); ) {
		level_vertex_id					= m_mark_stack.back();
		m_mark_stack.resize				(m_mark_stack.size() - 1);
		CLevelGraph::CVertex			*node = level_graph().vertex(level_vertex_id);
		level_graph().begin				(level_vertex_id,I,E);
		m_marks[level_vertex_id]		= true;
		for ( ; I != E; ++I) {
			u32							next_level_vertex_id = node->link(I);
			if (!level_graph().valid_vertex_id(next_level_vertex_id))
				continue;
			
			if (m_marks[next_level_vertex_id])
				continue;

			GameGraph::_GRAPH_ID		next_game_vertex_id = cross().vertex(next_level_vertex_id).game_vertex_id();
			VERIFY						(next_game_vertex_id < graph().vertices().size());
			if (next_game_vertex_id != (GameGraph::_GRAPH_ID)game_vertex_id) {
				if	(
						std::find(
							m_current_fringe.begin(),
							m_current_fringe.end(),
							next_game_vertex_id
						)
						==
						m_current_fringe.end()
					)
					m_current_fringe.push_back	(next_game_vertex_id);
				continue;
			}

			m_mark_stack.push_back		(next_level_vertex_id);
		}
	}
}
示例#6
0
void CGameGraphBuilder::iterate_distances	(const float &start, const float &amount)
{
	Progress							(start);

	m_results.assign					(level_graph().header().vertex_count(),0);
	
	float								amount_i = amount/float(graph().vertices().size());
	for (int i=0, n=(int)graph().vertices().size(); i<n; ++i) {
		if (i) {
			for (int k=0, kn=(int)level_graph().header().vertex_count(); k<kn; ++k)
				m_distances[i][k]		= m_distances[i - 1][k];
		}

		recursive_update				(i,start + amount_i*float(i),amount_i);
	}

	Progress							(start + amount);
}
bool CSpaceRestrictorWrapper::inside				(u32 level_vertex_id, bool partially_inside, float radius) const
{
	const Fvector					&position = level_graph().vertex_position(level_vertex_id);
	float							offset = level_graph().header().cell_size()*.5f - EPS_L;
	if (partially_inside)
		return						(
			inside					(construct_position(level_graph(),level_vertex_id,position.x + offset,position.z + offset),radius) || 
			inside					(construct_position(level_graph(),level_vertex_id,position.x + offset,position.z - offset),radius) ||
			inside					(construct_position(level_graph(),level_vertex_id,position.x - offset,position.z + offset),radius) || 
			inside					(construct_position(level_graph(),level_vertex_id,position.x - offset,position.z - offset),radius) ||
			inside					(Fvector().set(position.x,position.y,position.z),radius)
		);
	else
		return						(
			inside					(construct_position(level_graph(),level_vertex_id,position.x + offset,position.z + offset),radius) && 
			inside					(construct_position(level_graph(),level_vertex_id,position.x + offset,position.z - offset),radius) && 
			inside					(construct_position(level_graph(),level_vertex_id,position.x - offset,position.z + offset),radius) && 
			inside					(construct_position(level_graph(),level_vertex_id,position.x - offset,position.z - offset),radius) &&
			inside					(Fvector().set(position.x,position.y,position.z),radius)
		);
}
示例#8
0
void CAI_Space::load				(LPCSTR level_name)
{
//	Msg						("level %s",level_name);
	unload					(true);

#ifdef DEBUG
	Memory.mem_compact		();
	u32						mem_usage = Memory.mem_usage();
	CTimer					timer;
	timer.Start				();
#endif

	m_level_graph			= xr_new<CLevelGraph>();
	m_cross_table			= xr_new<CGameLevelCrossTable>();
	R_ASSERT2				(cross_table().header().level_guid() == level_graph().header().guid(), "cross_table doesn't correspond to the AI-map");
	R_ASSERT2				(cross_table().header().game_guid() == game_graph().header().guid(), "graph doesn't correspond to the cross table");
	m_graph_engine			= xr_new<CGraphEngine>(
		_max(
			game_graph().header().vertex_count(),
			level_graph().header().vertex_count()
		)
	);
	
	const CGameGraph::SLevel &current_level = game_graph().header().level(level_name);
	R_ASSERT2				(current_level.guid() == level_graph().header().guid(), "graph doesn't correspond to the AI-map");
	
#ifdef DEBUG
	if (!xr_strcmp(current_level.name(),level_name))
		validate			(current_level.id());
#endif

	level_graph().level_id	(current_level.id());
	game_graph().set_current_level(current_level.id());

	m_cover_manager->compute_static_cover	();

#ifdef DEBUG
	Msg						("* Loading ai space is successfully completed (%.3fs, %7.3f Mb)",timer.GetElapsed_sec(),float(Memory.mem_usage() - mem_usage)/1048576.0);
#endif
}
示例#9
0
void CGameGraphBuilder::fill_marks			(const float &start, const float &amount)
{
	Progress							(start);

	m_marks.assign						(level_graph().header().vertex_count(),false);
	graph_type::const_vertex_iterator	I = graph().vertices().begin();
	graph_type::const_vertex_iterator	E = graph().vertices().end();
	for ( ; I != E; ++I)
		mark_vertices					((*I).second->data().level_vertex_id());
	m_marks.flip						();
	
	Progress							(start + amount);
}
示例#10
0
void CGameGraphBuilder::load_level_graph	(const float &start, const float &amount)
{
	Progress				(start);

	Msg						("Loading AI map");
	
	VERIFY					(!m_level_graph);
	m_level_graph			= xr_new<CLevelGraph>(*m_level_name);
	
	Msg						("%d nodes loaded",level_graph().header().vertex_count());
	
	Progress				(start + amount);
}
示例#11
0
void CGameGraphBuilder::mark_vertices		(u32 level_vertex_id)
{
	CLevelGraph::const_iterator			I, E;
	m_mark_stack.reserve				(8192);
	m_mark_stack.push_back				(level_vertex_id);

	for ( ; !m_mark_stack.empty(); ) {
		level_vertex_id					= m_mark_stack.back();
		m_mark_stack.resize				(m_mark_stack.size() - 1);
		CLevelGraph::CVertex			*node = level_graph().vertex(level_vertex_id);
		level_graph().begin				(level_vertex_id,I,E);
		m_marks[level_vertex_id]		= true;
		for ( ; I != E; ++I) {
			u32							next_level_vertex_id = node->link(I);
			if (!level_graph().valid_vertex_id(next_level_vertex_id))
				continue;
			
			if (!m_marks[next_level_vertex_id])
				m_mark_stack.push_back	(next_level_vertex_id);
		}
	}
}
示例#12
0
float CGameGraphBuilder::path_distance		(const u32 &game_vertex_id0, const u32 &game_vertex_id1)
{
//	return					(graph().vertex(game_vertex_id0)->data().level_point().distance_to(graph().vertex(game_vertex_id1)->data().level_point()));

	VERIFY					(m_graph_engine);

	graph_type::CVertex		&vertex0 = *graph().vertex(game_vertex_id0);
	graph_type::CVertex		&vertex1 = *graph().vertex(game_vertex_id1);

	typedef GraphEngineSpace::CStraightLineParams	CStraightLineParams;
	CStraightLineParams		parameters(vertex0.data().level_point(),vertex1.data().level_point());

	float					pure_distance = vertex0.data().level_point().distance_to_xz(vertex1.data().level_point());
//	float					pure_distance = vertex0.data().level_point().distance_to(vertex1.data().level_point());
	VERIFY					(pure_distance < parameters.max_range);

	u32						level_vertex_id = level_graph().check_position_in_direction(vertex0.data().level_vertex_id(),vertex0.data().level_point(),vertex1.data().level_point());
	if (level_graph().valid_vertex_id(level_vertex_id))
		return				(pure_distance);

	bool					successfull = 
		m_graph_engine->search(
			level_graph(),
			vertex0.data().level_vertex_id(),
			vertex1.data().level_vertex_id(),
			&m_path,
			parameters
		);

	if (successfull)
		return				(parameters.m_distance);

	Msg						("Cannot build path from [%d] to [%d]",game_vertex_id0,game_vertex_id1);
	Msg						("Cannot build path from [%f][%f][%f] to [%f][%f][%f]",VPUSH(vertex0.data().level_point()),VPUSH(vertex1.data().level_point()));
	R_ASSERT2				(false,"Cannot build path, check AI map");
	return					(flt_max);
}
示例#13
0
void CGameGraphBuilder::fill_distances		(const float &start, const float &amount)
{
	Progress							(start);

	m_distances.resize					(graph().vertices().size());
	{
		DISTANCES::iterator				I = m_distances.begin();
		DISTANCES::iterator				E = m_distances.end();
		for ( ; I != E; I++) {
			(*I).resize					(level_graph().header().vertex_count());
			xr_vector<u32>::iterator	i = (*I).begin();
			xr_vector<u32>::iterator	e = (*I).end();
			for ( ; i != e; i++)
				*i						= u32(-1);
		}
	}

	Progress							(start + amount);
}
void CSpaceRestrictorWrapper::fill_shape			(const CShapeData::shape_def &shape)
{
	Fvector							start,dest;
	switch (shape.type) {
		case 0 : {
			start.sub				(Fvector().set(shape.data.sphere.P),Fvector().set(shape.data.sphere.R,0.f,shape.data.sphere.R));
			dest.add				(Fvector().set(shape.data.sphere.P),Fvector().set(shape.data.sphere.R,0.f,shape.data.sphere.R));
			start.add				(object().o_Position);
			dest.add				(object().o_Position);
			break;
		}
		case 1 : {
			Fvector					points[8] = {
				Fvector().set(-.5f,-.5f,-.5f),
				Fvector().set(-.5f,-.5f,+.5f),
				Fvector().set(-.5f,+.5f,-.5f),
				Fvector().set(-.5f,+.5f,+.5f),
				Fvector().set(+.5f,-.5f,-.5f),
				Fvector().set(+.5f,-.5f,+.5f),
				Fvector().set(+.5f,+.5f,-.5f),
				Fvector().set(+.5f,+.5f,+.5f)
			};
			start					= Fvector().set(flt_max,flt_max,flt_max);
			dest					= Fvector().set(flt_min,flt_min,flt_min);
			Fmatrix					Q;
			Q.mul_43				(m_xform,shape.data.box);
			Fvector					temp;
			for (int i=0; i<8; ++i) {
                Q.transform_tiny	(temp,points[i]);
				start.x				= _min(start.x,temp.x);
				start.y				= _min(start.y,temp.y);
				start.z				= _min(start.z,temp.z);
				dest.x				= _max(dest.x,temp.x);
				dest.y				= _max(dest.y,temp.y);
				dest.z				= _max(dest.z,temp.z);
			}
			break;
		}
		default : NODEFAULT;
	}
	
	level_graph().iterate_vertices	(start,dest,border_merge_predicate(this,m_level_graph));
}
示例#15
0
void CLevelSpawnConstructor::init								()
{
	// loading level graph
	string_path				file_name;
	FS.update_path			(file_name,"$game_levels$",*m_level.name());
	strcat_s				(file_name,"\\");
	m_level_graph			= new CLevelGraph(file_name);
	
	// loading cross table
	m_game_spawn_constructor->game_graph().set_current_level	(game_graph().header().level(*m_level.name()).id());
	m_cross_table			= &game_graph().cross_table();

	// loading patrol paths
	FS.update_path			(file_name,"$game_levels$",*m_level.name());
	strcat					(file_name,"\\level.game");
	if (FS.exist(file_name)) {
		IReader				*stream	= FS.r_open(file_name);
		VERIFY				(stream);
		m_game_spawn_constructor->patrol_path_storage().load_raw(&level_graph(),&cross_table(),&game_graph(),*stream);
		FS.r_close			(stream);
	}
}
示例#16
0
void CGameGraphBuilder::load_graph_point	(NET_Packet &net_packet)
{
	string256				section_id;
	u16						id;
	net_packet.r_begin		(id);
	R_ASSERT				(M_SPAWN == id);
	net_packet.r_stringZ	(section_id);

//	if (xr_strcmp("graph_point",section_id))
//		return;

	CSE_Abstract			*entity = F_entity_Create(section_id);
	if (!entity) {
		Msg					("Cannot create entity from section %s, skipping",section_id);
		return;
	}

	CSE_ALifeGraphPoint		*graph_point = smart_cast<CSE_ALifeGraphPoint*>(entity);
	if (!graph_point) {
		F_entity_Destroy	(entity);
		return;
	}

	entity->Spawn_Read		(net_packet);

	vertex_type				vertex;
	vertex.tLocalPoint		= graph_point->o_Position;
	// check for duplicate graph point positions
	{
		graph_type::const_vertex_iterator	I = graph().vertices().begin();
		graph_type::const_vertex_iterator	E = graph().vertices().end();
		for ( ; I != E; ++I) {
			if ((*I).second->data().tLocalPoint.distance_to_sqr(vertex.tLocalPoint) < EPS_L) {
				Msg			("! removing graph point [%s][%f][%f][%f] because it is too close to the another graph point",entity->name_replace(),VPUSH(entity->o_Position));
				return;
			}
		}
	}

	vertex.tGlobalPoint		= graph_point->o_Position;
	vertex.tNodeID			= level_graph().valid_vertex_position(vertex.tLocalPoint) ? level_graph().vertex_id(vertex.tLocalPoint) : u32(-1);
	if (!level_graph().valid_vertex_id(vertex.tNodeID)) {
		Msg					("! removing graph point [%s][%f][%f][%f] because it is outside of the AI map",entity->name_replace(),VPUSH(entity->o_Position));
		return;
	}

	{
		graph_type::const_vertex_iterator	I = graph().vertices().begin();
		graph_type::const_vertex_iterator	E = graph().vertices().end();
		for ( ; I != E; ++I) {
			if ((*I).second->data().tNodeID == vertex.tNodeID) {
				Msg			("! removing graph point [%s][%f][%f][%f] because it has the same AI node as another graph point",entity->name_replace(),VPUSH(entity->o_Position));
				return;
			}
		}
	}

	vertex.tNeighbourCount	= 0;
	Memory.mem_copy			(vertex.tVertexTypes,graph_point->m_tLocations,GameGraph::LOCATION_TYPE_COUNT*sizeof(GameGraph::_LOCATION_ID));
	vertex.tLevelID			= 0;
	vertex.tDeathPointCount = 0;
	vertex.dwPointOffset	= 0;

	graph().add_vertex		(vertex,graph().vertices().size());

	F_entity_Destroy		(entity);
}
示例#17
0
void CGameGraphBuilder::recursive_update	(const u32 &game_vertex_id, const float &start, const float &amount)
{
	Progress					(start);

	u32							level_vertex_id = graph().vertex(game_vertex_id)->data().level_vertex_id();
	xr_vector<u32>				&distances = m_distances[game_vertex_id];
	m_distances[m_results[level_vertex_id]][level_vertex_id]	= u32(-1);

	m_current_fringe.reserve	(distances.size());
	m_next_fringe.reserve		(distances.size());
	distances.assign			(distances.size(),u32(-1));
	m_current_fringe.push_back	(level_vertex_id);
	u32							curr_dist = 0;
	u32							total_count = 0;

	u32							vertex_count = graph().header().vertex_count();

	float						amount_i = 
		amount
		/
		(
			float(vertex_count)*
			float(level_graph().header().vertex_count())
		);

	Progress					(start);
	for ( ; !m_current_fringe.empty(); ) {
		xr_vector<u32>::iterator			I = m_current_fringe.begin();
		xr_vector<u32>::iterator			E = m_current_fringe.end();
		for ( ; I != E; ++I) {
			u32								*result = &m_results[*I];
			VERIFY							(curr_dist < m_distances[*result][*I]);
			*result							= game_vertex_id;

			distances[*I]					= curr_dist;
			CLevelGraph::const_iterator		i, e;
			CLevelGraph::CVertex			*node = level_graph().vertex(*I);
			level_graph().begin				(*I,i,e);
			for ( ; i != e; ++i) {
				u32							dwNexNodeID = node->link(i);
				if (!level_graph().valid_vertex_id(dwNexNodeID))
					continue;
				
				if (m_marks[dwNexNodeID])
					continue;
				
				if (distances[dwNexNodeID] <= curr_dist)
					continue;

				if (m_distances[m_results[dwNexNodeID]][dwNexNodeID] <= (curr_dist + 1))
					continue;

				m_next_fringe.push_back		(dwNexNodeID);
				m_marks[dwNexNodeID]		= true;
			}
		}
		
		I = m_current_fringe.begin();
		E = m_current_fringe.end();
		for ( ; I != E; ++I)
			m_marks[*I]		= false;

		total_count			+= m_current_fringe.size();
		m_current_fringe	= m_next_fringe;
		m_next_fringe.clear	();
		++curr_dist;

		Progress			(start + amount_i*float(total_count));
	}

	Progress				(start + amount);
}
示例#18
0
void CLevelSpawnConstructor::correct_objects					()
{
	u32						m_level_graph_vertex_id = u32(-1);
	u32						dwStart = game_graph().header().vertex_count(), dwFinish = game_graph().header().vertex_count(), dwCount = 0;
	for (u32 i=0; i<game_graph().header().vertex_count(); ++i)
		if (game_graph().vertex(i)->level_id() == m_level.id()) {
			if (m_level_graph_vertex_id == u32(-1))
				m_level_graph_vertex_id = i;
			dwCount++;
		}
	
	for (int i=0; i<(int)game_graph().header().vertex_count(); i++)
		if (game_graph().vertex(i)->level_id() == m_level.id()) {
			if (dwStart > (u32)i)
				dwStart = (u32)i;
		}
		else {
			if ((dwStart <= (u32)i) && (dwFinish > (u32)i)) {
				dwFinish = i;
				break;
			}
		}
	if (dwStart >= dwFinish) {
		string4096			S;
		sprintf				(S,"There are no graph vertices in the game graph for the level '%s' !\n",*m_level.name());
		R_ASSERT2			(dwStart < dwFinish,S);
	}

	for (int i=0; i<(int)m_spawns.size(); i++) {
		if (!m_spawns[i]->used_ai_locations()) {
			m_spawns[i]->m_tGraphID = (GameGraph::_GRAPH_ID)m_level_graph_vertex_id;
			m_spawns[i]->m_fDistance = 0.f;
			m_spawns[i]->m_tNodeID = game_graph().vertex(m_level_graph_vertex_id)->level_vertex_id();
			continue;
		}
		Fvector				position = m_spawns[i]->o_Position;
		position.y			+= y_shift_correction;
		m_spawns[i]->m_tNodeID = level_graph().vertex(u32(-1),position);
		VERIFY				(level_graph().valid_vertex_id(m_spawns[i]->m_tNodeID));
		if (m_spawns[i]->used_ai_locations() && !level_graph().inside(level_graph().vertex(m_spawns[i]->m_tNodeID),position)) {
			Fvector			new_position = level_graph().vertex_position(m_spawns[i]->m_tNodeID);
			clMsg			("[%s][%s][%s] : position changed from [%f][%f][%f] -> [%f][%f][%f]",*m_level.name(),*m_spawns[i]->s_name,m_spawns[i]->name_replace(),VPUSH(position),VPUSH(new_position));
			m_spawns[i]->o_Position	= new_position;
		}
		u32					dwBest = cross_table().vertex(m_spawns[i]->m_tNodeID).game_vertex_id();
		if (game_graph().vertex(dwBest)->level_id() != m_level.id()) {
			string4096	S1;
			char		*S = S1;
			S			+= sprintf(S,"Corresponding graph vertex for the spawn point is located on the ANOTHER level\n",m_spawns[i]->name_replace());
			S			+= sprintf(S,"Current level  : [%d][%s]\n",m_level.id(),*game_graph().header().level(m_level.id()).name());
			S			+= sprintf(S,"Conflict level : [%d][%s]\n",game_graph().vertex(dwBest)->level_id(),*game_graph().header().level(game_graph().vertex(dwBest)->level_id()).name());
			S			+= sprintf(S,"Probably, you filled offsets in \"game_levels.ltx\" incorrect");
			R_ASSERT2	(game_graph().vertex(dwBest)->level_id() == m_level.id(),S1);
		}

		float				fCurrentBestDistance = cross_table().vertex(m_spawns[i]->m_tNodeID).distance();
		if (dwBest == u32(-1)) {
			string4096	S1;
			char		*S = S1;
			S			+= sprintf(S,"Can't find a corresponding GRAPH VERTEX for the spawn-point %s\n",m_spawns[i]->name_replace());
			S			+= sprintf(S,"Level ID    : %d\n",m_level.id());
			S			+= sprintf(S,"Spawn index : %d\n",i);
			S			+= sprintf(S,"Spawn node  : %d\n",m_spawns[i]->m_tNodeID);
			S			+= sprintf(S,"Spawn point : [%7.2f][%7.2f][%7.2f]\n",m_spawns[i]->o_Position.x,m_spawns[i]->o_Position.y,m_spawns[i]->o_Position.z);
			R_ASSERT2	(dwBest != -1,S1);
		}
		m_spawns[i]->m_tGraphID		= (GameGraph::_GRAPH_ID)dwBest;
		m_spawns[i]->m_fDistance	= fCurrentBestDistance;
	}
}
示例#19
0
void CLevelSpawnConstructor::generate_artefact_spawn_positions	()
{
	// create graph engine
	VERIFY								(!m_graph_engine);
	m_graph_engine						= new CGraphEngine(m_level_graph->header().vertex_count());

	xr_vector<u32>						l_tpaStack;
	SPAWN_STORAGE						zones;
	l_tpaStack.reserve					(1024);
	SPAWN_STORAGE::iterator				I = m_spawns.begin();
	SPAWN_STORAGE::iterator				E = m_spawns.end();
	for ( ; I != E; I++) {
		CSE_ALifeAnomalousZone			*zone = smart_cast<CSE_ALifeAnomalousZone*>(*I);
		if (!zone)
			continue;

//		if (!level_graph().valid_vertex_position(zone->o_Position)) {
//			zone->m_artefact_spawn_count	= 0;
//			zone->m_artefact_position_offset		= m_level_points.size();
//			continue;
//		}

		zone->m_tNodeID						= level_graph().vertex(zone->m_tNodeID,zone->o_Position);
		if (!level_graph().valid_vertex_position(zone->o_Position) || !level_graph().inside(zone->m_tNodeID,zone->o_Position))
			zone->m_tNodeID					= level_graph().vertex(u32(-1),zone->o_Position);
		const CGameLevelCrossTable::CCell	&cell = cross_table().vertex(zone->m_tNodeID);
		zone->m_tGraphID					= cell.game_vertex_id();
		zone->m_fDistance					= cell.distance();

		graph_engine().search			(
			level_graph(),
			zone->m_tNodeID,
			zone->m_tNodeID,
			&l_tpaStack,
			SFlooder<
				float,
				u32,
				u32
			>(
				zone->m_offline_interactive_radius,
				u32(-1),
				u32(-1)
			)
		);
		
		l_tpaStack.erase				(
			std::remove_if(
				l_tpaStack.begin(),
				l_tpaStack.end(),
				remove_too_far_predicate(
					&level_graph(),
					zone->o_Position,
					zone->m_offline_interactive_radius
				)
			),
			l_tpaStack.end()
		);
/*
		if (zone->m_artefact_spawn_count >= l_tpaStack.size()) 
		{
			zone->m_artefact_spawn_count	= (u16)l_tpaStack.size();
#ifndef IGNORE_ZERO_SPAWN_POSITIONS
			if (!zone->m_artefact_spawn_count) {
				Msg						("! CANNOT GENERATE ARTEFACT SPAWN POSITIONS FOR ZONE [%s] ON LEVEL [%s]",zone->name_replace(),*level().name());
				Msg						("! ZONE [%s] ON LEVEL [%s] IS REMOVED BY AI COMPILER",zone->name_replace(),*level().name());
				R_ASSERT3				(zone->m_story_id == INVALID_STORY_ID,"Cannot remove story object",zone->name_replace());
				R_ASSERT3				(!zone->m_spawn_control,"Cannot remove spawn control object",zone->name_replace());
				zones.push_back			(zone);
				l_tpaStack.clear		();
				continue;
			}
#endif
		}
		else		*/
			std::random_shuffle			(l_tpaStack.begin(),l_tpaStack.end());

		zone->m_artefact_position_offset= m_level_points.size();
		m_level_points.resize			(zone->m_artefact_position_offset + zone->m_artefact_spawn_count);

//		Msg								("%s  %f [%f][%f][%f] : artefact spawn positions",zone->name_replace(),zone->m_fRadius,VPUSH(zone->o_Position));

		LEVEL_POINT_STORAGE::iterator	I = m_level_points.begin() + zone->m_artefact_position_offset;
		LEVEL_POINT_STORAGE::iterator	E = m_level_points.end();
		xr_vector<u32>::iterator		i = l_tpaStack.begin();
		for ( ; I != E; ++I, ++i) {
			(*I).tNodeID				= *i;
			(*I).tPoint					= level_graph().vertex_position(*i);
			(*I).fDistance				= cross_table().vertex(*i).distance();
//			Msg							("    [%f][%f][%f] : %f",VPUSH((*I).tPoint),zone->o_Position.distance_to((*I).tPoint));
		}
		
		l_tpaStack.clear				();
	}

#ifndef IGNORE_ZERO_SPAWN_POSITIONS
	I									= std::remove_if(m_spawns.begin(),m_spawns.end(),remove_invalid_zones_predicate(this,&zones));
	m_spawns.erase						(I,m_spawns.end());
#endif
}
void CSpaceRestrictorWrapper::verify_connectivity	()
{
	{
		std::sort					(m_internal.begin(),m_internal.end());
		BORDER::iterator			I = std::unique(m_internal.begin(),m_internal.end());
		m_internal.erase			(I,m_internal.end());
	}

	u32								start_vertex_id = u32(-1);
	CLevelGraph::const_vertex_iterator	I = level_graph().begin();
	CLevelGraph::const_vertex_iterator	E = level_graph().end();
	for ( ; I != E; ++I)
		if (!inside(level_graph().vertex(I),true)) {
			start_vertex_id			= level_graph().vertex(I);
			break;
		}

	if (!level_graph().valid_vertex_id(start_vertex_id)) {
		Msg							("Warning : restrictor %s covers the whole AI map");
		return;
	}

	level_graph().set_mask			(m_border);
	
	xr_vector<u32>					nodes;
	
	graph_engine().search			(
		level_graph(),
		start_vertex_id,
		start_vertex_id,
		&nodes,
		GraphEngineSpace::CFlooder(
			GraphEngineSpace::_dist_type(6000),
			GraphEngineSpace::_iteration_type(-1),
			u32(-1)
		)
	);

	level_graph().clear_mask		(m_border);

	VERIFY							(nodes.size() + m_internal.size() <= level_graph().header().vertex_count());
	if (nodes.size() + m_internal.size() == level_graph().header().vertex_count())
		return;

	Msg								("! %d nodes are disconnected!",level_graph().header().vertex_count() - (nodes.size() + m_internal.size()));

	R_ASSERT3						(
		nodes.size() + m_internal.size() == level_graph().header().vertex_count(),
		"Restrictor separates AI map into several disconnected components",
		object().name_replace()
	);
}
示例#21
0
void CGameGraphBuilder::save_graph			(const float &start, const float &amount)
{
	Progress				(start);

	Msg						("Saving graph");

	// header
	CMemoryWriter				writer;
	CGameGraph::CHeader			header;
	header.m_version			= XRAI_CURRENT_VERSION;
	VERIFY						(graph().vertices().size() < (u32(1) << (8*sizeof(GameGraph::_GRAPH_ID))));
	header.m_vertex_count		= (GameGraph::_GRAPH_ID)graph().vertices().size();
	VERIFY						(graph().edge_count() < (u32(1) << (8*sizeof(GameGraph::_GRAPH_ID))));
	header.m_edge_count			= (GameGraph::_GRAPH_ID)graph().edge_count();
	header.m_death_point_count	= 0;
	header.m_guid				= m_graph_guid;

	// levels
	CGameGraph::SLevel			level;
	level.m_offset.set			(0,0,0);
	level.m_id					= 0;
	level.m_name				= m_level_name;
	level.m_section				= "";
	level.m_guid				= level_graph().header().guid();

	header.m_levels.insert		(std::make_pair(level.m_id,level));

	header.save					(&writer);

	{
		u32								edge_offset = graph().vertices().size()*sizeof(CGameGraph::CVertex);

		graph_type::const_vertex_iterator	I = graph().vertices().begin();
		graph_type::const_vertex_iterator	E = graph().vertices().end();
		for ( ; I != E; ++I) {
			CGameGraph::CVertex		&vertex = (*I).second->data();

			VERIFY					((*I).second->edges().size() < 256);
			vertex.tNeighbourCount	= (u8)(*I).second->edges().size();
			vertex.dwEdgeOffset		= edge_offset;
			edge_offset				+= vertex.tNeighbourCount*sizeof(CGameGraph::CEdge);

			writer.w				(&vertex,sizeof(CGameGraph::CVertex));
		}
	}
	
	{
		graph_type::const_vertex_iterator	I = graph().vertices().begin();
		graph_type::const_vertex_iterator	E = graph().vertices().end();
		for ( ; I != E; ++I) {
			graph_type::const_iterator	i = (*I).second->edges().begin();
			graph_type::const_iterator	e = (*I).second->edges().end();
			for ( ; i != e; ++i) {
				GameGraph::CEdge			edge;
				VERIFY						((*i).vertex_id() < (u32(1) << (8*sizeof(GameGraph::_GRAPH_ID))));
				edge.m_vertex_id			= (GameGraph::_GRAPH_ID)(*i).vertex_id();
				edge.m_path_distance		= (*i).weight();

				writer.w					(&edge.m_vertex_id,sizeof(edge.m_vertex_id));
				writer.w_float				(edge.m_path_distance);
			}
		}
	}

#ifdef PRIQUEL
	writer.save_to				(m_graph_name);
#else // PRIQUEL
	string_path					file_name;
	strconcat					(sizeof(file_name),file_name,*m_level_name,GAME_LEVEL_GRAPH);
	writer.save_to				(file_name);
#endif // PRIQUEL
	Msg							("%d bytes saved",int(writer.size()));

	Progress					(start + amount);
}