📄 g_main.cpp
字号:
for( i = 0; i < game.maxclients; i++ )
{
ent = &g_edicts[ 1 + i ];
if ( !ent->inuse || !ent->entity )
{
continue;
}
PersistantData.AddEnt( ent->entity );
}
}
/*
=================
WriteLevel
=================
*/
void WriteLevel
(
const char *filename,
qboolean autosave
)
{
int i;
int num;
edict_t *edict;
Archiver arc;
if ( autosave )
{
for( i = 0; i < game.maxclients; i++ )
{
edict = &g_edicts[ 1 + i ];
if ( !edict->inuse && !edict->entity )
{
continue;
}
delete edict->entity;
}
}
arc.Create( filename );
// write out the version number
arc.WriteInteger( GAME_API_VERSION );
arc.WriteInteger( SAVEGAME_VERSION );
// Write out the pending events. These are written first in case
// later objects need to post events when reading the archive.
G_ArchiveEvents( arc );
// write out level_locals_t
arc.WriteObject( &level );
// write out consoles
arc.WriteObject( &consoleManager );
// write out script librarian
arc.WriteObject( &ScriptLib );
// write out gravity paths
arc.WriteObject( &gravPathManager );
// write out paths
arc.WriteObject( &PathManager );
// write out script controller
arc.WriteObject( &Director );
// write out surface manager
arc.WriteObject( &surfaceManager );
// write out Viewmodel manager (for debugging only)
arc.WriteObject( &Viewmodel );
// count the entities
num = 0;
for( i = 0; i < globals.num_edicts; i++ )
{
edict = &g_edicts[ i ];
if ( edict->inuse && edict->entity && !( edict->entity->flags & FL_DONTSAVE ) )
{
num++;
}
}
// write out all the entities
arc.WriteInteger( globals.num_edicts );
arc.WriteInteger( num );
for( i = 0; i < globals.num_edicts; i++ )
{
edict = &g_edicts[ i ];
if ( !edict->inuse || !edict->entity || ( edict->entity->flags & FL_DONTSAVE ) )
{
continue;
}
arc.WriteObject( edict->entity );
}
arc.Close();
}
void G_WriteLevel
(
const char *filename,
qboolean autosave
)
{
// If we get an error, call the server's error function
if ( setjmp( G_AbortGame ) )
{
G_ExitWithError();
}
WriteLevel( filename, autosave );
}
/*
=================
ReadLevel
SpawnEntities will already have been called on the
level the same way it was when the level was saved.
That is necessary to get the baselines set up identically.
The server will have cleared all of the world links before
calling ReadLevel.
No clients are connected yet.
=================
*/
void ReadLevel
(
const char *filename
)
{
int i;
int num;
Archiver arc;
int version;
int savegame_version;
LoadingSavegame = true;
// Get rid of anything left over from the last level
G_LevelShutdown();
G_ResetEdicts();
arc.Read( filename );
// read the version number
arc.ReadInteger( &version );
if ( version < GAME_API_VERSION )
{
gi.error( "Savegame from an older version (%d) of Sin.\n", version );
}
else if ( version > GAME_API_VERSION )
{
gi.error( "Savegame from version %d of Sin.\n", version );
}
arc.ReadInteger( &savegame_version );
if ( savegame_version < SAVEGAME_VERSION )
{
gi.error( "Savegame from an older version (%d) of Sin.\n", version );
}
else if ( savegame_version > SAVEGAME_VERSION )
{
gi.error( "Savegame from version %d of Sin.\n", version );
}
// Read in the pending events. These are read in first in case
// later objects need to post events.
G_UnarchiveEvents( arc );
// read level_locals_t
arc.ReadObject( &level );
// read consoles
arc.ReadObject( &consoleManager );
// read script librarian
arc.ReadObject( &ScriptLib );
// read gravity paths
arc.ReadObject( &gravPathManager );
// read paths
arc.ReadObject( &PathManager );
// read script controller
arc.ReadObject( &Director );
// read surface manager
arc.ReadObject( &surfaceManager );
// read Viewmodel manager (for debugging only)
arc.ReadObject( &Viewmodel );
// read all the entities
arc.ReadInteger( &globals.num_edicts );
arc.ReadInteger( &num );
for( i = 0; i < num; i++ )
{
arc.ReadObject();
}
arc.Close();
// call the precache scripts
G_Precache();
LoadingSavegame = false;
}
void G_ReadLevel
(
const char *filename
)
{
// If we get an error, call the server's error function
if ( setjmp( G_AbortGame ) )
{
G_ExitWithError();
}
ReadLevel( filename );
}
/*
=================
GetGameAPI
Returns a pointer to the structure with all entry points
and global variables
=================
*/
game_export_t *GetGameAPI
(
game_import_t *import
)
{
gi = *import;
globals.apiversion = GAME_API_VERSION;
globals.Init = G_InitGame;
globals.Shutdown = G_ShutdownGame;
globals.SpawnEntities = G_SpawnEntities;
globals.CreateSurfaces = CreateSurfaces;
globals.WriteGame = G_WriteGame;
globals.ReadGame = G_ReadGame;
globals.WriteLevel = G_WriteLevel;
globals.ReadLevel = G_ReadLevel;
globals.ClientThink = G_ClientThink;
globals.ClientConnect = G_ClientConnect;
globals.ClientUserinfoChanged = G_ClientUserinfoChanged;
globals.ClientDisconnect = G_ClientDisconnect;
globals.ClientBegin = G_ClientBegin;
globals.ClientCommand = G_ClientCommand;
globals.RunFrame = G_RunFrame;
globals.ServerCommand = G_ServerCommand;
globals.edict_size = sizeof(edict_t);
globals.console_size = sizeof(netconsole_t);
globals.conbuffer_size = sizeof(netconbuffer_t);
globals.surface_size = sizeof(netsurface_t);
return &globals;
}
#ifndef GAME_HARD_LINKED
// this is only here so the functions in q_shared.c and q_shwin.c can link
void Sys_Error
(
const char *error,
...
)
{
va_list argptr;
char text[1024];
va_start (argptr, error);
vsprintf (text, error, argptr);
va_end (argptr);
gi.error (ERR_FATAL, "%s", text);
}
void Com_Printf
(
const char *msg,
...
)
{
va_list argptr;
char text[1024];
va_start (argptr, msg);
vsprintf (text, msg, argptr);
va_end (argptr);
gi.dprintf ("%s", text);
}
#endif
//======================================================================
/*
=================
G_ClientEndServerFrames
=================
*/
void G_ClientEndServerFrames
(
void
)
{
int i;
edict_t *ent;
// calc the player views now that all pushing
// and damage has been added
for( i = 0; i < maxclients->value; i++ )
{
ent = g_edicts + 1 + i;
if ( !ent->inuse || !ent->client || !ent->entity )
{
continue;
}
ent->entity->ProcessEvent( EV_ClientEndFrame );
}
}
/*
=================
G_EndDMLevel
The timelimit or fraglimit has been exceeded
=================
*/
void G_EndDMLevel
(
void
)
{
int num;
TriggerChangeLevel *ent;
char *s, *t, *f;
static const char *seps = " ,\n\r";
// stay on same level flag
if ( DM_FLAG( DF_SAME_LEVEL ) )
{
G_BeginIntermission( level.mapname.c_str() );
return;
}
// see if it's in the map list
if ( *sv_maplist->string )
{
s = strdup(sv_maplist->string);
f = NULL;
t = strtok( s, seps );
while ( t != NULL )
{
if ( !stricmp( t, level.mapname.c_str() ) )
{
// it's in the list, go to the next one
t = strtok( NULL, seps );
if ( t == NULL )
{ // end of list, go to first one
if ( f == NULL ) // there isn't a first one, same level
G_BeginIntermission( level.mapname.c_str() );
else
G_BeginIntermission( f );
}
else
{
G_BeginIntermission( t );
}
free(s);
return;
}
if (!f)
{
f = t;
}
t = strtok(NULL, seps);
}
free(s);
}
if ( !level.nextmap.length() )
{
// search for a changelevel
num = G_FindClass( 0, "target_changelevel" );
if ( !num )
{
// the map designer didn't include a changelevel,
// so go back to the same level
G_BeginIntermission( level.mapname.c_str() );
}
else
{
ent = ( TriggerChangeLevel * )G_GetEntity( num );
G_BeginIntermission( ent->Map() );
}
}
}
/*
=================
G_CheckDMRules
=================
*/
void G_CheckDMRules
(
void
)
{
int i;
gclient_t *cl;
if ( level.intermissiontime )
{
return;
}
if ( !deathmatch->value )
{
return;
}
if ( timelimit->value )
{
if ( level.time >= timelimit->value * 60 )
{
gi.bprintf( PRINT_HIGH, "Timelimit hit.\n" );
G_EndDMLevel();
return;
}
}
if ( fraglimit->value )
{
for( i = 0; i < maxclients->value; i++ )
{
cl = game.clients + i;
if ( !g_edicts[ i + 1 ].inuse )
{
continue;
}
if ( cl->resp.score >= fraglimit->value )
{
gi.bprintf( PRINT_HIGH, "Fraglimit hit.\n" );
G_EndDMLevel();
return;
}
}
}
}
void G_MoveClientToIntermission
(
Entity *ent
)
{
// Display the scores for the client
if ( deathmatch->value || coop->value )
{
ent->client->showinfo = true;
G_DeathmatchScoreboardMessage( ent, NULL );
gi.unicast( ent->edict, true );
}
}
void G_BeginIntermission
(
const char *map
)
{
edict_t *client;
Entity *ent;
Entity *path;
int i,num;
Event *event, event2;
assert( map );
if ( !map )
{
gi.dprintf( "G_BeginIntermission : Null map name\n" );
return;
}
if ( level.missionfailed )
{
// don't allow map changes when a mission has failed
return;
}
if ( level.intermissiontime )
{
// already activated
return;
}
level.intermissiontime = level.time;
if ( level.clearsavegames && ( map[ 0 ] != '*' ) )
{
level.nextmap = str( "*" ) + map;
}
else
{
level.nextmap = map;
}
level.clearsavegames = false;
level.exitintermission = !( deathmatch->value || coop->value );
// find an intermission spot
num = G_FindClass( 0, "info_player_intermission" );
// Only do the camera stuff if the node exists.
if ( num )
{
ent = G_GetEntity( num );
SetCamera( ent );
event = new Event( EV_Camera_Orbit );
// Find the end node
num = G_FindTarget( 0, "endnode1" );
if ( num )
{
path = G_GetEntity( num );
event->AddEntity( path );
ent->ProcessEvent( event );
event = new Event( EV_Camera_JumpCut );
ent->ProcessEvent( event );
}
}
// Display scores for all the clients
for( i = 0; i < maxclients->value; i++ )
{
client = g_edicts + 1 + i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -