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"); }
IC shared_str CGameSpawnConstructor::actor_level_name() { string256 temp; return ( strconcat( sizeof(temp), temp, *game_graph().header().level( game_graph().vertex( m_actor->m_tGraphID )->level_id()).name(), ".spawn" ) ); }
void CAI_Space::unload (bool reload) { script_engine().unload (); xr_delete (m_graph_engine); xr_delete (m_level_graph); xr_delete (m_cross_table); if (!reload) m_graph_engine = xr_new<CGraphEngine>(game_graph().header().vertex_count()); }
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 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 CLevelSpawnConstructor::fill_level_changers () { for (u32 i=0, n=(u32)level_changers().size(); i<n; ++i) { if (level_id(level_changers()[i]->m_caLevelToChange) != m_level.id()) continue; bool found = false; GRAPH_POINT_STORAGE::const_iterator I = m_graph_points.begin(); GRAPH_POINT_STORAGE::const_iterator E = m_graph_points.end(); for ( ; I != E; ++I) if (!xr_strcmp(*level_changers()[i]->m_caLevelPointToChange,(*I)->name_replace())) { bool ok = false; for (u32 ii=0, nn = game_graph().header().vertex_count(); ii<nn; ++ii) { if ((game_graph().vertex(ii)->level_id() != m_level.id()) || !game_graph().vertex(ii)->level_point().similar((*I)->o_Position,.001f)) continue; level_changers()[i]->m_tNextGraphID = (GameGraph::_GRAPH_ID)ii; level_changers()[i]->m_tNextPosition = (*I)->o_Position; level_changers()[i]->m_tAngles = (*I)->o_Angle; level_changers()[i]->m_dwNextNodeID = game_graph().vertex(ii)->level_vertex_id(); ok = true; break; } R_ASSERT3 (ok,"Cannot find a correspndance between graph and graph points from level editor! Rebuild graph for the level ",*level_changers()[i]->m_caLevelToChange); level_changers().erase (level_changers().begin() + i); --i; --n; found = true; break; } if (!found) { clMsg ("Graph point %s not found (level changer %s)",*level_changers()[i]->m_caLevelPointToChange,level_changers()[i]->name_replace()); VERIFY (false); } } }
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 CAI_Space::init () { VERIFY (!m_ef_storage); m_ef_storage = xr_new<CEF_Storage>(); VERIFY (!m_game_graph); m_game_graph = xr_new<CGameGraph>(); VERIFY (!m_graph_engine); m_graph_engine = xr_new<CGraphEngine>(game_graph().header().vertex_count()); VERIFY (!m_cover_manager); m_cover_manager = xr_new<CCoverManager>(); VERIFY (!m_patrol_path_storage); m_patrol_path_storage = xr_new<CPatrolPathStorage>(); VERIFY (!m_script_engine); m_script_engine = xr_new<CScriptEngine>(); script_engine().init (); extern string4096 g_ca_stdout; setvbuf (stderr,g_ca_stdout,_IOFBF,sizeof(g_ca_stdout)); }
void CLevelSpawnConstructor::update_artefact_spawn_positions () { u32 level_point_count = m_game_spawn_constructor->level_point_count(); SPAWN_STORAGE::iterator I = m_spawns.begin(); SPAWN_STORAGE::iterator E = m_spawns.end(); for ( ; I != E; ++I) { CSE_Abstract *abstract = *I; CSE_ALifeObject *alife_object = smart_cast<CSE_ALifeObject*>(abstract); // R_ASSERT3 (level_graph().valid_vertex_id(alife_object->m_tNodeID),"Invalid node for object ",alife_object->name_replace()); R_ASSERT2 (alife_object,"Non-ALife object!"); VERIFY (game_graph().vertex(alife_object->m_tGraphID)->level_id() == m_level.id()); // alife_object->m_spawn_control = ""; CSE_ALifeAnomalousZone *zone = smart_cast<CSE_ALifeAnomalousZone*>(abstract); if (zone) { zone->m_artefact_position_offset = level_point_count; level_point_count += zone->m_artefact_spawn_count; // Msg ("%s %f [%f][%f][%f] : artefact spawn positions",zone->name_replace(),zone->m_fRadius,VPUSH(zone->o_Position)); // for (u32 i=zone->m_artefact_position_offset; i<level_point_count; ++i) // Msg (" [%f][%f][%f] : %f",VPUSH(m_level_points[i].tPoint),zone->o_Position.distance_to(m_level_points[i].tPoint)); } } m_game_spawn_constructor->add_level_points (m_level_points); }
void CGameSpawnConstructor::save_spawn (LPCSTR name, LPCSTR output) { CMemoryWriter stream; m_spawn_header.m_version = XRAI_CURRENT_VERSION; m_spawn_header.m_guid = generate_guid(); m_spawn_header.m_graph_guid = game_graph().header().guid(); m_spawn_header.m_spawn_count = spawn_graph().vertex_count(); m_spawn_header.m_level_count = (u32)m_level_spawns.size(); stream.open_chunk (0); stream.w_u32 (m_spawn_header.m_version); save_data (m_spawn_header.m_guid,stream); save_data (m_spawn_header.m_graph_guid,stream); stream.w_u32 (m_spawn_header.m_spawn_count); stream.w_u32 (m_spawn_header.m_level_count); stream.close_chunk (); stream.open_chunk (1); save_data (spawn_graph(),stream); stream.close_chunk (); stream.open_chunk (2); save_data (m_level_points,stream); stream.close_chunk (); stream.open_chunk (3); save_data (m_patrol_path_storage,stream); stream.close_chunk (); stream.open_chunk (4); m_game_graph->save (stream); stream.close_chunk (); stream.save_to (*spawn_name(output)); }
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 CGameSpawnConstructor::process_actor (LPCSTR start_level_name) { m_actor = 0; LEVEL_SPAWN_STORAGE::iterator I = m_level_spawns.begin(); LEVEL_SPAWN_STORAGE::iterator E = m_level_spawns.end(); for ( ; I != E; ++I) { if (!(*I)->actor()) continue; Msg ("Actor is on the level %s",*game_graph().header().level(game_graph().vertex((*I)->actor()->m_tGraphID)->level_id()).name()); VERIFY2 (!m_actor,"There must be the SINGLE level with ACTOR!"); m_actor = (*I)->actor(); } R_ASSERT2 (m_actor,"There is no ACTOR spawn point!"); if (!start_level_name) return; if (!xr_strcmp(*actor_level_name(),start_level_name)) return; const CGameGraph::SLevel &level = game_graph().header().level(start_level_name); GameGraph::_GRAPH_ID dest = GameGraph::_GRAPH_ID(-1); GraphEngineSpace::CGameLevelParams evaluator(level.id()); CGraphEngine *graph_engine = xr_new<CGraphEngine>(game_graph().header().vertex_count()); bool failed = !graph_engine->search(game_graph(),m_actor->m_tGraphID,GameGraph::_GRAPH_ID(-1),0,evaluator); if (failed) { Msg ("! Cannot build path via game graph from the current level to the level %s!",start_level_name); float min_dist = flt_max; Fvector current = game_graph().vertex(m_actor->m_tGraphID)->game_point(); GameGraph::_GRAPH_ID n = game_graph().header().vertex_count(); for (GameGraph::_GRAPH_ID i=0; i<n; ++i) { if (game_graph().vertex(i)->level_id() == level.id()) { float distance = game_graph().vertex(i)->game_point().distance_to_sqr(current); if (distance < min_dist) { min_dist = distance; dest = i; } } } if (!game_graph().vertex(dest)) { Msg ("! There is no game vertices on the level %s, cannot jump to the specified level",start_level_name); return; } } else dest = (GameGraph::_GRAPH_ID)evaluator.selected_vertex_id(); m_actor->m_tGraphID = dest; m_actor->m_tNodeID = game_graph().vertex(dest)->level_vertex_id(); m_actor->o_Position = game_graph().vertex(dest)->level_point(); xr_delete (graph_engine); }