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

📄 g_utils.cpp

📁 this keik game source
💻 CPP
📖 第 1 页 / 共 3 页
字号:
			bestspot = spot;
			bestdistance = bestplayerdistance;
			}
		}

	if ( bestspot )
		{
		return bestspot;
		}

	// if there is a player just spawned on each and every start spot
	// we have no choice to turn one into a telefrag meltdown
	num = G_FindClass( 0, "info_player_deathmatch" );
	spot = G_GetEntity( num );

	return spot;
	}

Entity *SelectDeathmatchSpawnPoint
	(
	void
	)

	{
	if ( DM_FLAG( DF_SPAWN_FARTHEST ) )
		{
		return SelectFarthestDeathmatchSpawnPoint();
		}
	else
		{
		return SelectRandomDeathmatchSpawnPoint();
		}
	}

Entity *SelectCoopSpawnPoint
	(
	void
	)

	{
   const char *tname;
	Entity *spot = NULL;
	int num;

	num = 0;
	while( ( num = G_FindClass( num, "info_player_coop" ) ) != 0 )
		{
		spot = G_GetEntity( num );
      tname = spot->TargetName();
		if ( !game.spawnpoint.length() || !tname || !tname[ 0 ] )
			{
			break;
			}

		if ( Q_stricmp( game.spawnpoint.c_str(), spot->TargetName() ) == 0 )
			{
			break;
			}
		}

	return spot;
	}


/*
===========
SelectSpawnPoint

Chooses a player start, deathmatch start, coop start, etc
============
*/
void SelectSpawnPoint
	(
	Vector &origin,
	Vector &angles,
	int *gravaxis
	)

	{
   const char * tname;
	Entity *spot = NULL;
	Entity *spot2 = NULL;
	int num;

   if ( ( level.training == 2 ) && game.spawnpoint.length() )
      {
		num = 0;
		while( ( num = G_FindClass( num, "info_player_progressivestart" ) ) != 0 )
			{
			spot2 = G_GetEntity( num );
         tname = spot2->TargetName();
			if ( !tname || !tname[ 0 ] )
				{
				break;
				}

			if ( Q_stricmp( game.spawnpoint.c_str(), spot2->TargetName() ) == 0 )
				{
            spot = spot2;
				break;
				}
			}
		}
   else if ( deathmatch->value || level.training == 1 )
		{
		spot = SelectDeathmatchSpawnPoint();
		}
	else if ( coop->value )
		{
		spot = SelectCoopSpawnPoint();
		}

	// find a single player start spot
	if ( !spot )
		{
		num = 0;
		while( ( num = G_FindClass( num, "info_player_start" ) ) != 0 )
			{
			spot = G_GetEntity( num );
         tname = spot->TargetName();
			if ( !game.spawnpoint.length() || !tname || !tname[ 0 ] )
				{
				break;
				}

			if ( Q_stricmp( game.spawnpoint.c_str(), spot->TargetName() ) == 0 )
				{
				break;
				}
			}

		if ( !spot )
			{
			if ( !game.spawnpoint.length() )
				{
				// there wasn't a spawnpoint without a target, so use any
				num = G_FindClass( 0, "info_player_start" );
				spot = G_GetEntity( num );
				}

			if ( !spot || !spot->entnum )
				{
				gi.error( "Couldn't find spawn point %s\n", game.spawnpoint.c_str() );
				}
			}
		}

	origin = spot->worldorigin + "0 0 9";
	angles = spot->angles;
	if ( gravaxis )
		{
		*gravaxis = spot->gravaxis;
		}
	}

/*
=============
M_CheckBottom

Returns false if any part of the bottom of the entity is off an edge that
is not a staircase.

=============
*/
int c_yes, c_no;

qboolean M_CheckBottom
	(
	Entity *ent
	)

	{
	Vector	mins, maxs, start, stop;
	trace_t	trace;
	int		x, y;
	float		mid, bottom;
	
	mins = ent->worldorigin + ent->mins * 0.5;
	maxs = ent->worldorigin + ent->maxs * 0.5;

	// if all of the points under the corners are solid world, don't bother
	// with the tougher checks
	// the corners must be within 16 of the midpoint
	start[ 2 ] = mins[ 2 ] - 1;

	for( x = 0; x <= 1; x++ )
		{
		for( y = 0; y <= 1; y++ )
			{
			start[ 0 ] = x ? maxs[ 0 ] : mins[ 0 ];
			start[ 1 ] = y ? maxs[ 1 ] : mins[ 1 ];
			if ( gi.pointcontents( start.vec3() ) != CONTENTS_SOLID )
				{
				goto realcheck;
				}
			}
		}

	c_yes++;
	return true;		// we got out easy

realcheck:
	
	c_no++;

	//
	// check it for real...
	//
	start[ 2 ] = mins[ 2 ];
	
	// the midpoint must be within 16 of the bottom
	start[ 0 ] = stop[ 0 ] = ( mins[ 0 ] + maxs[ 0 ] ) * 0.5;
	start[ 1 ] = stop[ 1 ] = ( mins[ 1 ] + maxs[ 1 ] ) * 0.5;
	stop[ 2 ] = start[ 2 ] - 3 * STEPSIZE;//2 * STEPSIZE;

	trace = G_Trace( start, vec_zero, vec_zero, stop, ent, MASK_MONSTERSOLID, "M_CheckBottom 1" );

	if ( trace.fraction == 1.0 )
		{
		return false;
		}

	mid = bottom = trace.endpos[ 2 ];
	
	// the corners must be within 16 of the midpoint	
	for( x = 0; x <= 1; x++ )
		{
		for( y = 0; y <= 1; y++ )
			{
			start[ 0 ] = stop[ 0 ] = x ? maxs[ 0 ] : mins[ 0 ];
			start[ 1 ] = stop[ 1 ] = y ? maxs[ 1 ] : mins[ 1 ];
			
			trace = G_Trace( start, vec_zero, vec_zero, stop, ent, MASK_MONSTERSOLID, "M_CheckBottom 2" );
			
			if ( trace.fraction != 1.0 && trace.endpos[ 2 ] > bottom )
				{
				bottom = trace.endpos[ 2 ];
				}

			if ( trace.fraction == 1.0 || mid - trace.endpos[ 2 ] > STEPSIZE )
				{
				return false;
				}
			}
		}

	c_yes++;
	return true;
	}

char *G_CopyString
	(
	const char *in
	)

	{
	char	*newb;
	char	*new_p;
	int	i,l;

	assert( in );
	
	l = strlen( in ) + 1;

	newb = ( char * )gi.TagMalloc( l, TAG_LEVEL );
	new_p = newb;

	for( i = 0; i < l; i++ )
		{
		if ( ( in[ i ] == '\\' ) && ( i < l - 1 ) )
			{
			i++;
			if ( in[ i ] == 'n' )
				{
				*new_p++ = '\n';
				}
			else
				{
				*new_p++ = '\\';
				}
			}
		else
			{
			*new_p++ = in[ i ];
			}
		}
	
	return newb;
	}

int G_FindClass
	( 
	int entnum, 
	const char *classname 
	)

	{
	edict_t *from;

	for ( from = &g_edicts[ entnum + 1 ]; from < &g_edicts[ globals.num_edicts ] ; from++ )
		{
		if ( !from->inuse )
			{
			continue;
			}
		if ( !Q_stricmp ( from->entity->getClassID(), classname ) )
			{
			return from->s.number;
			}
		}

	return 0;
	}

int G_FindTarget
	( 
	int entnum, 
	const char *name 
	)

	{
   edict_t  *from;
   Entity   *next;

   if ( name && name[ 0 ] )
      {
      from = &g_edicts[ entnum ];
      next = world->GetNextEntity( str( name ), from->entity );
      if ( next )
			{
         return next->entnum;
			}
		}

	return 0;
	}

EXPORT_FROM_DLL Entity *G_NextEntity
	(
	Entity *ent
	)
	
	{
	edict_t *from;

	if ( !g_edicts )
		{
		return NULL;
		}

	if ( !ent )
		{
		ent = world;
		}

	if ( !ent )
		{
		return NULL;
		}

	for ( from = ent->edict + 1; from < &g_edicts[ globals.num_edicts ] ; from++ )
		{
		if ( !from->inuse || !from->entity )
			{
			continue;
			}

		return from->entity;
		}

	return NULL;
	}

//
// QuakeEd only writes a single float for angles (bad idea), so up and down are
// just constant angles.
//
Vector G_GetMovedir
	(
	void
	)

	{
	float	angle;

	angle = G_GetFloatArg( "angle" );
	if ( angle == -1 )
		{
		return Vector( 0, 0, 1 );
		}
	else if ( angle == -2 )
		{
		return Vector( 0, 0, -1 );
		}

	angle *= ( M_PI * 2 / 360 );
	return Vector( cos( angle ), sin( angle ), 0 );
	}

/*
=================
KillBox

Kills all entities that would touch the proposed new positioning
of ent.  Ent should be unlinked before calling this!
=================
*/
qboolean KillBox
	(
	Entity *ent
	)
	
	{
	int		i;
	int		num;
	edict_t	*touch[ MAX_EDICTS ];
	edict_t	*hit;
   Vector   min;
   Vector   max;
   int      fail;

   fail = 0;

   min = ent->worldorigin + ent->mins;
   max = ent->worldorigin + ent->maxs;
	num = gi.BoxEdicts( min.vec3(), max.vec3(), touch, MAX_EDICTS, AREA_SOLID );
   for( i = 0; i < num; i++ )
		{
		hit = touch[ i ];
		
      if ( !hit->inuse || ( hit->entity == ent ) || !hit->entity || ( hit->entity == world ) )
			{
			continue;
			}

      hit->entity->Damage( ent, ent, hit->entity->health + 100000, ent->worldorigin, vec_zero, vec_zero, 
         0, DAMAGE_NO_PROTECTION, MOD_TELEFRAG, -1, -1, 1.0f );

		//
		// if we didn't kill it, fail
		//
		if ( hit->entity->getSolidType() != SOLID_NOT )
			{
         fail++;
			}
		}

	//
	// all clear
	//
	return !fail;
	}

