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"); }
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); }
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); }
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(); } }
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); } } }
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) ); }
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 ¤t_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 }
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); }
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); }
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); } } }
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); }
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)); }
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); } }
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); }
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); }
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; } }
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() ); }
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); }