⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 g_main.cpp

📁 this keik game source
💻 CPP
📖 第 1 页 / 共 5 页
字号:
		
      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 + -