📄 g_main.cpp
字号:
if (!client->inuse)
continue;
ent = G_GetEntity( client->s.number );
G_MoveClientToIntermission( ent );
}
// tell the script that the player's not ready so that if we return to this map,
// we can do something about it.
Director.PlayerNotReady();
}
/*
=============
G_ExitLevel
=============
*/
void G_ExitLevel
(
void
)
{
char command[ 256 ];
int j;
edict_t *ent;
// kill the sounds
Com_sprintf( command, sizeof( command ), "stopsound\n" );
gi.AddCommandString( command );
Com_sprintf( command, sizeof( command ), "gamemap \"%s\"\n", level.nextmap.c_str() );
gi.AddCommandString( command );
level.nextmap = "";
level.exitintermission = 0;
level.intermissiontime = 0;
G_SaveClientData();
// Tell all the client that the level is done
for( j = 1; j <= game.maxclients; j++ )
{
ent = &g_edicts[ j ];
if ( !ent->inuse || !ent->entity )
{
continue;
}
ent->entity->ProcessEvent( EV_Player_EndLevel );
}
G_ClientEndServerFrames();
// tell the script that the player's not ready so that if we return to this map,
// we can do something about it.
Director.PlayerNotReady();
}
void G_DrawCSystem
(
void
)
{
Vector pos;
Vector ang;
Vector f;
Vector r;
Vector u;
Vector v;
pos.x = csys_posx->value;
pos.y = csys_posy->value;
pos.z = csys_posz->value;
ang.x = csys_x->value;
ang.y = csys_y->value;
ang.z = csys_z->value;
ang.AngleVectors( &f, &r, &u );
G_DebugLine( pos, pos + f * 48, 1.0, 0, 0, 1 );
G_DebugLine( pos, pos + r * 48, 0, 1.0, 0, 1 );
G_DebugLine( pos, pos + u * 48, 0, 0, 1.0, 1 );
}
/*
================
G_RunFrame
Advances the world by 0.1 seconds
================
*/
void G_RunFrame
(
void
)
{
edict_t *edict;
Entity *ent;
int num;
qboolean showentnums;
int start;
int end;
// If we get an error, call the server's error function
if ( setjmp( G_AbortGame ) )
{
G_ExitWithError();
}
level.framenum++;
level.time = level.framenum * FRAMETIME;
if ( g_showmem->value )
{
DisplayMemoryUsage();
}
// exit intermissions
if ( level.exitintermission )
{
G_ExitLevel();
return;
}
// if the player in the server and the mission has failed, show the loadmenu
if ( g_edicts[ 1 ].inuse && level.missionfailed && ( level.missionfailedtime < level.time ) )
{
// restart the entire server
gi.AddCommandString( "con_clearfade\n" );
gi.AddCommandString( "menu_loadgame\n" );
return;
}
path_checksthisframe = 0;
// Reset debug lines
G_InitDebugLines();
// testing coordinate system
if ( csys_draw->value )
{
G_DrawCSystem();
}
PathManager.ShowNodes();
// don't show entnums during deathmatch
showentnums = ( sv_showentnums->value && ( !deathmatch->value || sv_cheats->value ) );
// Process most of the events before the physics are run
// so that we can affect the physics immediately
G_ProcessPendingEvents();
//
// treat each object in turn
//
for( edict = active_edicts.next, num = 0; edict != &active_edicts; edict = level.next_edict, num++ )
{
assert( edict );
assert( edict->inuse );
assert( edict->entity );
level.next_edict = edict->next;
// Paranoia - It's a way of life
assert( num <= MAX_EDICTS );
if ( num > MAX_EDICTS )
{
gi.dprintf( "Possible infinite loop in G_RunFrame.\n");
break;
}
ent = edict->entity;
level.current_entity = ent;
if ( g_timeents->value )
{
start = G_Milliseconds();
G_RunEntity( ent );
end = G_Milliseconds();
if ( g_timeents->value <= ( end - start ) )
{
G_DebugPrintf( "%d: '%s'(%d) : %d\n", level.framenum, ent->targetname.c_str(), ent->entnum, end - start );
}
}
else
{
G_RunEntity( ent );
}
if ( showentnums )
{
G_DrawDebugNumber( ent->worldorigin + Vector( 0, 0, ent->maxs.z + 2 ), ent->entnum, 2, 1, 1, 0 );
}
}
// Process any pending events that got posted during the physics code.
G_ProcessPendingEvents();
// see if it is time to end a deathmatch
G_CheckDMRules();
// build the playerstate_t structures for all players
G_ClientEndServerFrames();
// see if we should draw the bounding boxes
G_ClientDrawBoundingBoxes();
// show how many traces the game code is doing
if ( sv_traceinfo->value )
{
if ( sv_traceinfo->value == 3 )
{
G_DebugPrintf( "%0.1f : Total traces %d\n", level.time, sv_numtraces );
}
else
{
gi.dprintf( "%0.1f : Total traces %d\n", level.time, sv_numtraces );
}
}
// reset out count of the number of game traces
sv_numtraces = 0;
}
void G_ClientThink
(
edict_t *ent,
usercmd_t *ucmd
)
{
// If we get an error, call the server's error function
if ( setjmp( G_AbortGame ) )
{
G_ExitWithError();
}
if ( ent->entity )
{
current_ucmd = ucmd;
level.current_entity = ent->entity;
ent->entity->ProcessEvent( EV_ClientMove );
current_ucmd = NULL;
}
}
/*
===========
G_PutClientInServer
Called when a player connects to a server
============
*/
void G_PutClientInServer
(
edict_t *ent
)
{
if ( !ent->entity )
{
G_InitSpawnArguments();
G_SetSpawnArg( "classname", "player" );
game.force_entnum = true;
game.spawn_entnum = ent->s.number;
G_CallSpawn();
game.force_entnum = false;
if ( ent->entity && ent->entity->isSubclassOf( Player ) )
{
( ( Player * )ent->entity )->Init();
}
}
}
/*
===========
G_ClientBegin
called when a client has finished connecting, and is ready
to be placed into the game. This will happen every level load.
============
*/
void G_ClientBegin
(
edict_t *ent,
qboolean loadgame
)
{
// If we get an error, call the server's error function
if ( setjmp( G_AbortGame ) )
{
G_ExitWithError();
}
if ( ent->inuse && ent->entity )
{
// the client has cleared the client side viewangles upon
// connecting to the server, which is different than the
// state when the game is saved, so we need to compensate
// with deltaangles
ent->entity->SetDeltaAngles();
}
else
{
// a spawn point will completely reinitialize the entity
G_InitEdict( ent );
G_InitClientResp( ent->client );
G_PutClientInServer( ent );
}
if ( level.intermissiontime && ent->entity )
{
G_MoveClientToIntermission( ent->entity );
}
else
{
// send effect if in a multiplayer game
if ( game.maxclients > 1 )
{
gi.bprintf (PRINT_HIGH, "%s entered the game\n", ent->client->pers.netname);
}
}
// make sure all view stuff is valid
if ( ent->entity )
{
ent->entity->ProcessEvent( EV_ClientEndFrame );
}
}
void FixDeadBodiesForPlayer
(
edict_t *ent
)
{
int i,playernum;
edict_t *body;
if ( !deathmatch->value )
return;
playernum = ent-g_edicts-1;
for ( i=0; i<BODY_QUEUE_SIZE; i++ )
{
body = &g_edicts[ ( int )maxclients->value + 1 + i ];
if ( ( body->s.skinnum == playernum ) && ( body->s.modelindex != ent->s.modelindex ) )
{
body->s.renderfx |= RF_DONTDRAW;
body->s.skinnum = -1;
}
}
}
/*
===========
G_ClientUserInfoChanged
called whenever the player updates a userinfo variable.
The game can override any of the settings in place
(forcing skins or names, etc) before copying it off.
============
*/
void G_ClientUserinfoChanged
(
edict_t *ent,
const char *userinfo
)
{
const char *s;
int playernum;
Player *player;
str model;
float fov;
Event *ev;
// If we get an error, call the server's error function
if ( setjmp( G_AbortGame ) )
{
G_ExitWithError();
}
player = ( Player * )ent->entity;
ent->client->ps.pmove.pm_flags &= ~PMF_OLDNOCLIP;
s = Info_ValueForKey( userinfo, "cl_oldnoclip" );
if (strlen(s))
{
if ( atoi(s) )
{
ent->client->ps.pmove.pm_flags |= PMF_OLDNOCLIP;
}
}
// set name
s = Info_ValueForKey( userinfo, "name" );
strncpy (ent->client->pers.netname, s, sizeof(ent->client->pers.netname)-1);
// Don't allow zero length names
if ( !strlen( ent->client->pers.netname ) )
strcpy( ent->client->pers.netname, "Blade" );
if ( deathmatch->value )
{
// set skin
s = Info_ValueForKey( userinfo, "skin" );
strncpy( ent->client->pers.skin, s, sizeof( ent->client->pers.skin ) - 1 );
}
// Don't allow zero length skins
if ( !strlen( ent->client->pers.skin ) )
{
strcpy( ent->client->pers.skin, "blade_base" );
}
// set model only if player not a mutant
if ( !( player && ( player->flags & (FL_MUTANT|FL_SP_MUTANT) ) ) )
{
s = Info_ValueForKey( userinfo, "model" );
COM_StripExtension( s, ent->client->pers.model );
strcat( ent->client->pers.model, ".def" );
// Don't allow zero length models
if ( !strlen( ent->client->pers.model ) )
{
strcpy( ent->client->pers.model, "pl_blade.def" );
}
// Only allow models that the server sets up in the players script file
model = ent->client->pers.model;
if ( !game.ValidPlayerModels.ObjectInList( model ) )
{
// Fall back to blade
strcpy( ent->client->pers.model, "pl_blade.def" );
}
#ifdef SIN_DEMO
if ( 1 )
#else
// Always be blade in single player
if ( !deathmatch->value )
#endif
{
strcpy( ent->client->pers.model, "pl_blade.def" );
}
// Call the player's setModel function if he exists
// Prepend 'models/' to make things easier
if ( !strchr( ent->client->pers.model, '*' ) && !strchr( ent->client->pers.model, '\\' ) && !strchr( ent->client->pers.model, '/' ) )
{
model = "models/";
model += ent->client->pers.model;
}
else
{
model = ent->client->pers.model;
}
if ( player && !player->deadflag && ( player->model != model ) )
{
player->setModel( model );
player->RandomAnimate( "idle", NULL );
}
}
// Fov
if ( player )
{
fov = atof( Info_ValueForKey( userinfo, "fov" ) );
if ( fov < 1 )
{
fov = 90;
}
else if ( fov > 160 )
{
fov = 160;
}
ev = new Event( EV_Player_Fov );
ev->AddFloat( fov );
player->ProcessEvent( ev );
}
// Player number
playernum = ent - g_edicts - 1;
// combine name, skin and model into a configstring
gi.configstring (CS_PLAYERSKINS+playernum, va("%s\\%s\\%s",
ent->client->pers.netname,
ent->client->pers.model,
ent->client->pers.skin));
// handedness
s = Info_ValueForKey( userinfo, "hand" );
if ( strlen( s ) )
{
ent->client->pers.hand = atoi( s );
}
// save off the userinfo in case we want to check something later
strncpy( ent->client->pers.userinfo, userinfo, sizeof( ent->client->pers.userinfo )-1 );
// Hide the bodies that are associated with this player so that
// no weird animations show up on the client
if ( ( !LoadingSavegame ) && ( deathmatch->value || coop->value ) )
FixDeadBodiesForPlayer( ent );
}
/*
===========
G_ClientConnect
Called when a player begins connecting to the server.
The game can refuse entrance to a client by returning false.
If the client is allowed, the connection process will continue
and eventually get to ClientBegin()
Changing levels will NOT cause this to be called again.
============
*/
qboolean G_ClientConnect
(
edict_t *ent,
const char *userinfo
)
{
const char *value;
// If we get an error, call the server's error function
if ( setjmp( G_AbortGame ) )
{
G_ExitWithError();
}
// check to see if they are on the banned IP list
value = Info_ValueForKey( userinfo, "ip" );
if ( SV_FilterPacket( value ) )
{
return false;
}
// check for a password
value = Info_ValueForKey( userinfo, "password" );
if ( strcmp( password->string, value ) != 0 )
{
return false;
}
// if there is already a body waiting for us (a loadgame), just
// take it, otherwise spawn one from scratch
if ( ent->inuse == false )
{
// clear the respawning variables
G_InitClientResp( ent->client );
if ( !game.autosaved )//|| !ent->client->pers.weapon)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -