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

📄 g_spawn.cpp

📁 this keik game source
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	int		c2;

	c = 0;
	c2 = 0;

	for( e = active_edicts.next; e != &active_edicts; e = next )
		{
		assert( e );
		assert( e->inuse );
		assert( e->entity );

		next = e->next;

		if ( e == g_edicts )
			{
			continue;
			}

		ent = e->entity;
		if ( !ent->moveteam.length() )
			{
			continue;
			}

		if ( ent->flags & FL_TEAMSLAVE )
			{
			continue;
			}

		chain = ent;
		ent->teammaster = ent;
		c++;
		c2++;
		for( e2 = next; e2 != &active_edicts; e2 = next2 )
			{
			assert( e2 );
			assert( e2->inuse );
			assert( e2->entity );

			next2 = e2->next;

			ent2 = e2->entity;
			if ( !ent2->moveteam.length() )
				{
				continue;
				}

			if ( ent2->flags & FL_TEAMSLAVE )
				{
				continue;
				}

			if ( ent->moveteam == ent2->moveteam )
				{
				c2++;
				chain->teamchain = ent2;
				ent2->teammaster = ent;
				chain = ent2;
				ent2->flags |= FL_TEAMSLAVE;
				}
			}
		}

	gi.dprintf( "%i teams with %i entities\n", c, c2 );
	}

/*
==============
G_LevelShutdown

Get rid of anything left over from the last level
==============
*/
void G_LevelShutdown
   (
   void
   )

   {
	PathManager.SavePaths();

	assert( active_edicts.next );
	assert( active_edicts.next->prev = &active_edicts );
	assert( active_edicts.prev );
	assert( active_edicts.prev->next = &active_edicts );
	assert( free_edicts.next );
	assert( free_edicts.next->prev == &free_edicts );
	assert( free_edicts.prev );
	assert( free_edicts.prev->next == &free_edicts );

	while( active_edicts.next != &active_edicts )
		{
		assert( active_edicts.next != &free_edicts );
		assert( active_edicts.prev != &free_edicts );

		assert( active_edicts.next );
		assert( active_edicts.next->prev = &active_edicts );
		assert( active_edicts.prev );
		assert( active_edicts.prev->next = &active_edicts );
		assert( free_edicts.next );
		assert( free_edicts.next->prev == &free_edicts );
		assert( free_edicts.prev );
		assert( free_edicts.prev->next == &free_edicts );

		if ( active_edicts.next->entity )
			{
			delete active_edicts.next->entity;
			}
		else
			{
			G_FreeEdict( active_edicts.next );
			}
		}

   globals.num_edicts = game.maxclients + 1;

   // Reset the gravity paths
   gravPathManager.Reset();

   // close all the scripts
	Director.CloseScript();

   // invalidate player readiness
   Director.PlayerNotReady();

   // clearout any waiting events
  	G_ClearEventList();

	gi.FreeTags( TAG_LEVEL );
   }

/*
==============
G_ResetEdicts
==============
*/
void G_ResetEdicts
   (
   void
   )

   {
   int i;

   memset( g_edicts, 0, game.maxentities * sizeof( g_edicts[ 0 ] ) );

	// Add all the edicts to the free list
	LL_Reset( &free_edicts, next, prev );
	LL_Reset( &active_edicts, next, prev );
	for( i = 0; i < game.maxentities; i++ )
		{
		LL_Add( &free_edicts, &g_edicts[ i ], next, prev );
		}

	for (i=0 ; i<game.maxclients ; i++)
		{
     	// set client fields on player ents
		g_edicts[ i + 1 ].client = game.clients + i;
		G_InitClientResp (&game.clients[i]);
		}

   globals.num_edicts = game.maxclients + 1;
   }

/*
==============
G_MapInit

Set up for a new map.  This is called for loading savegames, so anything done here should
be compatible with G_ReadGame.
==============
*/
void G_MapInit
   (
   const char *mapname
   )

   {
	G_ClearEventList();
	PathManager.Init( mapname );

   // init level and console script variables
   consoleVars.ClearList();
	levelVars.ClearList();
   }

/*
==============
G_LevelStart

Does all post-spawning setup.  This is NOT called for savegames.
==============
*/
void G_LevelStart
   (
   void
   )

   {
   ScriptThread *gamescript;
   const char   *scriptname;

   // initialize secrets
   levelVars.SetVariable( "total_secrets", level.total_secrets );
   levelVars.SetVariable( "found_secrets", level.found_secrets );

	G_FindTeams();

   // Create the mission computer
   consoleManager.CreateMissionComputer();

   // call the precache scripts
   G_Precache();

   //
   // start executing the game script
   //
	scriptname = ScriptLib.GetGameScript();
	if ( scriptname && scriptname[ 0 ] )
		{
   	gamescript = Director.CreateThread( scriptname, LEVEL_SCRIPT );
		if ( gamescript )
			{
			// start at the end of this frame
			gamescript->Start( 0 );
			}
		}
   }