qboolean IsNumeric
	(
	const char *str
	)
	
	{
	int len;
	int i;
	qboolean dot;

	if ( *str == '-' )
		{
		str++;
		}

	dot = false;
	len = strlen( str );
	for( i = 0; i < len; i++ )
		{
		if ( !isdigit( str[ i ] ) )
			{
			if ( ( str[ i ] == '.' ) && !dot )
				{
				dot = true;
				continue;
				}
			return false;
			}
		}

	return true;
	}

void G_InitEdict 
	(
	edict_t *e
	)

	{
	e->inuse = true;
	e->s.number = e - g_edicts;

   // make sure a default scale gets set
   e->s.scale = 1.0f;
	e->s.renderfx |= RF_FRAMELERP;
	e->spawntime = level.time;
	e->s.frame = 0;
	e->s.prevframe = -1;
	}

/*
=================
findradius

Returns entities that have origins within a spherical area

findradius (origin, radius)
=================
*/
Entity *findradius
	(
	Entity *startent,
	Vector org,
	float rad
	)

	{
	Vector	eorg;
	edict_t	*from;
	float		r2;

	if ( !startent )
		{
		startent = world;
		}

	if ( !startent )
		{
      return NULL;
      }

	// square the radius so that we don't have to do a square root
	r2 = rad * rad;

	assert( startent->edict );
	for ( from = startent->edict + 1; from < &g_edicts[ globals.num_edicts ]; from++ )
		{
		if ( !from->inuse )
			{
			continue;
			}

		assert( from->entity );

      eorg = org - from->entity->centroid;

		// dot product returns length squared
		if ( ( eorg * eorg ) <= r2 )
			{
			return from->entity;
			}
		}

	return NULL;
	}

/*
=================
findclientinradius

Returns clients that have origins within a spherical area

findclientinradius (origin, radius)
=================
*/
Entity *findclientsinradius
	(
   Entity *startent,
	Vector org,
	float rad
	)

	{
	Vector	eorg;
	edict_t	*ed;
	float		r2;
   int      i;

   // square the radius so that we don't have to do a square root
	r2 = rad * rad;

 	for( i = startent->entnum; i < game.maxclients; i++ )
      {
		ed = &g_edicts[ 1 + i ];

		if ( !ed->inuse || !ed->entity )
			{
			continue;
			}

      eorg = org - ed->entity->centroid;

		// dot product returns length squared
		if ( ( eorg * eorg ) <= r2 )
			{
			return ed->entity;
			}
		}

	return NULL;
	}

const char *G_GetNameForSurface
	(
	csurface_t *s
	)

	{
	switch( s->flags & MASK_SURF_TYPE )
		{
		case SURF_TYPE_WOOD :
			return "wood";

		case SURF_TYPE_METAL :
			return "metal";

		case SURF_TYPE_STONE :
			return "stone";

		case SURF_TYPE_CONCRETE :
			return "concrete";

		case SURF_TYPE_DIRT :
			return "dirt";

		case SURF_TYPE_FLESH :
			return "flesh";

		case SURF_TYPE_GRILL :
			return "grill";

		case SURF_TYPE_GLASS :
			return "glass";

		case SURF_TYPE_FABRIC :
			return "fabric";

		case SURF_TYPE_MONITOR :
			return "monitor";

		case SURF_TYPE_GRAVEL :
			return "gravel";

		case SURF_TYPE_VEGETATION :
			return "vegetation";

		case SURF_TYPE_PAPER :
			return "paper";

		case SURF_TYPE_DUCT :
			return "duct";

		case SURF_TYPE_WATER :
			return "water";
		}

	return "";
	}

void G_InitDebugLines
	(
	void
	)

	{
	*gi.DebugLines = DebugLines;
	*gi.numDebugLines = 0;

	currentVertex = vec_zero;
	vertColor = Vector( 1, 1, 1 );
	vertAlpha = 1;
	vertexIndex = 0;
	}

void G_AllocDebugLines
	(
	void
	)

	{
	g_numdebuglines = gi.cvar( "g_numdebuglines", "4096", CVAR_LATCH );

	DebugLines = ( debugline_t * )gi.TagMalloc( ( int )g_numdebuglines->value * sizeof( debugline_t ), TAG_GAME );

   G_InitDebugLines();
	}

void G_DebugLine
	(
	Vector start,
	Vector end,
	float r,
	float g,
	float b,
	float alpha
	)

	{
	debugline_t *line;

   if ( !g_numdebuglines )
      {
      return;
      }

	if ( *gi.numDebugLines >= g_numdebuglines->value )
		{
		gi.dprintf( "G_DebugLine: Exceeded MAX_DEBUG_LINES\n" );
		return;
		}

	line = &DebugLines[ *gi.numDebugLines ];
	( *gi.numDebugLines )++;

	VectorCopy( start.vec3(), line->start );
	VectorCopy( end.vec3(), line->end );
	VectorSet( line->color, r, g, b );
	line->alpha = alpha;
	}

⌨️ 快捷键说明

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