/* * G_ExitLevel */ void G_ExitLevel( void ) { int i; edict_t *ent; char command[256]; const char *nextmapname; bool loadmap = true; unsigned int timeLimit; const unsigned int wrappingPoint = 0x70000000; level.exitNow = false; nextmapname = G_SelectNextMapName(); timeLimit = g_timelimit->integer > 0 ? max( g_timelimit->integer, 60 ) : 60; timeLimit *= 60 * 1000; // if it's the same map see if we can restart without loading if( !level.hardReset && !Q_stricmp( nextmapname, level.mapname ) ) { if( ( (signed)level.time < (signed)( wrappingPoint-timeLimit ) ) && G_RespawnLevel() ) { loadmap = false; } } if( loadmap ) { BOT_RemoveBot( "all" ); // MbotGame (Disconnect all bots before changing map) Q_snprintfz( command, sizeof( command ), "gamemap \"%s\"\n", nextmapname ); trap_Cmd_ExecuteText( EXEC_APPEND, command ); } G_SnapClients(); // clear some things before going to next level for( i = 0; i < gs.maxclients; i++ ) { ent = game.edicts + 1 + i; if( !ent->r.inuse ) continue; ent->r.client->level.showscores = false; if( ent->health > ent->max_health ) ent->health = ent->max_health; // some things are only cleared when there's a new map load if( loadmap ) { ent->r.client->connecting = true; // set all connected players as "reconnecting" ent->s.team = TEAM_SPECTATOR; } } }
/* * G_SnapFrame * It's time to send a new snap, so set the world up for sending */ void G_SnapFrame( void ) { edict_t *ent; game.realtime = trap_Milliseconds(); // level.time etc. might not be real time //others G_UpdateServerInfo(); // exit level if( level.exitNow ) { G_ExitLevel(); return; } AITools_Frame(); //MbotGame //give think time to AI debug tools // finish snap G_SnapClients(); // build the playerstate_t structures for all players G_SnapEntities(); // add effects based on accumulated info along the frame // set entity bits (prepare entities for being sent in the snap) for( ent = &game.edicts[0]; ENTNUM( ent ) < game.numentities; ent++ ) { if( ent->s.number != ENTNUM( ent ) ) { if( developer->integer ) G_Printf( "fixing ent->s.number (etype:%i, classname:%s)\n", ent->s.type, ent->classname ? ent->classname : "noclassname" ); ent->s.number = ENTNUM( ent ); } // temporary filter (Q2 system to ensure reliability) // ignore ents without visible models unless they have an effect if( !ent->r.inuse ) { ent->r.svflags |= SVF_NOCLIENT; continue; } else if( ent->s.type >= ET_TOTAL_TYPES || ent->s.type < 0 ) { if( developer->integer ) G_Printf( "'G_SnapFrame': Inhibiting invalid entity type %i\n", ent->s.type ); ent->r.svflags |= SVF_NOCLIENT; continue; } else if( !( ent->r.svflags & SVF_NOCLIENT ) && !ent->s.modelindex && !ent->s.effects && !ent->s.sound && !ISEVENTENTITY( &ent->s ) && !ent->s.light && !ent->r.client ) { if( developer->integer ) G_Printf( "'G_SnapFrame': fixing missing SVF_NOCLIENT flag (no effect)\n" ); ent->r.svflags |= SVF_NOCLIENT; continue; } ent->s.effects &= ~EF_TAKEDAMAGE; if( ent->takedamage ) ent->s.effects |= EF_TAKEDAMAGE; if( GS_MatchPaused() ) { // when in timeout, we don't send entity sounds entity_sound_backup[ENTNUM( ent )] = ent->s.sound; ent->s.sound = 0; } } }