/*
==============
G_Precache

Calls precache scripts
==============
*/
void G_Precache
   (
   void
   )

   {
   const char *scriptname;
   int i;

   //
   // load in global0-9.scr
   // 
   for( i = 0; i < 10; i++ )
      {
      G_LoadAndExecScript( va( "global/global%i.scr", i ) );
      }

   //
   // load in precache0-9.scr
   // 
   if ( precache->value )
      {
      for( i = 0; i < 10; i++ )
         {
         G_LoadAndExecScript( va( "global/precache%i.scr", i ) );
         }
      }

   //
   // load in players0-9.scr
   //
   for( i = 0; i< 10; i++ )
      {
      G_LoadAndExecScript( va( "global/players%i.scr", i ) );
      }

   //
   // load in universal_script.scr
   //
   G_LoadAndExecScript( "global/universal_script.scr", "precache:" );

   //
   // precache for the game script
   //
	scriptname = ScriptLib.GetGameScript();
	if ( scriptname && scriptname[ 0 ] )
		{
      G_LoadAndExecScript( scriptname, "precache:" );
		}
   }

/*
==============
G_SpawnEntities

Creates a server's entity / program execution context by
parsing textual entity definitions out of an ent file.
==============
*/
void G_SpawnEntities
	(
	const char *mapname, 
	const char *entities, 
	const char *spawnpoint
	)

	{
	int			inhibit;
	const char	*com_token;
	float			skill_level;
	const char	*value;
	int			spawnflags;
	qboolean		world_spawned;
	cvar_t		*lowdetail;
   int         i=0;
#if 0
   Class       *obj;
   Entity      *ent;
#endif

	// If we get an error, call the server's error function
	if ( setjmp( G_AbortGame ) )
		{
		G_ExitWithError();
		}

	lowdetail = gi.cvar( "r_lowdetail", "0", CVAR_ARCHIVE );

   // Init the level variables
   level = level_locals_t();
   level.mapname = mapname;
	game.spawnpoint = spawnpoint;

   if ( !LoadingServer )
      {
      // Get rid of anything left over from the last level
      G_LevelShutdown();

      G_ResetEdicts();

      // Set up for a new map
      G_MapInit( mapname );
      }

   // Init surface manager & consoles
   surfaceManager.Reset();
   globals.num_surfaces = 0;
   memset (g_surfaces, 0, game.maxsurfaces * sizeof (g_surfaces[0]));
   
   globals.num_consoles = 0;
   memset (g_consoles, 0, game.maxconsoles * sizeof (g_consoles[0]));

	skill_level = floor( skill->value );
   skill_level = bound( skill_level, 0, 3 );
	if ( skill->value != skill_level )
		{
		gi.cvar_forceset( "skill", va( "%f", skill_level ) );
		}

   gameVars.SetVariable( "skill", skill_level );

	// reset out count of the number of game traces
	sv_numtraces = 0;

   level.playerfrozen = false;

	inhibit = 0;
	world_spawned = false;

   // parse ents
	while (1)
		{
		// parse the opening brace	
		com_token = COM_Parse (&entities);
		if (!entities)
			{
			break;
			}
		if (com_token[0] != '{')
			{
			gi.error ("G_LoadFromFile: found %s when expecting {",com_token);
			}

      i++;
      if ( !( i % 20 ) )
         gi.IncrementStatusCount( 20 );

		entities = G_ParseEdict (entities);

		// remove things (except the world) from different skill levels or deathmatch
		value = G_GetSpawnArg( "spawnflags" );
		if ( world_spawned && value )
			{
			spawnflags = atoi( value );
			if (deathmatch->value)
				{
				if ( spawnflags & SPAWNFLAG_NOT_DEATHMATCH )
					{
					inhibit++;
					continue;
					}
				}
			else
				{
				if (
					((skill->value == 0) && (spawnflags & SPAWNFLAG_NOT_EASY)) ||
					((skill->value == 1) && (spawnflags & SPAWNFLAG_NOT_MEDIUM)) ||
					(((skill->value == 2) || (skill->value == 3)) && (spawnflags & SPAWNFLAG_NOT_HARD) ||
					( coop->value && (spawnflags & SPAWNFLAG_NOT_COOP) )) ||
               ( !developer->value && ( spawnflags & SPAWNFLAG_DEVELOPMENT ) ) ||
               ( lowdetail->value && ( spawnflags & SPAWNFLAG_DETAIL ) )
					)
					{
					inhibit++;
					continue;
					}
				}
			}

		game.force_entnum = !world_spawned;
		game.spawn_entnum = 0;
		G_CallSpawn();
		world_spawned = true;

#if 0
      // have to fix G_CallSpawn so that freed entities are accounted for
      if ( obj && obj->isSubclassOf( Entity ) )
         {
         ent = ( Entity * )obj;

	      // Sanity check to see if we're expecting a B-Model
	      assert( !( ( ent->edict->solid == SOLID_BSP ) && !ent->edict->s.modelindex ) );
	      if ( ( ent->edict->solid == SOLID_BSP ) && !ent->edict->s.modelindex )
		      {
		      if ( ent->edict->s.number == 0 )
			      {
			      gi.error( "No model for worldspawn!" );
			      }
		      else
			      {
			      gi.dprintf( "Deleting %s with SOLID_BSP and no model\n", ent->getClassID() );
			      delete ent;
			      }
		      }
         }
#endif
		}	

	game.force_entnum = false;
	gi.dprintf ("%i entities inhibited\n", inhibit);

	G_InitSpawnArguments();

   if ( !LoadingServer || game.autosaved )
      {
      G_LevelStart();
      }
	}

/*
=================
G_Spawn

Either finds a free edict, or allocates a new one.
Try to avoid reusing an entity that was recently freed, because it
can cause the client to think the entity morphed into something else
instead of being removed and recreated, which can cause interpolated
angles and bad trails.
=================
*/
edict_t *G_Spawn
	(
	void
	)

	{
	int		i;
	edict_t	*e;

	e = &g_edicts[ ( int )maxclients->value + 1 ];
	for ( i = maxclients->value + 1; i < globals.num_edicts; i++, e++ )
		{
		// the first couple seconds of server time can involve a lot of
		// freeing and allocating, so relax the replacement policy
		if ( !e->inuse && ( e->freetime < 2 || level.time - e->freetime > 0.5 ) )
			{
			assert( e->next );
			assert( e->prev );
			LL_Remove( e, next, prev );
			G_InitEdict( e );
			assert( active_edicts.next );
			assert( active_edicts.prev );
			LL_Add( &active_edicts, e, next, prev );
			assert( e->next );
			assert( e->prev );
			return e;
			}
		}
	
	if ( i == game.maxentities )
		{
		gi.error( "G_Spawn: no free edicts" );
		}
		
	globals.num_edicts++;
	assert( e->next );
	assert( e->prev );
	LL_Remove( e, next, prev );
	G_InitEdict( e );
	assert( active_edicts.next );
	assert( active_edicts.prev );
	LL_Add( &active_edicts, e, next, prev );
	assert( e->next );
	assert( e->prev );

	assert( e->next != &free_edicts );
	assert( e->prev != &free_edicts );

	return e;
	}

/*
=================
G_FreeEdict

Marks the edict as free
=================
*/
void G_FreeEdict 
	(
	edict_t *ed
	)

	{
	gclient_t *client;

	assert( ed != &free_edicts );

	// unlink from world
	gi.unlinkentity ( ed );

	assert( ed->next );
	assert( ed->prev );

	if ( level.next_edict == ed )
		{
		level.next_edict = ed->next;
		}
	
	LL_Remove( ed, next, prev );

	assert( ed->next == ed );
	assert( ed->prev == ed );
	assert( free_edicts.next );
	assert( free_edicts.prev );

	client = ed->client;
	memset( ed, 0, sizeof( *ed ) );
	ed->client = client;
	ed->freetime = level.time;
	ed->inuse = false;
   ed->s.number = ed - g_edicts;

	assert( free_edicts.next );
	assert( free_edicts.prev );

	LL_Add( &free_edicts, ed, next, prev );

	assert( ed->next );
	assert( ed->prev );
	}

/*
==============
G_InitClientPersistant

This is only called when the game first initializes in single player,
but is called after each death and level change in deathmatch
==============
*/
void G_InitClientPersistant 
	(
	gclient_t *client
	)

	{
	memset( &client->pers, 0, sizeof( client->pers ) );

	client->pers.health		= 100;
	client->pers.max_health	= 100;
	}


void G_InitClientResp
	(
	gclient_t *client
	)

	{
	memset( &client->resp, 0, sizeof( client->resp ) );
	client->resp.enterframe = level.framenum;
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -